클린 아키텍처 / 3계층 아키텍처

Joowon Jang·2025년 1월 15일

클린 아키텍처 (Clean Architecture)

로버트 C. 마틴(“아저씨” 또는 Uncle Bob)이 제안한 소프트웨어 아키텍처로, 시스템을 계층화하여 유지보수성과 확장성을 높이는 것을 목표로 한다.

구조

클린 아키텍처는 여러 개의 원형 계층으로 구성된다.
바깥 계층은 안쪽 계층에 의존할 수 있지만, 안쪽 계층은 바깥 계층을 모르도록 설계한다.

주요 계층

  • 엔티티 (Entities)
    비즈니스 규칙을 담당하는 핵심 도메인 모델
    데이터베이스, UI 등 외부 요소에 영향을 받지 않음

  • 유즈케이스 (Use Cases)
    애플리케이션의 주요 기능(비즈니스 로직)을 담당
    엔티티와 협력하여 작업 수행
    외부 프레임워크나 데이터베이스 변경과 무관하게 독립적

  • 인터페이스 어댑터 (Interface Adapters)
    데이터 변환 및 전달을 담당 (ex: Controller, Presenter, Repository)
    유즈케이스와 외부 시스템(웹, DB, API) 간의 연결 역할

  • 프레임워크 및 드라이버 (Frameworks & Drivers)
    UI, 데이터베이스, 외부 API 등 기술적 요소 포함
    변경이 잦은 부분이며, 내부 로직과 분리되어야 함

3계층 아키텍처 (Three-Tier Architecture)

3계층 아키텍처는 클린 아키텍처보다 단순한 계층 구조를 가지며, 전통적인 웹 애플리케이션에서 많이 사용된다.

구조

  • 프레젠테이션 계층 (Presentation Layer, UI Layer)
    사용자의 요청을 처리하고 응답을 반환 (ex: 웹 페이지, REST API 컨트롤러)

  • 비즈니스 로직 계층 (Business Logic Layer, Service Layer)
    핵심 애플리케이션 로직 담당
    데이터베이스와 UI 사이에서 중재 역할 수행

  • 데이터 접근 계층 (Data Access Layer, Persistence Layer)
    데이터베이스와 직접 상호작용
    DAO(Data Access Object) 또는 Repository 패턴 활용

클린 아키텍처 vs 3계층 아키텍처

대규모 프로젝트에서는 유지보수성, 확장성, 테스트 용이성이 매우 중요한데,
클린 아키텍처는 3계층 아키텍처보다 이러한 요소들을 더욱 철저하게 고려하여 설계되었기 때문에, 큰 프로젝트에서 선호된다.

의존성 역전 원칙(DIP, Dependency Inversion Principle) 적용

3계층 아키텍처의 문제

상위 계층이 하위 계층에 직접 의존하는 경우가 많다.
예를 들어, Service Layer는 Repository Layer에 강하게 결합되기 때문에, 데이터베이스 변경이 서비스 로직에 영향을 줄 가능성이 있다.

클린 아키텍처의 해결책

비즈니스 로직(Use Cases)이 인프라(DB, API, UI 등)에 의존하지 않도록 설계한다.

의존성 역전 원칙(DIP)을 적용하여, 모든 의존성이 내부(core)에서 외부(infrastructure)로 흐르도록 만들기 때문에 DB나 외부 API가 변경되더라도, 비즈니스 로직을 수정할 필요가 없다.

프레임워크에 의존하지 않음

3계층 아키텍처의 문제

Service Layer가 데이터베이스 ORM, API 라이브러리 등에 직접 의존하는 경우가 많다.
즉, 특정 기술(예: Prisma, TypeORM, Firebase)을 선택하면, 이를 변경하기 어려움.

클린 아키텍처의 해결책

비즈니스 로직(Use Cases)은 특정 프레임워크(Next.js, NestJS, Express 등)에 의존하지 않는다.

데이터베이스 ORM이 변경되더라도, Adapter에서 의존성 주입을 통하기 때문에 Use Cases에는 영향을 주지 않음.

유지보수성과 확장성이 뛰어남

3계층 아키텍처의 문제

비즈니스 로직과 데이터베이스 로직이 강하게 결합되기 쉬우며, 코드가 증가할수록 Service Layer가 비대해지는 문제가 발생한다.

새로운 기능을 추가하려면 여러 계층에서 중복된 코드가 생길 수 있음

클린 아키텍처의 해결책

비즈니스 로직을 Use Case로 분리하여, 각 기능이 독립적으로 동작할 수 있도록 설계합니다.
예를 들어, SigninUsecase, SignupUsecase 같은 개별 유즈케이스를 정의

새로운 기능을 추가할 때, 기존 코드를 수정하지 않고도 확장 가능 (OCP: 개방-폐쇄 원칙)

모듈화와 팀 간 협업 용이

3계층 아키텍처의 문제

Service Layer가 커지면서 기능별로 코드가 뒤섞이는 문제 발생

여러 팀이 협업할 때, 코드 변경이 다른 팀의 코드에 영향을 줄 수 있음

클린 아키텍처의 해결책

Use Case 단위로 기능을 나누면, 각 팀이 독립적으로 개발할 수 있음


구조를 모두 이해한 후에 이 글을 보면 쉽겠지만, 말만으로는 잘 이해가 안된다...
다음에 Next.js와 TypeScript로 구현한 각 아키텍처를 포스팅할 예정이다.

profile
깊이 공부하는 웹개발자

0개의 댓글