Dev.YoungKyu
YoungKyu's Devlog
전체 방문자
오늘
어제
  • 분류 전체보기
    • 부스트캠프
    • iOS
    • visionOS
    • Backend
    • 알고리즘
    • CS
    • Git
    • Python
    • 끄적끄적

블로그 메뉴

  • 홈
  • 🌝 티스토리 홈
  • ⭐️ 깃허브
  • 태그

공지사항

인기 글

최근 댓글

최근 글

태그

  • 알고리즘
  • MVC
  • Git
  • ImageResource
  • AVAudioSession
  • 소프트웨어 공학
  • alamofire
  • 부스트캠프
  • Swift5.7
  • SwiftUI
  • authenticationinterceptor
  • 소프트웨어 테스트
  • 소프트웨어공학
  • swift
  • jekyll
  • Concurrency
  • 오블완
  • guard
  • ios
  • CS
  • boj
  • 백준
  • 모듈화
  • AutoLayout
  • 티스토리챌린지
  • Optional
  • constraint
  • Python
  • if let
  • image

티스토리

hELLO · Designed By 정상우.
Dev.YoungKyu
iOS

번역) SwiftUI 간단한 뷰 레이아웃 구성하기

번역) SwiftUI 간단한 뷰 레이아웃 구성하기
iOS

번역) SwiftUI 간단한 뷰 레이아웃 구성하기

2025. 6. 6. 18:12

해당 글은 Apple 공식문서를 번역한 글로 의역이나 잘못 번역된 내용이 있을 수 있습니다.
정확한 내용은 원문을 참고해주세요.
https://developer.apple.com/documentation/swiftui/laying-out-a-simple-view

개요

뷰의 레이아웃을 만들려면, 먼저 자식 뷰들의 계층을 구성합니다. 그런 다음, 자식 뷰의 크기와 간격을 설정 파라미터와 frame, padding 같은 뷰 수정자를 통해 조정할 수 있습니다.

레이아웃 구성 방식에 대해 더 알고 싶다면 스택 뷰로 레이아웃 만들기를 참고하세요.

 

뷰 계층 구성하기

다음은 메시징 서비스에서 받은 메시지를 표시하기 위한 뷰 예시입니다.

이 뷰는 HStack을 사용하여 발신자를 나타내는 뷰와 메시지 내용을 담는 뷰를 나란히 배치합니다:


  
struct MessageRow: View {
let message: Message
var body: some View {
HStack {
ZStack {
Circle()
.fill(Color.yellow)
Text(message.initials)
}
Text(message.content)
}
}
}

아래는 MessageRow 뷰의 스크린샷이며, 뷰의 경계를 보여주는 테두리가 포함되어 있습니다.

노란색 원이 할당된 공간을 가득 채우는 것을 볼 수 있습니다.

SwiftUI가 뷰 계층을 렌더링할 때, 각 자식 뷰를 재귀적으로 *계산(evaluates) 합니다.

부모 뷰는 포함된 자식 뷰에 크기를 제안(propose) , 자식은 그에 따른 크기를 반환합니다.

  • MessageRow 뷰는 HStack에 전체 크기를 제안합니다.
  • HStack은 자식 뷰들에게 공간을 나눠주고, 시스템 기본 간격을 유지합니다.
  • ZStack은 내부 자식들인 Circle과 Text에 크기를 제안합니다.
  • Circle은 제안된 공간을 최대한 활용하고, Text는 자신의 콘텐츠에 맞게 최소한의 공간만 사용합니다.
  • ZStack은 가장 큰 자식 뷰(Circle)의 크기를 반환합니다.

이후 부모 뷰는 자식 뷰들을 배치하여 최종 렌더링합니다.
SwiftUI의 뷰 계층 구조를 직접 실습해보고 싶다면, Introducing SwiftUI 튜토리얼의 리스트 및 네비게이션 만들기 섹션을 참고하세요.

 

뷰 크기 제한하기

앞서 사용된 SwiftUI 내장 뷰들은 각기 다른 방식으로 크기를 처리합니다:

  • *부모가 제공하는 공간을 가득 채우는 뷰(Expand to fill the space offered by their parent)
    • ex) Color, LinearGradient, Circle
  • *콘텐츠에 따라 크기를 갖는 뷰(ideal size that varies according to their contents)
    • ex) Text, HStack 그리고 container views
  • *항상 고정된 크기를 갖는 뷰(ideal size that never varies)
    • ex) Toggle, DatePicker

