| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- swagger
- jQuery 4.0
- Passkey
- GTM
- 프론트엔드
- Gemini
- GPT
- Github Copilot
- 프롬프트 엔지니어링
- 미래
- Visual Studio 2026
- #IT트렌드
- 가상시나리오
- ChatGPT
- 리포지토리 인텔리전스
- 패스키
- 생산성
- geo
- ASP.NET
- github
- AI
- jira
- YouTrack
- 벡터 인덱싱
- 보안
- GA4
- The Singularity is Here
- SEO
- Dooray
- Today
- Total
Beyond Frontend
.NET 클린 아키텍처 가이드 본문
왜 우리는 '아키텍처'를 고민해야 할까요?
소프트웨어 개발을 '집 짓기'에 비유해 봅시다. 튼튼한 설계도(아키텍처) 없이 감으로만 집을 짓기 시작하면, 처음에는 빠르게 벽을 세우는 것처럼 보일 수 있습니다. 하지만 나중에 방을 하나 더 만들거나, 주방 배관을 수리해야 할 때가 되면 어디를 어떻게 건드려야 할지 몰라 큰 곤경에 빠지게 됩니다. 최악의 경우, 집 전체를 허물어야 할 수도 있습니다.
이 문서는 .NET 환경에서 클린 아키텍처(Clean Architecture) 라는 잘 만들어진 설계도를 이해하기 위한 안내서입니다. 클린 아키텍처의 4가지 핵심 계층인 Domain, Application, Infrastructure, Presentation이 각각 어떤 역할을 하는지, 그리고 왜 이렇게 계층을 나누는 것이 장기적으로 소프트웨어의 유지보수성, 확장성, 테스트 용이성을 극적으로 향상시키는지 명확하게 이해하는 것을 목표로 합니다.
먼저 아키텍처의 전체적인 큰 그림과 가장 중요한 원칙인 '의존성 규칙'을 살펴본 후, 각 계층을 하나씩 자세히 탐험해 보겠습니다.
1. 클린 아키텍처의 큰 그림: 의존성 규칙
클린 아키텍처를 관통하는 단 하나의 황금률을 꼽으라면 단연 '의존성 규칙(The Dependency Rule)'입니다.
핵심 규칙
모든 의존성은 바깥에서 안쪽으로만 향해야 한다.
이는 코드의 참조 방향이 항상 Presentation/Infrastructure → Application → Domain 순서를 따라야 함을 의미합니다. 안쪽 계층은 바깥쪽 계층에 대해 아무것도 알지 못해야 합니다.
규칙의 의미
이 규칙을 지키면 다음과 같은 강력한 이점을 얻게 됩니다.
"비즈니스의 핵심 규칙(Domain)은 UI나 데이터베이스 기술(Presentation/Infrastructure)이 바뀌는 것에 전혀 영향을 받지 않는다."
예를 들어, 데이터베이스를 MSSQL에서 다른 것으로 바꾸거나, 웹 기술을 MVC에서 다른 것으로 변경하더라도 비즈니스의 심장인 Domain 계층 코드는 단 한 줄도 수정할 필요가 없게 됩니다. 이것이 바로 클린 아키텍처가 추구하는 핵심 목표입니다.
전체 구조 한눈에 보기
각 계층은 솔루션에서 별도의 프로젝트로 분리되며, 다음과 같은 핵심 역할을 담당합니다.
| 계층 (프로젝트명) | 핵심 역할 |
| Domain (SiteCommon.Domain) | 비즈니스의 심장: 핵심 규칙과 데이터 구조 정의, 클래스/엔터티 |
| Application (SiteCommon.Application) | 비즈니스의 두뇌: 사용자의 요청을 처리하는 작업 흐름 |
| Infrastructure (SiteCommon.Infrastructure) | 외부와의 연결 통로: 데이터베이스, 외부 API 연동 |
| Presentation (SiteCommon.Web) | 사용자와의 접점: 웹 화면과 API 엔드포인트 |

