SwiftUI로 Mac다운 앱을 만드는 과정에서 겪은 선택 상태, 드래그 앤 드롭, 키보드 단축키, 컨텍스트 메뉴, 툴바 관련 문제들과 WWDC 27 이후의 변화에 대한 업데이트입니다.
제 지난 글에서 SwiftUI를 사용해 Mac다운 앱을 만드는 이야기를 했는데, 예상보다 조금 더 큰 반응을 얻었습니다. Mastodon에서 여러번 언급되었고, iOS Dev Weekly에 실렸으며, Swift Blog Carnival의 5월 호에 영감을 주기도 했고, 결국 John Gruber가 Daring Fireball에서 언급하기도 했습니다. 아마 "Mac-assed"라는 표현을 대중화한 데 가장 큰 책임이 있는 인물이라고 해도 될 것입니다.
이 모든 관심의 결과로 Apple의 한 엔지니어가 몇 가지 메모와 함께 연락을 주기도 했습니다. 우리는 몇 차례 이메일을 주고받았고, 저는 몇 개의 레이더를 등록했으며, 이제 WWDC 27이 끝난 시점에서 이 글은 이전에 제가 썼던 문제들에 대한 작은 업데이트 역할을 합니다.
선택 상태와 관련해서는, 이전 글을 쓸 당시에는 제가 알지 못했던 \.backgroundProminence환경 값이 있습니다.
문서에 따르면, "List와 Table 같은 뷰뿐 아니라 ShapeStyle.selection 같은 표준 도형 스타일도 전경 뷰의 배경 prominence를 자동으로 업데이트합니다."
즉, SwiftUI에는 이미 제가 \.isEmphasized라고 불렀던 것과 매우 비슷한 내장 개념이 존재합니다. List나 Table을 사용하고 있다면, 선택 prominence가 바뀔 때 이 값을 확인할 수 있습니다.
물론 List나 Table을 사용하지 않는다면 — 그리고 어느 정도 진지한 수준의 커스터마이징을 하려 한다면 아마 사용하지 않을 가능성이 큽니다 — 이전에 제가 언급한 접근 방식이 여전히 맞는 방법입니다. 직접 포커스를 추적하고 그 상태를 환경을 통해 아래로 전달하세요.
차이점은, 직접 \.isEmphasized 값을 만드는 대신 \.backgroundProminence를 재사용할 수 있다는 점입니다. 그러면 나중에 커스텀 행을 List나 Table 안에 넣게 되더라도 조금 더 잘 호환된다는 좋은 부수 효과가 있습니다.
또한 저는 커스텀 행을 더 유용하게 만들기 위해 List가 어떤 것을 노출할 수 있을지에 대한 몇 가지 아이디어와 함께 FB23095823를 등록했습니다. 저는 여전히 이것이 올바른 방향이라고 생각합니다. AppKit이나 UIKit으로 작업할 때는 셀과 행에 대해 엄청난 수준의 유연성이 있고, 제가 전달한 피드백은 List를 그 수준의 가능성에 더 가깝게 만들려는 시도입니다.
27 운영체제 릴리스에 도입되었고 macOS 26에서도 이미 사용 가능한 것으로 보이는 새로운 .onDragSessionUpdatedAPI가 있습니다. 이것은 SwiftUI에서 드래그 앤 드롭과 관련해 제가 가진 가장 큰 문제, 즉 드래그 세션을 시작부터 볼 수 있어야 한다는 문제를 해결해 줍니다.
아직 직접 테스트해 보지는 않았지만, 문서상으로는 정확히 빠져 있던 마지막 조각처럼 보입니다. 이제는 드래그가 시작될 때 UI를 업데이트하고, 드롭이 내 뷰 바깥에서 일어나더라도 세션이 끝날 때 안정적으로 정리할 수 있어야 합니다.
이것은 정확히 AppKit이 아주 오래전부터 할 수 있었던 종류의 일이므로, SwiftUI가 이 부분에서 더 가까워지는 모습을 보게 되어 반갑습니다.
그렇다고 해도 제 앱들은 보통 최신 두 개의 메이저 운영체제 버전을 지원하므로, 아마 저는 2년 뒤에나 이것을 본격적으로 만져 보기 시작할 것 같습니다.
또 하나 언급할 만한 것은 27 릴리스의 새로운 .reorderablemodifier입니다. 단지 순서 변경을 허용하려는 것이라면, 이것이 가야 할 방법일 것입니다.
이전에 언급했듯이, .onMoveCommand는 iOS에서 사용할 수 없습니다. 우회 방법은 macOS에서도 동작하는 .onKeyPress 같은 더 저수준의 추상화를 사용하는 것입니다.
이 방법도 동작은 하지만 완전히 같은 것은 아닙니다. .onMoveCommand가 의도를 다룬다는 점에서 더 적절한 API입니다. 저는 사용자가 아래쪽 화살표 키를 눌렀다는 사실 자체에는 큰 관심이 없습니다. 제가 중요하게 생각하는 것은 사용자가 아래로 이동하고 싶어 한다는 점입니다.
처음에는 .onMoveCommand를 iOS에서 사용할 수 없는 이유가 UIResponder에 대응하는 move* selector가 없기 때문이라고 생각했습니다. 그런데 곧 .onMoveCommand가 tvOS에서는 사용 가능하다 는 것을 알게 되었습니다.
그래서 저는 다시 이것이 단순한 API 가용성의 공백이라고 생각하게 되었습니다. tvOS에서 의미가 있다면, 하드웨어 키보드가 흔하고 화살표 키 탐색이 당연하게 기대되는 iPadOS에서는 더욱 분명히 의미가 있습니다.
이 문제에 대해서는 FB23095985를 등록했습니다. 이런 작은 플랫폼 차이들이야말로 크로스 플랫폼 UI 프레임워크의 약속을 약화시키는 정확한 요소입니다. 각각은 따로 보면 작지만, 실제 UI 코드를 공유하려고 하면 순식간에 크게 누적됩니다.
그 밖에 제가 언급했던 다른 문제들에 대해서는, 컨텍스트 메뉴가 현재 열려 있는지 알 수 없다는 점에 대해 FB23097100을 등록했고, 툴바 API의 사용성을 개선하자는 내용으로 FB23102836을 등록했습니다.
컨텍스트 메뉴 문제는 여전히 특히 답답하게 느껴집니다. 제대로 된 Mac 인터페이스를 만들려 하지 않는다면 사소해 보일 수 있는 종류의 문제입니다. iOS에서는 시스템이 상호작용에 관련된 항목을 시각적으로 들어 올려 보여줄 수 있습니다. macOS에서는 앱이 대상 자체를 표현할 수 있을 만큼 충분한 정보를 가져야 합니다.
툴바와 관련해서는, WWDC 27에서 어떤 항목이 오버플로 메뉴로 먼저 이동해야 하는지 관리하는 데 도움을 주는 새로운 .visibilityPrioritymodifier가 도입되었습니다. 이것이 제 문제를 실제로 해결해 주는 것은 아니지만, 언급은 해두는 편이 좋겠다고 생각했습니다.