View in English

  • 메뉴 열기 메뉴 닫기
  • Apple Developer
검색
검색 닫기
  • Apple Developer
  • 뉴스
  • 둘러보기
  • 디자인
  • 개발
  • 배포
  • 지원
  • 계정
페이지에서만 검색

빠른 링크

5 빠른 링크

비디오

메뉴 열기 메뉴 닫기
  • 컬렉션
  • 주제
  • 전체 비디오
  • 소개

더 많은 비디오

스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.

  • 소개
  • 자막 전문
  • 코드
  • SwiftUI의 새로운 기능

    어느 Apple 플랫폼에서나 훌륭한 앱를 빌드하는 데 도움이 되는 SwiftUI의 새로운 기능을 알아보세요. Liquid Glass로 앱에 완전히 새로운 디자인과 분위기를 주는 방법을 살펴봅니다. 프레임워크 개선 사항 및 새로운 도구로 성능을 높이고 웹 콘텐츠 및 리치 텍스트 편집과 같은 고급 기능을 통합하는 방법을 확인할 수 있습니다. 또한 SwiftUI로 3차원 뷰를 구현하는 등 더 새로운 영역까지 확장하는 방법도 살펴보세요.

    챕터

    • 0:00 - Introduction
    • 1:22 - Make the new design shine
    • 6:59 - Framework foundations
    • 14:33 - SwiftUI across the system
    • 20:04 - Expand SwiftUI views
    • 25:01 - Next steps

    리소스

    • Adopting Liquid Glass
    • Applying Liquid Glass to custom views
    • dragContainer(for:in:selection:_:)
    • draggable(containerItemID:)
    • Human Interface Guidelines
    • Populating SwiftUI menus with adaptive controls
      • HD 비디오
      • SD 비디오

    관련 비디오

    WWDC25

    • 몰입감 넘치는 앱을 위한 Metal 렌더링의 새로운 기능
    • 보조 접근을 위해 앱 사용자 정의하기
    • 새로운 디자인으로 SwiftUI 앱 빌드하기
    • 위젯의 새로운 기능
    • 코딩 실습: AttributedString으로 SwiftUI에서 풍부한 텍스트 경험 만들기
    • 코딩 실습: Xcode로 현지화하기
    • 함께하면 더욱 탁월한 SwiftUI 및 RealityKit
    • Instruments로 SwiftUI의 성능 최적화하기
    • iPad 앱 디자인 향상하기
    • Swift 동시성 사용하기
    • Swift Charts를 3차원으로 가져오기
    • SwiftUI 공간 레이아웃 만나보기
    • SwiftUI에서 동시성 살펴보기
    • SwiftUI용 WebKit 만나보기
    • visionOS 26의 새로운 기능
    • visionOS에서 SwiftUI로 장면 설정하기
  • 비디오 검색…

    안녕하세요, Anna입니다 저는 Peter입니다 저희는 SwiftUI 팀 엔지니어입니다 SwiftUI의 새로운 사안에 대해 이야기하게 되어 기쁩니다 저성능 관련 개선사항부터 사용자 인터페이스 상의 버튼에 이르기까지 시스템 전반에 걸쳐 몇 가지 주요 개선점을 공유해 드리겠습니다 텍스트와 웹 기반 콘텐츠와는 상호작용하기가 쉽습니다 SwiftUI도 더 많은 곳에서 사용되고 있죠 SwiftUI 다음으로 저와 Anna가 가장 좋아하는 것은 등산 중에 사진을 찍는 것입니다 Peter와 저는 여행을 계획하고 공유하는 앱을 만들었습니다 SwiftUI 개선사항을 많이 활용해 보기에도 사용하기에도 좋은 앱이죠 먼저, 모든 새로운 시스템 기능을 보여드리고 이 기능을 통해 우리 앱이 얼마나 멋지게 완성되었는지 보여드리겠습니다 성능과 애니메이션, 레이아웃 관련 개선사항도 공유하겠습니다 Peter는 Apple 플랫폼 전반에 걸쳐 SwiftUI를 사용할 수 있는 새로운 환경을 소개해드릴 예정입니다 마지막으로, 웹 콘텐츠 및 리치 텍스트 지원 등 SwiftUI 뷰의 새 기능에 대해 깊이 알아볼 것입니다 새 디자인과 함께 앱을 돋보이게 만드는 방법부터 시작해보죠 새로운 디자인 시스템은 쾌적하고 유동적인 경험을 선사합니다 Apple 플랫폼 전반에서 일관된 경험이라면 더욱 그렇죠

    저희는 앱을 다시 컴파일링해 외관을 새롭게 꾸몄습니다 앱의 구조는 변하지 않았습니다 내비게이션 컨테이너가 새로운 디자인에 맞춰 업데이트되었습니다

    iPad와 macOS에서 앱 사이드바가 유리처럼 보이며 주변 콘텐츠를 반사하고 있죠 탭 막대도 업데이트되었습니다 iPhone에서는 새롭고 더 컴팩트한 외관이 돋보입니다

    탭 막대를 비롯해 도구 막대 항목 대부분이 Liquid Glass로 나타나죠 탐색 전환 중, 이 항목은 변형되기도 합니다 직접 보세요

    저희 앱은 새로운 도구 막대 Spacer API를 사용해 조정됩니다 고정 스페이스를 사용해 설정 버튼과 위 아래 버튼을 분리합니다

    도구 막대 항목이 눈에 띄도록 Liquid Glass는 색조를 지원합니다

    Peter와 저는 테두리가 있는 눈에 띄는 버튼 스타일에 색조를 적용했습니다 이제 앱에서 스크롤하면 도구 막대가 가장자리 콘텐츠에 흐림 효과를 적용합니다 이 스크롤 에지 효과는 막대 아래에 무엇이 있든 콘텐츠가 잘 읽히게 해줍니다

    사용자는 다음 여행지를 찾을 때 검색 기능을 이용합니다 이제 검색은 iPhone 하단에 정렬돼 인체공학적으로 쉽게 사용 가능하죠 저희가 사용한 기존 코드는 검색 가능한 수정자를 NavigationSplitView 바깥에 두었습니다 검색을 하단 정렬하기 위해 코드를 변경할 필요가 없었어요

    iPad에서도 동일한 위치를 적용하니 검색 기능이 상단 후행 코너에서 새로운 외관을 갖추게 되었습니다

    검색 가능한 수정자로 어느 때보다 빠르게 검색할 수 있습니다 여행지를 검색하는 탭 기반 앱의 경우 이제 검색 탭이 탭 막대의 나머지 부분과는 분리되어 나타나며 검색 필드에 맞게 변형됩니다 외관을 새롭게 단장하려면, 탭이 검색 역할을 갖도록 설정합니다 시스템 전체의 제어 기능도 신선하게 느껴집니다 토글, 세분화된 선택기 및 슬라이더와 같은 기능 말이죠 맞춤형 뷰도 다르지 않습니다 새로운 디자인을 활용할 수 있는 API도 존재합니다 저희 앱에는 맞춤형 뷰에 glass 효과를 적용했고 주변 콘텐츠를 아름답게 반사하는 모습을 볼 수 있습니다 이전의 사진처럼요 이런 업데이트는 새 디자인으로 구축할 수 있는 가능성에 비하면 아무것도 아닙니다 채택 모범 사례부터 고급 사용자 지정에 이르기까지 이를 활용하는 방법에 대해 자세히 알아보려면 '새로운 디자인으로 Swift UI 앱 구축하기'를 시청하세요 iPadOS 26에서는 사용자가 당신의 앱과 상호작용하는 것에 대한 흥미로운 개선점이 몇 가지 있었습니다 사람들이 아래로 스와이프하면 이제 앱에 메뉴 막대가 표시되어 자주 쓰는 작업을 더 빠르게 처리할 수 있습니다

    MacOS에서 메뉴 막대 구축 시 사용한 명령 API로 이제 iPad에서도 같은 결과를 낼 수 있습니다 저희 앱에는 다음 여행을 위한 메모 기능이 있기 때문에 몇 가지 텍스트 편집 명령도 추가했습니다 여행을 계획할 때는 여러 앱을 동시 사용하는 경우가 많습니다 iPad에서 내용을 보는 작업이 훨씬 더 유연해졌습니다 이제 사용자는 앱 크기를 유동적으로 조정할 수 있습니다

    이렇게 Split View Navigation을 사용하는 앱은 시스템이 가능한 공간에 따라 자동으로 열을 보이거나 숨깁니다 앱 크기 조정 기능을 구현하려면 UIRequiresFullscreen와 같이 화면을 전체 크기로 고정하는 API를 외부로 마이그레이션합니다 이 속성 키는 iPadOS 26에서 더 이상 지원되지 않습니다 iPad 앱에서 크기 조정 가능한 창과 새로운 메뉴 막대를 디자인하는 방법을 알아보려면 'iPad 앱의 디자인 개선하기'를 시청하세요 macOS에서 창 크기 조정도 더 유동적으로 변했습니다 콘텐츠 뷰 크기의 변경사항 때문에 크기를 재조정하는 경우 이제 SwiftUI가 콘텐츠와 창 사이 애니메이션을 동기화 합니다 저희 앱은 새 창 재조정 앵커로 애니메이션이 시작되는 곳을 꼭 맞게 설정했습니다

    콘텐츠의 여러 부분 간의 연속성을 유지하는 데 좋은 방법입니다 설정 보기에서 탭을 전환하는 것과 같죠 또한 SwiftUI 구성요소에 대한 개선점 덕분에 저희 앱이 더 강력해졌습니다 강력한 성능부터 사용 편의성 개선 및 새로운 콘텐츠 레이아웃에 이르기까지 SwiftUI로 앱을 개발하기에 정말 좋은 시점입니다 프레임워크 성능 개선 또한 저희 앱과 당신의 앱을 포함한 Apple 플랫폼 전반의 모든 앱에 이점을 가져다 줍니다 여러 주요 영역의 핵심 개선사항도 공유드리고자 합니다 여기에는 목록, 스크롤 및 프로파일링이 포함됩니다 저는 특히 macOS의 목록에 대한 개선사항이 마음에 드는데요 macOS에서 100,000여 개 항목 목록 로딩이 6배 더 빨라졌습니다 이 목록은 최대 16배 더 빠르게 업데이트됩니다 목록이 클수록 성능이 더 크게 향상되며 모든 플랫폼에 개선사항이 적용됩니다

    저희 여행 계획 앱 사용자의 경험도 향상시키는 업데이트입니다 여행지 검색, 필터링, 기존 여행지 업데이트 등 모든 경험에서요 스크롤링도 크게 향상되었습니다

    사용자가 앱에서 스크롤하면 시스템은 일정 시간 내에 SwiftUI가 다음 프레임을 렌더링할 수 있도록 합니다 하지만 마감시간까지 모든 작업이 완료되지 않으면 프레임이 떨어지게 됩니다 그 누구도 원치 않는 결과죠 앱의 결함이나 지연으로 이어질 수 있기 때문입니다 iOS 및 macOS 사용자 인터페이스 업데이트를 통해 SwiftUI 스케줄링 경험이 개선되었습니다 반응성을 향상시키고 SwiftUI가 다음 프레임에 대비해 더 많은 작업을 처리하도록 해줍니다 대체로 높은 프레임 속도로 빠르게 스크롤하는 동안 앱이 중단될 가능성을 줄여주죠 이 다이어그램의 LazyVStack과 같이, 스크롤 뷰 내에 지연 스택을 넣을 때 SwiftUI는 포함된 보기가 나타나기 직전까지 로딩을 지연시킵니다 이제 중첩된 스크롤 뷰도 이와 같은 동작을 합니다 사진 캐러셀과 같은 뷰를 만드는 데 좋습니다 앱에 어떤 성능 문제가 남아 있는지 이해하려면 Xcode에서 새로운 SwiftUI 성능 도구를 사용하면 됩니다 긴 뷰 본문 업데이트 또는 플랫폼 보기 업데이트와 같은 다양한 성능 문제 영역에서 빠른 조치가 가능한 여러 방법을 사용할 수 있습니다 산을 잘 타는 Peter 만큼이나 앱을 빠르게 만들려면 아직 해야 할 일이 좀 남은 것 같죠

    새로운 도구를 더 깊이 이해하려면 'Instruments로 SwiftUI의 성능 최적화하기'를 시청하세요

    앱 구축에 있어 동시 프로그래밍은 또 다른 근본적인 부분입니다 Swift는 구조화된 동시성을 지원해 컴파일 시점의 데이터 레이스 안전 검증이 가능합니다 저와 Peter가 저희 동시 코드에서 버그를 찾는 데에도 도움이 되었죠 버그가 앱에 영향을 주기 전에요 구조화된 동시성 추가에 대해 자세히 알아보려면 'Swift 동시성 사용하기'를 시청하세요 SwiftUI에서 Swift 동시성을 사용하는 방법을 알아보려면 'SwiftUI에서 동시성 살펴보기'를 시청하세요

    앱이 동시에 데이터를 로드하는 동안 애니메이션을 시연할게요 애니메이션화에는 애니메이션 가능한 프로토콜을 사용합니다 이때 사용자 지정 애니메이션 데이터 속성을 정의해 드로잉 방향을 제외한 모든 모양 속성을 애니메이션화 합니다

    전체 애니메이션 데이터 선언을 추가할 때 말이죠 드로잉 방향을 제외하는 것만 해도 코드가 정말 많습니다 새로운 애니메이션 매크로를 사용하면 사용자 지정 애니메이션 데이터 속성을 삭제하고 SwiftUI로 하여금 자동으로 합성하도록 만들 수 있습니다 저는 AnimatableIgnored 매크로로 드로잉 방향처럼 애니메이션을 원하지 않는 속성을 제외합니다 레이아웃은 이제 3차원으로 작업합니다

    SwiftUI에는 이미 익숙한 수정자에 새로운 깊이 기반 변형이 도입되어 직접적인 볼류메트릭 레이아웃 없이도 더 많은 작업이 가능합니다 VisionOS에서 저희 앱을 사용하면 하이킹 경로를 계획할 수 있습니다 주어진 시점에 어느 지점에서 등산 중인지에 따라 하늘의 태양을 보여주는 기능도 추가하고자 합니다 일반적인 2D 정렬 대신 새로운 Alignment3D 유형을 사용해 태양을 정렬하겠습니다 Spatial Overlay 수정자로 태양을 배치합니다 시간대에 따라 오버레이의 정렬을 조정합니다

    멋지네요 이제 살갗이 타서 고생하진 않겠어요 이건 visionOS 26 공간 레이아웃 개선사항으로 할 수 있는 일들의 일부에 불과하죠 ‘SwiftUI 공간 레이아웃 만나보기’에서 공간 경험을 구축하기 위한 새로운 도구를 만나보세요 저와 Peter의 배낭은 항상 너무 꽉 차있었어요 그래서 앱에 볼륨을 추가해 짐의 사양을 풀어내도록 했죠 조작 가능한 수정자는 앱의 객체와 상호작용할 수 있도록 합니다 여기 물병의 모형이 있네요 사용자가 집어 들고 옮길 수 있는 모형입니다

    아직 챙겨야 할 품목을 명확히 하기 위해 새로운 장면 스냅 API를 사용해 환경에서 이 정보를 읽을 수 있도록 합니다

    이런식으로 테이블에 받침대를 스냅된 항목으로 추가합니다

    새로운 볼류메트릭 API를 사용하면 정말 새로운 경험을 구현할 수 있습니다 멋지네요

    SwiftUI에는 창, 볼륨, 장면 등 visionOS와 관련된 더 많은 개선 사항이 있습니다 창 복원부터 새로운 장면 유형까지 다양하죠 사용법을 배우려면 'visionOS에서 SwiftUI로 장면 설정하기'를 확인하세요 'vision OS의 새로운 기능'에서 플랫폼의 새 기능도 만나보세요 와, 작품처럼 완벽한 개선 사항이네요 다음 스냅 하이킹은 순식간에 준비할 수 있겠네요 정말 그래요 지난번 여행에서 찍은 사진 좀 보세요

    완전 사파리죠 진짜 좋아보이네요, Anna 올해 SwiftUI처럼 뷰파인더를 확장하기에 좋은 곳이네요 앱은 시스템 전반에 걸쳐 SwiftUI의 이점을 활용할 수 있죠 장면에 대한 개선사항과 위젯 및 컨트롤의 새로운 API 덕분에 앱이 플랫폼과 정말 잘 어우러집니다 SwiftUI는 다른 프레임워크와는 훨씬 더 잘 작동합니다 장면은 앱의 뷰에 대한 루트 컨테이너입니다 인터페이스의 분리된 부분을 나타내죠 앱 본문에 선언하여 장면에 액세스할 수 있습니다 WindowGroup을 예로 들어보죠 올해부터는 장면 브리징을 통해 UIKit과 AppKit 라이프사이클 앱에서 SwiftUI 장면 요청이 가능합니다 장면 브리징은 최고예요 UIKit과 AppKit 라이프사이클 앱과 SwiftUI 장면의 상호운용이 가능하죠 앱은 이를 통해 SwiftUI 전용 장면 유형을 열거나 UIKit 또는 AppKit 코드에서 바로 SwiftUI 독점 기능을 사용합니다 MenuBarExtra와 ImmersiveSpace 같은 장면 유형을 사용할 수 있죠 windowStyle 및 immersiveEnvironmentBehavior 등 장면 수정자와도 잘 작동합니다 장면 브리징은 올해 SwiftUI의 새 장면 유형과 함께 작동합니다 macOS Tahoe와 visionOS 26 RemoteImmersiveSpace와 같이 Mac 앱에서 새로운 장면을 사용해

    Apple Vision Pro에서 스테레오 콘텐츠를 렌더링할 수 있습니다 RemoteImmersiveSpace에서 CompositorServices로 렌더링하죠 Mac 앱은 호버 효과와 입력 이벤트를 사용할 수 있습니다 CompositorServices Metal 및 RemoteImmersiveSpace에 대해 알아보고 사용법을 배우려면 '몰입감 넘치는 앱을 위한 Metal 렌더링의 새로운 기능'을 보세요 인지 장애가 있는 사용자를 위한 스페셜 모드인 AssistiveAccess도 있습니다 새 AssistiveAccess 장면 유형을 채택하면 이 모드로 설정된 iPhone에서 앱이 UI를 나타낼 수 있습니다 이 API와 iOS 26 앱에 AssistiveAccess를 도입하는 방법을 더 알고 싶으면 '보조 접근을 위해 앱 사용자 정의하기'를 확인하세요. 올해 SwiftUI에는 AppKit 작업에 몇 가지 큰 개선사항이 있습니다 장면 브리징 외 SwiftUI 뷰가 있는 시트도 표시할 수 있죠 앱에서 SwiftUI를 점진적으로 채택하기에 좋은 방법입니다 NSGestureRecognizerRepresentable로 AppKit 제스처를 SwiftUI로 연결할 수 있습니다 그리고 Interface Builder에서 NSHostingView를 사용할 수 있죠 또한, 올해 SwiftUI는 RealityKit과 함께 작업하는 API를 더 많이 제공합니다 이런 개선점은 SwiftUI 코드에서 RealityKit과의 상호작용을 모두 간소화합니다 RealityKit 엔티티는 이제 Observable을 준수하여 SwiftUI 뷰의 변경사항을 더 쉽게 관찰할 수 있도록 합니다 개선된 좌표 전환 API도 있습니다 RealityKit에서 프레젠테이션에 향상된 지원을 바로 제공하죠 새로운 구성요소를 사용하면 이와 같은 SwiftUI 팝오버를 RealityKit 엔티티에서 곧바로 표시할 수 있습니다 사진 찍으러 등산 갈 때 가고픈 곳을 정확히 표시할 수 있죠 SwiftUI와 RealityKit 간 통합에는 첨부파일 구성요소, 동기화 애니메이션, 구성요소 바인딩 및 RealityView의 새 크기 조정 동작처럼 더 많은 것이 있습니다 SwiftUI와 RealityKit를 계속 같이 사용하는 방법은 '함께하면 더욱 탁월한 SwiftUI 및 RealityKit'에서 알아보세요 저는 제어 센터의 제어 기능을 정말 좋아합니다 휴대폰으로 집을 단축키로 기기를 심지어는 카메라까지 제어할 수 있습니다 올해, watchOS 26과 macOS Tahoe는 커스텀 제어 기능을 제공합니다 플랫폼에서 컨트롤을 사용할 수 있게 돼 정말 기쁜데요 Mac 제어 센터에서 바로 맞춤형 제어 기능에 접근할 수 있습니다 산책 중이라면 Watch에서 딱 한 번 탭해서 가장 좋아하는 사진을 표시할 수 있죠 굉장하죠 저도 위젯을 정말 좋아합니다 앱에서 정보를 한눈에 얻을 수 있잖아요 올해부터 위젯을 VisionOS와 CarPlay에서 사용할 수 있습니다 VisionOS에서는 공유 공간에서 위젯의 모양을 사용자 지정할 수 있습니다 저희 앱에는 카운트다운 위젯을 추가했습니다 새로운 levelOfDetail 환경 값을 사용했죠

    위젯에 가까이 다가가면 확장되어 지난번에 갔을 때 찍은 사진이 나타납니다 다음 등산 출사는 언제 갈지 한눈에 볼 수 있죠 7일 밖에 안 남았네요 올해 위젯엔 CarPlay 실시간 현황 푸시 기반 업데이트 API 및 WatchOS 관련성을 위한 새 API 등 더 많은 새 기능이 있습니다 '위젯의 새로운 기능'에서 자세한 내용을 확인하세요 올해, SwiftUI 뷰 기능이 확장되었습니다 리치 텍스트 편집부터 3D 차트에 이르기까지 기존 SwiftUI의 기능과 외관이 새롭게 단장되었습니다 이제 앱에서 웹 콘텐츠를 곧바로 임베드 할 때 WebKit에서 WebView와 같은 SwiftUI API의 전체 세트를 활용할 수 있습니다 WebView는 앱에서 웹 콘텐츠를 표시하는 새 SwiftUI 뷰입니다 Safari와 마찬가지로 WebKit으로 구동되죠 앱은 WebView를 초기화하여 URL을 표시할 수 있습니다 페이지를 커스텀하고 이와 상호작용하려면 WebView로 새 Swift 전용 observable 모델 유형인 WebPage를 표시할 수 있죠 WebPage는 웹과의 풍부한 상호작용을 가능하게 합니다 프로그래밍을 통해 페이지에서 탐색하고 페이지 속성에 접근하죠

    WebKit이 SwiftUI를 지원하는 새로운 방법도 다양해졌습니다 사용자 에이전트 커스텀이나 JavaScript 호출 커스텀 URL 스킴 등 다양하죠 새로운 WebKit API에 대해 배우고 싶다면 'SwiftUI용 WebKit 만나보기'를 시청하세요 저희는 가족들에게 등산이 그렇게 어렵지 않다고 설득해왔어요 Swift Charts를 통해 3D가 새로 지원되니 직접 보여주기만 하면 되죠 3D 차트를 보여주려면 Chart3D를 선언합니다 Chart3D는 3차원 플롯을 보여줍니다 새로운 Z-특정 수식어로 3D 공간 크기를 지정할 수 있죠 저번 등산에서 재채기를 그렇게 한 이유를 알겠네요 사인파였잖아요 앱에 3D 차트를 추가하는 방법을 배우려면 'Swift Charts를 3차원으로 가져오기'를 시청하세요 다른 앱과 여행 데이터를 공유할 수 있도록 Mac 앱에 드래그 앤 드롭 기능을 도입했어요 올해 드래그 앤 드롭에도 앱에서 활용할 주요 개선사항이 있습니다 드래그가 가능한 수정자의 새 변형을 사용해 여러 항목 주변으로 드래그 할 수 있어요 새 dragContainer 수정자도 가능하죠 이렇게 하면 뷰가 드래그 항목을 담는 컨테이너와 같아집니다 선택한 사항에 기반해 전송할 항목을 반환하죠

    커스텀 선택 동작과 함께 작동하죠 이 수정자를 사용하면 드롭이 실행될 때 항목을 지연 드래그하도록 SwiftUI가 요청하죠

    새로운 DragConfiguration API로 앱에서 지원되는 드래그 작업을 사용자화할 수 있습니다 여기서는 삭제가 허용됩니다 새 OnDragSessionUpdated 수정자로 이벤트를 관찰합니다 사진을 삭제하기 전 종료 단계에서 종료된 항목을 확인합니다

    이제 Dock의 휴지통으로 드래그하면 사진이 삭제됩니다

    드래그할 때 드래그 미리보기가 어떻게 보이는지 맞춤화하려면 포메이션을 지정하세요

    스택 포메이션은 항목을 서로 멋지게 겹쳐 놓습니다 좋아 보이네요 플롯 작업이나 여행 공유 외에도 친구들도 함께 참여할 수 있으면 좋겠어요 친구들이 사진에 댓글을 달게 하는 방법을 연구하고 있습니다 SwiftUI가 새롭게 지원하는 리치 텍스트 편집 기능은 이러한 경험을 구축하는 데 좋습니다

    이제 TextView에 AttributedString가 지원됩니다 TextEditor에서 AttributedString에 바인딩을 전달해 내장형 텍스트 포매팅 제어 기능으로 지인들이 사진에 댓글을 남길 수 있도록 구현했어요 굉장하죠

    이 냄새 나나요? SwiftUI에서 맛있는 리치 텍스트 냄새가 나네요 올해에는 리치 텍스트와 현지화 선택지가 늘어났습니다 '코딩 실습: AttributedString으로 SwiftUI에서 리치 텍스트 경험 만들기'로 더 많이 알아보세요 단락 스타일 커스텀, 속성 변환에 더해 사용자가 앱을 사용하게 하는 제한 속성까지도 커스텀이 가능합니다 '코딩 실습: Xcode로 현지화하기'를 통해 어떤 언어로든 멋진 경험을 만들어보세요 SwiftUI를 사용하는 새 방법이라니 정말 신나는데요 다른 요소와의 다리가 되어주네요 저번 등산에서 찍은 사진 좀 보세요

    언제 한번 같이 가야해요 이제 새로운 앱으로 사진을 좀 더 찍을 시간입니다 앱에서 새 디자인이 주는 새로운 분위기와 느낌을 직접 보고 앱을 다듬는 새 API를 사용해보세요 새로운 성능 도구로 앱의 성능을 점검합니다 새 볼륨과 공간 레이아웃으로 앱에 깊이를 더해보세요 리치 텍스트와 WebKit 개선점으로 앱 경험을 더 풍부하게 만드세요 그 어느 때보다 더 많은 곳에서 컨트롤과 위젯을 활용하세요 올해 SwiftUI에서 모험을 즐겨보세요 이번 성능 개선 덕분에 다음 등산은 보다 힘들이지 않고 갈 수 있겠죠? 갈 준비 됐나요? 그럼요

    • 2:27 - Toolbar spacer

      import SwiftUI
      
      struct TripDetailView: View {
          var body: some View {
              NavigationStack {
                  TripList()
                      .toolbar {
                          ToolbarItemGroup(placement: .primaryAction) {
                              UpButton()
                              DownButton()
                          }
      
                          ToolbarSpacer(.fixed, placement: .primaryAction)
      
                          ToolbarItem(placement: .primaryAction) {
                              SettingsButton()
                          }
                      }
              }
          }
      }
      
      struct TripList: View {
          var body: some View {
              Text("TripList")
          }
      }
      
      struct UpButton: View {
          var body: some View {
              Button("Up", systemImage: "chevron.up") { }
          }
      }
      
      struct DownButton: View {
          var body: some View {
              Button("Down", systemImage: "chevron.down") { }
          }
      }
      
      struct SettingsButton: View {
          var body: some View {
              Button("List Settings", systemImage: "ellipsis") { }
          }
      }
    • 2:52 - Toolbar item tint

      import SwiftUI
      
      struct InspectorView: View {
          var body: some View {
              NavigationStack {
                  InspectorMap()
                      .toolbar {
                          ToolbarItem(placement: .primaryAction) {
                              SaveLocationButton()
                                  .buttonStyle(.borderedProminent)
                                  .tint(.pink)
                          }
                      }
              }
          }
      }
      
      struct InspectorMap: View {
          var body: some View {
              Text("InspectorMap")
          }
      }
      
      struct SaveLocationButton: View {
          var body: some View {
              Button("SaveLocationButton") { }
          }
      }
    • 3:30 - Searchable

      import SwiftUI
      
      struct PlannerSplitView: View {
          @State private var query: String = ""
      
          var body: some View {
              NavigationSplitView {
                  Text("Sidebar")
              } detail: {
                  Text("Detail")
              }
              .searchable(
                  text: $query,
                  prompt: "What are you looking for?"
              )
          }
      }
    • 4:12 - Search tab

      import SwiftUI
      
      struct HealthTabView: View {
          @State private var text: String = ""
          
          var body: some View {
              TabView {
                  Tab("Summary", systemImage: "heart") {
                      NavigationStack {
                          Text("Summary")
                      }
                  }
                  Tab("Sharing", systemImage: "person.2") {
                      NavigationStack {
                          Text("Sharing")
                      }
                  }
                  Tab(role: .search) {
                      NavigationStack {
                          Text("Search")
                      }
                  }
              }
              .searchable(text: $text)
          }
      }
    • 4:37 - Glass effect

      import SwiftUI
      
      struct ToTopButton: View {
          var body: some View {
              Button("To Top", systemImage: "chevron.up") {
                  scrollToTop()
              }
              .padding()
              .glassEffect()
          }
      
          func scrollToTop() {
              // Scroll to top of view
          }
      }
    • 5:20 - Menu bar commands

      import SwiftUI
      
      @main
      struct TravelPhotographyApp: App {
          var body: some Scene {
              WindowGroup {
                  RootView()
              }
              .commands {
                  TextEditingCommands()
              }
          }
      }
      
      struct RootView: View {
          var body: some View {
              Text("RootView")
          }
      }
    • 6:40 - Window resize anchor

      import SwiftUI
      
      struct SettingsTabView: View {
          @State private var selection: SectionTab = .general
          var body: some View {
              TabView(selection: $selection.animation()) {
                  Tab("General", systemImage: "gear", value: .general) {
                      Text("General")
                  }
                  Tab("Sections", systemImage: "list.bullet", value: .sections) {
                      Text("Sections")
                  }
              }
              .windowResizeAnchor(.top)
          }
      }
      
      enum SectionTab: Hashable {
          case general
          case sections
      }
    • 11:24 - @Animatable macro

      import SwiftUI
      
      @Animatable
      struct LoadingArc: Shape {
          var center: CGPoint
          var radius: CGFloat
          var startAngle: Angle
          var endAngle: Angle
          @AnimatableIgnored var drawPathClockwise: Bool
      
          func path(in rect: CGRect) -> Path {
              // Creates a `Path` arc using properties
              return Path()
          }
      }
    • 12:15 - Spatial overlay

      import RealityKit
      import SwiftUI
      
      struct Map: View {
          @Binding var timeAlignment: Alignment3D
      
          var body: some View {
              Model3D(named: "Map")
                  .spatialOverlay(
                      alignment: timeAlignment
                  ) {
                      Sun()
                  }
          }
      }
      
      struct Sun: View {
          var body: some View {
              Model3D(named: "Sun")
          }
      }
    • 13:04 - Manipulable and surface snapping

      import ARKit
      import RealityKit
      import SwiftUI
      
      struct BackpackWaterBottle: View {
          @Environment(\.surfaceSnappingInfo) var snappingInfo: SurfaceSnappingInfo
      
          var body: some View {
              VStackLayout().depthAlignment(.center) {
                  waterBottleView
                      .manipulable()
      
                  Pedestal()
                      .opacity(
                          snappingInfo.classification == .table ? 1.0 : 0.0)
              }
          }
      
          var waterBottleView: some View {
              Model3D(named: "waterBottle")
          }
      }
      
      struct WaterBottleView: View {
          var body: some View {
              Model3D(named: "waterBottle")
          }
      }
      
      struct Pedestal: View {
          var body: some View {
              Model3D(named: "pedestal")
          }
      }
    • 15:00 - SwiftUI scenes

      import SwiftUI
      
      @main
      struct PhotoWalk: App {
          var body: some Scene {
              WindowGroup(id: "AppContents") {
                  PhotoWalkContent()
              }
          }
      }
      
      struct PhotoWalkContent: View {
          var body: some View {
              Text("PhotoWalkContent")
          }
      }
    • 16:28 - Assistive Access scene

      import SwiftUI
      
      @main
      struct PhotoWalk: App {
        var body: some Scene {
          WindowGroup {
            ContentView()
          }
      
          AssistiveAccess {
            AssistiveAccessContentView()
          }
        }
      }
      
      struct ContentView: View {
        var body: some View {
          Text("ContentView")
        }
      }
      
      struct AssistiveAccessContentView: View {
        var body: some View {
          Text("AssistiveAccessContentView")
        }
      }
    • 17:52 - SwiftUI presentations from RealityKit

      import RealityKit
      import SwiftUI
      
      struct PopoverComponentView: View {
          @State private var popoverPresented: Bool = false
          var body: some View {
              RealityView { c in
                  let mapEntity = Entity()
      
                  let popover = Entity()
                  mapEntity.addChild(popover)
                  popover.components[PresentationComponent.self] = PresentationComponent(
                      isPresented: $popoverPresented,
                      configuration: .popover(arrowEdge: .bottom),
                      content: DetailsView()
                  )
              }
          }
      }
      
      struct DetailsView: View {
          var body: some View {
              Text("DetailsView")
          }
      }
    • 19:24 - Level of detail

      import SwiftUI
      import WidgetKit
      
      struct PhotoCountdownView: View {
          @Environment(\.levelOfDetail) var levelOfDetail: LevelOfDetail
          var body: some View {
              switch levelOfDetail {
              case .default:
                  RecentPhotosView()
              case .simplified:
                  CountdownView()
              default:
                  Text("Unknown level of detail")
              }
          }
      }
      
      struct RecentPhotosView: View {
          var body: some View {
              Text("RecentPhotosView")
          }
      }
      
      struct CountdownView: View {
          var body: some View {
              Text("CountdownView")
          }
      }
    • 20:28 - WebView

      import SwiftUI
      import WebKit
      
      struct HikeGuideWebView: View {
          var body: some View {
              WebView(url: sunshineMountainURL)
          }
      
          var sunshineMountainURL: URL {
              URL(string: "sunshineMountainURL")!
          }
      }
    • 20:44 - WebView with WebPage

      import SwiftUI
      import WebKit
      
      struct InAppBrowser: View {
          @State private var page = WebPage()
      
          var body: some View {
              WebView(page)
                  .ignoresSafeArea()
                  .onAppear {
                      page.load(URLRequest(url: sunshineMountainURL))
                  }
          }
      
          var sunshineMountainURL: URL {
              URL(string: "sunshineMountainURL")!
          }
      }
    • 21:35 - 3D charts

      import Charts
      import SwiftUI
      
      struct HikePlotView: View {
          var body: some View {
              Chart3D {
                  SurfacePlot(
                      x: "x", y: "y", z: "z") { x, y in
                          sin(x) * cos(y)
                      }
                      .foregroundStyle(Gradient(colors: [.orange, .pink]))
              }
              .chartXScale(domain: -3 ... 3)
              .chartYScale(domain: -3 ... 3)
              .chartZScale(domain: -3 ... 3)
          }
      }
    • 22:18 - macOS drag and drop

      import SwiftUI
      
      struct DragDropExample: View {
          @State private var selectedPhotos: [Photo.ID] = []
          var body: some View {
              ScrollView {
                  LazyVGrid(columns: gridColumns) {
                      ForEach(model.photos) { photo in
                          view(photo: photo)
                              .draggable(containerItemID: photo.id)
                      }
                  }
              }
              .dragContainer(for: Photo.self, selection: selectedPhotos) { draggedIDs in
                  photos(ids: draggedIDs)
              }
              .dragConfiguration(DragConfiguration(allowMove: false, allowDelete: true))
                  .onDragSessionUpdated { session in
                      let ids = session.draggedItemIDs(for: Photo.ID.self)
                          if session.phase == .ended(.delete) {
                              trash(ids)
                              deletePhotos(ids)
                          }
                  }
              .dragPreviewsFormation(.stack)
          }
      }
    • 23:55 - Rich text view

      import SwiftUI
      
      struct CommentEditor: View {
          @Binding var commentText: AttributedString
      
          var body: some View {
              TextEditor(text: $commentText)
          }
      }

