풀스택 디자인 패턴 가이드
이 기술을 사용하여 엔드투엔드 풀스택 시스템을 조언, 아키텍처 설계 및 리팩토링하세요. 식별 가능한 아키텍처 마찰을 해결하기 위해 패턴을 엄격히 적용하고, 추상적인 추측을 위해 사용하지 마세요.
핵심 원칙
- 문제 중심 선택: 명시적인 아키텍처 마찰 또는 코드 냄새(예: prop drilling, 비대한 신 컴포넌트, 긴밀한 API 결합, 테스트 불가능한 로직, 연쇄적인 네트워크 실패) 없이 디자인 패턴을 도입하지 마세요.
- 명확한 아키텍처 경계: 다음 간의 명확한 경계를 유지하세요:
- 뷰 / 프레젠테이션: props로 구동되는 단순하고 선언적인 컴포넌트
- 클라이언트 상태 및 상호작용: 헤드리스 훅, 중앙 집중식 저장소, 서버 상태 캐싱
- API / 계약 계층: 타입이 지정된 스키마, DTO 어댑터, 안티 커럽션 계층
- 도메인 및 데이터 액세스: 분리된 비즈니스 규칙과 리포지토리 기반 데이터베이스 액세스
- 과잉 엔지니어링 방지: 단순한 CRUD 페이지나 표준 웹 앱에 복잡한 엔터프라이즈 추상화(예: 마이크로 프론트엔드, CQRS, 분산 pub/sub)를 적용하지 마세요.
패턴 결정 매트릭스 및 트리거 휴리스틱
| 계층 | 코드베이스의 증상 / 마찰 | 권장 패턴 | 아키텍처 경계 |
|---|---|---|---|
| 프론트엔드 UI | API 가져오기, 포맷팅, JSX 레이아웃을 혼합한 신 컴포넌트 | 컨테이너 / 프레젠테이션 | UI 렌더링과 데이터 가져오기 분리 |
| 프론트엔드 UI | 대화형 컴포넌트(모달, 드롭다운) 내부의 긴밀하게 결합된 스타일링 | 헤드리스 컴포넌트 / 커스텀 훅 | 상태 및 키보드/상호작용 로직 격리 |
| 프론트엔드 UI | 유연한 하위 요소가 필요한 경직된 컴포넌트 API | 복합 컴포넌트 | 선언적 부모-자식 상태 공유 (예: Tabs, Select) |
| 프론트엔드 UI | 깊은 prop drilling 또는 동기화되지 않은 다중 컴포넌트 UI 상태 | Observer / Store (Zustand/Redux/Context) | 공유 클라이언트 상태 중앙 집중화 |
| 풀스택 API | 백엔드 API 스키마 변경으로 프론트엔드 UI 컴포넌트 손상 | 어댑터 패턴 (데이터 매퍼) | DTO를 뷰 모델로 변환하는 안티 커럽션 계층 |
| 풀스택 API | 느린 네트워크로 인해 사용자 작업 확인 전에 UI가 대기 | 롤백이 있는 낙관적 UI | 트랜잭션 롤백으로 뒷받침되는 즉각적인 UI 응답 |
| 백엔드 | SQL/ORM 호출이 라우트 핸들러 또는 서비스 내에 분산됨 | 리포지토리 패턴 | 지속성 쿼리와 비즈니스 규칙 분리 |
| 백엔드 | 인라인 if-else를 사용하여 여러 타사 SDK 인스턴스화 | 팩토리 패턴 | 객체 및 클라이언트 생성 중앙 집중화 |
| 백엔드 | 가격, 인증 또는 알고리즘을 계산하는 계단식 if-else / switch | 전략 패턴 | 인터페이스 뒤에 교체 가능한 알고리즘 캡슐화 |
| 백엔드 / 분산 | 핵심 비즈니스 액션이 5개 이상의 관련 없는 부작용 트리거 | Observer / 이벤트 기반 (Pub/Sub) | 도메인 이벤트 또는 메시지 큐를 통한 부작용 분리 |
| 백엔드 / 분산 | 외부 API 지연 시간으로 인한 스레드 고갈 및 연쇄 다운타임 | 서킷 브레이커 | 빠른 실패, 폴백 응답, 다운스트림 상태 프로빙 |
심층 분석: 풀스택 패턴 및 구현 규칙
1. 프론트엔드: 컨테이너 / 프레젠테이션 패턴
- 컨텍스트:
useEffect, 쿼리, 데이터 변환, 레이아웃 JSX를 결합하여 컴포넌트가 200줄 이상으로 커지는 경우. - 규칙:
- 프레젠테이션 컴포넌트: props를 통해서만 데이터와 콜백을 받음; 순수하며 API 모크 없이 Storybook에서 쉽게 테스트 가능.
- 컨테이너 (또는 페이지 훅): 서버 데이터를 가져오고, 로딩/오류 상태를 관리하며, 변환된 데이터를 전달.
2. 프론트엔드: 헤드리스 컴포넌트 및 커스텀 훅 패턴
- 컨텍스트: 다양한 시각적 디자인에서 재사용이 필요한 복잡한 대화형 동작 (자동 완성, 다단계 마법사, 아코디언).
- 규칙:
- 상태, 키보드 핸들러, ARIA 속성을 헤드리스 커스텀 훅(예:
useAutocomplete,useDisclosure)으로 추출. - 스타일링과 DOM 마크업은 완전히 소비자에게 맡김.
- 상태, 키보드 핸들러, ARIA 속성을 헤드리스 커스텀 훅(예:
3. 프론트엔드: 복합 컴포넌트
- 컨텍스트: 수많은 구성 props를 전달하지 않고 응집력 있는 내부 상태가 필요한 깊이 연관된 하위 부분이 있는 컴포넌트.
- 규칙:
- React Context를 활용하여 부모와 자식 간에 암시적으로 통신 (
<Accordion><Accordion.Item /><Accordion.Panel /></Accordion>).
- React Context를 활용하여 부모와 자식 간에 암시적으로 통신 (
4. 통합: 어댑터 패턴 (안티 커럽션 계층)
- 컨텍스트: 타사 REST/GraphQL 페이로드가 UI 컴포넌트 props 또는 핵심 도메인 모델로 직접 유출됨.
- 규칙:
- 원시 백엔드 DTO 키가 프론트엔드 컴포넌트 prop 형태를 결정하도록 두지 마세요.
- 명시적인 매퍼 함수(예:
toUserViewModel(dto: UserApiDto): UserVM)를 생성하여 스키마 변경으로부터 UI 컴포넌트를 보호.
5. 통합: 롤백이 있는 낙관적 UI
- 컨텍스트: 네트워크 지연 시간이 응답성을 저해하는 빈번한 사용자 상호작용 (좋아요, 토글, 작업 완료, 재정렬).
- 규칙:
- 상호작용 시 로컬 상태를 즉시 업데이트.
- 서버 변이를 큐에 넣고, 거부되면 이전 스냅샷으로 롤백하고 비침해적으로 사용자에게 알림.
6. 백엔드: 리포지토리 패턴
- 컨텍스트: 비즈니스 로직이 ORM 쿼리(Prisma, TypeORM, Drizzle, SQL)와 얽혀 있음.
- 규칙:
- 서비스는 인터페이스(예:
OrderRepository)와만 상호작용. - 도메인 로직을 리포지토리 외부에, 쿼리 빌딩을 서비스 외부에 유지.
- 서비스는 인터페이스(예:
7. 백엔드: 전략 및 팩토리 패턴
- 컨텍스트: 교체 가능한 공급자 (결제 게이트웨이, 알림 채널, 파일 저장소).
- 규칙:
- 공통 인터페이스(
PaymentGateway)를 통해 동작 표준화. - 팩토리/레지스트리를 사용하여 구성 또는 테넌트에 따라 구체적인 구현체를 결정.
- 공통 인터페이스(
8. 백엔드: 서킷 브레이커 패턴
- 컨텍스트: 간헐적인 다운타임 또는 심각한 지연 시간을 겪는 외부 마이크로서비스 또는 타사 API.
- 규칙:
- 실패 임계값을 추적. 상태 전환:
Closed(정상) ->Open(빠른 실패, 캐시/폴백 반환) ->Half-Open(카나리 프로브).
- 실패 임계값을 추적. 상태 전환:
에이전트 출력 워크플로
아키텍처 조언 또는 풀스택 코드 리팩토링 요청 시:
- 경계 및 병목 지점 식별: 마찰이 UI 렌더링, 상태 동기화, API 계약 불일치, 또는 백엔드 결합 중 어디에 있는지 파악.
- 일치하는 패턴 선택: 특정 코드 냄새를 해결하는 명확한 근거와 함께 패턴 제안.
- 전후 예시 제공: 분리된 책임을 보여주는 간결하고 관용적인 코드 스니펫 제공.
- 테스트 가능성 및 유지보수성 강조: 리팩토링이 단위/컴포넌트 테스트를 단순화하고 향후 변경으로부터 보호하는 방법 설명.