2 분 소요

클린 아키텍처 / DDD(도메인 주도 설계) 구조

Next.js 기반 프로젝트에서 클린 아키텍처(Clean Architecture) + 계층별 역할 분리하기

클린 아키텍처 핵심 2가지 원칙

1. 단방향 의존성 원칙 (Dependency Rule)

내부 계층은 외부 계층에 의존할 수 없으며, 외부 계층은 내부 계층에 의존해야한다.
의존성 방향 = 바깥 → 안쪽만 허용

🤔 이 과정에서 내부계층의 infra를 상위계층에서 사용하기 위해 IoC + DI (제어 역전 + 의존성 주입)이 필요하다.

  • IoC(Inversion of Control)제어 역전
    “프레임워크”가 알아서 객체 생성 + 흐름 제어
  • DI(Dependency Injection)의존성 주입
    필요한 객체(Repository 등)를 직접 만들지 않고, 외부에서 대신 넣어주는 것

    (이부분은 다음에 정리해보자..)

2. 관심사의 분리 (Separation of Concerns)

서비스(Service) 계층 분리하기, 각 계층은 특정 역할 하나에만 집중해야한다.

🎯 각 디렉토리의 계층과 역할

// 클린 아키텍처 레이어 계층 구조
page  adapter  service  repository  entity(domain) 구조
계층 역할 (책임) 핵심 개념
page UI / View (presentation Layer) 사용자 화면, 이벤트 발생
adapter Controller (Interface Adapters Layer) API 요청 처리, 데이터 가공
service UseCase (Application Layer) 서비스 로직, 규칙 처리
repository 데이터 처리 (Infra Layer) 외부 저장소(DB/API)에 접근
entity 순수 비즈니스 규칙 처리 (Domain Layer) 핵심 데이터 객체 & 규칙 처리

* Entity 계층 → Domain 계층 내부의 핵심 객체

폴더구조 살펴보기

일단 이해가 어려우니.. 강사님이 만든 폴더구조를 살펴보기..

app/ //사용자의 요청이 들어오는 Next.js의 페이지 컴포넌트
├── api/ //Controller (API 엔드포인트)
   └── categories/
       └── route.ts //client에게 요청 받고 UseCase 호출 후 응답 반환

application/ //서비스, 비즈니스 로직 실행 계층
├── usecases/
   └── category/
       └── dto/ //요청/응답 구조 정의
           └── CategoryDto.ts
       └── GetCategoryListUsecase.ts //카테고리 리스트 조회 비즈니스 로직

domain/ //도메인 계층 (비즈니스 규칙 중심)
├── entities/ //핵심 비즈니스 모델 정의(Entity)
   └── Category.ts
├── repository/ //무슨 데이터를 어떻게 요청할 수 있는지(인터페이스) 정의
   └── CategoryRepository.ts

infra/ //실제 구현 계층
└── repositories/
    └── supabase/
        └── SbUserRepository.ts //데이터 가져오는 구체적인 방법

위에서부터 순서대로 살펴보자..🫠

1. app/ (UI / page 계층)

2. api/ (controller / adapter 계층)

  • 외부와 내부의 데이터를 연결하는 어댑터 역할
  • 외부 요청을 받는 역할
  • 요청 데이터 검증 (Request DTO 검증 + 전달)
  • Response DTO 변환 (클라이언트가 보기 좋게 가공, Entity → DTO 변환)
  • Service 호출, Service / UseCase에 있는 핵심 로직 실행

3. application/ (usecase / service 계층)

  • 비즈니스 로직 처리
  • Repository 호출
  • 비즈니스 로직 처리 중 필요한 데이터 가공(API로 받은 데이터(DTO) → Entity 변환)
  • Repository Interface를 호출해서 데이터를 가져오거나 저장

4. domain/ (Entity, Business Logic / entity 계층)

  • 서비스 비즈니스에 대한 “핵심 개념”과 “규칙(룰)”만 정의
  • entity : 핵심 비즈니스 데이터 모델
  • repository interface : 데이터 접근 명세(필요한 메서드 정의)

5. infra/ (실제 구현 / repository 계층)

  • 데이터베이스, 외부 API 등 구체적인 구현 담당

🤔 DTO 변환 왜 필요한가?

예를 들어 DB에 저장된 카테고리 데이터가 이렇게 생겼을 때

// Entity
export class Category {
  constructor(
    public id: number,
    public name: string,
    public order: number,
    public createdAt: Date
  ){}
}

클라이언트에서 원하는 데이터가 아래와 같을 때 entity 데이터를 그대로 보내면 필요 없는 데이터도 보내진다.
불필요한 데이터 제거, 구조를 맞추기 위해 필요

[
  {
    id: 1,
    name: "americano",
    order: 1,
  },
];


글로 적으니 좀 정리가 되는 것 같지만 아직 잘 모르겠다,, 일단 만들어 보는 걸루

댓글남기기