frame 수정자를 사용하면 뷰의 크기를 명시적으로 제한할 수 있습니다. 예를 들어 원의 너비를 40pt로 제한하려면 다음과 같이 작성합니다:


  
struct MessageRow: View {
let message: Message
var body: some View {
HStack {
ZStack {
Circle()
.fill(Color.yellow)
Text(message.initials)
}
.frame(width: 40)
Text(message.content)
}
}
}

SwiftUI는 frame 수정자를 적용하면 해당 뷰를 감싸는 새로운 뷰로 View Hierarchy에 추가됩니다.
(When you add a frame modifier, SwiftUI wraps the affected view, effectively adding a new view to the view hierarchy.)

이제 ZStack은 너비가 40pt로 고정되었고, Circle은 이 작은 공간 내에서 최대한 확장되며, HStack은 남은 공간을 메시지 텍스트에 할당합니다

SwiftUI가 이 새로운 계층 구조를 *계산(evaluates)할 때, frame 수정자는 감싸고 있는 ZStack의 너비를 지정된 값으로 고정합니다.

이후의 크기 계산은 이전과 동일하게 진행되며, 이때 Circle은 이제 frame의 40포인트 너비 제약 내에서 더 작은 공간을 채우게 됩니다.

이를 통해 HStack은 메시지 텍스트를 표시하는 다른 자식 뷰들에 더 많은 공간을 제공 할 수 있게 됩니다.

 

정렬을 통한 배치

원이 메시지 텍스트의 상단과 맞춰지도록 하려면, HStack에 alignment: .top을 지정할 수 있습니다


  
struct MessageRow: View {
let message: Message
var body: some View {
HStack(alignment: .top) {
ZStack {
Circle()
.fill(Color.yellow)
Text(message.initials)
}
.frame(width: 40)
Text(message.content)
}
}
}

하지만 적용 후에도 뷰들이 상단에 맞춰지지 않은 것처럼 보일 수 있습니다.

Xcode에서 원에 테두리를 추가하거나 원을 선택해보면 실제로 상단 정렬이 적용되어 있다는 것을 확인할 수 있습니다.

이 문제는 frame에 너비만 지정하고 높이는 지정하지 않았기 때문입니다.

따라서 원은 가능한 모든 높이를 사용하려고 하며, 그로 인해 시각적으로 오해가 발생한 것입니다.

명시적으로 높이도 지정하면 해결됩니다:


  
struct MessageRow: View {
let message: Message
var body: some View {
HStack(alignment: .top) {
ZStack {
Circle()
.fill(Color.yellow)
Text(message.initials)
}
.frame(width: 40, height: 40)
Text(message.content)
}
}
}

이제 HStack의 콘텐츠가 상단 정렬되며, HStack 자체는 MessageRow 뷰의 중앙에 배치됩니다.

 

패딩 추가하기

뷰의 가장자리와 콘텐츠가 시각적으로 붙어 있는 것을 방지하려면 padding을 추가하세요.

이는 지정된 방향에 일정 공간을 삽입하여, 내부 콘텐츠의 사용 가능 공간을 줄입니다.


  
struct MessageRow: View {
let message: Message
var body: some View {
HStack(alignment: .top) {
ZStack {
Circle()
.fill(Color.yellow)
Text(message.initials)
}
.frame(width: 40, height: 40)
Text(message.content)
}
.padding([.horizontal])
}
}

padding 수정자는 시스템 기본 여백을 사용하며, 필요시 다른 값을 지정할 수도 있습니다.

저작자표시 (새창열림)

'iOS' 카테고리의 다른 글

의존성 역전을 통한 독립적인 네트워크 모듈 설계하기  (2) 2025.06.15
Demystify SwiftUI - Identify: SwiftUI는 뷰를 어떻게 구분할까?  (0) 2025.06.09
번역) SwiftUI 커스텀 뷰 선언하기  (0) 2025.06.06
애플 로그인 서버부터 클라이언트까지(Swift + Nest.js + TypeScript)  (1) 2025.05.22
CoreData 개요 및 동시성  (0) 2025.05.21
  • 개요
  • 뷰 계층 구성하기
  •  
  • 뷰 크기 제한하기
  •  
  • 정렬을 통한 배치
  •  
  • 패딩 추가하기
'iOS' 카테고리의 다른 글
  • 의존성 역전을 통한 독립적인 네트워크 모듈 설계하기
  • Demystify SwiftUI - Identify: SwiftUI는 뷰를 어떻게 구분할까?
  • 번역) SwiftUI 커스텀 뷰 선언하기
  • 애플 로그인 서버부터 클라이언트까지(Swift + Nest.js + TypeScript)
Dev.YoungKyu
Dev.YoungKyu
iOS를 공부하고 있습니다

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.