Skip to content

[Work 35] Presentation 계층 모델의 구조를 통일했습니다. - #16

Merged
sangYuLv merged 7 commits into
developfrom
WORK-35
Aug 18, 2026
Merged

[Work 35] Presentation 계층 모델의 구조를 통일했습니다.#16
sangYuLv merged 7 commits into
developfrom
WORK-35

Conversation

@sangYuLv

@sangYuLv sangYuLv commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

JIRA

📝 작업 내용

📌 요약

  • Presentation 모델 구조에 대한 규칙 정리
  • 규칙 기반으로 기존 구조 수정

🔍 상세

Presentation 모델 변환 패턴 통일

기존에는 일부 ViewModel이 Domain 타입(Place, Route, RouteStep)을 @Published로 직접 노출하고 있어서, View가 Domain 계층에 의존하고 있었습니다.
모든 ViewModel에 동일한 패턴을 적용했습니다:

  • 내부에는 Domain 타입을 유지하여 UseCase 호출에 사용
  • @Published로는 Presentation 타입만 노출 (PlaceInfo, RouteItem 등)

신규 모델 추가

RouteItemRouteStepItem을 추가하여 Route/RouteStep의 표시용 변환을 담당하도록 했습니다.
기존에 RouteCard에 있던 formatDuration 로직을 RouteStepItem으로 이동하여 중복을 제거했습니다.

PlaceInfo 구조 변경

기존 PlaceInfotag: PlaceType으로 Domain enum을 직접 들고 있었습니다.
tagTitle: String, tagColor: UIColor로 변경하여 View가 Domain enum에 의존하지 않도록 했습니다.
PlaceTagCapsuleinit(_ placeType:) 대신 init(title:color:)만 사용하도록 변경했습니다.

💬 리뷰 노트

작업 이전에 Presentation 모델을 두는 이유와 어떤 규칙을 가지고 구조를 통일할지 정리했습니다.
해당 내용을 이해를 위해 공유합니다!

Presentation 모델을 두는 이유

Domain 모델은 비즈니스 로직을 위한 구조이고, View는 표시를 위한 가공된 데이터가 필요합니다.
이 둘을 분리하면:

  • View가 Domain 변경에 영향받지 않음
  • 표시 로직(포맷팅, 색상 결정 등)이 View에 흩어지지 않고 변환 시점에 집중됨

적용한 규칙

  • 변환은 Presentation 모델의 init(domain:)에서 수행
  • PlaceType, TransportType enum은 래핑하지 않되, Presentation 모델의 프로퍼티에는 display 값으로 풀어서 저장
  • VC→VC 전달(라우팅)에는 Domain 타입 유지 (표시가 아닌 라우팅 관심사)

Presentation model 네이밍 컨벤션

역할 접미사 예시
일반 표시용 ~Info PlaceInfo, AppointmentInfo
리스트/카드 항목 ~Item AppointmentListItem, RouteItem, RouteStepItem
맥락 특화 서술적 이름 AppointmentLocation, Participant, MyRouteSummary
선택 가능한 enum ~State / ~Option LocationPermissionState, LocationSharingOption

MainActor isolation 경고 해결

커밋

Domain→Presentation 변환 과정에서 .map(PlaceInfo.init) 같은 함수 참조 문법을 사용했는데, 이 프로젝트의 default-isolation=MainActor 설정과 맞물려 Call to main actor-isolated initializer in a synchronous nonisolated context 경고가 발생했습니다.

PlaceInfo.init은 함수 참조 문법으로, .map(PlaceInfo.init)은 컨텍스트 정보가 없는 형태입니다.

함수 참조는 독립적인 함수 값으로 취급되어 actor context를 잃지만, 클로저는 둘러싼 코드의 actor context를 상속합니다.
.map { PlaceInfo(place: $0) } 형태로 변경하여 해결했습니다.

구조 정리 문서

도메인 모델과 프레젠테이션 모델 각 구조에 대한 다이어그램/문서 작업을 진행 중입니다.
완성 후 JIRA 문서에 추가할 예정입니다!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI 코드 리뷰 - 아키텍처 관점

이 PR은 도메인 모델(Place, Route, RouteStep, TransportType 등)을 View 레이어에서 직접 사용하던 구조를 Presentation Model(PlaceInfo, RouteItem, RouteStepItem, AppointmentRouteParticipant 등)로 분리하는 리팩터링이다. ViewModel이 도메인 원본을 내부에 유지하고 Presentation Model로 변환한 값만 Published로 노출하는 방향은 계층 분리 측면에서 올바르다. 다만 PlaceInfo와 RouteStepItem이 UIKit(UIColor)을 직접 import하여 UI 프레임워크에 의존하게 된 점은 Presentation Model의 테스트 가능성을 저해하며, 동일한 포맷팅 로직(formatDuration)이 RouteStepItem에 static으로 존재하면서 RouteItem이 이를 참조하는 구조는 RouteItem이 RouteStepItem의 내부 구현에 결합되는 문제를 만든다.

Comment thread WhereAreYou/WhereAreYou/Presentation/PresentationModel/PlaceInfo.swift Outdated
Comment thread WhereAreYou/WhereAreYou/Presentation/PresentationModel/RouteStepItem.swift Outdated

@snughnu snughnu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했습니다! 규칙 괜찮은거 같아요 🙊

@sangYuLv
sangYuLv merged commit 495ea3a into develop Aug 18, 2026
5 checks passed
@sangYuLv
sangYuLv deleted the WORK-35 branch August 18, 2026 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants