Skip to content

《실전 React 19.3 & TypeScript: jQuery 레거시에서 완성하는 게시판 아키텍처》 ​

사내 개발자를 위한 단일 코드베이스 점진적 리팩터링 & 풀스택 실무 가이드

📦 실습 예제 풀스택 소스코드 패키지 (.zip)
Spring Boot 3 백엔드 + React 19.3 프론트엔드 + 14단계 챕터별 실습 코드 및 스냅샷이 모두 포함되어 있습니다. (node_modules 및 빌드 캐시 제외)
예제 소스 다운로드 (.zip)

🗺️ 단일 게시판 코드의 14단계 진화 로드맵 ​


🚀 풀스택 실습 환경 구성 및 따라하기 안내 ​

TIP

jQuery만 써 보셨고 React는 처음이신가요? 1장 코드에는 JSX, useState, useEffect, async/await, interface, axios 같은 낯선 개념이 한꺼번에 등장합니다. 먼저 Chapter 00. 준비운동을 한 번 훑어보고 시작하십시오. 각 장 첫머리의 📋 처음 만나는 개념 표와 본문의 🆕 처음 보는 문법 박스가 새 문법이 어디서 설명되는지 친절하게 짚어 줍니다.

본 교재는 코드를 눈으로 읽기만 하는 책이 아닙니다.
개발자가 직접 한 줄씩 코드를 작성(Hands-on)하고 브라우저와 콘솔, 자동 테스트에서 동작을 검증하며 아키텍처의 진화를 체감할 수 있도록 설계되었습니다.

📥 예제 소스 다운로드 및 Git 저장소

0) 사전 요구사항 및 대상 기술 스택 버전 (Prerequisites) ​

실습을 시작하기 전 아래 런타임 버전이 설치되어 있는지 확인하십시오. 에디터 확장 ESLint, Prettier와 브라우저 확장 React Developer Tools, Redux DevTools(9장 Zustand 연동용)도 함께 설치하십시오(0장 0.2).

구분기술 스택권장 버전비고
런타임Node.jsv22.x LTS 이상 (최소 v20.19+)프론트엔드 빌드 및 Vitest 실행
백엔드Java (JDK) / Spring BootJDK 21 LTS / Spring Boot 3.3+내장 H2 인메모리 DB 사용
코어React / TypeScript / ViteReact 19.3 / TS 5.6+ / Vite 5.4+useOptimistic, <Activity>, Compiler 대응
아키텍처Zustand / React Router / AxiosZustand 5.0+ / Router 7.x (또는 6.26+) / Axios 1.7+1분 TTL 캐싱, ProtectedRoute 가드, Single-Flight 인터셉터
최적화/테스트TanStack Virtual / Vitest / RTL / MSWReact Virtual 3.x / Vitest 2.1+ / RTL 16.x / MSW 2.4+10,000건 가상 스크롤, 단위·통합 시나리오 테스트

1) 프로젝트 디렉터리 구성 ​

react19-board-architecture/
├── backend/                   # Spring Boot 3 백엔드 (H2 DB, REST API: 8080)
│   └── src/main/resources/static/
│       ├── legacy-board.html  # 👈 1장에서 해부할 jQuery 레거시 게시판 (부록 D 위젯 실습 겸용)
│       └── docs/              # 👈 이 교재의 HTML 뷰어 (오프라인 열람 가능)
├── frontend/                  # React 19.3 + TypeScript 프론트엔드 (Vite: 3000)
│   ├── src/
│   │   ├── App.tsx            # 최상위 레이아웃 (내비게이션 + <ErrorBoundary> + <AppRouter>, 11~12장)
│   │   ├── BoardApp.tsx       # 👈 메인 컴포넌트. 처음 받으면 14장까지 마친 "최종 완성본"이 들어 있고,
│   │   │                      #    1장에서 내용을 비우고 처음부터 직접 작성합니다
│   │   ├── practice/          # 👈 2.5장 미니 React 렌더러, 13장 10,000개 댓글 가상 스크롤 실험 파일
│   │   ├── hooks/             # 👈 5장·13장 로직 분리 Custom Hook (usePagination, usePostFilter, useBoardShortcuts)
│   │   ├── components/        # 👈 6~8장, 10장, 12~13장 컴포넌트 (PostCreateModal, PostDetailModal, LikeButton,
│   │   │   └── common/        #    BoardTable<T>, ErrorBoundary, VirtualList 등)
│   │   ├── context/           # 👈 6장 계층형 댓글 트리 Context & Provider (CommentContext.tsx)
│   │   ├── types/             # 👈 7장 DTO 타입 계약 및 런타임 타입 가드 (board.ts, post.ts)
│   │   ├── stores/            # 👈 9~11장 Zustand 스토어 (usePostStore, useDraftStore, useAuthStore)
│   │   ├── router/            # 👈 11장 React Router v7 설정 및 ProtectedRoute 인가 가드
│   │   ├── views/             # 👈 11장 로그인 페이지(LoginPage.tsx) 및 부록 B Ant Design/Tailwind 뷰
│   │   ├── api/               # 👈 12장 Single-Flight httpClient.ts 및 도메인 postRepository.ts
│   │   └── snapshots/         # 👈 장별 BoardApp.tsx 완성본 (막힐 때 비교/복원용)
│   ├── tests/                 # 👈 10·12·14장 Vitest + RTL 단위/격리/통합 테스트와 MSW 핸들러(handlers.ts)
│   └── package.json           # 프론트엔드 의존성 및 실습/테스트 스크립트
└── .vscode/                   # VS Code 공통 설정

