SwiftUI의 Liquid Glass: iOS 26에서 Return을 출시하며 얻은 세 가지 패턴
Apple의 Liquid Glass는 한 줄짜리 SwiftUI API입니다: .glassEffect().1 제 명상 타이머 앱인 Return은 iOS, macOS, tvOS 전반에서 이를 아홉 번 사용합니다.2 그중 하나는 커스텀 Shape에 이 모디파이어를 적용하여 타이머 숫자 자체를 글리프 단위로 liquid glass로 변환합니다.

흥미로운 질문은 한 줄짜리 코드를 넘어서면 무슨 일이 벌어지는가입니다. Apple의 Human Interface Guidelines는 엄격한 레이어링 규칙을 명시합니다: Liquid Glass는 기능적 레이어(컨트롤, 내비게이션, 일시적 UI)에 속하며 콘텐츠 레이어에는 절대 사용해서는 안 됩니다.3 Return의 아홉 가지 사용 사례 중 대부분은 교과서적인 기능 레이어 적용입니다: 피커, 버튼, 컨트롤 스트립, 일시정지 상태 배지가 그것입니다. 흥미로운 사용 사례는 규칙을 깨지 않으면서도 구부리는 세 가지입니다.
이 글에서는 제가 출시한 세 가지 패턴, 그것들이 존중하는 규칙, 저를 사로잡았던 함정, 그리고 의도적으로 사용하지 않은 API 영역을 다룹니다.
TL;DR
- iOS 26은 Liquid Glass를
.glassEffect(_:in:)로 제공합니다. 기본 변형은.regular이고 기본 모양은Capsule입니다.1 - Return은 한 줄짜리 코드를 넘어서는 세 가지 패턴을 사용합니다: 커스텀
Shape에 글래스 적용(Core Text 글리프 패스를 통한 타이머 텍스트), 거울 패턴(뒤집힌 + 마스킹된 사본을 통한 아래쪽 반사), 그리고 기능 레이어 HUD 오버레이. - Apple HIG 규칙: 기능 레이어에는 Liquid Glass를, 콘텐츠 레이어에는 표준 머티리얼을 사용하세요.3
- 저는 의도적으로
GlassEffectContainer를 사용하지 않았습니다. 모핑 API는 Return에서 사용 사례가 없으며(어떤 글래스 요소도 다른 요소로 애니메이션되지 않음), 렌더링 성능 차이도 벤치마킹하지 않았습니다. 이는 측정되지 않은 트레이드오프이지 권장 사항이 아닙니다.1 - 함정: 평면 배경 위의 글래스는 평면처럼 보이고, 떨림 없는 숫자 렌더링에는 고정폭 셀이 필요하며, tvOS의
HStack은 layout-direction 환경 값을 무시하고, reduce-motion은 모핑 애니메이션에서 반드시 존중되어야 합니다.
한 줄짜리 API와 레이어링 규칙
Apple은 WWDC 2025에서 주요 디자인 기둥으로 도입된 작은 표면적의 Liquid Glass를 제공합니다:113
Text("Hello, World!")
.font(.title)
.padding()
.glassEffect() // default: .regular variant, Capsule shape
Text("Hello, World!")
.glassEffect(in: .rect(cornerRadius: 16)) // custom shape
Text("Hello, World!")
.glassEffect(.regular.tint(.orange).interactive()) // tint + touch reactivity
세 가지 노브: 변형(.regular 또는 .clear), 모양(임의의 Shape), 그리고 GlassEffectStyle 체인(tint, interactive). 이것이 단일 뷰에 대한 API의 전부입니다. 다중 뷰 렌더링은 별도의 GlassEffectContainer가 처리하는데, 이에 대해서는 뒤에서 다루겠습니다.
HIG는 API보다 더 엄격합니다. Apple의 Human Interface Guidelines는 모든 iOS 26+ 인터페이스에 두 개의 레이어를 정의합니다:3
- 콘텐츠 레이어: 사용자가 소비하는 문서, 목록, 사진 또는 미디어. 여기에는 표준 머티리얼(기존의
.regularMaterial,.thinMaterial등)을 사용하세요. - 기능 레이어: 컨트롤, 내비게이션, 탭 바, 사이드바, 일시적 오버레이. 여기에는 Liquid Glass를 사용하세요.
Apple의 구체적 지시는 다음과 같습니다: “Don’t use Liquid Glass in the content layer. Liquid Glass works best when it provides a clear distinction between interactive elements and content, and including it in the content layer can result in unnecessary complexity and a confusing visual hierarchy.”3
이 규칙은 실제 앱에 적용해 보기 전까지는 제약처럼 들립니다. Return은 명상 타이머입니다. 콘텐츠 레이어는 호흡 이미지와 모든 것 뒤에서 재생되는 루프 비디오입니다. 기능 레이어는 duration picker, 시작/일시정지/정지 버튼 스택, 보조 설정 버튼 행, 그리고 (tvOS의 경우) 일시정지 상태 배지입니다. Return의 아홉 가지 글래스 사용 사례 중 여덟 개는 교과서적인 기능 레이어 적용입니다: iOS와 macOS 코드 경로용 세 가지 duration picker 변형, 시작/일시정지 토글, 정지 버튼, 설정 버튼 행, tvOS 일시정지 표시기, 그리고 하나의 추가 일시적 컨트롤 오버레이가 있습니다.4
아홉 번째는 의도적인 엣지 케이스(타이머 숫자 자체에 적용된 Liquid Glass)이며, 다음 섹션에서 자세히 다룹니다.
패턴 1: 커스텀 Shape에 글래스 적용
Return의 타이머 숫자는 글래스 배경 위에 그려진 텍스트가 아닙니다. 글래스 자체가 텍스트입니다. .glassEffect(.clear, in:)은 임의의 Shape를 받으며,9 Shape는 Path를 생성하는 프로토콜입니다.10 그래서 트릭은 다음과 같습니다: Core Text를 사용하여 타이머 문자열을 글리프 패스로 변환한 다음,11 그 패스-as-Shape를 .glassEffect에 전달합니다.56
import SwiftUI
@preconcurrency import CoreText
struct GlassTextShape: Shape {
let text: String
let font: CTFont
func path(in rect: CGRect) -> Path {
guard !text.isEmpty else { return Path() }
let combinedPath = CGMutablePath()
let attrString = NSAttributedString(string: text, attributes: [.font: font])
let line = CTLineCreateWithAttributedString(attrString)
guard let runs = CTLineGetGlyphRuns(line) as? [CTRun], !runs.isEmpty else {
return Path()
}
for run in runs {
let glyphCount = CTRunGetGlyphCount(run)
guard glyphCount > 0 else { continue }
var glyphs = [CGGlyph](repeating: 0, count: glyphCount)
var positions = [CGPoint](repeating: .zero, count: glyphCount)
let range = CFRange(location: 0, length: glyphCount)
CTRunGetGlyphs(run, range, &glyphs)
CTRunGetPositions(run, range, &positions)
for i in 0..<glyphCount {
guard let glyphPath = CTFontCreatePathForGlyph(font, glyphs[i], nil) else { continue }
let transform = CGAffineTransform(translationX: positions[i].x, y: positions[i].y)
combinedPath.addPath(glyphPath, transform: transform)
}
}
// Core Text y-axis is flipped vs SwiftUI; flip then re-bound and center.
var swiftPath = Path(combinedPath).applying(CGAffineTransform(scaleX: 1, y: -1))
let flippedBounds = swiftPath.boundingRect
let offsetX = rect.midX - flippedBounds.midX
let offsetY = rect.midY - flippedBounds.midY
return swiftPath.applying(CGAffineTransform(translationX: offsetX, y: offsetY))
}
}
Return/Return/GlassTextShape.swift의 실제 프로덕션 코드입니다.5 path(in:) 함수는 Core Text를 사용해 문자열을 레이아웃하고, 각 CTRun을 순회하며, 각 글리프의 CGPath를 추출하여 하나의 CGMutablePath로 합칩니다. 합친 후에는 두 가지 명백하지 않은 단계가 따릅니다: Core Text의 좌표계는 원점을 좌하단에 두는 반면 SwiftUI의 Path는 좌상단에 두므로, CGAffineTransform(scaleX: 1, y: -1)로 패스를 뒤집어야 합니다. 그러면 뒤집힌 패스의 boundingRect는 음수 y 값을 가지게 되므로, translation을 적용해 SwiftUI가 Shape에 전달하는 rect 내부에 다시 중앙 정렬합니다. 이 두 변환 중 하나라도 건너뛰면 글리프가 거꾸로 렌더링되거나 화면 밖에 그려집니다.
그런 다음 적용은 한 줄로 끝납니다:
Rectangle()
.fill(.clear)
.glassEffect(.clear, in: textShape)
.frame(width: cellWidth, height: cellHeight)
투명한 Rectangle은 히트 타겟 자리표시자이고, 실제 시각적 표현은 textShape가 생성하는 모양입니다. 글리프 패스 모양을 사용하면 Liquid Glass 머티리얼이 글리프 윤곽선만 채웁니다. 그 결과 타이머의 각 숫자는 별개의 liquid-glass 형태가 되어, 그 뒤에서 실행되는 어떤 애니메이션이든 굴절시킵니다.6
HIG의 미묘한 차이. Apple이 명시한 규칙은 기능 레이어에는 Liquid Glass, 콘텐츠 레이어에는 표준 머티리얼이며, 한 가지 명시적 예외가 있습니다: 콘텐츠 레이어의 일시적 인터랙티브 컨트롤(슬라이더, 토글)은 활성화될 때 Liquid Glass를 사용할 수 있습니다.3 Return의 타이머 숫자는 컨트롤이 아니라 상태 표시입니다: Timer.publish(every: 1, ...)로부터 초당 한 번 업데이트되며 탭 제스처가 없습니다(상태를 토글하는 것은 그 아래 시작/일시정지 버튼입니다). 따라서 여기에 Liquid Glass를 사용하는 것은 의도적인 엣지 케이스이며, 글자 그대로의 인터랙티브성보다는 의도상 “일시적 인터랙티브 컨트롤”에 가깝습니다. 숫자가 사용자가 세션 내내 바라보는 시각적 초점이기 때문입니다. 저는 규칙을 깨는 것이 아니라 구부리고 있습니다. HIG를 엄격하게 읽는 리뷰어라면 이것이 표준 머티리얼이어야 한다고 주장할 수 있지만, 저는 타이머가 진행률 표시기와 같은 계열의 경과 시간 컨트롤 표면이라고 주장합니다. Apple의 문서는 이 사례를 직접적으로 판결하지 않습니다.
왜 Text + 배경 대신 커스텀 Shape인가. 글래스 배경 위에 렌더링된 Text는 글래스 위의 텍스트로 읽힙니다. 글래스 자체로 렌더링된 Text는 다른 시각적 카테고리로 읽힙니다. 사용자는 숫자를 기능적 전경으로, 구체적으로는 통과해서 보기 위해 존재하는 일시적 요소로 인식합니다.
패턴 2: 거울 패턴
Return은 타이머 아래에 페이드 아웃되는 반사를 표시합니다. 실제 프로덕션 코드입니다:6

