본문으로 건너뛰기
개발 머꼬
개발 노트Vue
hohyeon.dev35

1만 행 테이블이 체크박스 하나에 멈추던 것을 v-memo로 줄인 과정

  • #Engineering Note
  • #Performance
  • #Vue

문제 발생

행이 1만 개인 표에서 체크박스 하나를 눌러도 화면이 눈에 띄게 멈췄습니다. 선택 상태가 바뀌면 전체 행이 다시 비교됐기 때문입니다.

원인 분석

Vue의 갱신은 이미 빠르지만 공짜는 아닙니다. 행마다 여러 바인딩이 있으면 값이 그대로여도 비교 비용이 행 수만큼 쌓입니다.

Vue는 이런 경우를 위한 디렉티브를 제공합니다. 문서 설명대로 v-memo의존성 배열을 기준으로 템플릿의 하위 트리를 메모이제이션하며, 배열의 모든 값이 지난 렌더와 같으면 그 하위 트리 전체의 갱신을 건너뜁니다.

용도도 명확히 한정돼 있습니다 — v-memo는 성능이 중요한 시나리오의 미세 최적화만을 위해 제공되며 거의 필요하지 않습니다. 도움이 되는 가장 흔한 경우는 큰 v-for 목록(길이 > 1000)을 렌더할 때입니다.

주의도 함께 있습니다 — 메모이제이션 배열을 올바르게 지정하는 것이 중요하며, 그렇지 않으면 실제로 적용되어야 할 갱신을 건너뛸 수 있습니다. 그리고 구조적 제약 — v-memov-for 안에서는 동작하지 않으므로, 함께 쓸 때는 같은 요소에 써야 합니다.

해결 방안

  1. 같은 요소에 v-for와 함께 씁니다.
<tr v-for="row in rows" :key="row.id" v-memo="[row.id === selectedId, row.updatedAt]">
  <td>{{ row.name }}</td>
  <td><input type="checkbox" :checked="row.id === selectedId" /></td>
</tr>

선택 상태가 바뀐 두 행만 갱신되고 나머지는 건너뜁니다.

  1. 배열에 화면에 쓰이는 값을 빠짐없이 넣습니다. 빠뜨린 값이 바뀌면 화면이 갱신되지 않습니다 — 이 디렉티브의 유일하고 실질적인 위험입니다.

  2. 먼저 측정합니다. 문서가 "거의 필요하지 않다"고 적을 만큼 특수한 도구입니다. 수백 행 규모에서는 key를 제대로 주는 것만으로 충분한 경우가 대부분입니다.

  3. v-once와 구분합니다. 문서 설명대로 빈 배열(v-memo="[]")은 기능적으로 v-once와 같습니다 — 절대 바뀌지 않는 정적 블록에는 v-once가 의도를 더 잘 드러냅니다.

  4. 다른 해법을 먼저 검토합니다. 가상 스크롤(보이는 행만 렌더)이 1만 행 문제에는 대개 더 큰 효과를 냅니다. v-memo는 그 위에 얹는 마지막 손질입니다.

  5. 제거 조건을 함께 적어둡니다. 미세 최적화는 코드를 읽기 어렵게 만듭니다 — 왜 넣었는지와 어떤 조건에서 빼도 되는지를 주석으로 남깁니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.