IMPORTANT

예제 코드는 "최종 완성본"입니다. frontend/src 아래의 스토어, 라우터, API 계층 등은 14장까지 마친 상태로 들어 있어, 받자마자 npm run dev로 완성된 게시판을 볼 수 있습니다. 1장에서는 BoardApp.tsx만 비우고 처음부터 작성하며, 각 장의 본문 코드는 그 장 시점의 모습이라 최종본과 다를 수 있습니다(예: 9~10장 본문 스토어는 axios를 직접 쓰지만, 12장 이후 최종본 스토어는 postRepository를 씁니다). 각 장 첫머리의 🏁 이 장의 시작 파일 박스가 어느 스냅샷에서 시작하는지 알려 주며, 장이 끝나면 snapshots/의 같은 장 파일과 비교하십시오.

2) 터미널 2개로 실습 환경 기동하기 ​

실습을 위해 2개의 터미널 창을 열어 각각 백엔드와 프론트엔드를 실행합니다:

bash
# [터미널 1] 백엔드(Spring Boot 3) 실행 (포트: 8080)
cd backend
./mvnw spring-boot:run
# (Windows PowerShell / CMD의 경우: .\mvnw.cmd spring-boot:run)

# [터미널 2] 프론트엔드(React 19.3) 실행 (포트: 3000)
cd frontend
npm install
npm run dev

3) 브라우저 접속 주소 ​

  • jQuery 레거시 화면 확인: http://localhost:8080/legacy-board.html
  • React 19.3 점진적 리팩터링 실습 화면: http://localhost:3000
  • HTML 교재 뷰어 (웹 서빙): http://localhost:8080/docs/index.html
  • 2.5장 미니 React 엔진 터미널 실습: cd frontend && npm run practice:mini-react
  • 전체 자동 테스트 실행: cd frontend && npm run test

🗂 챕터별 원고 바로가기 (Chapters) ​

TIP

각 장은 일관된 학습 구조로 짜여 있습니다. 📋 처음 만나는 개념 → 🏁 이 장의 시작 파일 → 본문 풀코드 실습(🆕 처음 보는 문법, 일상 비유 & Mermaid 다이어그램, 💡 확인하기, 🔬 심화) → 💪 [직접 해보기] 실습 미션(정답 토글 포함) → 🚀 이번 장 핵심 요약 및 다음 단계(핵심 3줄, 바뀐 파일, 자주 하는 실수, 셀프 체크).

  1. Chapter 00. 시작하기 전에: jQuery 개발자를 위한 React 19 준비운동 👈 React·JSX·불변성이 처음이라면 여기부터
  2. Chapter 01. 돌아가기만 하는 사내 레거시: jQuery 게시판의 종말
  3. Chapter 02. React 렌더링 엔진의 비밀: 가상 DOM(Fiber)과 불변성
  4. Chapter 03. 훅의 규칙과 클로저 트랩(Stale Closure)의 정복
  5. Chapter 04. 한 파일에 몰린 관심사: Fat Component의 위기
  6. Chapter 05. Custom Hook 패턴으로 로직 독립시키기 (+ 첫 자동 테스트)
  7. Chapter 06. 계층형 댓글 트리와 React Context API (DI 격리)
  8. Chapter 07. 게시판 DTO와 컴포넌트 경계선의 타입 계약
  9. Chapter 08. 어디든 재사용 가능한 제네릭 BoardTable<T> 제작
  10. Chapter 09. 상태는 언제 컴포넌트를 떠나야 하는가? (Zustand 철학)
  11. Chapter 10. '좋아요' 낙관적 업데이트와 React 19.3 useOptimistic & Zustand 롤백
  12. Chapter 11. 라우터 네비게이션 가드를 활용한 인가(Authorization) AOP
  13. Chapter 12. HTTP 레이어 격리와 프론트엔드 에러 바운더리(<ErrorBoundary>)
  14. Chapter 13. 10,000개 댓글 렌더링 최적화와 가상 스크롤 & React 19.3 신기능
  15. Chapter 14. 실전 Vitest와 Testing Library & MSW 통합 테스트

[부록 (Appendix)] 실무 현장 투입을 위한 엔터프라이즈 확장 ​


