4주차 목표 설정

카테고리 주간 실행 목표 (Action Item) 결과
01. 문제해결 매일 알고리즘 문제 1개 풀이로 논리적 사고 훈련 ⭐ ⭐ ⭐
02. 설계 코드 작성 전, 주석으로 로직을 먼저 설계하는 습관 갖기
03. 구현 React 공식 문서 실습을 통해 탄탄한 기본기 구현
04. 품질 기본 테스트 케이스 외에 나만의 예외 케이스 1개 추가 검증
05. 유지보수 변수 명명에 의미를 담아 가독성 높은 코드 작성하기
06. 협업 작업 현황을 팀원들에게 즉시 공유하여 투명한 소통 유지 ⭐ ⭐
07. 태도 과제 부여 시 의도와 상위 카테고리를 먼저 분석하는 습관
08. 비즈니스 이해 사용자 입장에서 UI/UX의 편의성을 고민하며 코드 생산
09. AI & 생산성 배포 자동화 프로세스를 구축하여 개발 생산성 극대화
10. 학습 민첩성 기존의 단순 Merge 대신 Pull Request를 활용한 코드 리뷰 및 흐름 파악 ⭐ ⭐ ⭐

 

 

4주차 목표 후기

4주차에 설정한 목표를 대부분 해내지 못했다.

특히 협업시 바이브코딩으로 만들어낸 소스코드를 내가 이해하지 못했다.

남의 코드 역시 100% 이해하지 못했고 이 부분을 내가 알아 볼 수 있고 설명 할 수 있는 레벨에서 코드를 생성해야겠다고 느꼈다.

3/21 BFS DFS

트리의 부모 찾기, leetcode 섬의 개수

https://forrest7.tistory.com/39

 

[React] "React는 왜 빠를까?" 딥다이브: Virtual DOM과 Diffing 알고리즘

 

1. 왜 DOM이 있는데 Virtual DOM을 만들까?

브라우저의 실제 DOM은 느리지 않습니다. 진짜 느린 것은 DOM이 변경될 때 발생하는 브라우저의 '렌더링 과정(Reflow/Repaint)'입니다.

브라우저의 가혹한 렌더링 과정

JavaScript로 DOM을 조작할 때마다 브라우저는 다음 과정을 거칩니다.

  1. Recalculate Style: 스타일 계산
  2. Layout (Reflow): 요소의 크기와 위치 재계산
  3. Paint: 화면에 그리기

만약 1,000개의 리스트를 하나씩 수정하면 이 무거운 과정을 1,000번 반복할 수도 있습니다. Virtual DOM은 일종의 '버퍼링' 역할을 하여, 변경 사항을 모았다가 실제 DOM에 단 한 번만 반영(Batch Update)함으로써 이 비용을 획기적으로 줄입니다.

2. VDOM은 항상 빠를까? (반전 주의)

"전체 HTML 페이지를 다 수정할 때는 오히려 VDOM이 더 느립니다."
그 이유는 간단합니다.

  • 새로운 VDOM 트리를 생성해야 함
  • 이전 트리와 비교(Diffing) 알고리즘을 돌려야 함
  • 결국 실제 DOM도 전체를 다 갈아엎어야 함

즉, 작업 단계가 하나 더 추가되는 셈입니다. VDOM은 데이터가 부분적으로 자주 바뀔 때 최적의 효율을 냅니다.

3. React Diffing 알고리즘: O(n)의 비밀

React가 사용하는 Diffing 알고리즘이 O(n^3)에서 O(n)으로 파격적인 다이어트를 할 수 있었던 이유는 "완벽한 최소 변경 경로"를 찾는 것을 포기하고, "현실적인 지름길"을 선택했기 때문입니다. 이를 Heuristic Reconciliation(휴리스틱 비교)이라고 부릅니다.

 

3-1. 계층별 비교 (Level-by-Level Check)

  • 동일 레벨 비교: React는 트리를 순회할 때 같은 층위에 있는 노드들끼리만 비교합니다.
  • 비교 생략: 만약 어떤 노드가 부모를 갈아탔다면, React는 이를 '이동'으로 인식하지 않고 이전 부모 아래의 노드는 삭제, 새 부모 아래의 노드는 새로 생성합니다.
  • 이 덕분에 전체 트리를 훑지 않고 위에서 아래로 딱 한 번만 훑고 내려가면 끝납니다. (O(n)의 첫 번째 비결)

3-2. 엘리먼트 타입에 의한 가지치기 (Bailing out by Type)

  • 타입이 다르면? (<div> rightarrow <span>): 그 아래에 자식이 1,000개가 달려 있어도 React는 더 이상 비교하지 않습니다. "아, 이건 아예 다른 거구나"라고 결론짓고 기존 서브트리를 통째로 날린 뒤 새로 만듭니다.
  • 타입이 같으면? (<div> rightarrow <div>): 오직 변경된 속성(Attribute)이나 텍스트 내용만 업데이트하고 다음 자식으로 넘어갑니다.
  • 이 방식은 복잡한 하위 트리 비교 연산을 순식간에 종료(Short-circuit)시켜 버립니다.

