-
프로젝트 파일 구조 및 네이밍에 대해 (with. TCA & Coordinator 패턴)iOS 2022. 8. 20. 11:40
안녕하세요. 그린입니다🍏
이번 포스팅의 분량은 아주아주 짧습니다!
새로운 프로젝트를 진행하면서 모듈화된 프로젝트의 통일된 파일 구조를 잡아가고 네이밍에 대해 고민함에 있어 기준을 삼고 정해본걸 공유해볼까합니다🙌
프리뷰
우선 들어가기에 앞서 프로젝트의 큰 틀을 설명해봐야 이해가 쉬울것 같아요.
아키텍쳐로는 TCA(The Composable Architecture)를 사용하게 될 것이고 코디네이터 패턴을 적용하여 화면 전환을 담당해줍니다.
TCA에 적합한 코디네이터 패턴 라이브러리인 TCACoordinators를 사용합니다.
해당 라이브러리를 몰라도 이번 포스팅은 전혀 전혀 문제가 되지 않습니다.
단지 코디네이터 패턴만 알고 계시면 됩니다!
그럼에도 혹시 이것이 뭔지 궁금하시다면 아래 포스팅을 참고해주세요🙏🏻
https://green1229.tistory.com/272
자 그럼 이러한 아키텍쳐와 패턴을 취할것이고 추가로 모든 컴포넌트 및 구현되는 기능 단위를 모듈화 시킬 것입니다.
프로젝트 파일 구조 및 네이밍에 앞서
이제 본격적인 설명에 앞서 도식화로 보여드리면서 얘기해보는게 제일 베스트일것 같아요.
조금 비루하지만 Pages로 만들기 너무 시간이 오래걸려서 패드로 도식화를 시켜봤어요..!
우선 간단히 네이밍까지 정해야 하기에 선제조건을 정해보겠습니다.
만들 프로젝트의 네임은 Movie라고 칭하겠습니다.
그리고 만들 기능은 하나만 두어서 자신의 선호 영화 리스트를 확인하고 그 영화의 세부 사항까지 볼 수 있는 FavoriteMovie라는 기능을 두겠습니다.
즉 화면은 FavoriteMovieList와 FavoriteMovieDetail이 됩니다.
그걸 참고하셔서 아래 구조를 봐주세요🙌
전체 프로젝트 파일 구조 및 네이밍 도식화
전체 구조는 이렇습니다.
하늘색 선이 연결된곳은 전부 폴더를 뜻하고 주황색 선이 연결된 지점은 전부 파일을 뜻합니다.
확장자명도 붙여놔서 헷갈리진 않을것 같아요..!
최끝단만 파일이고 나머지는 전부 폴더 계층 구조라 보면 됩니다🙌
우선 Project는 Movie라는 프로젝트명을 가진 그룹과 Module이라는 것으로 나눠져 있습니다.
여기서 Module은 각각 라이브러리가 되어 모듈화가 이뤄집니다.
이 모듈들을 조합해 Feature를 구성하고 그 Feature의 각 기능들도 라이브러리로 구성해 모듈이 됩니다.
결국 Movie에서 아래 모듈을 import해서 올려 앱을 구성하는 구조라 보면됩니다.
전체 프로젝트 파일 구조 및 네이밍 키 포인트
위에서 나온 전체적인 구조를 잡는데 키 포인트로 선정한 기준들을 말씀드릴께요.
앞으로 밑에서 나올 설명에도 도움이 됩니다🙋🏻
- Screen이라는 네이밍은 하나의 독립적인 화면과 기능을 담당하는 최소 단위
(즉, List, Detail은 독립적으로 있어도 해당 화면과 기능을 나타남에 있어 문제가 없음)
- 최상단 App 모듈은 Feature를 조합해 앱을 구성
- Feature 모듈은 Screen을 조합해 각 Feature인 기능을 구성
- Screen보다 작은 단위인 View로 제일 적게 나누는 단위는 Core가 없는 단순 DS의 뷰 컴포넌트로 생각하며
Screen의 제일 최소 단위는 해당 View를 가져다 쓰며 실제 Core가 존재하는 기능 단위로 판단그럼 전체 구조 및 기준이 된 키 포인트는 이렇고 세부적으로 쪼개서 알아보겠습니다!
Movie 파일 구조 및 네이밍
프로젝트를 실제로 만들기 위한 필수적인 파일들입니다.
App의 리소스가 될 Resources 폴더와 리소스를 바탕으로 앱을 실제 설정해줄 Source 그룹으로 나눕니다.
리소스 그룹에는 우리가 흔히 생각할 수 있는 에셋, 런치스크린, Info 파일 등이 올 수 있어요.
소스 그룹에는 앱과 뷰의 라이프싸이클을 관리해주는 앱/씬 딜리게이트 파일과 실제 앱을 띄워서 보여주고 제일 최단에서 컨트롤하는 AppView/Core 파일을 가지고 있습니다.
이 View/Core의 네이밍은 TCA 즉, 상태기반 단방향 아키텍쳐의 기조에서 가져왔으며 각자 아키텍쳐나 조직에 맞는 네이밍을 택해도 됩니다.
핵심은 해당 그룹들에 어떤 역할의 파일들이 들어가느냐 입니다.
Component 파일 구조 및 네이밍
이제 위 앱을 이루기 위해 사용할 모듈들 중 공통적인 기능이라 볼 수 있는 컴포넌트 모듈의 구조에 대해 알아볼께요!
컴포넌트는 독립적으로 화면을 나타내지 않습니다.
즉 우리가 흔히 아는 디자인 시스템이라고 하죠? (줄여서 DS라 부르겠습니다.)
DS에서 정의된 뷰 컴포넌트들을 구성하는 구조가 있을거에요.
여기서 DS 정의된 뷰 컴포넌트들은 독립적으로 어떤 화면을 이루진 않고 각 컴포넌트들이 모여서 스크린을 이뤄 유의미한 화면을 이루게 되죠.
그렇기에 DS를 Feature로 볼 수 없고 Component로 보게 됩니다.
아..! 여기서 Component와 Feature 그룹의 차이를 간단히 말씀드리면,
Feature는 Component에서 구현된 녀석들을 필요한 부분에 가져와 사용하고 실제적인 유의미한 화면 및 기능 단위의 제공을 할 수 있는 파일들의 집합입니다.
그러니까 회원가입 / 로그인 / 설정 / 주문 / 영화 찾기 등 도메인이라 불릴 수 있는 단위를 뜻합니다.
그 반면 Component는 도메인이 아닌 각 피쳐에서 도메인을 구현할 수 있도록 도울 수 있는 공통적인 그룹입니다.
그렇기에 이 그룹안에는 아까 말했던 DS와 모델, 네트워크 및 다양한 사이드이펙트 처리를 할 수 있는 서비스 그리고 에러나 익스텐션 파일들의 집합을 담고 있는 Common으로 네이밍해 가져갈 수 있습니다.
DS에는 위에 나온 Views라는 그룹외에도 컬러, 폰트, 아이콘 등 다양하게 존재할 수 있습니다.
Feature 파일 구조 및 네이밍
이제 실제 도메인이라 불릴 수 있고 유의미한 기능을 하는 단위인 피쳐에 대해 알아보시죠!
현재는 FavoriteMoview라는 하나의 도메인만 있습니다.
해당 도메인은 앞서 소개에서 말했듯 선호하는 영화 리스트와 그 리스트를 클릭해 해당 영화의 세부 정보를 볼 수 있는 디테일로 구성되어 있을거에요.
즉 이 도메인을 이루기 위해서는 선호 영화 목록을 나타내고 기능을 할 수 있는 리스트라는 스크린 단위와 세부 정보로 들어가 띄워주고 그 안에서 세부 기능을 할 수 있는 디테일이라는 스크린 단위, 두 스크린의 조합입니다.
그걸 명심하고 구조를 보시죠!
해당 피쳐를 구성하기 위해 스크린은 무조건 필요합니다.
그렇기에 스크린 그룹안에 List와 Detail 그룹이 들어가고 그 안에서 해당 실제 화면과 기능의 구현 파일이 있습니다.
위의 키포인트에서 알 수 있듯 해당 UI를 담당하는 파일의 네이밍은 하나의 유의미한 작은 기능을 할 수 있으니 View 대신 Screen이라고 붙여줍니다.
FavoriteMovieCore는 이 두 스크린 파일들을 리듀서에서 조합해 전체적으로 다뤄주는것입니다.
그 다음 코디네이터 패턴을 이용한다고 했기에 해당 피쳐에서 화면 전환을 담당해줄 코디네이터를 구성해야합니다.
예를들어 리스트의 아이템을 클릭하면 세부 정보 화면으로 넘어가고 거기서 back을 클릭하면 다시 리스트 화면으로 넘어가는등 이것을 해당 코디네이터에서 처리해주죠.
그렇기에 코디네이터 그룹을 만들고 역할을 담당해줄 파일을 만들어줍니다.
코디네이터 파일의 네이밍은 도메인의 이름이 들어가있기에 타 파일들과 헷갈리지 않도록 Coordinator를 명시적으로 붙여줍니다.
각 피쳐들 단위에서 코디네이터가 있고 이 피쳐들끼리도 화면 전환을 담당해줄 코디네이터를 또 필요 시 App 모듈에서 생성 해 관리해주면 됩니다.
마무리
자 이렇게 어느정도 프로젝트 파일 및 네이밍에 대해 기준을 세웠어요.
물론 개개인마다 다르고 사용하는 기술 스택과 조직에 따라 많이 다르겠지만 저는 이렇게 사용하는걸 공유하고 기록하고 싶었습니다!
아직 나아가는 과정이라 불안정할 수 있기에 언제든 반박 및 의견 환영입니다!!!!🥳🥳🥳
'iOS' 카테고리의 다른 글
removeArrangedSubview(_:) VS removeFromSuperview() (0) 2022.11.14 dSYM (feat. Firebase Crashlytics) (0) 2022.08.29 NSCache vs URLCache (0) 2022.08.01 @main vs @UIApplicationMain (0) 2022.07.21 UIKit에서 SwiftUI로 LifeCycle 변환하기 (0) 2022.07.14