iOS 7 이후로 Apple이 이렇게 대담한 디자인 변화를 가져온 적이 있었나요? iOS 26에서 등장한 Liquid Glass는 그냥 예쁜 시각 효과 하나 추가된 게 아닙니다. Apple 플랫폼 전체의 UI 철학을 뒤흔드는 완전히 새로운 디자인 언어예요.
반투명한 유리 소재가 주변 콘텐츠를 실시간으로 반사하고 굴절시키면서, 터치에 반응해 유기적으로 변형되는 모습은 — 솔직히 처음 봤을 때 입이 떡 벌어졌습니다.
근데 "와 멋지다"만으로는 앱을 만들 수 없잖아요.
그래서 이 글에서는 SwiftUI에서 Liquid Glass를 실제로 어떻게 구현하는지, 어떤 API를 쓰는지, 그리고 어떤 실수를 피해야 하는지를 실전 코드 예제와 함께 하나하나 정리해 봤습니다. 개인적으로 며칠간 이것저것 만져보면서 알게 된 팁도 같이 넣었으니 끝까지 읽어보시면 도움이 될 거예요.
Liquid Glass란 무엇인가?
Liquid Glass는 WWDC 2025에서 공개된 Apple의 차세대 머티리얼 시스템입니다. iOS 26, iPadOS 26, macOS Tahoe 26, watchOS 26, tvOS 26, visionOS 26까지 — 모든 Apple 플랫폼에 걸쳐 통일된 디자인 언어로 적용돼요.
기존의 UIBlurEffect나 .ultraThinMaterial과는 완전히 다른 차원의 이야기입니다. 핵심 특성을 정리하면 이렇습니다.
- 렌징(Lensing): 기존 블러가 빛을 산란시키는 방식과 달리, Liquid Glass는 빛을 실시간으로 굴절시킵니다. 진짜 유리를 통해 보는 것 같은 광학 효과가 나와요.
- 물질화(Materialization): 요소가 나타날 때 빛의 굴절이 점진적으로 변조되면서 자연스럽게 등장합니다.
- 유동성(Fluidity): 젤 같은 질감으로 터치에 반응하고, 눌림·바운스·쉬머(shimmer) 같은 인터랙션을 제공해요.
- 모핑(Morphing): 컨트롤 상태 간 동적 변형이 일어납니다. 여러 유리 요소가 물방울처럼 합쳐지거나 분리되는데, 이게 정말 매력적이에요.
- 적응성(Adaptivity): 배경 콘텐츠, 색상 모드, 크기에 따라 자동으로 조정됩니다.
핵심 철학은 간단합니다. Liquid Glass는 콘텐츠 위에 떠 있는 내비게이션 레이어예요. 탭 바, 툴바, 플로팅 버튼 같은 컨트롤에 적용하는 거지, 리스트나 텍스트 같은 메인 콘텐츠에 쓰는 게 아닙니다. 이 원칙만 기억하면 반은 성공이에요.
glassEffect 수정자: Liquid Glass의 시작점
SwiftUI에서 Liquid Glass를 적용하는 핵심 API는 .glassEffect() 수정자입니다. 자, 그럼 기본부터 살펴볼까요.
기본 사용법
import SwiftUI
struct BasicGlassView: View {
var body: some View {
Text("안녕하세요, Liquid Glass!")
.padding()
.glassEffect() // 기본값: .regular 변형, .capsule 형태
}
}
이것만으로도 텍스트 뒤에 반투명한 유리 효과가 적용됩니다. 기본적으로 .regular 변형과 .capsule 형태가 사용돼요. 생각보다 간단하죠?
glassEffect의 전체 시그니처는 이렇게 생겼습니다.
func glassEffect<S: Shape>(
_ glass: Glass = .regular,
in shape: S = DefaultGlassEffectShape,
isEnabled: Bool = true
) -> some View
중요한 포인트 하나: .glassEffect()는 수정자 체인의 마지막에 적용해야 합니다. 패딩, 프레임 등 레이아웃 수정자 뒤에 위치시키세요. 순서를 잘못하면 렌더링이 의도대로 안 나와서 한참 헤맬 수 있습니다. (저도 처음에 이것 때문에 시간 좀 날렸어요.)
Glass 변형(Variant) 이해하기
Glass 구조체는 세 가지 변형을 제공합니다. 각각 용도가 꽤 명확하게 나뉘어 있어요.
| 변형 | 투명도 | 적응성 | 용도 |
|---|---|---|---|
.regular |
중간 | 완전 | 대부분의 UI 요소에 기본으로 사용 |
.clear |
높음 | 제한적 | 미디어가 풍부한 배경 위의 요소 |
.identity |
없음 | 해당 없음 | 조건부로 유리 효과를 비활성화할 때 |
.clear를 언제 쓰냐면, 세 가지 조건을 모두 만족할 때입니다. (1) 요소가 미디어가 풍부한 콘텐츠 위에 있고, (2) 디밍 레이어가 콘텐츠에 부정적 영향을 주지 않으며, (3) 유리 위의 콘텐츠가 굵고 밝을 때요. 사실 대부분의 경우에는 그냥 .regular를 쓰면 됩니다.
// 조건부로 유리 효과 비활성화
.glassEffect(isEnabled ? .regular : .identity)
틴팅(Tinting)으로 의미 전달하기
Liquid Glass에 색상 틴트를 입히면 시각적으로 의미를 전달할 수 있습니다. 근데 여기서 중요한 건, 틴트는 장식이 아니라 의미 전달 수단이라는 점이에요. 예쁘다고 모든 버튼에 색을 입히면 안 됩니다.
주요 액션 버튼이나 상태를 나타낼 때만 사용하세요.
// 기본 틴트
Text("주요 액션")
.padding()
.glassEffect(.regular.tint(.blue))
// 투명도 조절된 틴트
Text("보조 액션")
.padding()
.glassEffect(.regular.tint(.purple.opacity(0.6)))
참고로 틴트 메서드는 체이닝이 가능하고, 순서는 상관없습니다.
// 이 두 줄은 동일하게 동작합니다
.glassEffect(.regular.tint(.orange).interactive())
.glassEffect(.regular.interactive().tint(.orange))
interactive()로 터치 반응 추가하기
.interactive() 수정자를 추가하면 유리 요소에 풍부한 터치 인터랙션이 적용됩니다. (iOS에서만 사용 가능해요.) 어떤 동작들이 활성화되냐면:
- 누를 때 스케일링 효과
- 바운스 애니메이션
- 쉬머(shimmer) 효과
- 터치 포인트에서 빛이 인접한 유리로 퍼져나가는 효과
Button(action: { /* 액션 */ }) {
Image(systemName: "plus")
.font(.title2)
.foregroundStyle(.white)
.frame(width: 56, height: 56)
}
.glassEffect(.regular.tint(.blue).interactive())
플로팅 액션 버튼(FAB)이나 퀵 액션 컨트롤 같은 주요 인터랙션 요소에 쓰세요. 모든 버튼에 다 붙이면 오히려 산만해집니다. 절제가 핵심이에요.
다양한 셰이프 적용하기
Liquid Glass는 다양한 형태로 적용할 수 있습니다. Swift의 Shape 프로토콜을 준수하는 셰이프라면 뭐든 가능해요.
// 캡슐 (기본값)
.glassEffect(.regular, in: .capsule)
// 원형
.glassEffect(.regular, in: .circle)
// 둥근 사각형
.glassEffect(.regular, in: RoundedRectangle(cornerRadius: 16))
// 컨테이너 동심 모서리 (컨테이너 모서리에 자동 정렬)
.glassEffect(.regular, in: .rect(cornerRadius: .containerConcentric))
// 타원형
.glassEffect(.regular, in: .ellipse)
// 커스텀 셰이프
.glassEffect(.regular, in: MyCustomShape())
특히 .containerConcentric 옵션은 꼭 기억해두세요. 컨테이너나 윈도우의 모서리 반경에 자동으로 맞춰주기 때문에, 앱 전체에서 일관된 시각적 조화를 만들어낼 수 있습니다. 개인적으로 가장 자주 쓰게 되는 옵션이에요.
GlassEffectContainer: 유리 요소 그룹화
여기서부터 Liquid Glass의 진짜 힘이 드러나기 시작합니다. GlassEffectContainer는 여러 유리 요소를 하나의 통합된 구성으로 묶어주는 컨테이너 뷰예요.
왜 GlassEffectContainer가 필요한가?
핵심적인 제약 사항이 하나 있습니다.
유리는 다른 유리를 샘플링할 수 없습니다.
즉, 유리 효과가 적용된 뷰 위에 다른 유리 효과를 중첩하면 렌더링이 깨집니다. GlassEffectContainer는 공유 샘플링 영역을 제공해서 이 문제를 해결해줘요. 이것 때문에 처음에 꽤 헤맸는데, 한번 알고 나면 간단합니다.
GlassEffectContainer가 해주는 일을 정리하면:
- 여러 유리 셰이프를 통합 구성으로 결합
- 공유 샘플링 영역으로 렌더링 성능 향상
- 유리 요소 간 모핑 전환 활성화
- 인접한 요소들이 물방울처럼 자연스럽게 합쳐지는 효과
GlassEffectContainer(spacing: 8) {
HStack(spacing: 12) {
Button(action: { /* 홈 */ }) {
Image(systemName: "house")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
Button(action: { /* 검색 */ }) {
Image(systemName: "magnifyingglass")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
Button(action: { /* 설정 */ }) {
Image(systemName: "gearshape")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
}
}
spacing 파라미터의 역할
spacing 파라미터는 모핑 임계값을 설정합니다. 이 거리보다 가까운 요소들은 애니메이션 중에 시각적으로 합쳐져요. 물방울이 서로 가까워지면 하나로 합쳐지는 것과 같은 원리입니다. (이 비유가 정말 딱 맞아요.)
// 40pt 이내의 요소들이 모핑 시 합쳐짐
GlassEffectContainer(spacing: 40.0) {
ForEach(tools) { tool in
ToolButton(tool: tool)
.glassEffect(.regular.interactive())
}
}
glassEffectID: 유체 모핑 전환 구현
개인적으로 Liquid Glass에서 가장 감탄했던 기능입니다. glassEffectID를 사용하면 서로 다른 UI 상태 간에 유리 요소가 유체처럼 변형되는 모핑 애니메이션을 만들 수 있어요.
모핑이 작동하려면 네 가지 조건이 필요합니다
- 요소들이 같은
GlassEffectContainer안에 있어야 합니다 - 각 뷰에 공유 네임스페이스를 사용한
glassEffectID가 있어야 합니다 - 뷰가 조건부로 표시/숨김되어 모핑을 트리거해야 합니다
- 상태 변경에 애니메이션이 적용되어야 합니다
네 가지 조건이 좀 까다로워 보이지만, 코드로 보면 꽤 직관적입니다.
struct ExpandableToolbar: View {
@State private var isExpanded = false
@Namespace private var namespace
var body: some View {
GlassEffectContainer(spacing: 30) {
HStack(spacing: 16) {
// 메인 토글 버튼
Button {
withAnimation(.bouncy) {
isExpanded.toggle()
}
} label: {
Image(systemName: isExpanded ? "xmark" : "plus")
.font(.title2)
.frame(width: 50, height: 50)
}
.glassEffect(.regular.tint(.blue).interactive())
.glassEffectID("toggle", in: namespace)
// 확장 시 나타나는 추가 버튼들
if isExpanded {
Button {
// 카메라 액션
} label: {
Image(systemName: "camera")
.frame(width: 50, height: 50)
}
.glassEffect(.regular.interactive())
.glassEffectID("camera", in: namespace)
Button {
// 공유 액션
} label: {
Image(systemName: "square.and.arrow.up")
.frame(width: 50, height: 50)
}
.glassEffect(.regular.interactive())
.glassEffectID("share", in: namespace)
}
}
}
}
}
플러스 버튼을 탭하면, 추가 버튼들이 기존 유리에서 분리되어 나오는 듯한 유체 애니메이션이 재생됩니다. 다시 탭하면 버튼들이 다시 합쳐지면서 사라져요. 처음 보면 진짜 "오..." 하게 됩니다.
glassEffectUnion: 멀리 떨어진 요소 그룹화
GlassEffectContainer의 spacing만으로는 해결 안 되는 상황이 있습니다. 서로 멀리 떨어져 있지만 시각적으로는 하나의 유리 그룹처럼 보여야 하는 경우죠. Apple Maps의 줌 컨트롤(+/- 버튼)을 떠올려보세요.
이럴 때 glassEffectUnion을 씁니다.
struct ZoomControls: View {
@Namespace private var ns
var body: some View {
GlassEffectContainer {
VStack(spacing: 0) {
Button(action: { /* 확대 */ }) {
Image(systemName: "plus")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
.glassEffectUnion(id: "zoom", namespace: ns)
Divider()
Button(action: { /* 축소 */ }) {
Image(systemName: "minus")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
.glassEffectUnion(id: "zoom", namespace: ns)
}
}
}
}
같은 id와 namespace를 공유하는 요소들이 하나의 유리 형태로 렌더링됩니다. 개별 버튼이 아니라 하나의 통합된 컨트롤처럼 보이게 되는 거예요.
내장 버튼 스타일 활용하기
사실 매번 .glassEffect()를 직접 붙이는 게 번거로울 수 있습니다. 빠르게 적용하고 싶을 때는 내장 버튼 스타일을 쓰면 편해요.
// 기본 유리 버튼 — 보조 액션에 적합
Button("일반 버튼") { }
.buttonStyle(.glass)
// 강조 유리 버튼 — 주요 액션에 적합
Button("강조 버튼") { }
.buttonStyle(.glassProminent)
// 색상 틴트가 적용된 강조 버튼
Button("컬러 버튼") { }
.buttonStyle(.glassProminent)
.tint(.purple)
// 원형 버튼
Button("원형") { }
.buttonStyle(.glass)
.buttonBorderShape(.circle)
.buttonStyle(.glass)는 편리하지만, .glassEffect() 수정자에 비해 커스터마이징이 제한적입니다. 세밀하게 제어하고 싶다면 직접 .glassEffect()를 사용하는 게 낫습니다.
시스템 컨트롤의 자동 적용
좋은 소식이 있습니다. iOS 26으로 빌드하면 많은 시스템 컨트롤에 Liquid Glass가 자동으로 적용돼요. 코드를 한 줄도 안 바꿔도요.
// 탭 바 — 자동으로 Liquid Glass 적용
TabView {
HomeView()
.tabItem { Label("홈", systemImage: "house") }
SearchView()
.tabItem { Label("검색", systemImage: "magnifyingglass") }
}
// 내비게이션 바 — 자동으로 Liquid Glass 적용
NavigationStack {
ContentView()
.navigationTitle("내 앱")
}
// 툴바
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("완료") { }
}
}
// 검색 바
.searchable(text: $searchQuery)
Alert, Sheet, Popover 같은 프레젠테이션도 자동으로 유리 스타일이 적용됩니다. 리컴파일만 했는데 앱이 확 달라 보이는 경험, 꽤 신선해요.
접근성(Accessibility) 고려사항
디자인이 아무리 멋져도 접근성을 무시하면 안 되겠죠. 다행히 Liquid Glass는 사용자의 접근성 설정에 자동으로 적응합니다.
- 투명도 줄이기(Reduce Transparency): 유리의 프로스팅이 강화되어 가독성이 올라갑니다
- 대비 높이기(Increase Contrast): 더 선명한 색상과 테두리가 적용돼요
- 움직임 줄이기(Reduce Motion): 애니메이션과 탄성 효과가 줄어듭니다
- iOS 26.1+ 틴트 모드: 설정 → 디스플레이 및 밝기에서 사용자가 불투명도를 직접 조절할 수 있어요
필요하다면 수동으로 접근성 환경 값에 대응할 수도 있습니다.
struct AccessibleGlassView: View {
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
var body: some View {
Text("접근 가능한 유리")
.padding()
.glassEffect(reduceTransparency ? .identity : .regular)
}
}
그런데 Apple의 권장사항은 명확합니다. 시스템이 알아서 처리하게 두세요. 진짜 특별한 이유가 있을 때만 수동으로 오버라이드하는 게 좋습니다.
흔한 실수와 해결 방법
Liquid Glass를 처음 쓸 때 빠지기 쉬운 함정들을 모아봤습니다. 미리 알아두면 디버깅 시간을 확 줄일 수 있어요.
실수 1: 기존 배경과 충돌
.background()로 이미 배경을 설정한 뷰에 .glassEffect()를 얹으면 배경이 유리 효과를 완전히 가려버립니다. 생각보다 이 실수를 많이 해요.
// ❌ 잘못된 사용 — 배경이 유리를 가림
Image(systemName: "star")
.frame(width: 50, height: 50)
.background(Circle().fill(.purple))
.glassEffect()
// ✅ 올바른 사용 — 틴트로 색상 표현
Image(systemName: "star")
.frame(width: 50, height: 50)
.glassEffect(.regular.tint(.purple))
실수 2: 모든 곳에 유리 효과 남용
유리 레이어가 너무 많으면 대비 문제가 빠르게 쌓입니다. 탭 바 + 카드 + 시트가 전부 겹치면 그냥 흐릿한 덩어리가 돼버려요.
// ❌ 과도한 유리 사용
VStack {
Text("제목").glassEffect() // 불필요
ForEach(items) { item in
ItemRow(item: item).glassEffect() // 리스트에 유리 사용 금지
}
}
// ✅ 내비게이션 레이어에만 유리 사용
VStack {
Text("제목")
ForEach(items) { item in
ItemRow(item: item)
}
}
.overlay(alignment: .bottomTrailing) {
FloatingActionButton()
.glassEffect(.regular.tint(.blue).interactive())
}
실수 3: GlassEffectContainer 없이 인접한 유리 배치
앞서 말했듯이, 유리는 다른 유리를 샘플링할 수 없습니다. 인접한 유리 요소는 반드시 GlassEffectContainer로 감싸세요.
// ❌ 각 유리가 독립적으로 샘플링 — 시각적 아티팩트 발생 가능
HStack {
Text("A").padding().glassEffect()
Text("B").padding().glassEffect()
}
// ✅ 컨테이너로 공유 샘플링 영역 제공
GlassEffectContainer {
HStack {
Text("A").padding().glassEffect()
Text("B").padding().glassEffect()
}
}
실수 4: Sheet에서 Form 배경 문제
이건 좀 의외의 함정인데요. Form은 자체적으로 불투명한 배경을 갖고 있어서, Liquid Glass 시트 안에서 Form을 쓰면 유리 효과가 완전히 가려집니다. .scrollContentBackground(.hidden)으로 기본 배경을 숨겨줘야 해요.
.sheet(isPresented: $showSettings) {
NavigationStack {
Form {
// 설정 항목들...
}
.scrollContentBackground(.hidden) // Form 배경 제거
.navigationTitle("설정")
}
.presentationDetents([.medium, .large])
}
기존 앱 마이그레이션 전략
기존 앱을 Liquid Glass로 옮기는 게 부담스러울 수 있는데, 생각보다 많은 부분이 자동으로 처리됩니다. iOS 26 SDK로 리컴파일하는 것만으로도 시스템 컨트롤(NavigationBar, TabBar 등)은 코드 변경 없이 Liquid Glass 스타일로 전환돼요.
물론 커스텀 UI가 많을수록 수동 작업이 필요합니다. 권장하는 점진적 마이그레이션 전략은 이렇습니다.
- 시스템 컨트롤 확인: iOS 26으로 빌드 후 자동 적용된 결과를 먼저 점검하세요
- 커스텀 UINavigationBarAppearance 제거: iOS 15용 트윅이 iOS 26에서 깨질 수 있습니다
- 비핵심 영역부터 적용: 플로팅 버튼, 보조 메뉴 등에 먼저 시도해보세요
- #available 분기: iOS 26 API를 조건부로 적용해서 하위 버전 호환성을 유지합니다
if #available(iOS 26, *) {
FloatingButton()
.glassEffect(.regular.tint(.blue).interactive())
} else {
FloatingButton()
.background(.ultraThinMaterial, in: Circle())
}
혹시 Liquid Glass 적용이 아직 준비되지 않았다면, Apple이 다음 메이저 iOS 릴리즈까지 사용할 수 있는 임시 옵트아웃 옵션을 제공하고 있으니 참고하세요.
// 전역적으로 Liquid Glass 비활성화
ContentView()
.environment(\.glassRenderingMode, .disabled)
실전 예제: 미디어 플레이어 오버레이
자, 이제 지금까지 배운 걸 다 합쳐서 실제 앱에서 쓸 수 있는 미디어 플레이어 오버레이를 만들어 봅시다.
struct MediaPlayerOverlay: View {
@State private var isPlaying = false
@State private var showPlaylist = false
@Namespace private var playerNamespace
var body: some View {
GlassEffectContainer(spacing: 20) {
VStack(spacing: 16) {
// 현재 재생 정보
HStack {
Image(systemName: "music.note")
.font(.title3)
VStack(alignment: .leading) {
Text("지금 재생 중")
.font(.caption)
.foregroundStyle(.secondary)
Text("좋아하는 노래 제목")
.font(.subheadline)
.fontWeight(.medium)
}
Spacer()
}
.padding()
.glassEffect(.regular)
.glassEffectID("info", in: playerNamespace)
// 재생 컨트롤
HStack(spacing: 24) {
Button(action: { /* 이전 곡 */ }) {
Image(systemName: "backward.fill")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
Button(action: { isPlaying.toggle() }) {
Image(systemName: isPlaying ? "pause.fill" : "play.fill")
.font(.title)
.frame(width: 56, height: 56)
}
.glassEffect(.regular.tint(.blue).interactive())
Button(action: { /* 다음 곡 */ }) {
Image(systemName: "forward.fill")
.frame(width: 44, height: 44)
}
.glassEffect(.regular.interactive())
}
// 재생목록 버튼
if showPlaylist {
Button(action: { /* 재생목록 열기 */ }) {
Label("재생목록", systemImage: "list.bullet")
.padding()
}
.glassEffect(.regular.interactive())
.glassEffectID("playlist", in: playerNamespace)
}
}
}
.padding()
}
}
이 예제에서 GlassEffectContainer로 모든 유리 요소를 감싸고, glassEffectID로 모핑 전환을 지원하며, 틴트와 .interactive()를 적절히 조합해 계층적 UI를 구성했습니다. 이런 패턴 하나만 익혀두면 다양한 오버레이 UI에 응용할 수 있어요.
자주 묻는 질문 (FAQ)
Liquid Glass는 이전 iOS 버전에서도 쓸 수 있나요?
아니요. .glassEffect()와 관련 API들은 iOS 26 이상에서만 동작합니다. 이전 버전을 지원해야 한다면 #available(iOS 26, *) 분기를 사용하고, 폴백으로 .ultraThinMaterial 같은 걸 쓰세요.
Liquid Glass가 앱 성능에 영향을 미치나요?
실시간 렌더링이니까 GPU 리소스를 쓰긴 합니다. 하지만 Apple이 하드웨어 가속으로 상당히 최적화해놨고, GlassEffectContainer를 사용하면 공유 샘플링 영역 덕분에 렌더링 효율이 올라갑니다. 유리 레이어를 과도하게 겹치지만 않으면 성능 문제는 거의 없을 거예요.
기존 앱을 iOS 26으로 빌드하면 자동으로 Liquid Glass가 적용되나요?
네, 부분적으로요. NavigationBar, TabBar, Toolbar 같은 시스템 컨트롤은 iOS 26 SDK로 리컴파일하면 자동 적용됩니다. 하지만 커스텀 뷰에는 .glassEffect()를 직접 붙여야 해요.
UIKit에서도 Liquid Glass를 사용할 수 있나요?
네, 가능합니다. UIKit에서는 UIGlassView와 UIGlassEffect를 사용해요. UIVisualEffectView와 비슷한 패턴으로, 뷰를 생성하고 효과를 설정한 뒤 뷰 계층에 추가하면 됩니다. SwiftUI와 UIKit을 섞어 쓰는 하이브리드 앱에서도 두 프레임워크 모두에서 일관되게 Liquid Glass를 적용할 수 있어요.
Liquid Glass를 완전히 비활성화할 수 있나요?
네. 앱 전체에서 끄려면 .environment(\.glassRenderingMode, .disabled)를 루트 뷰에 적용하면 됩니다. 이건 Apple이 다음 메이저 릴리즈까지 제공하는 임시 조치예요. 장기적으로는 Liquid Glass를 적극 채택하는 방향으로 가는 게 맞습니다.