[P-Reinforce] 2026-04-20: 15-Level React Mastery Curriculum Integrated

This commit is contained in:
2026-04-20 16:35:21 +09:00
parent 507f07fe7b
commit 6edd49abfd
31 changed files with 514 additions and 0 deletions
@@ -0,0 +1,15 @@
# 🍼 [LEVEL 1] 리액트의 심장: UI는 상태(State)의 함수다
## 1. 생각의 전환: "어떻게(How)"가 아니라 "무엇을(What)"
- **HTML/JS 방식**: "버튼을 찾아서, 클릭 이벤트를 걸고, 텍스트를 바꾼다." (명령형)
- **리액트 방식**: "상태가 `ON`이면 '켜짐'을 보여주고, `OFF`이면 '꺼짐'을 보여준다." (선언형)
- **교훈**: 중급 주니어는 DOM을 직접 건드리지 않는다. 오직 **상태**만 건드린다.
## 2. 불변성(Immutability): 왜 `push`는 안되나요?
- 리액트는 "값이 바뀌었네?"를 메모리 주소값으로 판단한다.
- `arr.push(1)`은 주소는 그대로고 내용만 바뀐다. 리액트는 바뀐 줄 모른다!
- **정답**: `setArr([...arr, 1])` 처럼 항상 **새로운 복사본**을 던져라.
## 3. 단방향 데이터 흐름: 물은 위에서 아래로 흐른다.
- 부모가 자식에게 주는 건 `Props`. 자식이 부모를 바꾸려면 부모가 준 `함수`를 호출하라.
- **하지 말 것**: 자식이 부모의 상태를 몰래 바꾸는 '매직'은 시스템을 망친다.
@@ -0,0 +1,16 @@
# 🧠 [LEVEL 2] Hook의 심연: 단순 사용을 넘어 오용 방지로
## 1. `useEffect`는 '타이머'가 아니다. '동기화' 장치다.
- 초보는 `useEffect`를 함수 실행기로 쓴다.
- 중급은 **"이펙트가 어떤 상태와 외부 시스템(API, 라이브러리)을 동기화하는가?"**를 고민한다.
- **Check**: 의존성 배열(`[]`)에 넣은 변수가 정말 이 이펙트의 원인인가?
## 2. Custom Hooks: 논리의 분리
- 컴포넌트 안에 `fetch`, `loading`, `error` 가 가닥가닥 널려 있다면 실패!
- `useFetchData()` 라는 나만의 훅을 만들어 논리만 쏙 뽑아내라.
- **성공 가이드**: UI 담당 컴포넌트는 `const { data } = useMyLogic();` 한 줄로 끝나야 한다.
## 3. `useRef`: 사라지지 않는 기억
- `useState`는 바뀔 때마다 화면을 다시 그린다(Refrender).
- `useRef`는 값이 바뀌어도 화면을 그리지 않는다.
- **용도**: 이전 화면의 값 저장, DOM 직접 접근(포커스 등), 타이머 ID 보관.
@@ -0,0 +1,17 @@
# 🏗️ [LEVEL 3] 컴포넌트 아키텍처: 벽돌 쌓기에서 성 짓기로
## 1. Props Drilling을 멈춰라!
- 할아버지가 손자에게 데이터 주려고 아빠, 삼촌을 거쳐가는 코드는 죄악이다.
- **해결책**: `Context API`를 쓰거나, **Component Composition(컴포넌트 합성)**을 사용하라.
- 아예 `<Layout content={<GrandChild />} />` 처럼 자식을 통째로 넘겨라.
## 2. 관심사의 분리: Container-Presenter 패턴
- **Container**: 데이터 가져오기, 로직 처리. (머리)
- **Presenter**: CSS, 스타일, 데이터 보여주기. (몸통)
- **효과**: 스타일만 바꾸고 싶을 때 로직 코드를 안 봐도 된다.
## 3. Atomic Design 맛보기
- `Atom`: 버튼, 입력창 (가장 작은 단위)
- `Molecule`: 검색바 (Atom의 결합)
- `Organism`: 헤더, 푸터 (복잡한 구조)
- **기준**: 아톰은 프로젝트 어디서든 쓰일 수 있게 **순수(Pure)**해야 한다.
@@ -0,0 +1,15 @@
# ⚡ [LEVEL 4] 렌더링 최적화: "내 앱은 왜 렉이 걸릴까?"
## 1. 렌더링은 공짜가 아니다
- 부모가 그려지면 자식도 그려진다. 이게 계속되면 성능 폭발이다.
- `React.memo`: "너 아까랑 준 거 똑같은데? 다시 그리지 마!"
- `useMemo`: 복잡한 계산 결과물 재사용.
- `useCallback`: 함수 재생성 방지.
## 2. '성급한 최적화'는 독이다
- 모든 컴포넌트에 `memo`를 바르는 건 멍청한 짓이다.
- 진짜 느린 부분(리스트 1000개 로딩 등)을 찾아서 **프로파일러(DevTools)**로 찍어보고 최적화하라.
## 3. Key값의 중요성: `index`는 최후의 수단이다
- `map` 돌릴 때 `index`를 key로 쓰면, 리스트 순서가 바뀔 때 리액트가 멘붕에 빠진다.
- 반드시 데이터의 **Unique ID**를 써라. 그래야 리액트가 "아, 순서만 바뀌었네?" 하고 영리하게 대처한다.
@@ -0,0 +1,15 @@
# 🌐 [LEVEL 5] 상태 관리의 거버넌스: 어디에 저장할 것인가?
## 1. 상태에도 거주지가 있다
- **Local State**: 그 컴포넌트만 알면 되는 것 (Input 입력값 등).
- **Global State**: 온 동네가 알아야 하는 것 (로그인 정보, 테마).
- **Server State**: 서버에서 빌려온 것 (게시글 목록).
## 2. 서버 상태는 `React Query`에게 맡겨라
- `useEffect`로 API 호출해서 `loading` 관리하던 시대는 끝났다.
- 캐싱, 재시도, 로딩 상태를 자동으로 해주는 라이브러리를 써서 **'신선한 데이터'**만 관리하라.
## 3. 상태의 최소화 (Single Source of Truth)
- `firstName``lastName`이 있는데 `fullName` 이라는 상태를 또 만들지 마라.
- `fullName`은 렌더링할 때 그냥 합쳐서 보여주면 된다.
- 상태가 많아질수록 동기화 오류(버그)의 확률은 급상승한다.
@@ -0,0 +1,13 @@
# 🧹 [LEVEL 6] 리액트 클린 코드: 누구나 이해하는 코드
## 1. 조건부 렌더링의 품격
- `condition && <Component />` 는 편하지만, `condition`이 0일 때 화면에 0이 찍히는 대참사가 난다.
- 가급적 `condition ? <Component /> : null` 을 써서 명확하게 표현하라.
## 2. 구조 분해 할당(Destructuring) 생활화
- `props.user.name`, `props.user.age` ... 보는 사람 숨넘어간다.
- `const { name, age } = user;` 로 깔끔하게 정리하고 시작하라.
## 3. Early Return: 코드를 날씬하게
- `if (loading) return <Loading />` 처럼 실패나 예외 케이스를 먼저 쳐내라.
- 뒤로 갈수록 **'진짜 중요한 핵심 로직'**만 남아서 가독성이 폭발한다.
@@ -0,0 +1,15 @@
# 🛡️ [LEVEL 7] 테스트라는 안전망: 버그 없는 코드를 향하여
## 1. "내 코드는 완벽해"라는 착각을 버려라
- 실무자는 자기 코드를 믿지 않는다, **테스트 코드**를 믿는다.
- `Unit Test`: 함수 하나가 1+1=2를 내뱉는지 확인.
- `Integration Test`: 컴포넌트와 컴포넌트가 만나서 잘 돌아가는지 확인.
## 2. Vitest & React Testing Library (RTL)
- RTL의 철학: "사용자가 보듯 테스트하라."
- `getByRole('button')` 처럼 사용자가 버튼을 찾듯 코드를 짜야 한다.
- **Tip**: 내부 구현(State 값 등)이 아니라 **화면에 무엇이 나오는가**를 테스트하라.
## 3. TDD(Test Driven Development) 맛보기
- 테스트를 먼저 쓰고 코드를 짜라.
- 복잡한 비즈니스 로직일수록 TDD는 당신의 퇴근 시간을 앞당겨준다.
@@ -0,0 +1,14 @@
# 📡 [LEVEL 8] API 통신의 품격: 서버와 대화하는 법
## 1. Axios Interceptor: 공항 입입국 심사
- 매번 API 쏠 때마다 토큰 넣고 에러 처리할 건가?
- `interceptor`를 써서 모든 요청에 **자동으로 인증 토큰**을 붙이고, 에러 응답은 한 곳에서 처리하라.
## 2. HTTP 에러 핸들링 (401, 404, 500)
- 401(미인증)이 뜨면 자동으로 로그인 페이지로 보내거나 토큰을 갱신하라.
- 사용자는 하얀 화면이 아니라 "잠시 후 다시 시도해 주세요"라는 친절한 메시지를 원한다.
## 3. API 추상화 (Service Layer)
- 컴포넌트 안에 `axios.get('/api/users')` 를 직접 쓰지 마라.
- `userService.js` 파일을 따로 만들어 함수화하라.
- **이점**: API 주소가 바뀌어도 파일 하나만 고치면 된다.
@@ -0,0 +1,15 @@
# 🎨 [LEVEL 9] 스타일 거버넌스: 디자인 시스템 구축하기
## 1. CSS-in-JS vs Utility-First
- `Styled-components`: 컴포넌트 중심의 스타일링. 가독성이 좋다.
- `Tailwind CSS`: 클래스 기반의 빠른 개발. 생산성이 미쳤다.
- **중급의 선택**: 팀의 규모와 프로젝트 성격에 맞는 도구를 제안할 줄 알아야 한다.
## 2. Design Tokens: 마법의 변수
- `#FF5733` 이라고 직접 쓰지 마라.
- `theme.primary` 라고 변수(Token)를 써라.
- 회장님이 "빨간색 다 파란색으로 바꿔!" 라고 할 때 1초 만에 끝낼 수 있다.
## 3. 반응형 디자인 (Responsive)
- 모바일 우선(Mobile First)으로 생각하라.
- 작은 화면에서 먼저 짜고 큰 화면으로 넓혀가는 것이 논리적으로 훨씬 간결하다.
@@ -0,0 +1,15 @@
# 🏗️ [LEVEL 10] 모던 스택의 선택: Vite와 Next.js
## 1. 전광석화 같은 개발: Vite
- `Create React App(CRA)`은 이제 느리고 무겁다.
- `Vite`는 브라우저의 기본 기능을 써서 서버 구동이 빛보다 빠르다.
- **교훈**: 도구가 바뀌면 개발 경험이 바뀌고, 개발 경험은 생산성이다.
## 2. Server Side Rendering (SSR) & Next.js
- 구글 검색 로봇이 내 사이트를 잘 찾게 하려면(SEO) Next.js가 필수다.
- "깜빡임 없는 페이지 전환" + "빠른 첫 로딩"의 조화.
- **핵심**: 언제 CSR(클라이언트)을 쓰고 언제 SSR(서버)을 쓸지 구분하라.
## 3. 폴더 구조의 미학
- `components`, `hooks`, `services`, `utils`, `pages`.
- 누가 프로젝트를 열었을 때 **"아, 여긴 뭐가 있겠구나"**라고 짐작하게 만들어라.
@@ -0,0 +1,12 @@
# 🚑 [LEVEL 11] 최후의 방어선: 에러 바운더리와 로깅
## 1. Error Boundary: 앱의 수호신
- 컴포넌트 하나에서 에러가 났다고 전체 앱이 하얗게 죽어서는 안 된다.
- 에러가 난 부분만 "문제가 발생했습니다"라고 보여주고 나머지는 살려둬라.
## 2. Sentry: 눈에 보이지 않는 버그 잡기
- 사용자의 컴퓨터에서 나는 에러는 개발자가 알 수 없다.
- `Sentry` 같은 도구를 연동해서, 에러가 나는 즉시 개발자에게 이메일로 제보하게 하라.
## 3. 사용자 경험(UX) 배려: Skeleton UI
- 데이터 로딩 중일 때 뱅글뱅글 도는 `Spinner` 보다는, 데이터가 들어올 자리를 미리 보여주는 `Skeleton`이 심리적으로 훨씬 빠르다.
@@ -0,0 +1,14 @@
# 🚀 [LEVEL 12] 배포 프로토콜: 세상으로 나가는 마지막 관문
## 1. GitHub Actions: 비서 채용하기
- 내가 `Push` 하면 자동으로 테스트 돌리고, 에러 없으면 배포까지 해주는 비서를 고용하라.
- **CI(지속적 통합)**: 코드 합칠 때마다 검사하기.
- **CD(지속적 배포)**: 코드 합치면 바로 서버에 올리기.
## 2. Vercel & Netlify
- 예전에는 서버 세팅에 며칠이 걸렸다.
- 지금은 클릭 몇 번으로 전 세계에 내 앱을 서비스할 수 있다.
## 3. 환경 변수(ENV) 관리: 보안의 핵심
- API Key나 비밀번호를 절대 깃허브에 올리지 마라.
- `.env` 파일을 쓰고, 배포 환경 설정에서 따로 관리하라. **이거 하나로 회사 기밀이 털릴 수 있다.**
@@ -0,0 +1,14 @@
# 💎 [LEVEL 13] 타입스크립트: 흔들리지 않는 코드의 뼈대
## 1. 인터페이스(Interface)와 타입(Type)
- "이 데이터는 어떻게 생겼어?"를 미리 정의하라.
- 오타 때문에 발생하는 멍청한 버그의 90%를 막아준다.
- **원칙**: `any`를 쓰는 것은 코딩을 포기하는 것이다. 죽어도 `any`는 쓰지 마라.
## 2. 제네릭(Generic): 유연하면서도 안전하게
- 어떤 타입이 들어올지 모르지만, 들어온 타입 그대로 내뱉고 싶을 때 사용하라.
- 재사용 가능한 컴포넌트(`Button<T>`, `Select<T>`)를 만들 때 중급자의 실력이 여기서 드러난다.
## 3. 타입 추론과 좁히기(Narrowing)
- 리액트가 타입을 똑똑하게 유추하게 도와줘라.
- `if (user)` 처럼 타입을 좁혀서 `undefined` 에러를 원천 차단하라.
@@ -0,0 +1,14 @@
# ♿ [LEVEL 14] 웹 접근성: 모두를 위한 배려
## 1. Semantic HTML의 진정한 의미
- `<div>` 로만 도배하지 마라. 스크린 리더는 `<div>`를 이해하지 못한다.
- `<button>`, `<nav>`, `<main>`, `<header>`를 적재적소에 써라.
- **이점**: 이건 단순히 착한 일이 아니라, **검색 엔진 최적화(SEO)**와 직결된다.
## 2. ARIA(Accessible Rich Internet Applications)
- 표준 태그로 설명이 안 될 때 `aria-label` 등을 써서 힌트를 줘라.
- "이 버튼은 메뉴를 닫는 버튼입니다"라고 기계에게 알려주는 배려다.
## 3. 키보드 네비게이션
- 마우스 없이도 탭(`Tab`) 키만으로 내 앱의 모든 기능을 쓸 수 있게 하라.
- 누군가에게는 이것이 세상과 소통하는 유일한 길이다.
@@ -0,0 +1,15 @@
# 🤝 [LEVEL 15] 협업과 거버넌스: 혼자 하는 게 아니다
## 1. 전설의 PR(Pull Request) 쓰기
- "수정함" 한마디는 무책임하다.
- **무엇을(What), 왜(Why), 어떻게(How)** 했는지, 그리고 스크린샷을 첨부하라.
- 동료의 시간을 아껴주는 것이 최고의 실력이다.
## 2. 코드 리뷰 매너 (The Kodari Way)
- 코드를 비판하되 사람은 비판하지 마라.
- "왜 이렇게 했나요?" 보다는 "이런 방식은 어떨까요?"라고 제안하라.
- **Pn 규칙**: P1(꼭 수정), P2(권장), P3(질문/제안) 식으로 중요도를 표시하라.
## 3. 문서화(Documentation): 미래의 나에게 보내는 편지
- 복잡한 로직은 **주석**이나 **README**에 남겨라.
- 3개월 뒤의 당신은 오늘의 당신을 절대 기억하지 못한다.