2. 각 계층별 역할과 책임 상세 분석
2.1. Domain 계층: 비즈니스의 심장
핵심 비유: 회사의 가장 중요한 내부 규정과 서식
Domain 계층은 '회사의 가장 중요한 내부 규정과 서식'과 같습니다. 이 규정들은 회사가 어떤 이메일 시스템이나 회계 프로그램을 사용하는지와는 완전히 독립적으로 존재해야 하는 회사의 핵심 자산입니다.
역할과 책임
Domain 계층의 유일한 책임은 기술과 무관한 순수한 비즈니스 규칙과 데이터 구조를 정의하는 것입니다. 이 계층은 우리 비즈니스가 무엇인지, 어떤 데이터를 다루고 어떤 규칙을 따라야 하는지를 코드로 표현하는 곳입니다.
주요 구성 요소
- 엔티티 (Entities): 비즈니스의 주인공입니다. 예를 들어 회원, 상품, 주문과 같은 핵심 데이터 모델이 여기에 해당합니다.
- 리포지토리 인터페이스 (Repository Interfaces): "데이터를 저장하거나 조회해줘" 와 같은 **'요구사항 명세서'**입니다. IOrderRepository 와 같이 인터페이스만 정의할 뿐, 실제 데이터베이스에 어떻게 저장하는지에 대한 코드는 전혀 포함하지 않습니다. 마치 법적 구속력이 있는 계약서와 같습니다. IOrderRepository 계약서는 '주문을 저장하는 기능이 반드시 존재해야 하며, Order 객체를 받아야 한다'고 명시할 뿐, '어떻게' 저장할지는 Infrastructure 계층의 책임으로 남겨둡니다. 이 계약 덕분에 Application 계층은 데이터베이스를 전혀 몰라도 자신 있게 저장 기능을 요청할 수 있습니다.
- 도메인 예외 (Domain Exceptions): 비즈니스 규칙에 어긋나는 특별한 상황을 정의합니다. 예를 들어 재고 부족 예외(SoldOutException)가 있습니다.
이것만은 꼭!
"외부 라이브러리 참조 최소화" 규칙이 매우 중요합니다. 만약 이 계층이 특정 JSON 라이브러리(Newtonsoft.Json)나 데이터베이스 기술에 의존하게 되면, Domain의 순수성이 깨지고 나중에 해당 기술을 교체하기가 매우 어려워집니다.
이렇게 정의된 핵심 규칙(Domain)을 가지고 실제 사용자의 요청을 처리하는 두뇌 역할을 하는 Application 계층을 알아보겠습니다.
2.2. Application 계층: 비즈니스의 두뇌
핵심 비유: 숙련된 매니저
Application 계층은 '숙련된 매니저'와 같습니다. 매니저는 회사의 규정(Domain)을 완벽하게 이해하고 있으며, 고객의 요청(Request)이 들어오면 각 기술 부서(Infrastructure)에 필요한 일을 지시하고 그 결과를 취합하여 고객에게 보고하는 역할을 수행합니다.
역할과 책임
이 계층의 책임은 Domain 계층의 객체들을 조합하여 사용자의 요구사항(Use Case)을 처리하는 것입니다. '회원 가입 처리', '주문 생성'과 같은 구체적인 비즈니스 시나리오가 여기에 구현됩니다.
주요 구성 요소
- 서비스 클래스 (Service Classes): '주문 처리(OrderService)', '회원 가입(MemberService)'과 같이 사용자의 구체적인 작업 시나리오를 실행하는 로직을 담고 있습니다.
- DTOs (Data Transfer Objects): 웹 화면(Presentation)과 서비스 간에 데이터를 안전하게 전달하기 위한 전용 데이터 상자입니다. Domain의 핵심 엔티티를 외부 계층에 직접 노출하지 않도록 보호하는 매우 중요한 역할을 합니다.
- 유효성 검사 (Validator): 사용자가 입력한 값이 올바른 형식인지(예: 이메일 형식) 검사하는 로직을 담당합니다.
이것만은 꼭!
"HttpContext 접근 금지" 규칙을 지켜야 합니다. HttpContext는 웹 환경에만 존재하는 객체입니다. 이 규칙의 중요성을 시나리오로 설명해 보겠습니다. 주문 처리 로직이 Application 서비스에 있다고 상상해 보세요. 이 서비스는 웹(HttpContext)에 의존하지 않기 때문에, 여러분은 바로 그 서비스를 웹 API, 모바일 앱 백엔드, 데스크톱 애플리케이션, 심지어 매일 보고서를 생성하는 간단한 콘솔 앱에서도 완벽하게 재사용할 수 있습니다. 이 규칙이야말로 여러분의 핵심 로직을 진정으로 이식 가능하고 미래에도 경쟁력 있게 만드는 열쇠입니다.
Application 계층은 '데이터를 저장해줘'라고 명령만 할 뿐, 실제로 어떻게 저장하는지는 모릅니다. 그 실제 실행을 담당하는 Infrastructure 계층을 살펴보겠습니다.
2.3. Infrastructure 계층: 외부와의 연결 통로
핵심 비유: 각종 장비와 도구를 다루는 기술 전문가 팀
Infrastructure 계층은 '각종 장비와 도구를 다루는 기술 전문가 팀'에 비유할 수 있습니다. 매니저(Application)가 "이메일을 보내세요"라고 지시하면, 이메일 서버와 통신하는 구체적인 방법을 아는 전문가가 실제로 이메일을 발송하는 것과 같습니다.
역할과 책임
이 계층의 핵심 책임은 Application과 Domain 계층에서 정의한 인터페이스(요구사항 명세서)를 실제로 구현하는 것입니다. 데이터베이스에 연결하고, 외부 결제 시스템과 통신하고, 파일을 저장하는 등 '외부 세계'와 관련된 모든 기술적인 구현이 여기에 위치합니다.
주요 구성 요소
이 계층은 "실제 기술"을 다루는 곳으로, 다음과 같은 다양한 구현체들이 포함됩니다.
- 데이터베이스 접근 구현체: DbContext(Entity Framework Core용)나 Dapper를 사용한 리포지토리 구현체들.
- 외부 시스템 연동 클라이언트: 결제 대행사(Payment Gateway) 클라이언트, 캐싱을 위한 Redis 클라이언트, 또는 이메일/SMS 메시지를 발송하는 서비스 구현체들.
이것만은 꼭!
이 아키텍처의 핵심 전략 중 하나는 데이터 접근에 하이브리드 패턴을 사용하는 것입니다. 즉, '적합한 도구를 적합한 작업에 사용'하는 원칙입니다. 데이터를 생성, 수정, 삭제(Commands)할 때는 Entity Framework Core의 강력한 변경 추적 기능을 활용하여 데이터 무결성을 보장합니다. 하지만 복잡하고 성능이 중요한 데이터 조회(Queries) 시에는 Dapper를 사용하여 최적화된 순수 SQL을 직접 실행합니다. 이 하이브리드 접근 방식은 우리에게 안전성과 속도를 모두 제공합니다. 이 모든 것은 '의존성 역전 원칙(DIP)' 덕분에 가능하며, 나중에 데이터베이스를 바꾸고 싶을 때 Application 코드 변경 없이 Infrastructure의 구현체만 교체하면 되는 유연성을 부여합니다.
이제 모든 내부 로직과 외부 연동 준비가 끝났습니다. 마지막으로 사용자가 이 모든 기능을 어떻게 만나게 되는지 Presentation 계층에서 확인해 보겠습니다.