VStack(spacing: 0) {
GlassTimerText(text: displayTime, fontSize: fontSize)
.accessibilityLabel("Time remaining: \(accessibleDescription)")
if showReflection {
GlassTimerText(text: displayTime, fontSize: fontSize)
.scaleEffect(x: 1, y: -1)
.mask(
LinearGradient(
stops: [
.init(color: .white.opacity(0.2), location: 0),
.init(color: .clear, location: 0.6)
],
startPoint: .top,
endPoint: .bottom
)
)
.offset(y: -8)
.accessibilityHidden(true)
}
}
세 가지 변환이 거울을 구성하며, 모두 표준 SwiftUI 프리미티브입니다:14
scaleEffect(x: 1, y: -1)이 두 번째 사본을 거꾸로 뒤집습니다..mask(LinearGradient(...))가 반사를 상단의 20% 불투명도에서 60% 아래의 완전 투명까지 페이드시킵니다..offset(y: -8)이 반사를 8 포인트 위로 끌어올려 보이는 이음새를 남기지 않고 원본과 맞붙게 합니다.
반사에 적용된 .accessibilityHidden(true) 모디파이어는 핵심적입니다. VoiceOver가 미러링된 시간을 두 번 읽어서는 안 되며, 원본의 accessibilityLabel과 accessibilityAddTraits(.updatesFrequently)은 이미 위의 메인 GlassTimerText 인스턴스에 부착되어 있고, 반사는 순수하게 장식적입니다.
왜 이것이 특히 Liquid Glass와 잘 작동하는가. 반사는 GlassTimerText로부터 글래스 머티리얼을 상속합니다. 원본이 놓인 모든 배경(호흡 원 그라데이션, 비디오, 틴트된 장면)이 두 사본을 통해 굴절됩니다. 거울은 글래스 전용 코드가 필요하지 않습니다. 글래스 머티리얼이 굴절을 무료로 처리합니다. 전체 효과는 세 개의 모디파이어와 하나의 그라데이션입니다.
접근성 비용. Reduce-motion 사용자도 여전히 거울을 보지만, 시간 업데이트 사이의 글래스 머티리얼 애니메이션은 다른 곳에서 @Environment(\.accessibilityReduceMotion)을 통해 억제됩니다.7 반사 자체는 정적이며, 숫자 전환 사이의 모핑만 애니메이션됩니다.
패턴 3: 일시적 컨트롤을 위한 글래스 HUD 오버레이
Return의 나머지 여덟 가지 글래스 사용 사례는 교과서적인 기능 레이어 적용입니다.4 각각은 동일한 패턴을 따릅니다:

