jQuery / Selector / :even - 짝수 인덱스 요소를 선택하는 선택자

jQuery의 :even은 선택된 요소 목록에서 인덱스가 0·2·4인 요소, 즉 첫 번째·세 번째·다섯 번째 요소를 선택합니다. 이 선택자는 jQuery 3.4부터 비권장이므로 새 코드에서는 같은 선택 결과에 .even()을 사용하는 편이 적합합니다. CSS의 :nth-child(even)과는 세는 기준과 시작 숫자가 다릅니다.

:even과 .even()의 버전·기준

:even 선택자 문서는 0부터 세는 짝수 인덱스와 3.4의 비권장 지정을 설명합니다. 대안인 .even() 메서드는 jQuery 3.5에 추가되었습니다. 오래된 jQuery 1.x 파일을 그대로 불러온 상태에서 .even()으로만 바꾸면 사용할 수 없으므로, 페이지가 실제로 로드한 버전도 확인해야 합니다.

이 글의 코드는 Windows의 브라우저에서 jQuery 3.7.1과 4.0.0으로 실행해 결과를 확인했습니다. :even은 확인한 두 버전에서 모두 동작했습니다. 비권장이라는 말과 이미 제거되었다는 말은 구분하며, 앞으로 작성하거나 보강하는 코드에서는 권장 대안으로 바꿉니다.

짝수 인덱스와 짝수 번째는 다릅니다

표현 세는 대상·시작 선택되는 위치
:even 또는 .even() 현재 선택 목록, 0부터 인덱스 0·2·4: 첫째·셋째·다섯째
:nth-child(even) 각 부모의 형제 요소, 1부터 둘째·넷째·여섯째 자식
:nth-child(odd) 각 부모의 형제 요소, 1부터 첫째·셋째·다섯째 자식

하나의 목록에서 li만 형제로 있다면 .even()과 :nth-child(odd)의 결과가 같을 수 있습니다. 그러나 여러 목록의 li를 한 번에 선택하면 .even()은 합쳐진 선택 목록을 기준으로 계산합니다. :nth-child()는 부모마다 다시 세고, 선택한 태그 종류뿐 아니라 모든 형제 요소의 위치를 기준으로 판단합니다.

두 목록을 비교하는 전체 실행 예제

아래 전체 코드를 UTF-8의 even-demo.html로 저장해 브라우저에서 엽니다. 인터넷으로 공식 jQuery 배포 파일을 읽으므로 네트워크 연결이 필요합니다. 예제는 4.0.0을 고정해 사용하며 별도 패키지 설치는 필요하지 않습니다. A와 B 목록에는 각각 li 세 개가 있습니다.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Even indexes and sibling positions</title>
  <style>
    body { font: 16px/1.6 sans-serif; margin: 24px; }
    .items { padding: 0; list-style: none; }
    .items li { padding: 8px 14px; border: 1px solid #ddd; }
    .marked { background: #fff0b3; }
    button { margin: 4px; padding: 8px; }
  </style>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
  <h1>Even indexes and sibling positions</h1>
  <div id="groups">
    <ul class="items"><li id="a1">A1</li><li id="a2" class="keep">A2</li><li id="a3" class="keep">A3</li></ul>
    <ul class="items"><li id="b1" class="keep">B1</li><li id="b2">B2</li><li id="b3" class="keep">B3</li></ul>
  </div>
  <button type="button" id="combined">Combined .even()</button>
  <button type="button" id="per-parent">Each list .even()</button>
  <button type="button" id="css-even">CSS :nth-child(even)</button>
  <button type="button" id="reset">Reset</button>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      function show($chosen) {
        $("#groups li").removeClass("marked");
        $chosen.addClass("marked");
        const ids = $chosen.map((_, item) => item.id).get().join(", ");
        $("#result").text(`${ids || "none"} | ${$chosen.length}`);
      }
      $("#combined").on("click", () => show($("#groups li").even()));
      $("#per-parent").on("click", function () {
        let $chosen = $();
        $(".items").each(function () {
          $chosen = $chosen.add($(this).children("li").even());
        });
        show($chosen);
      });
      $("#css-even").on("click", () => show($("#groups li:nth-child(even)")));
      $("#reset").on("click", () => show($()));
      show($("#groups li").even());
    });
  </script>
</body>
</html>

처음 열면 전체 여섯 요소의 인덱스 0·2·4인 A1·A3·B2가 강조되며 결과는 다음과 같습니다.

a1, a3, b2 | 3

버튼별 결과를 확인하고 초기화하기

  1. Combined .even()은 두 목록을 합쳐 계산합니다. 결과는 a1, a3, b2 | 3입니다.
  2. Each list .even()은 각 목록의 자식 li를 별도로 선택합니다. 부모마다 처음부터 세므로 a1, a3, b1, b3 | 4가 됩니다.
  3. CSS :nth-child(even)은 각 목록의 두 번째 자식을 선택하므로 a2, b2 | 2입니다.
  4. Reset은 강조 표시를 지우고 none | 0을 표시합니다. 항목 자체는 삭제하지 않습니다. 다시 Combined 버튼을 누르면 첫 결과로 돌아옵니다.

show는 기존 강조 클래스를 전체에서 지운 다음 새 결과에만 붙입니다. 목록별 선택에서는 각 부모의 결과를 add로 합쳐 표시하므로, 계산 범위가 전체 선택인지 부모별인지 코드와 화면을 함께 비교할 수 있습니다.

기존 :even 코드를 .even()으로 옮기기

기존 선택자에서 :even을 떼고, 나머지 선택으로 얻은 jQuery 객체 뒤에 .even()을 호출합니다. 예제를 처음 연 상태나 Combined 버튼을 누른 뒤 개발자 도구의 Console에서 다음 부분 코드를 실행합니다. 첫 두 줄은 같은 선택을 만들고, 세 번째는 형제의 짝수 번째를 선택합니다.

const ids = $set => $set.map((_, item) => item.id).get().join(", ");
console.log(ids($("#groups li:even")));
console.log(ids($("#groups li").even()));
console.log(ids($("#groups li:nth-child(even)")));
a1, a3, b2
a1, a3, b2
a2, b2

마이그레이션하면서 .even()을 :nth-child(even)으로 바꾸면 단순한 문법 교체가 아니라 선택 의미가 달라집니다. 행의 줄무늬를 부모별로 넣을 것인지, 검색·필터를 통과한 결과에서 번갈아 고를 것인지 먼저 결정합니다. :even은 jQuery 확장이므로 CSS 스타일시트에 그대로 쓰는 선택자로 생각하지 않습니다.

필터 순서와 문서 변경에 주의하기

예제의 keep 클래스는 A2·A3·B1·B3에 있습니다. 먼저 $("#groups li.keep").even()으로 범위를 줄이면 A2·B1이 선택됩니다. 반대로 $("#groups li").even().filter(".keep")는 전체의 짝수 인덱스를 고른 뒤 keep을 남겨 A3만 선택합니다. 체인의 순서가 달라지면 인덱스를 계산하는 목록도 달라집니다.

선택 결과는 자동으로 갱신되는 목록이 아닙니다. 항목을 추가·삭제하거나 필터 조건을 바꾼 뒤 현재 순서로 다시 강조하려면 선택과 .even()을 다시 실행합니다. 예제가 반응하지 않으면 Network에서 jQuery 파일의 로딩을, Console에서 오류와 jQuery.fn.jquery 값을 확인합니다. 같은 페이지에 여러 버전을 중복 로드하지 않았는지도 살펴봅니다.