2.4. Presentation 계층: 사용자와의 접점
핵심 비유: 잘 꾸며진 매장 또는 안내 데스크
Presentation 계층은 '잘 꾸며진 매장 또는 안내 데스크'와 같습니다. 고객(사용자)을 맞이하고, 주문을 받아 내부의 매니저(Application)에게 전달하며, 처리된 결과(요리, 상품)를 고객에게 보기 좋게 전달하는 역할을 합니다.
역할과 책임
이 계층의 책임은 사용자로부터 입력을 받아 Application 계층에 전달하고, 그 처리 결과를 사용자에게 보여주는 것입니다. 웹에서는 HTML 화면을 렌더링하거나 API 응답(JSON)을 생성하는 일이 여기에 해당합니다.
주요 구성 요소
- 컨트롤러 (Controllers): 사용자의 HTTP 요청을 가장 먼저 받는 교통 경찰입니다. 요청을 분석하여 어떤 Application 서비스에 전달할지 결정합니다.
- 뷰모델 (ViewModels): 특정 화면을 표시하기 위해 가공된 전용 데이터 모델입니다. ViewBag을 사용하는 것은 마치 "물건 10개를 10개의 각기 다른 얇은 비닐봉지에 담아 덜렁덜렁 들고 가는 것"과 같습니다. 찢어지기 쉽고(런타임 에러), 뭐가 어디 있는지 알기 어렵습니다. 반면 ViewModel은 "그 10개의 물건을 칸막이가 있는 튼튼한 여행용 캐리어에 깔끔하게 담아 가는 것"과 같습니다. 안전하고 명확하며, 데이터를 관리하기 훨씬 수월해집니다.
- 뷰 (Views): 실제 사용자에게 보여지는 HTML 결과물입니다. Razor 문법을 사용하여 만들어집니다.
이것만은 꼭!
제가 아무리 강조해도 지나치지 않습니다: 컨트롤러는 무조건 '가볍게(Thin)' 유지하세요. 컨트롤러 안에서 비즈니스 규칙에 대한 if/else 문을 작성하기 시작하는 순간, 여러분은 유지보수 불가능한 애플리케이션으로 가는 미끄러운 비탈길에 올라선 것입니다. 그 로직은 반드시 Application 계층으로 밀어내십시오. 그곳이 제자리입니다.
지금까지 각 계층의 역할과 규칙을 개별적으로 살펴보았습니다. 마지막으로 이들이 어떻게 협력하여 하나의 요청을 처리하는지 전체 흐름을 따라가 보겠습니다.

