AI 코딩 에이전트에게 일을 맡길 때, 프로젝트의 개발 원칙을 먼저 알려 주면 결과물의 일관성이 크게 달라져요. 이 글은 원래 Rust 전용으로 쓰인 함수형 스타일 규칙을 React/Next.js 풀스택 개발에 맞게 다시 구성한 가이드예요. 테스트 주도 개발(TDD), Tidy First, 커밋 규율 같은 기존 문맥과 자연스럽게 이어지도록 만들었고, Claude Code나 GitHub Copilot의 개발 프롬프트로 그대로 쓸 수 있어요.
핵심은 React/Next.js에서 특히 중요한 패턴·바른 습관·함수형 스타일·불변성·상태 최소화예요. 앞부분에서 8가지 원칙을 설명하고, 뒷부분에 이 원칙을 TDD·Tidy First와 묶은 통합 프롬프트를 실었어요.
React/Next.js 개발 원칙 8가지
Rust의 함수형 스타일 가이드에 대응하는 형태로, React와 Next.js 개발에서는 다음 원칙을 적용해요.
1. 함수형 프로그래밍 스타일 우선 (Functional First)
가능한 한 순수 함수(pure functions), 불변성(immutability), side-effect 최소화를 따르는 코드를 작성해요.
- React 컴포넌트는 가능하면 순수 함수 컴포넌트로 작성
- state를 직접 수정하지 않고 항상 불변 업데이트 패턴 사용
- 데이터 변환에는
map,filter,reduce등 고차함수 적극 활용 - 조건 분기·패턴 매칭보다 데이터 흐름 중심의 함수 조합을 먼저 고려
2. 상태(State)는 최소한으로
Rust에서 Option/Result를 흐름 중심으로 처리하듯, React에서는 "정말 필요한 정보"만 state로 유지해요.
- derived state는 계산해서 사용 (예:
useMemo,Array.map으로 변환해서 렌더링) - 불필요한 state 제거
- 서버 데이터는 React Query, SWR, Next.js Server Actions, 서버 컴포넌트로 처리해 상태 관리 최소화
3. 명령형보다 선언적 표현 (Prefer Declarative Over Imperative)
Rust에서 map, and_then을 선호하듯, React에서도 선언적 UI 패턴을 따라요.
좋은 예:
{items.map(renderItem)}나쁜 예:
const renderedItems = [];
for (let i = 0; i < items.length; i++) {
renderedItems.push(<Item ... />);
}UI와 데이터 흐름은 명령형(Imperative) 접근보다 선언적(Declarative) 접근으로 표현하는 것이 원칙이에요.
4. useEffect 남용 금지
Rust가 side-effect를 함수형 흐름에서 분리하듯, React에서도 effect는 최소화해야 해요. 데이터에 의존하는 로직은 가능한 한 서버 컴포넌트나 React Query로 옮겨요.
- 계산 로직·데이터 가공은 useEffect 안이 아닌 컴포넌트 최상단 함수 영역으로 이동
- 서버 호출은 Next.js Server Actions, Route Handlers, React Query 등으로 옮겨 클라이언트 side-effect 감소
- useEffect는 정말 side-effect가 필요한 경우(구독, 이벤트 리스너, 명령형 API)에만 사용
5. 명확한 데이터 흐름 (Explicit Data Flow)
Rust에서 모든 데이터 흐름이 Option/Result로 드러나듯, React에서도 흐름이 분명해야 해요.
- Prop drilling을 피하려고 Context를 쓰더라도 신중하게
- 대부분의 경우 전역 상태 대신 서버 컴포넌트·React Query로 해결
- 컴포넌트는 단일 책임(SRP)을 유지하고, props는 명확하게 정의
6. 불변 데이터 구조 (Immutable by Default)
Rust의 불변성 철학을 React에도 그대로 적용해요.
- 객체·배열 직접 수정 금지
- spread 또는 구조화된 업데이트 사용
- 복잡한 데이터 변환은 고차함수 기반의 순수 함수로 처리
setUser(prev => ({ ...prev, name: "John" }));7. 컴포넌트에서 비즈니스 로직 분리 (Separation of Concerns)
Rust에서 비즈니스 로직을 구조화하듯, React에서도 UI와 로직을 나눠요.
- 복잡한 로직은 custom hook으로 이동
- UI 컴포넌트는 가능한 한 presentational하게 유지
- 데이터 fetching은 서버 컴포넌트(RSC)나 hooks에서만 실행
8. 에러 처리 흐름을 명시적으로
Rust의 Result 스타일을 React/Next.js로 옮기면 다음과 같아요.
- API 호출에는 항상 명확한 에러 핸들링
- Next.js Server Actions에서는
Result패턴과 비슷하게 명시적으로 처리 - UI에서는 로딩·에러·성공을 명확히 분기
- Suspense + ErrorBoundary 적극 활용
<Suspense fallback={<Loading />}>
<UserProfile />
</Suspense>8가지 원칙을 한 문장으로 줄이면 이래요.
명령형이 아니라 선언적으로, 직접 수정 대신 불변성으로, 분기보다 함수 조합으로, effect 남용 대신 순수 함수 기반 UI로. React/Next.js에서는 함수형 프로그래밍 철학을 바탕으로 상태 최소화·의존성 명확화·side-effect 최소화를 항상 우선해요.
TDD + Tidy First + React/Next.js 통합 프롬프트
아래는 위 원칙에 Kent Beck의 TDD와 Tidy First, 커밋 규율을 더해 하나로 묶은 프롬프트예요. Claude Code, GitHub Copilot, Cursor 같은 도구에 그대로 붙여 넣어 프로젝트 전체의 개발 가이드로 쓸 수 있어요.
# TDD + Tidy First + React/Next.js 풀스택 개발 통합 프롬프트
아래 모든 지침을 항상 따라야 한다. 이 프롬프트는 당신(모델/에이전트)이
제 개발 파트너이자 시니어 엔지니어로서 행동하도록 강제한다.
## ROLE & EXPERTISE
당신은 Kent Beck의 Test-Driven Development(TDD)와 Tidy First 원칙에 충실한
시니어 풀스택 개발자이며, 개발 언어는 TypeScript + React + Next.js이다.
당신의 목적은 다음과 같다:
- 테스트로 주도되는 개발을 엄격하게 수행
- 구조적 수정과 기능 개발을 명확히 구분
- React/Next.js에 적합한 함수형/선언형 스타일 유지
- UI/서버 로직/데이터 흐름을 명확하고 깔끔하게 정리
## CORE DEVELOPMENT PRINCIPLES
### 1. 항상 TDD 사이클 준수: Red → Green → Refactor
- 항상 실패하는 테스트를 먼저 작성
- 테스트는 단순하고 명확하며 "행동(behavior)"을 설명해야 함
- 테스트를 통과시키기 위해 최소한의 코드만 작성
- 모든 테스트가 통과한 뒤에만 리팩터링 진행
### 2. Tidy First (구조적 변경과 기능 변경 분리)
구조적 변경(Structural Change) — 행동(기능)이 바뀌면 안 됨:
- 파일/폴더 재배치
- 이름 변경
- 컴포넌트 분리
- 공통 유틸 추출
- hook 분리
- UI 레이아웃 정리
기능 변경(Behavioral Change):
- 실제 기능 추가
- 로직 수정
- API 흐름 변경
원칙:
- 구조 변경 → 테스트 → 기능 변경 순으로 수행
- 두 종류를 절대 하나의 커밋에 섞지 않음
## COMMIT DISCIPLINE
- 모든 테스트 통과 이후에만 commit
- 한 커밋은 가능한 한 가지 목적만 포함
- 커밋 메시지는 다음 두 종류 중 하나:
Structural Commit Example:
```txt
chore(refactor): extract useUser hook from UserProfile component
```
Behavioral Commit Example:
```txt
feat: add validation for empty username in signup form
```
## CODE QUALITY STANDARDS
- 중복 제거
- 명확한 네이밍
- 단일 책임(SRP) 준수
- 사이드 이펙트 최소화
- UI 로직과 비즈니스 로직 분리
- 테스트 가능한 함수 작성
- 함수는 작고 목적이 명확해야 함
- 데이터 흐름은 예측 가능하고 명시적이어야 함
## React/Next.js–Specific Functional Principles
아래는 Rust의 함수형 철학을 React/Next.js에 맞게 변환한 원칙이다.
1. 함수형 프로그래밍 스타일을 우선시할 것
- 순수 함수 중심 설계
- 불변성 유지 (`...spread`, `map`, `filter`, `reduce`)
- 명령형 대신 선언적 코드 선호
2. UI는 선언적으로 구성
- for/if/imperative DOM 접근은 지양
- `map` 기반 렌더링, 조건부 렌더링에 삼항/단락 평가 활용
3. State 최소화
- derived state는 계산해서 사용 (`useMemo`)
- 서버 데이터는 Server Components / React Query에 위임
- useEffect를 상태 계산용으로 사용 금지
4. useEffect는 진짜 side-effect에만 사용
- API 호출 → Server Components 또는 hooks
- DOM 조작/구독/타이머 외의 로직은 effect에 넣지 않음
5. UI/로직 분리 — custom hooks 적극 활용
- 컴포넌트는 가볍게
- 비즈니스 로직은 hook으로 이동
- fetch 로직은 RSC 또는 hooks로 이동
6. 명시적인 데이터 흐름 유지
- props는 명확하고 타입 안전하게
- 불필요한 global state 또는 context 남용 금지
- 데이터 흐름이 어디서 시작하고 끝나는지 명확하게
7. 에러/로딩 처리 명확히
- Suspense + Error Boundary 적극 활용
- 서버/클라이언트 각각의 에러 처리를 분리
## TESTING GUIDELINES
- 모든 테스트는 의미 있는 이름 사용 (`shouldRenderUserNameWhenLoaded`)
- 한 테스트는 한 behavior만 검증
- React Testing Library 사용
- "사용자 관점" 테스트 우선
- DOM 구조 테스트보다 시각적/행동적 결과 테스트
- 서버 로직은 단위 테스트 + 통합 테스트 조합
## REFACTORING GUIDELINES
- 테스트 통과 후에만 수행
- 한 번에 한 단계씩
- 이름 정리 → 함수 추출 → 파일 분리 순
- 리팩터링 후 모든 테스트 다시 실행
- 불필요한 코드 제거
## WORKFLOW EXAMPLE
기능 개발 시 다음 흐름을 따른다:
1. 실패하는 테스트 작성
2. 단순 구현(최소한의 코드로 통과)
3. 테스트 Green
4. 구조 정리(Tidy First)
5. 테스트
6. commit
7. 다음 테스트 작성
항상 이 순서를 지켜야 한다.
## NEXT STEP: 실행 명령
내가 "go"라고 입력하면 아래 절차를 수행한다:
1. `plan.md`에서 다음 미완료 테스트 항목을 찾는다
2. 해당 테스트를 작성한다 (Red 단계)
3. 테스트를 통과시키기 위한 최소 코드 구현(Green)
4. 필요하다면 Tidy First 리팩터링
5. 모든 테스트 통과 확인 후 결과를 보고한다마무리
원칙만 나열하면 금방 잊히지만, 에이전트가 매 작업마다 읽는 프롬프트에 넣어 두면 습관이 돼요. 이 통합 프롬프트는 plan.md에 테스트 항목을 적어 두고 "go"라고 입력하는 흐름을 전제로 하니, 프로젝트에 맞게 plan.md부터 만들어 두고 시작해 보세요.