Developer Footer

  • 비디오
  • WWDC25
  • SwiftUI의 새로운 기능
  • 메뉴 열기 메뉴 닫기
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    메뉴 열기 메뉴 닫기
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    메뉴 열기 메뉴 닫기
    • 손쉬운 사용
    • 액세서리
    • 앱 확장 프로그램
    • App Store
    • 오디오 및 비디오(영문)
    • 증강 현실
    • 디자인
    • 배포
    • 교육
    • 서체(영문)
    • 게임
    • 건강 및 피트니스
    • 앱 내 구입
    • 현지화
    • 지도 및 위치
    • 머신 러닝
    • 오픈 소스(영문)
    • 보안
    • Safari 및 웹(영문)
    메뉴 열기 메뉴 닫기
    • 문서(영문)
    • 튜토리얼
    • 다운로드(영문)
    • 포럼(영문)
    • 비디오
    메뉴 열기 메뉴 닫기
    • 지원 문서
    • 문의하기
    • 버그 보고
    • 시스템 상태(영문)
    메뉴 열기 메뉴 닫기
    • Apple Developer
    • App Store Connect
    • 인증서, 식별자 및 프로파일(영문)
    • 피드백 지원
    메뉴 열기 메뉴 닫기
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(영문)
    • News Partner Program(영문)
    • Video Partner Program(영문)
    • Security Bounty Program(영문)
    • Security Research Device Program(영문)
    메뉴 열기 메뉴 닫기
    • Apple과의 만남
    • Apple Developer Center
    • App Store 어워드(영문)
    • Apple 디자인 어워드
    • Apple Developer Academy(영문)
    • WWDC
    Apple Developer 앱 받기
    Copyright © 2025 Apple Inc. 모든 권리 보유.
    약관 개인정보 처리방침 계약 및 지침