durationPicker
.frame(height: 50)
.frame(maxWidth: 320)
.glassEffect()
.padding(.horizontal, 20)
.transition(.opacity.combined(with: .scale(scale: 0.95)))
.transition(.opacity.combined(with: .scale(scale: 0.95)))이 핵심적인 부분입니다. 일시적 컨트롤의 Liquid Glass는 컨트롤이 전이할 때만 자연스럽게 느껴집니다. 화면에 영구적으로 자리 잡은 정적 글래스 HUD는 크롬으로 읽힙니다. 사용자가 탭하면 페이드+스케일로 들어왔다가 시선을 돌리면 다시 사라지는 글래스 HUD는 순간적인 컨트롤 표면으로 읽힙니다.
glassEffect에 대한 Apple의 문서는 이를 암묵적으로 언급합니다: 모디파이어는 “captures the content to send to the container to render”하며 “react[s] to touch and pointer interactions in real time.”합니다.1 애니메이션 훅은 API에 없지만 렌더링 파이프라인은 글래스 요소가 움직인다고 가정합니다. 정적 글래스 요소는 그 어포던스를 놓칩니다.
Return은 이 패턴을 duration picker(사용자가 탭하면 위로 슬라이드), 시작/일시정지 토글 버튼(항상 보이지만 누르면 스케일됨), 정지 버튼(세션 중에만 보임), 설정 버튼 행(duration picker 아래의 가로 컨트롤 스트립), 그리고 tvOS 일시정지 상태 배지(Apple TV에서 세션이 일시정지될 때만 보임)에 사용합니다. 다섯 가지 컨텍스트 모두 HIG의 기능 레이어 규칙을 존중합니다.3