👥 사내 스터디 리더(진행자)를 위한 5주 운영 키트 ​

퇴근 후 주 2~3회, 회당 1.5~2시간을 기준으로 5주 일정을 권장합니다. 각 장은 끝의 **"실습 미션"**과 **"핵심 요약(셀프 체크)"**으로 마무리하므로, 스터디 첫 10분은 지난주 장들의 셀프 체크를 서로 묻고 답하는 데 쓰면 효과가 배가됩니다.

주차범위핵심 성취선택 과제
Week 10장, 1장, 1.5장jQuery 게시판을 React 19로 옮기고 JSX와 useState·useRef를 손에 익힌다부록 D(기존 jQuery 페이지에 React 위젯 심기)
Week 22장, 3장, 4장, 4.5장Fiber 렌더링 원리와 불변성, Stale Closure 해결, 라우터 기초2.5장(미니 React 엔진 직접 만들기)
Week 35장, 6장, 7장Custom Hook 분리와 첫 단위 테스트, Context DI, DTO 타입 계약과 타입 가드7장 실습 미션(isPostDraft)
Week 48장, 9장, 10장제네릭 BoardTable<T>, Zustand 1분 캐시, useOptimistic + 롤백 테스트8장 사원 목록 테이블 미션
Week 511장, 12장, 13장, 14장<ProtectedRoute> 가드, Single-Flight 인터셉터, @tanstack/react-virtual, RTL 통합 테스트부록 A·B 배포 및 UI 브릿지

[Week 1] Ch 00 ~ 01.5: 선언적 멘탈 모델과 JSX ​

  • 토론 질문: "jQuery에서 $('#tbody').html()로 DOM을 직접 갈아 끼울 때와, React에서 posts 상태를 바꾸고 컴포넌트 함수를 다시 실행할 때의 렌더링 멘탈 모델 차이는 무엇인가?"
  • PR 검수 포인트: 컴포넌트 내부에서 document.querySelector나 innerHTML을 직접 호출하지 않고, 오직 JSX와 useState로만 화면을 선언적으로 그리는가? 리스트 렌더링의 key에 배열 인덱스 대신 고유 id(post.id)를 쓰는가?

[Week 2] Ch 02 ~ 04.5: 불변성의 원리와 클로저 트랩, 그리고 라우터 ​

  • 토론 질문: "post.title = '새제목'처럼 기존 객체 내부를 직접 고치면 왜 React 화면이 갱신되지 않는가? Object.is 참조 비교와 불변성이 React 렌더링에 미치는 영향은?"
  • PR 검수 포인트: 상태를 변경할 때 항상 [...prev, newItem]이나 { ...prev, title }처럼 새로운 불변 객체/배열을 만드는가? useEffect의 의존성 배열에 쓰인 외부 변수가 누락 없이 들어갔는가?

[Week 3] Ch 05 ~ 07: Custom Hook, Context, 타입 계약 ​

  • 토론 질문: "컴포넌트를 작게 쪼개는 UI 분할과 Custom Hook으로 로직을 도려내는 것은 언제 각각 쓰는가? 모든 데이터를 props로 내려보내지 않고 Context API를 써야 하는 명확한 기준은?"
  • PR 검수 포인트: usePagination, usePostFilter가 컴포넌트 뷰와 완전히 독립되어 있는가? 백엔드 Spring DTO와 프론트엔드 types/board.ts가 any 없이 1:1로 일치하며 모달 Props 계약이 엄격한가?

[Week 4] Ch 08 ~ 10: 제네릭 컴포넌트와 Zustand, 낙관적 업데이트 ​

  • 토론 질문: "모든 상태를 Zustand 전역 스토어에 넣으면 왜 안 되는가? 컴포넌트 로컬 상태, URL 파라미터, Zustand 전역 상태의 분리 기준은 무엇인가?"
  • PR 검수 포인트: 제네릭 BoardTable<T>의 컬럼 키 오타가 컴파일 시점에 빨간 줄로 잡히는가? Zustand 구독 시 useShallow나 단일 선택자를 썼는가? useOptimistic과 스토어 롤백 테스트가 통과하는가?

[Week 5] Ch 11 ~ 14: 라우터 인가, HTTP 격리, 가상화 최적화, 통합 테스트 ​

  • 토론 질문: "프론트엔드 화면 컴포넌트에서 axios.get을 직접 부르는 것을 왜 코드 리뷰에서 엄격히 금지해야 하는가? 클라이언트 <ProtectedRoute> 가드만으로 보안이 완성되지 않는 이유는?"
  • PR 검수 포인트: postRepository와 Single-Flight httpClient로 네트워크 계층이 격리되었는가? 10,000개 댓글 렌더링 시 @tanstack/react-virtual로 60fps가 유지되는가? npm run test로 MSW 기반 통합 테스트 3종이 모두 통과하는가?

Moon HomeLab Engineering Knowledge Hub