티스토리 뷰
1차 프로젝트부터 현재 3차 프로젝트를 진행하는 데 있어 매번 빠지지 않던 부분이 바로 클린아키텍처였다.
처음 프로젝트를 시작하면서 알게 된 클린 아키텍처를 1차에선 그 의미를 2차에선 필요성을 3차에선 실제 구현으로 이해도를 점차 확장해 왔다.
3차 프로젝트에서는 실제 구현도 하기로 했기 때문에, 좀 더 정확한 이해하기 위해 공부하기로 했다.
클린아키텍처란?
- 유사한 목적(관심사 분리- the separation of concerns)을 가지는 다양한 아키텍처를 통합하기 위해 고안한 아키텍처 패턴
특징
- 프레임워크에 독립적, 특정 기능을 갖춘 소프트웨어 라이브러리의 존재 여부에 의존하지 않음 → 프레임워크를 도구로 활용
- UI, DB, Web Server 또는 기타 외부 요소 없이도 비즈니스 규칙을 테스트할 수 있음
- UI는 시스템의 나머지 부분을 변경하지 않고도 쉽게 변경할 수 있음(UI와 독립적)
예를 들어) 비즈니스 규칙을 변경하지 않고도, 웹 UI를 콘솔 UI로 바꿀 수 있음. - DB의 종류와 무관, Oracle이나 SQL Server 대신 Mongo, BigTable, CouchDB 등을 사용할 수 있음.
- 외부 기관으로부터 독립적
도식화

- 해당 그림에서 가장 중요한 점은 바깥에서 안쪽으로 향한다는 것이다. 따라서, 안쪽은 바깥쪽의 변수/함수 등의 정의, 구현 등 어떤 것도 알 수 없다.
- Frameworks가 가장 바깥이고, Interface, Application, Business Rules로 들어갈수록 점차 안으로 들어간다.
- 원은 항상 4개를 유지하지는 않음 - 하지만, 각 원은 종속성 규칙을 항상 적용해야 한다.
Entities
- 기업 전체의 비즈니스 규칙을 캡슐화
- 엔티티는 메서드를 가진 객체, 데이터 구조와 함수의 집합일 수 있음
- 외부에서 변경 상황이 발생하더라도 변경될 가능성이 가장 낮음(단적으로, 음식점 웨이팅 관련 비즈니스만 제공하다가 공연, 전시회 등도 제공할 거다. 수준의 변경이 아닌 이상 변경되지않음)
UseCases
- 애플리케이션별 비즈니스 규칙을 포함
- 시스템의 모든 Use Cases를 캡슐화하고 구현 (이 시스템으로 뭘 할 거냐?)
Interface Adapters
- Usecases와 Entities의 format에서 외부 프레임워크의 format으로 변환되는 곳
Frameworks and Drivers
- DB, 웹 프레임워크 등의 프레임워크와 도구로 구성
원론적인 얘기는 여기까지! 이후는 3차 프로젝트까지 진행하면서 스스로 이해한 내용 및 질문 사항을 GPT의 도움으로 해결한 내용 (클린아키텍처는 비교적 정보가 많이 쌓여있다고 생각해서 AI로 답변을 받아도 될 것 같다고 판단했다.)
가장 중요한 적용 방법!

폴더링 구조를 보게 되면
크게 Data, Domain, Presentation, Network로 구성된 걸 확인할 수 있다.
Domain
- 앱의 전반적인 비즈니스 룰과 관련된 사항들이 담겨있다.
- Entity는 여기에 정의돼 있다.
- Error에 관한 정보도 정의 되어있는 데 세부적인 에러라기 보다, 포괄적으로 발생하는 에러가 담겨있다. 세부 API마다 발생하는 에러는 Domain보다 바깥에서 정의
- Repository, Service의 Interface가 여기에 속한다.
Data
- DB, API와 관련된 사항들이 담겨있다. - 가져온 데이터는 DTO로 되어있다. (SwiftDataBookDTO, AladinBookDTO 등)
- Usecase에서는 DTO를 모르기 때문에 데이터 전달을 위해 Domain에 정의되어 있는 Entity를 사용한다. (BookDTO)
- Repository, Service의 구현체가 여기에 속한다.
- 진행 중인 프로젝트에선 Network 관련은 Network 폴더로 따로 폴더링 중.
Presentation
- UI와 관련된 사항들이 담겨있다 - 도식화의 가장 바깥쪽 원에 속한다.
- Presentation 영역은 DTO, Entity를 알 수 없기에 내부에서 VO를 만들어 사용한다.
- VO는 Usecase를 호출해서 전달받은 데이터를 가지고 생성한다. 이때, Usecase는 VO를 알지못하기에 단적인 데이터를 넘기거나, 데이터전달을 위한 타입을 선언해서 사용한다.
질문 사항들!(With GPT)
[1] Repository의 Interface는 Domain에 두고, 구현체는 Data에 두면서 Usecase의 Interface와 구현체는 Domain에 두는 이유는?
- 단순히 Interface는 Domain에, 구현체는 Data에 라는 개념이 아닌, Data와 Domain 계층이 가지는 개념을 이해해야한다.
- Domain 계층은 앱에서 절대 바뀌면 안 되는 내용이 포함한다.
- Usecase는 흐름을 조정하는 중심으로, 정의도 구현도 앱의 규칙 자체이다.
- 반면, Repository의 경우 구현체는 DB의 종류 (SwiftData, CoreData, MariaDB, MySql 등)에 따라 얼마든지 바뀔 수 있다. Repository의 형태는 동일하기 때문에 Domain에서 정의한다.
[2] Domain 영역은 언제바뀌나?
- Domain 영역은 핵심 비즈니스 규칙이기 때문에 거의 바뀌지 않는다. 하지만, 핵심 비즈니스 규칙 자체이기 때문에 비즈니스 규칙이 바뀌면 바뀐다. (그것도 큰 변화가,,,)
⇒ 예를 들어, 독립영화를 제공하는 앱이 일반영화도 제공한다고 해서 바뀌지는 않을거로 생각한다. (내부 비즈니스 로직에서 큰 변화가 없기 때문)
그렇지만, 도서 정보를 제공하는 앱에서 도서 + 음반 + 공연을 제공한다면, 비즈니스 로직에서 큰 변화가 생긴다.
가령 Entity만 보더라도 (작가, 가수 등은 같은 변수를 공유한다 해도) 책에는 없을 공연 시간, 장소 등의 변화가 생기기 때문에 Entity의 변화가 생기고 이에 따라 연관 함수, 변수들에 모든 변화가 일어날 거다.
[3] 도식화에서 원을 4개로 잡았고 Usecase를 Entity와 분리해 놓았는데 왜 3개로 쓰고 둘을 합쳐서 둘까?
- Domain 영역을 넓게 잡아서 Entity와 Usecase를 포함하게 잡은 경우!
- 계속해서 상기하는 내용이 Domain은 앱의 비즈니스 로직 그자체라는 것이다.
Entity와 Usecase는 비즈니스로직에 관련된 내용이라 변화가 작아야하고 Usecase가 비즈니스 로직의 구현에 맞아떨어지면 하나로 관리하는 경우가 있다. - 또 다른 이유로 폴더링 자체만 같이 하는 경우, Domain의 폴더링을 Entity, Interface, Usecase로 구분해서 폴더링을 하면 하나의 폴더에 있다 뿐이지 Entity+Intereface / Usecase 로 구분된다.
- 마지막으로 Usecase까지 분리하면 개념적으로 맞더라도, 현실적으로 관리 비용의 증가로 이어질 수 있다.
[4] Repo를 설계하고 구현하는 과정에서 DTO와 Entity의 수정에 관해 논의 한 적 있는데, Entity 수정은 안 바꾸는 게 맞다! 에 개념적으로 동의하는데 DTO 수정은 현실적인 문제일까?
- Entity는 원칙적으로 수정할 수 없어야 한 게 맞다! (요건 공부하면서 개념이 확실히 잡혀서 나도 동의!)
- 질문을 한 이유 : DTO는 원의 바깥에 해당하는 Data에 속하고 만약 DB가 바뀔 때, DTO가 바뀔 수 있지 않은가? 또는 API의 종류가 바뀔 때 DTO는 충분히 바뀔 수 있지 않나?
- DTO는 수정이 될 수 있고, 자주 바뀌기도 한다. 다만 이는 좋지 않다 - 할 수 있다면 수정을 최소화해야 한다.
- 이유
- 하위 호환성 문제
- 서버 API 응답 구조를 DTO로 정의했는데, 이걸 바꾸면 기존에 그 DTO를 쓰던 코드들이 다 깨질 수 있음
- 특히 REST API나 OpenAPI 스펙에 맞춘 경우, 클라이언트와 계약이 깨지게 됨
- 의존성 문제
- DTO를 프로젝트 전역에 퍼뜨려서 도메인 로직이나 UI가 DTO에 의존하게 되면…
- DTO 변경 = 도메인/Presentation 레벨까지 전부 변경 → 유지보수 지옥
- 하위 호환성 문제
[5] 4번 질문 이해를 했는데 4-2의 의존성 문제는 설계 실수 아닌가?
- 설계 실수 맞다! - DTO를 UI에서 쓰거나 ViewModel에서 쓰는게 잘못된 거다.
[6] Presentation 단에서 사용할 VO가 Usecase에서 전달해 줄 정보랑 같은데 Usecase에 정의 해두고 Presentation에서 사용하면 안 되나?
- 질문 이유: Domain의 Entity는 Domain이랑 Data에서 다 쓰는데 Presentation은 그러면 안 되나?
- 안된다! - 단순히 형태가 같을 뿐, Domain의 Entity랑은 다르게 VO는 사용처(역할)가 서로 완전히 다르다.
[7] 3차에서 처음으로 설계, 구현을 진행하고 있고 공부하면서 생각이 들었는데,
{ entity 정의 -> DTO 정의 -> Repo 정의 -> Repo 구현 -> usecase 정의 -> usecase 구현 } 순서로 진행했는데 잘못된거지?
{ usecase 정의(entity정의) -> repo 정의(DTO정의) -> repo 구현 -> usecase 구현 } 순서가 맞는 거 같은데?
- 생각한 순서가 정석에 훨씬 가까운 클린 아키텍처 설계 흐름이다.
- 지금 하고 있는 순서는 하향식 설계(Top-Down)가 아닌 상향식 설계(Bottom-Up)에 가까워서 초기에는 빨리 만들 수 있지만, 비즈니스 중심 설계라는 본래 목적에서는 어긋날 수 있다.
올바른 순서
1️⃣ UseCase 정의 (→ 필요 Entity 정의)
2️⃣ Repository Interface 정의 (→ 필요한 DTO 구조 파악)
3️⃣ Repository 구현 (→ DTO 작성)
4️⃣ UseCase 구현
[8] 마지막 확인차 질문! 외부 API를 호출은 Data 계층에서 하고, 여기에는 구현체가 있는 거지? Response는 DTO 형태고, API 호출 함수의 Interface는 Domain 계층에 있고, 이걸 Entity로 바꿔서 유스케이스로 넘겨주는 거지?
정확해요! 🎯
지금 말한 흐름은 클린 아키텍처의 외부 API 처리 방식에 아주 잘 맞습니다.
참고 자료
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
https://zeddios.tistory.com/1065
https://1000one.tistory.com/82
https://github.com/kudoleh/iOS-Clean-Architecture-MVVM/tree/master/ExampleMVVM
'프로그래밍 > 기초' 카테고리의 다른 글
| 함수와 클로저의 차이점 (0) | 2025.07.08 |
|---|---|
| CPU, RAM, 저장 장치의 역할과 상호 작용 (0) | 2025.07.01 |
| 메모리구조, ARC (with GC, 약한 참조, 미소유 참조) (0) | 2025.02.10 |
| Github 사용해보기 2 (0) | 2025.02.08 |
| Github 사용해보기 (0) | 2025.02.03 |
