클린 아키텍처 (정리)

원문: https://www.notion.so/1c7bf506e9948003ba4dd4a575d4f01e?pvs=1

복잡한 시스템일수록 구조가 중요하다. 클린 아키텍처는 유지 보수성과 확장성을 높이기 위해 설계된 아키텍처 패턴이다. (예제 코드는 NestJS 를 기반으로 했으며 추가 예제 코드는 SpringBoot+Lombok 이다.)


[1] 아키텍처 패턴이란?

(1) 정의

아키텍처 패턴은 소프트웨어의 전체 구조를 어떻게 설계할지에 대한 ‘전략적인 청사진’이다.

즉, 어떤 식으로 코드 구성 요소(모듈, 계층 등)를 나누고, 그 사이의 관계를 정할지를 정의한 일종의 설계 템플릿이다.

  • 예시

(2) 클린 아키텍처란?

1) 정의

  • 클린 아키텍처는 소프트웨어 시스템을 유연하고, 테스트 가능하고, 유지보수하기 쉽게 만드는 아키텍처 패턴이다.

  • 핵심은 의존성 방향을 내부 → 외부로만 향하게 해서 비즈니스 로직을 외부 기술(프레임워크, DB 등)과 분리하는 것이다.

2) 목적

  • 비즈니스 로직 보호

  • 테스트 용이성 증가

  • 프레임워크 독립성 확보

  • UI, DB, 외부 라이브러리로부터 독립

3) 아키텍처 구조 (원형 계층 구조)

  • 원형 계층 구조란?

  • 예시 구조

  • 바깥쪽은 안쪽에 의존해도 됨.

→ 클린 아키텍처는 마치 핵을 감싸는 양파같은 구조이다. 핵심 비즈니스 로직은 외부에 절대 영향을 받지 않도록 “보호”하는 구조이다.

4) 언제 사용하는가?

복잡하고 오래 유지복수해야 하는 백엔드 시스템에서 사용하면 효과가 크다.

  • 사용 안해도 되는 경우

정리하자면, “기술보다 도메인이 중요한 프로젝트” 일수록 클린 아키텍처가 잘 어울린다.

[2] 클린 아키텍처의 핵심 원칙

(1) 의존성 규칙 (Dependency Rule)

1) 정의

즉,

  1. 바깥쪽은 안쪽을 사용할 수 있다.

  2. 안쪽은 바깥쪽을 절대 몰라야 한다.

2) 원형 계층 구조에서 보면

plain text Entities ← 가장 핵심 Use Cases ← 안쪽 InterfaceAdapters Frameworks ← 바깥

  • 🔁 가능: Controller → UseCase

  • 🚫 불가능: UseCase → Controller

  • 🔁 가능: MySQLRepo → Entity

  • 🚫 불가능: Entity → MySQLRepo

3) 왜 중요한가?

  1. 비즈니스 로직의 독립성 확보

  2. 테스트 용이성

  3. 확장성 / 유연성

  4. 예시)

4) 정리

(2) SOLID 원칙

1) 정의

2) SOLID 5가지 원칙 정리

3) 1️⃣ 단일 책임 원칙 (SRP)

  1. 정의

  2. 왜 중요할까?

  3. 예시

  4. 실무에서의 팁

  5. 요약

3) 2️⃣ 개방-폐쇄 원칙 (OCP)

  1. 정의

  2. 왜 중요할까?

  3. 예시

  4. 실무에서의 팁

  5. 요약

4) 3️⃣ 리스코프 치환 원칙(LSP)

  1. 정의

  2. 왜 중요할까?

  3. 예시

  4. 실무에서의 팁

  5. 요약

5) 4️⃣ 인터페이스 분리 원칙(ISP)

  1. 정의

  2. 왜 중요할까?

  3. 예시

  4. 실무에서의 팁

  5. 요약

6-1) 5️⃣ 의존성 역전 원칙 (DIP : Dependency Inversion Principle)

  1. 정의

  2. 왜 중요할까?

  3. 예시

  4. 실무에서의 팁

  5. DIP가 중요한 순간

  6. 요약

6-2) 의존성 규칙 vs 의존성 역전 원칙

예시 코드가 똑같아 보여서 헷갈릴 수 있다.

실제로는 적용 대상과 강조점이 살짝 다르기 때문에 둘은 서로 다른 개념이다.

  1. 핵심 차이 요약

  2. 쉽게 기억하는 비유

  3. 결론

[3] 클린 아키텍처의 계층 구조 (Entities / UseCases / Interface Adapters / Frameworks)

(1) 전체 구조 한눈에 보기

image

  • 계층별 간단 요약

(2) 각 계층의 역할

1) Entities 계층 (도메인 모델)

핵심 비즈니스 규칙과 데이터 구조를 담는 계층

  • 외부 기술 완전 몰라도 됨

  • DB, 프레임워크와 완전히 분리됨

  • 변경이 거의 없어야 하고, 시스템의 가장 중요한 규칙을 담음

  1. 예시

2) Use Cases 계층 (Application business Logic)

사용자의 행동(흐름)을 정의하고, Entity를 조합해서 실행

  • Repository 인터페이스를 통해 DB 저장/조회

  • UseCase의 책임 : “무엇을 할 것인가”를 정의

  1. 예시

3) Interface Adapters 계층 (입출력 어댑터)

외부 세계와 내부 로직을 연결 주로 Controller, DTO, Repository 구현체 등이 여기에 포함

  1. 예시

4) Frameworks & Drivers 계층 (외부 기술)

웹 서버, DB, 이메일, 파일 시스템, 외부 API 등 NestJS, MySQL, Redis, S3 등이 여기에 포함됨

  • 테스트하기 어려운 기술적 요소들

  • 외부 도구로써 언제든 교체될 수 있어야 함


  • NestJS 폴더 구조 예시

  • 핵심 요약

(3) 계층 간 의존성 방향 (핵심 개념)

1) 개념 설명

의존성은 무조건 바깥 → 안쪽으로만 향해야 한다.

→ 즉, 바깥 계층은 안쪽 계층을 참조해도 되지만, 안쪽 계층은 바깥 계층을 절대 참조하면 안 된다.


  • 원형 구조로 볼 경우

  • 예시

  • 왜 이렇게 설계해야 할까?

  • 정리 요약

2) 실무에서의 구조 예시 (NestJS 기준)

클린 아키텍처 철학을 실제 NestJS 프로젝트 폴더 구조로 현실적으로 적용한 예시이다.

  • 기본 폴더 구조 예시

  • 각 폴더 별 책임 다시 정리

  • 의존성 주입 예시 (app.module.ts)

  • 실무 적용 팁

Comments