Skip to content

TagEditor에서 sheet의 detents 최적화

최윤진 edited this page Feb 9, 2026 · 5 revisions

Note

이 문서는 태그 추가 혹은 삭제 시 올라오는 sheet의 높이 최적화 해결에 대한 문서입니다

0. 요약

TagEditor는 내부 콘텐츠의 실제 크기를 실시간으로 측정하여 presentationDetents에 높이(sheetHeight)를 전달합니다.
이를 통해 태그 개수에 따라 시트의 크기가 유동적으로 변하는 UI를 구현하고 있습니다.

1. 구현 형태

image image
포커싱 ON - 태그 입력 포커싱 ON - 태그 레이아웃
image image
포커싱 OFF - 태그 입력 포커싱 OFF - 태그 레이아웃

2. 측정 원리 및 도구

SwiftUI의 레이아웃 시스템에서 자식 뷰의 크기를 상위 뷰로 전달하기 위해 GeometryReader를 배경(background)에 배치하는 기법을 사용합니다.

  • Background Measurement Pattern:

컨텐츠(TagLayout, tagField) 뒤에 GeometryReader를 깔고, 그 위에 투명한 뷰(Color.clear)를 씌워 geometry.size.height를 읽어옵니다.
이 방식은 실제 레이아웃에 영향을 주지 않으면서 렌더링 된 뷰의 크기를 정확히 측정할 수 있습니다.

2. 측정 영역 상세 (Measurement Areas)

높이 계산은 크게 태그 목록 영역입력 필드 영역 두 부분으로 나누어 측정된 후 합산됩니다.

A. 태그 목록 영역 (tagsHeight)

  • 대상: VStack 내부의 상단 ScrollView 영역입니다.
  • 측정 시점:
    1. 초기 로드 시 (onAppear): 뷰가 나타난 직후 DispatchQueue를 통해 비동기로 높이를 측정하여 초기값을 설정합니다.
    2. 데이터 변경 시 (onChange): tags 배열이 변경될 때마다 레이아웃이 다시 잡히므로, 이때 변경된 높이를 재측정합니다.
  • 특이 사항: 태그가 하나도 없을 때는 tagsHeight가 0이 되며, 태그가 늘어날수록 ScrollView의 콘텐츠 크기만큼 높이가 증가합니다.

B. 입력 필드 영역 (fieldHeight)

  • 대상: 하단의 tagField (텍스트 필드와 추가 버튼이 포함된 HStack) 영역입니다.
  • 측정 시점: 뷰가 로드되는 onAppear 시점에 측정합니다.
  • 보정값: 순수 컴포넌트 높이에 약 16의 여백 값을 더해(geometry.size.height + 16) 하단 여유 공간을 확보합니다.

3. 최종 높이 산출 (Calculation Logic)

최종적으로 시트에 적용될 높이(sheetHeight)는 앞서 측정한 두 영역의 높이와 사이 간격(spacing)을 합산하여 결정됩니다.

수식: sheetHeight = fieldHeight + tagsHeight + spacing

  • spacing 처리: VStackspacing 속성을 고려하여, 태그가 존재할 때만 간격 값(8)을 더해줍니다.
    태그가 비어있다면 간격을 0으로 처리하여 불필요한 공백을 제거합니다.
// 코드 로직 예시
sheetHeight = fieldHeight + tagsHeight + (tags.isEmpty ? 0 : spacing)

이 계산된 값은 .presentationDetents([.height(sheetHeight)]) Modifier에 전달되어 시트의 높이를 즉시 업데이트합니다.

4. 한계

이러한 동적 측정 방식은 사용자 경험(UX) 측면에서 콘텐츠에 딱 맞는 높이를 제공하지만, 기술적인 한계와 고려해야 할 사항이 존재합니다.

  • 비동기 업데이트의 복잡성:

뷰 렌더링 도중에 상태(State)를 변경하면 Modifying state during view update 경고가 발생할 수 있습니다.
이를 회피하기 위해 DispatchQueue.main.async를 사용하여 높이 업데이트를 다음 런루프(RunLoop)로 미루게 됩니다.
이로 인해 코드가 다소 복잡해지고 디버깅이 어려워질 수 있습니다.

  • sheet 자체의 safeArea:

상단의 표를 보면 알 수 있듯이, 태그 유무에 따라 키보드와 입력 필드 간의 간격(spacing)이 다릅니다.
해결 방법을 찾기 위해 노력했지만, SwiftUI, 혹은 UIKit에서 sheet 내부의 safeArea를 조절하는 방법을 찾지 못해 UI의 부조화가 나타나고 있습니다.

Clone this wiki locally