본문 바로가기
카테고리 없음

계층 구조

by WaDDak 2025. 4. 3.

좋아요! routes → controller → service → repository 구조는 백엔드의 역할을 명확히 나눠서 관리하는 설계 방식이에요.
대부분의 Clean Architecture 또는 MVC 변형 구조에서도 이 패턴이 많이 사용됩니다.


🧱 1. 전체 흐름 한눈에 보기

css
복사편집
[ Client (프론트엔드) ][ routes (tRPC/API) ][ controller ][ service ][ repository ][ DB ]

📌 각 계층 역할 설명

✅ 1. routes (라우터)

  • API endpoint 정의
  • input 스키마 검증 (Zod)
  • 인증 처리 (ex: protectedProcedure)
  • controller 호출

예: propertyRouter.ts

ts
복사편집
createProperty: protectedProcedure .input(z.object({ ... })) .mutation(async ({ input, ctx }) => { return await PropertyController.createProperty(input, ctx.session.user.id); }),

✅ 2. controller

  • 사용자 요청을 구체적인 작업 단위로 분배
  • 하나 이상의 서비스 호출 가능
  • 로직은 최대한 단순하게

예: PropertyController.ts

ts
복사편집
static async createProperty(data, userId) { return await PropertyService.createProperty(data, userId); }

✅ 3. service

  • 핵심 비즈니스 로직을 담당
  • 유효성 검사, 조건 처리, 중복 체크 등
  • 여러 repository를 조합 가능

예: PropertyService.ts

ts
복사편집
static async createProperty(data, userId) { const exists = await PropertyRepository.checkIfExists(data.address, data.postalCode); if (exists) throw new Error("Already exists"); return await PropertyRepository.insert(data, userId); }

✅ 4. repository

  • DB에 접근하는 실제 쿼리 처리
  • 오직 데이터베이스 입출력만 담당
  • 비즈니스 로직 없음

예: PropertyRepository.ts

ts
복사편집
static async insert(data, userId) { await db.insert(properties).values({ ...data, ownerId: userId }); }

🎯 이 구조의 장점

항목장점
유지보수성 계층별 역할이 분리되어 수정이 쉬움
테스트 용이 각 계층을 단위로 테스트 가능
재사용성 같은 Service 또는 Repository를 다른 API에서도 재사용 가능
보안/검증 강화 인증, 검증 로직을 routes와 service에 명확히 나눌 수 있음

 

Q.. 그럼 uuid를 생성한다거나 하는건 어디에 들어가는게 적합한가
 

ChatGPT의 말:

아주 좋은 질문이에요! uuid처럼 자동 생성되는 ID나 내부 처리용 데이터는 어느 계층에서 생성하느냐에 따라 의미가 달라져요.
각 계층의 책임을 고려해서 선택하면 좋습니다.


✅ 일반적인 규칙

계층UUID 생성 위치로서 적절성설명
Routes ❌ 나쁨 API 핸들러에서 생성하면 책임 분리가 안 됨
Controller ⭕ 가능 단순 생성만 하는 경우 컨트롤러에서 처리해도 무방
Service ✅ 가장 적절 uuid가 비즈니스 흐름의 일부라면 이곳에서 생성
Repository ❌ 나쁨 DB 입출력만 담당하므로, 생성 로직은 피하는 것이 좋음

🧠 기준을 이렇게 생각하면 쉬워요

  • uuid가 단순히 "기계적인 id 생성"이라면 → controller
  • uuid가 "비즈니스 흐름에 따라 조건부로 생성되어야 한다면" → service
  • DB에 저장만 하면 된다면 → repository는 생성하지 말고 받기만