이번에는 클린아키텍처를 잡을 때 폴더구조에 대해서 알아보도록 하자. Flutter를 가지고 설명을 해보도록 하겠다.
목차
- 들어가기에 앞서.
- Layout First
- Feature First
1. 들어가기에 앞서.
Flutter를 시작하고 여러 토이프로젝트를 하게 되면 느끼는 점이 다들 있겠지만 그중 공통적으로 느끼게 될 것 중 하나가 "굉장히 자유로운 아키텍처 선택" 일 것이다. 하지만 가끔 우리는 자유로운 것은 힘들 때가 많다. 예를 들어 코드컨벤션(Code Convention) 이 등장한 이유도 그중 하나일 것이다.
코드컨벤션이란 내가 작성한 코드를 다른사람들도 쉽게 이해할 수 있게 가독성 있는 코드를 작성하는 법에 대한 규칙이다. 코드컨벤션란 단어는 다소 생소할 수 있지만, 아주 친숙한 것이다. 코드를 작성하다가 빨간 줄 혹은 노란 줄로 밑줄이 쳐지는 것이 있는데, 이걸 린트(lint)라고 하고, 이게 바로 코드컨벤션과 에러체크를 도와주는 툴이다.
어쨌거나 너무나도 자유로우면 개발하기는 쉬우나, 여러사람들이 작업을 할 때는 그 자유로움이 큰 장애물이 되어서 돌아오기도 한다. 그래서 여러 명이서 개발을 할 때 나름 구조가 잘 잡혀있고 범용적이고 규칙적인걸 선호한다. 개인적으로 그 시작이 바로 폴더구조(Folder Structure)라고 생각한다 .
클린아키텍처에서 폴더구조를 정의할때 플러터에서는 크게 두 가지로 나누어서 정의하게 된다.
- 레이어 우선 구조 (Layer First)
- 기능 우선 구조 (Feature First)
우선 이 두 가지를 보러 들어가기 전, 이전에서 언급했던 내용을 다시 한번 짚어보도록 하자.
클린아키텍처에서 세 개의 별도 레이어로 구성이 된다.
- Data Layer
- Domain Layer
- Presentation Layer
이렇게 세개의 별도 레이어를 기준으로 작성을 해보도록 하겠다.
1. Layer First 구조(레이어 우선 구조)
레이어 우선구조는 코드들을 기능에 중점을 두지 않고 계층을 중점으로 폴더구조를 두는 방식이다.
lib
├── data
│ ├── remote
│ │ ├── repositories
│ │ │ ├── a_repository_impl.dart
│ │ │ └── b_repository_impl.dart
│ │ ├── models
│ │ │ ├── a_model.dart
│ │ │ └── b_model.dart
│ │ ├── services
│ │ │ ├── a_service.dart
│ │ │ └── b_service.dart
│ │ └── data_provider.dart
│ └── local
│ ├── ... # 로컬 데이터 관련 코드
├── domain
│ ├── entities
│ │ ├── a_entity.dart
│ │ └── b_entity.dart
│ ├── repositories
│ │ ├── a_repository.dart
│ │ └── b_repository.dart
│ ├── usecases
│ │ ├── featureA
│ │ │ ├── get_all.dart
│ │ │ └── get_filter.dart
│ │ └── featureB
│ │ ├── get.dart
│ │ └── alter.dart
│
├── presentation
│ ├── states
│ │ ├── a_state_provider.dart
│ │ └── b_state_provider.dart
│ ├── pages
│ │ ├── pageA
│ │ │ └── a_page.dart
│ │ └── pageB
│ │ └── b_page.dart
│ └── widgets
│ ├── a_widget.dart
│ └── b_widget.dart
└── main.dart
이렇게 Clean architecture에서 Data Layer와 Domain Layer 그리고 Presentation Layer를 지키면서 하나하나씩 추가하게 되는 방식이다.
장점으로는 레이어별로 구분이 되어서 직관성이 뛰어나고, 레이어 구조를 따라서 쉽게 확장할 수 있다.
단점으로는 개인적으로 느꼈을 때, 인수인계가 필요할 때 다소 복잡함이 있었다. 아무래도 사람에게 설명을 할 때에는 기능적으로 분류가 되어있는 게 조금 더 설명이 쉬운 것 같다.
2. Feature First 구조(기능 우선 구조)
이번에는 기능을 우선시해서 폴더구조를 두는 걸 알아보도록 하자.
기능은 다른 기능이 아니라, 유저의 로그인, 메인화면, 검색과 같은 기능별로 구성한 것으로 내용자체는 크게 다른 게 없다.
lib
├── features
│ ├── featureA
│ │ ├── domain
│ │ │ ├── entity
│ │ │ │ └── a_entity.dart
│ │ │ └── usecases
│ │ │ ├── get_all.dart
│ │ │ └── search.dart
│ │ ├── data
│ │ │ ├── models
│ │ │ │ └── a_model.dart
│ │ │ ├── services
│ │ │ │ └── a_service.dart
│ │ │ └── data_provider.dart
│ │ │
│ │ ├── presentation
│ │ │ ├── states
│ │ │ │ └── a_state_provider.dart
│ │ │ ├── pages
│ │ │ │ └── a_page.dart
│ │ │ └── widgets
│ │ │ │ └── a_widget.dart
│ ├── featureB
│ │ ├── domain
│ │ │ ├── entity
│ │ │ │ └── b_entity.dart
│ │ │ └── usecases
│ │ │ ├── get_all.dart
│ │ │ └── alter.dart
│ │ ├── data
│ │ │ ├── models
│ │ │ │ └── b_model.dart
│ │ │ ├── services
│ │ │ │ └── b_service.dart
│ │ │ └── data_provider.dart
│ │ │
│ │ ├── presentation
│ │ │ ├── states
│ │ │ │ └── b_state_provider.dart
│ │ │ ├── pages
│ │ │ │ └── b_page.dart
│ │ │ └── widgets
│ │ │ │ └── b_widget.dart
└── main.dart
이 기능별로 하는 건 확실히 보기가 더 편하다는 장점이 있다. 개인적으로는 이렇게 Feature구조를 따르는 것을 선호한다. 기획서를 보고 기능별로 추가할 때마다 특정 기능 폴더를 추가하고 작성을 하면 편리해서 그렇다.
Layer First와 Feature First 중 어느 게 더 좋다고 말을 할 수는 없다. 다만 프로젝트 규모와 복잡성, 개발팀의 성향, 유지관리 및 테스트 요구사항 그리고 특정 도메인의 특징 등을 파악하여 상황에 맞는 클린아키텍처 폴더구조를 따르는 것이 좋다.
참고자료
https://kodytechnolab.com/blog/layer-first-or-feature-first-flutter-project-structure/
https://dev.to/marwamejri/flutter-clean-architecture-1-an-overview-project-structure-4bhf
https://dev.to/leehack/journey-to-the-clean-architecture-for-my-flutter-app-138n
'Study > 기타' 카테고리의 다른 글
Clean Architecture 클린아키텍처, 객체지향 디자인 5원칙 SOLID[5부] (1) | 2024.03.23 |
---|---|
Clean Architecture 클린아키텍처, 객체와객체지향 프로그래밍[4부] (0) | 2024.03.20 |
Clean Architecture 클린아키텍처, Domain에 대하여 [2부] (0) | 2024.01.09 |
Clean Architecture 클린아키텍처에 대하여 [1부] (0) | 2024.01.08 |
3. REST API에 대한 이해 (0) | 2022.02.20 |