GlassEffectContainer 문제
Apple은 앱이 여러 뷰에서 .glassEffect()를 사용할 때마다 두 가지 이유로 GlassEffectContainer를 권장합니다: 더 나은 렌더링 성능(글래스 효과가 배치 처리됨)과 전환 중에 모양을 서로 모핑할 수 있는 기능.1
저는 사용하지 않았습니다. 그 추론은 애플리케이션 특화적이며, Apple의 가이던스에 대한 반박이 아닙니다. Return에는 아홉 개의 글래스 뷰가 있으며, 그중 어느 것도 서로 모핑할 필요가 없습니다.46 Duration picker는 시작 버튼으로 애니메이션되지 않습니다. 타이머 텍스트는 설정 버튼 행으로 애니메이션되지 않습니다. 각 글래스 요소는 독립적입니다. 모핑 API는 발동할 사용 사례가 없을 것이고, 컨테이너의 간격 규칙은 오늘날 조정이 필요 없는 레이아웃을 제약할 것입니다.
렌더링 성능 주장은 측정 없이는 완전히 반박할 수 없습니다. Apple의 문서는 컨테이너 외부의 “너무 많은” 글래스 효과가 성능을 저하시킬 수 있다고 경고합니다.1 Return의 아홉 개 뷰는 한 번에 화면을 공유하지 않습니다(duration picker는 메뉴 상태에서만 나타나고, 정지 버튼은 세션 중 일시정지일 때만 나타남). 어느 주어진 프레임에서든 세 개에서 네 개의 글래스 요소가 보이는 것을 셀 수 있고, 이는 iOS, iPadOS, macOS, watchOS, tvOS 전반에서 제가 테스트한 모든 디바이스에서 매끄러웠지만, 컨테이너로 감싼 것과 모디파이어만 사용한 것을 비교하는 instruments 트레이스를 실행하지는 않았습니다. 그래서 정직한 프레이밍은 다음과 같습니다: Return은 측정된 성능 동등성이 아니라 관찰된 양호한 사용자 경험에 기반하여 GlassEffectContainer를 건너뜁니다.
여기서 끌어낸 규칙: GlassEffectContainer는 여러 글래스 요소가 보이고 동시에 애니메이션되는 앱을 위한 것입니다. Apple의 예시는 glassEffectUnion(id:namespace:)을 사용한 심볼 세트 렌더링입니다: 네 개의 날씨 심볼이 하나의 단위로 유연하게 병합되고 분리됩니다.1 그것은 교과서적인 사용 사례입니다. 향후 Return 기능에서 글래스 요소가 모핑되거나 컨테이너의 간격 규칙을 공유해야 한다면, 그때 컨테이너가 추가할 올바른 도구가 됩니다. 오늘날의 앱에서는 아직 그 사례에 도달하지 않았습니다.
저를 사로잡았던 함정
프로덕션에서 발생한 세 가지 실제 버그입니다:
글래스 숫자 떨림. SF Pro Rounded는 비례 렌더링에서 가변 너비 숫자를 가집니다. 타이머가 카운트다운하면서 표시되는 문자열의 길이가 변하고, 주변 HStack이 매초 재배치되어 전체 타이머가 떨렸습니다. 해결책: 각 문자에 대한 고정폭 셀입니다. 각 숫자는 fontSize * 0.6의 cellWidth를, 각 콜론은 fontSize * 0.3을 받고, HStack은 안정적인 그리드가 됩니다.6
HStack(spacing: 0) {
ForEach(Array(text.enumerated()), id: \.offset) { _, char in
let isColon = char == ":"
let cellWidth = isColon ? colonCellWidth : digitCellWidth
GlassDigitCell(character: String(char), font: ctFont,
cellWidth: cellWidth, cellHeight: cellHeight)
}
}
이 셀은 Apple 표준이 아닙니다. 작은 고정 폰트 크기에서 비례 너비 렌더링에 대한 우회 방법입니다. .monospacedDigit()이 적용된 Apple의 SF Pro Rounded는 Text에서 동일한 문제를 해결할 수 있지만, 이 모디파이어는 커스텀 Shape 기반 글래스 렌더러에서는 사용할 수 없습니다. 고정 셀 레이아웃이 그 대체물입니다.
tvOS 레이아웃 방향 재정의. 동일한 GlassTimerText가 iOS, iPadOS, macOS, tvOS에서 실행되었습니다. 특히 tvOS에서는 iOS 버전이 환경 내 재정의를 존중했음에도 불구하고 HStack이 Right-to-Left 언어 환경에서 미러링되었습니다. 해결책: 환경 값과 명시적 flipsForRightToLeftLayoutDirection(false) 모디파이어 둘 다로 레이아웃 방향을 고정하며, 숫자 셀의 HStack에 직접 적용합니다(부모 VStack은 반사 사본이 이를 상속하도록 별도로 환경 재정의를 적용함):6
HStack(spacing: 0) { ... }
.flipsForRightToLeftLayoutDirection(false)
.environment(\.layoutDirection, .leftToRight)
이유: tvOS의 HStack은 일부 버전에서 환경 수준 재정의를 무시하는 것으로 보이며, flipsForRightToLeftLayoutDirection(false)는 더 안정적으로 존중되는 명시적 미러링 금지 계약입니다.12 이중 안전장치입니다.
숫자 모핑에서의 reduce-motion. Liquid Glass는 기본적으로 표시되는 문자열 사이의 모핑 전환을 애니메이션합니다. accessibilityReduceMotion이 활성화된 사용자는 모핑을 깜빡임으로 보았습니다. 해결책:6
.animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: displayTime)
이 애니메이션 모디파이어는 @Environment(\.accessibilityReduceMotion)을 읽어 reduce-motion이 켜져 있을 때 전환을 완전히 비활성화합니다. Apple의 접근성 가이던스는 명시적입니다: 모든 장식적 애니메이션은 사용자의 모션 선호도를 존중해야 합니다.7
Liquid Glass를 사용하지 말아야 할 때
거부도 디자인의 일부입니다.
콘텐츠 레이어에 Liquid Glass를 두지 마세요. Apple의 HIG는 명시적이며, 이 규칙을 무시하면 혼란스러운 계층 구조가 생깁니다: 사용자는 무엇이 인터랙티브이고 무엇이 콘텐츠인지 구분할 수 없습니다.3 글래스 효과가 목록 행이나 사진 카드를 장식하고 있다면, 디자인이 플랫폼과 싸우고 있는 것입니다.
평면 배경 위에 글래스를 사용하지 마세요. Liquid Glass는 뒤에 있는 것을 굴절시킵니다. “뒤에 있는 것”이 단일 솔리드 컬러라면, 굴절시킬 것이 없으므로 결과는 평면 틴트 사각형으로 읽힙니다. 글래스를 다양한 콘텐츠(그라데이션, 이미지, 비디오) 위에 두거나, 아니면 글래스를 전혀 사용하지 마세요. Return의 타이머 화면은 VideoBackgroundView를 통해 테마 기반 커버 이미지와 루프 비디오를 배경으로 실행하는데,4 이는 그 위의 글래스 요소가 항상 굴절시킬 텍스처를 가지도록 하기 위함입니다.
고빈도 콘텐츠에서의 글래스에 신중하세요. 글래스 머티리얼 렌더링은 GPU-bound이며, 글래스 모양 변경 사이의 기본 모핑 애니메이션 자체가 애니메이션입니다. 초당 한 번 업데이트되는 타이머는 제 테스트에서 괜찮지만, 60Hz의 파형이나 오디오 비주얼라이저는 검증되지 않았으며 모핑 애니메이션과 충돌할 가능성이 높습니다. 저는 상한선을 벤치마킹하지 않았습니다. 이를 측정된 임계값이 아닌 휴리스틱으로 취급하세요. Apple의 문서는 그것을 발표하지 않습니다.
reduce-motion을 테스트하지 않고 글래스를 출시하지 마세요. 모든 글래스 애니메이션은 accessibilityReduceMotion에 의해 게이트되어야 합니다.7 글래스 모양 사이의 기본 모핑은 단순한 페이드가 아니라 키네틱 효과입니다.
iOS 26+에서 출시되는 앱에 Liquid Glass가 의미하는 것
논지는 작습니다. Liquid Glass는 앱이 이미 HIG 레이어링 규칙을 존중할 때만 한 줄짜리 API입니다. 컨트롤을 기능 레이어에, 콘텐츠를 콘텐츠 레이어에 두는 SwiftUI 앱은 .glassEffect() 모디파이어로 Liquid Glass를 채택할 수 있고 기본적으로 네이티브하게 느껴집니다.
두 레이어를 섞는 앱(목록 행 내부의 컨트롤, 콘텐츠처럼 처리된 내비게이션 바, 사진 카드의 장식적 크롬)은 Liquid Glass를 채택해도 잘못 느껴집니다. 머티리얼은 옳지만, 그 아래의 아키텍처가 그렇지 않습니다.
커스텀 Shape 패턴(패턴 1)은 규칙을 깔끔하게 확장합니다. 기능적으로 컨트롤인 것은 무엇이든 Liquid Glass를 사용할 수 있으며, 그것이 전통적인 의미에서 “컨트롤”처럼 보이지 않더라도 마찬가지입니다. 타이머는 컨트롤이고, 레벨 미터는 컨트롤이며, 진행률 표시기는 컨트롤입니다. 그 각각의 Liquid Glass는 사양에 부합합니다.
이 글을 동일 앱의 데이터 레이어를 App Intents와 MCP 서버를 통해 출시하는 것에 대한 제 이전 글들과 함께 보세요. 시각 레이어는 동일 스택의 세 번째 표면입니다: 시스템 AI를 위한 타입드 엔티티, 크로스-LLM 에이전트를 위한 파일 형식, 그리고 디바이스 앞의 인간을 위한 Liquid Glass입니다.8
FAQ
iOS 26이 아닌 플랫폼에서 .glassEffect()를 사용할 수 있나요?
.glassEffect() 모디파이어는 iOS 26+, iPadOS 26+, macOS 26+, watchOS 26+, tvOS 26+, visionOS 26+입니다. 26 이전 플랫폼에는 .background(.regularMaterial) 등이 있어 프로스티드 글래스 효과는 만들지만 새로운 Liquid Glass 굴절은 만들지 못합니다.1
GlassEffectContainer가 시각적인 부분을 변경하나요?
컨테이너로 감싼 글래스 요소는 간격 규칙으로 인해 겹칠 때 모양을 함께 블렌딩할 수 있습니다. 컨테이너 없이는 각 .glassEffect()가 독립적입니다. 글래스 요소가 애니메이션 중에 유연하게 병합되어야 하는 앱에는 GlassEffectContainer가 올바른 도구입니다. 각 글래스 요소가 별개로 유지되어야 하는 앱에는 컨테이너가 오버헤드입니다.1
왜 Text를 직접 .foregroundStyle(.thinMaterial)과 함께 사용하지 않나요?
thinMaterial은 표준 머티리얼이지 Liquid Glass가 아닙니다. 시각적 표현은 프로스티드 글래스 오버레이이며, Liquid Glass의 굴절-with-light-bending 효과가 아닙니다.3 새로운 머티리얼처럼 보여야 하는 텍스트의 경우 .glassEffect(.clear, in: customShape)이 지원되는 경로입니다.
마케팅용 Liquid Glass 스크린샷을 어떻게 캡처하나요?
글래스 효과는 런타임에 GPU로 렌더링되므로, 스크린샷은 효과가 이미 적용된 상태로 시뮬레이터나 디바이스에서 촬영합니다. Apple의 공식 Liquid Glass 참조 이미지는 HIG 문서 페이지와 WWDC 2025 세션에서 제공됩니다.3
GlassTextShape는 임의의 텍스트에서 작동하나요, 아니면 숫자에만 작동하나요?
Core Text가 레이아웃할 수 있는 모든 문자열에서 작동합니다. Return은 숫자와 콜론에 사용하지만, 동일한 Shape는 문자, 심볼, 이모지(올바른 폰트 사용 시), 또는 혼합 문자열에서도 작동합니다. 성능은 글리프 수에 의해 제한됩니다. 글래스로 렌더링된 긴 단락은 비용이 많이 들겠지만, 6자 타이머는 사소합니다.
세 가지 패턴, 하나의 규칙, 그리고 의도적으로 건너뛴 하나의 API입니다. Liquid Glass는 iOS 26+ 앱의 세 번째 표면으로, 타입드 엔티티와 공유 파일 형식 위에 자리 잡습니다. 한 줄짜리 API는 실재합니다. 그 아래의 HIG 규칙이 한 줄 코드를 작동하게 만드는 것입니다.
References
-
Apple Developer, “Applying Liquid Glass to custom views”.
glassEffect(_:in:)모디파이어,GlassEffectContainer,glassEffectUnion(id:namespace:),glassEffectID(_:in:),GlassEffectTransition에 대한 문서. 기본 변형.regular, 기본 모양Capsule. ↩↩↩↩↩↩↩↩↩↩ -
저자의 Return, 2026년 4월 21일 App Store에 게시된 명상 타이머 앱으로 iPhone, iPad, Mac, Apple Watch, Apple TV에서 사용할 수 있습니다. iOS 26+ / macOS 26+에서 SwiftUI, SwiftData, HealthKit를 사용합니다. ↩
-
Apple Developer, “Materials” Human Interface Guidelines. Liquid Glass에 대한 기능 레이어와 콘텐츠 레이어 규칙을 정의: “Don’t use Liquid Glass in the content layer.” 일반 변형과 클리어 변형 및 그 의도된 용도를 나열합니다. ↩↩↩↩↩↩↩↩↩
-
Return/Return/ContentView.swift(일곱 개의.glassEffect()호출 사이트),Return/Return/GlassTimerText.swift(GlassDigitCell의 한 호출 사이트),Return/ReturnTV/TVContentView.swift(tvOS “Paused” 표시기의 한 호출 사이트)의 프로덕션 코드. 총 9개. 그리고 글래스 요소가 굴절시키는 테마 기반 커버 이미지와 루프 비디오를 렌더링하는Return/Return/VideoBackgroundView.swift. ↩↩↩↩ -
Return/Return/GlassTextShape.swift의 프로덕션 코드. Core Text를 둘러싼Shape준수 래퍼. 2025년 11월 26일 생성, 출시된 App Store v1.0에 포함됨. ↩↩ -
Return/Return/GlassTimerText.swift의 프로덕션 코드.GlassDigitCell,GlassTimerText,GlassTimerDisplay뷰. 고정폭 셀 레이아웃, 거울 반사, reduce-motion 게이팅을 구현. ↩↩↩↩↩↩↩ -
Apple Developer, “accessibilityReduceMotion” 환경 값. 앱은 사용자의 모션 선호도를 존중해야 하며, Liquid Glass의 기본 모핑 애니메이션은 이 값에 의해 게이트되어야 합니다. ↩↩↩
-
저자의 분석 App Intents Are Apple’s New API to Your App와 Two Agent Ecosystems, One Shopping List. 세 가지 표면 모델: Apple Intelligence를 위한 App Intents, 크로스-LLM 에이전트를 위한 MCP, 디바이스 앞의 인간을 위한 Liquid Glass. ↩
-
Apple Developer,
View의 “glassEffect(_:in:isEnabled:)”.in:파라미터는 임의의Shape준수 타입을 받습니다. 기본 모양은Capsule입니다. ↩ -
Apple Developer, “Shape” 프로토콜.
Shape는 주어진 사각형에 대해Path를 생성하는 모든 타입입니다. 커스텀 모양은 임의의CGPath데이터를 래핑할 수 있습니다. ↩ -
Apple Developer, “Core Text Programming Guide” 및
CTLineCreateWithAttributedString. Core Text는 어트리뷰티드 문자열을 글리프 런으로 레이아웃하고 글리프별 패스를 추출하는 데 사용되는 저수준 텍스트 엔진입니다. ↩ -
Apple Developer, “flipsForRightToLeftLayoutDirection(_:)”. 주변의
\.layoutDirection환경 값에 관계없이View의 RTL 미러링을 명시적으로 재정의합니다. ↩ -
Apple, “WWDC 2025 Highlights” via Apple Newsroom. iOS 26, iPadOS 26, macOS 26, watchOS 26, tvOS 26, visionOS 26 전반의 통합 디자인 머티리얼로 Liquid Glass 발표. 세션: “Meet Liquid Glass” (WWDC 2025), “Build a SwiftUI app with Liquid Glass”. ↩
-
Apple Developer, “LinearGradient”, “scaleEffect(x:y:anchor:)”, “mask(_:)”. 표준 SwiftUI 프리미티브, 모두 iOS 13부터 사용 가능. ↩