복잡한 시스템일수록 구조가 중요하다. 클린 아키텍처는 유지 보수성과 확장성을 높이기 위해 설계된 아키텍처 패턴이다. (예제 코드는 NestJS 를 기반으로 했으며 추가 예제 코드는 SpringBoot+Lombok 이다.)
아키텍처 패턴은 **소프트웨어의 전체 구조를 어떻게 설계할지에 대한 ‘전략적인 청사진’**이다.
즉, 어떤 식으로 코드 구성 요소(모듈, 계층 등)를 나누고, 그 사이의 관계를 정할지를 정의한 일종의 설계 템플릿이다.
클린 아키텍처는 소프트웨어 시스템을 유연하고, 테스트 가능하고, 유지보수하기 쉽게 만드는 아키텍처 패턴이다.
핵심은 의존성 방향을 내부 → 외부로만 향하게 해서 비즈니스 로직을 외부 기술(프레임워크, DB 등)과 분리하는 것이다.
→ 여기서 말하는 “내부(inner)”와 “외부(outer)”에 대한 정의는 다음과 같다.
내부는 외부를 몰라도 동작해야 하고, 외부는 내부를 사용할 수 있다.비즈니스 로직(Buisness Logic) : 시스템이 무엇을 해야 하는지를 정의하는 핵심 규칙프레임워크 독립성 : 특정 프레임워크(Spring, NestJS 등) 에 의존하지 않고도 비즈니스 로직이 동작할 수 있도록 만드는 것
예시) Spring Boot 없이도 OrderService 클래스의 calculateDiscount() 같은 함수는 그 자체로 테스트 가능해야한다.
// 순수 비즈니스 로직
class OrderService {
calculateDiscount(price: number, userLevel: string): number {
if (userLevel === 'VIP') return price * 0.8;
return price;
}
}
// 프레임워크 없이도 테스트 가능
const service = new OrderService();
console.log(service.calculateDiscount(10000, 'VIP')); // 8000 출력
→ calculateDiscount() 함수는 의존하는 외부 요소가 없다.
→ DB 연결❌, HTTP 요청❌, 프레임워크 어노테이션❌ (이러한 외부 기술은 별도의 계층에서 연결하고 주입해서 사용하는 구조)
→ 순수한 함수이기 때문에 테스트 코드에서 쉽게 호출 가능하다.
이런 코드를 순수 비즈니스 로직, 프레임워크 독립 코드 라고 부른다.
즉, 프레임워크 없이도 실행되고 테스트 가능해야 좋은 구조라는 뜻이다. → 유지보수성 + 테스트 용이성을 높여주는 핵심 설계 원칙이다.
계층형 구조를 원 형태로 표현한 것

예시 구조

src/
├── order/
│ ├── application/ ← Use Cases (내부)
│ │ └── order.service.ts
│ ├── domain/ ← Entities (내부)
│ │ └── order.entity.ts
│ ├── infrastructure/ ← 외부: DB 등
│ │ └── order.repository.ts
│ ├── interfaces/ ← 외부: Controller
│ │ └── order.controller.ts
│ └── order.module.ts