3-3. Key를 이용한 Map 매핑 (The Key Optimization)

  • 기존 방식: 첫 번째 요소부터 하나씩 대조하며 "얘가 걔인가?" 확인.
  • Key 방식: 새로운 리스트를 만들 때 기존 Key들을 Map에 담아둡니다. ({ 'key_a': Node_A, 'key_b': Node_B })
  • 새로운 노드를 렌더링할 때 Map에서 해당 Key를 바로 찾아내어(Map.get(key)) 위치만 옮깁니다.
  • 결과: 리스트를 한 번 순회($n$)하면서 Map에서 값을 찾는 과정(상수 시간)만 거치므로 리스트 비교 역시 O(n)에 수렴하게 됩니다.
  • 가장 결정적인 부분입니다. 자식 리스트를 비교할 때 Key가 없다면 순서대로 비교해야 하므로 O(n^2)에 가까운 연산(비효율적인 업데이트)이 발생할 수 있지만, Key가 있으면 이를 Hash Map 구조처럼 사용합니다.
  • React는 노드의 타입(HTML 태그나 컴포넌트 이름)을 가장 먼저 확인합니다.
  • 일반적인 트리 비교 알고리즘은 한 트리의 노드가 다른 트리의 어느 위치로든 갈 수 있다고 가정하고 모든 조합을 계산합니다. 하지만 React는 "웹 페이지에서 노드가 다른 부모 밑으로 가는 경우는 드물다"고 판단했습니다.
  • 왜 O(n)이 가능한지 그 내부 로직을 3가지 핵심 포인트로 짚어드릴게요.

4. 리스트와 Key: 핵심 피드백 정리

Q. Key가 없으면 어떻게 동작할까?

React는 자식들을 순서대로 비교합니다. 리스트 맨 앞에 새 요소가 추가되면, React는 "모든 요소가 바뀌었다"고 착각하고 전체를 다시 그리는 대참사가 일어납니다.

Q. UUID를 굳이 써야 할까?

아니요, 그럴 필요 없습니다. Key는 형제(Sibling) 사이에서만 고유하면 됩니다. 데이터베이스의 ID값이 있다면 그것이 베스트입니다. 전역적으로 유니크할 필요는 없습니다.

Q. Key를 넣는 게 무조건 나을까?

네, 리스트 렌더링 시 Key는 필수입니다. Key가 없으면 React는 인덱스 번호로 비교를 시도하며, 이는 데이터 정렬이나 삭제 시 예기치 못한 버그와 성능 저하를 일으킵니다.

Q. Key가 중복되면? (React vs Vue)

  • React: 콘솔 경고를 띄우고, 첫 번째 요소만 정상 처리하거나 렌더링이 꼬일 수 있습니다.
  • Vue: 비슷하게 경고를 주지만, 내부 최적화 방식에 따라 렌더링 결과가 다를 수 있습니다. 결론은 둘 다 중복 Key는 금기 사항입니다.

5. 심화 질문과 실무 가이드

비교할 때 '해시(Hash)'를 쓰면 더 빠르지 않을까?

이론적으로는 가능하지만, 트리 전체의 해시를 만드는 비용 자체가 큽니다. React는 이미 충분히 빠른 타입 비교와 Key 식별 전략을 택해 실용적인 최적화를 이루었습니다.

렌더링 최적화 (텍스트)

React는 div 안의 텍스트가 바뀔 때, 전체 텍스트를 지우고 새로 쓰는 게 아니라 변경된 마지막 부분만 취하는 방식 등으로 내부적인 최적화를 수행합니다.

⚠️ 실무에서 조심해야 할 점

  • data-key 사용: 리스트 엘리먼트에 Key를 명시하지 않으면 React가 훨씬 더 많은 연산을 수행해야 합니다.
  • State의 특성: React의 State는 메모리(RAM)에 저장됩니다. 브라우저를 새로고침하면 사라지는 이유가 바로 이것입니다. 히스토리를 관리하고 싶다면 별도의 저장 로직이 필요합니다.

6. 결론: 협업과 고도화

수요코딩이나 실무 협업 시, Requirement(명세서)를 고도화하면서 업무를 분할해 보세요.

"이 컴포넌트는 리스트 양이 많으니 고유 ID를 Key로 바인딩하고, 불필요한 재렌더링을 막기 위해 메모이제이션을 적용한다"

위와 같은 기준을 명세서에 녹여내면 더 수준 높은 개발이 가능해집니다!

'Jungle > WIL(Weekly I Learned)' 카테고리의 다른 글

[WIL] 7주  (0) 2026.04.16
[WIL] 6주  (0) 2026.04.06
[WIL] 5주  (0) 2026.03.27
[WIL] 3주  (0) 2026.03.19
[WIL] 2주  (0) 2026.03.12

+ Recent posts