3. 종합: 하나의 요청이 처리되는 여정
"사용자가 상품 상세 페이지를 요청하는 경우"를 예로 들어, 데이터와 제어의 흐름을 따라가 봅시다.
이 전체 프로세스는 의존성 주입(Dependency Injection, DI) 이라는 메커니즘을 통해 매끄럽게 연결됩니다. DI 컨테이너는 IGoodsRepository와 같은 인터페이스가 요청될 때마다 GoodsRepository와 같은 실제 구현체를 제공하는 역할을 담당합니다.
- [요청 접수] Presentation 계층
- 사용자의 브라우저가 /goods/detail/123 URL을 요청합니다.
- SiteCommon.Web 프로젝트의 GoodsController가 이 요청을 받습니다.

- [작업 지시] Application 계층
- GoodsController는 DI를 통해 주입받은 Application 계층의 IGoodsService 인터페이스에게 "상품번호 123번 정보를 가져와줘"라고 요청(메서드 호출)합니다.
- [데이터 조회] Infrastructure 계층
- GoodsService는 Domain 계층에 정의된 IGoodsRepository 인터페이스를 호출합니다.
- DI 컨테이너는 이 인터페이스에 매핑된 Infrastructure 계층의 실제 GoodsRepository 클래스를 GoodsService에 제공하고, 이 클래스의 메서드가 실행되어 데이터베이스에서 상품 정보를 조회합니다.
- [결과 반환 및 표시] Application → Presentation 계층
- 조회된 데이터는 역순(Infrastructure → Application → Presentation)으로 전달됩니다.
- Application 계층은 데이터베이스에서 가져온 원본 엔티티를 DTO(Data Transfer Object)로 변환하여 Controller에게 돌려줍니다. 이는 우리의 핵심 도메인 모델이 외부 세계에 실수로 노출되는 것을 막는 중요한 보안 및 설계 단계입니다.
- Controller는 이 DTO를 ViewModel에 담아 View에게 전달하고, 최종적으로 사용자에게는 완전한 상품 상세 HTML 페이지가 보여집니다.
이 흐름이 바로 '의존성 규칙'에 따라 요청이 안쪽으로 흘러 들어갔다가, 결과가 바깥쪽으로 나오는 전형적인 과정입니다.


4. 결론: 왜 이렇게 복잡하게 나눌까요?
클린 아키텍처는 처음에는 다소 복잡해 보일 수 있습니다. 하지만 이 구조를 통해 우리는 다음과 같은 3가지 핵심적인 가치를 얻게 됩니다.
- 유지보수성: UI 디자인이 전면 개편되어도, 핵심 비즈니스 로직(Domain, Application)은 수정할 필요가 없습니다. 오류가 발생했을 때 문제의 원인이 어느 계층에 있는지 파악하기 쉽습니다.
- 확장성: 새로운 기능(예: 새로운 결제 수단 추가)이 필요할 때, 영향을 받는 계층(주로 Infrastructure)에만 코드를 추가하면 되므로 기존 코드를 망가뜨릴 위험이 적습니다.
- 테스트 용이성: 각 계층이 독립적이기 때문에, UI 화면이나 실제 데이터베이스 연결 없이도 순수한 비즈니스 로직(Domain, Application)을 독립적으로, 그리고 매우 빠르게 테스트할 수 있습니다.
클린 아키텍처를 개발 속도에 부과되는 세금으로 생각하지 마십시오. 이것은 현명한 투자입니다. 이 투자는 프로젝트의 전체 수명에 걸쳐 배당금을 지급하며, 결과적으로 수년이 지나도 안정적이고, 변화에 잘 적응하며, 함께 일하기 즐거운 시스템을 만들어 줄 것입니다.
'Frontend Essentials' 카테고리의 다른 글
| 2026 에이전틱 웹과 GEO 전략 (0) | 2026.02.01 |
|---|---|
| 구조화된 데이터 최적화 전략 (1) | 2026.01.12 |
| GitHub Copilot 생산성 극대화 가이드 (0) | 2026.01.10 |
| jQuery 4.0 (0) | 2026.01.10 |
| GitHub Copilot 비즈니스 플랜 활용 방안 (0) | 2026.01.08 |
