macOS 27과 iPadOS 27에서 메뉴 항목 이미지가 사라집니다
이미지만 있고 제목이 없는 메뉴 항목은 macOS 27 SDK로 링크하면 macOS 27에서 아무것도 표시되지 않습니다. 이전 SDK에서는 Apple이 이 경우를 보호해 주며, 메뉴 항목의 제목과 속성 제목이 모두 비어 있으면 이미지를 자동으로 표시합니다.1 27로 다시 빌드하는 순간 그 보호는 더 이상 적용되지 않습니다.
macOS 27과 iPadOS 27은 대부분의 메뉴 항목 이미지를 기본적으로 숨기며, 무엇이 사라지는지는 어느 SDK로 링크했는지에 달려 있습니다. Apple은 그 결과를 “macOS 26.0 이전 동작과 비슷하다”고 설명합니다. 다시 말해 macOS 26이 메뉴 이미지를 폭넓게 도입했고, 27이 그 대부분을 거둬들이는 셈입니다.1
영향을 받는 프레임워크는 세 가지이고, 각각 해제 방법이 다릅니다. preferredImageVisibility를 검색해서 여기까지 왔는데 SwiftUI로 개발하고 있다면, 그 속성은 여러분에게 존재하지 않습니다.
요약
macOS 27은 macOS 26.0 이상으로 링크된 앱에서 메뉴 항목의 심볼 이미지를 기본적으로 숨깁니다. macOS 27 SDK로 링크된 앱은 심볼이 아닌 이미지까지 잃습니다.12 아이콘만 있는 메뉴 항목은 27 이전 SDK에서는 자동으로 보호되지만, 27로 다시 빌드하면 그 보호가 사라집니다.3 iPadOS 27은 메뉴 요소에 설정된 이미지를 기본적으로 숨깁니다.4 AppKit과 UIKit은 .automatic, .visible, .hidden 값을 갖는 preferredImageVisibility를 제공하고, SwiftUI는 대신 labelStyle(.titleAndIcon)을 사용합니다.5 설정, 공유, 프린트 항목은 시스템 전역에서 이미지를 유지하기 때문에, 일부 아이콘은 보이는 상태라 자기 앱의 이미지만 깨졌다고 결론 내리기 쉽습니다.
SDK별로 실제로 달라지는 것
AppKit의 이 동작은 세 개의 개별 릴리스 노트 항목으로 나뉘어 등장했고, 그중 둘은 수정 사항으로 분류되어 있습니다. 이 변경에 대한 요약들이 서로 어긋나는 이유가 여기에 있습니다.
| 링크 대상 | 심볼 이미지 | 심볼이 아닌 이미지 | 아이콘만 있는 항목 |
|---|---|---|---|
| macOS 26 이전 SDK | 영향 없음 | 영향 없음 | 영향 없음 |
| macOS 26.0 ~ 26.x | 숨김 | 표시 | 자동으로 표시 |
| macOS 27 SDK | 숨김 | 숨김 | 숨김 |
기준이 되는 항목은 NSMenu가 메뉴 항목의 모든 심볼 이미지를 기본적으로 숨기고 심볼이 아닌 이미지는 계속 표시하며, 이 변경이 macOS 26.0 이상으로 링크된 애플리케이션에 적용된다고 밝히고 있습니다.1
두 번째 항목은 숨김 범위를 넓힙니다. “macOS 27 SDK로 링크된 애플리케이션에서는 심볼 이미지와 심볼이 아닌 메뉴 항목 이미지가 모두 자동으로 숨겨집니다. 이전 SDK로 링크된 애플리케이션에서는 심볼이 아닌 이미지가 계속 자동으로 표시되어 기존 애플리케이션 동작과의 호환성이 유지됩니다.”2
세 번째 항목은 두 번 읽어볼 만합니다.3
“macOS 27 이전 SDK로 링크된 애플리케이션에서는, 메뉴 항목의 제목과 속성 제목이 모두 비어 있는 경우
NSMenu가 이제 메뉴 항목 이미지를 자동으로 표시합니다. 이미지가 메뉴 항목 내용을 나타내는 유일한 수단인 경우 기존 애플리케이션 동작을 그대로 유지하기 위한 조치입니다. macOS 27 SDK로 링크할 경우 이러한 이미지는 자동으로 숨겨지므로, 이런 설계를 사용하는 메뉴는preferredImageVisibilityAPI를 사용해 메뉴 항목 이미지가 계속 보이도록 해야 합니다.”
Apple은 아이콘만 있는 메뉴 항목을 위해 안전망을 만들어 놓고는, 그 안전망이 새 SDK까지 이어지지 않는다고 문서에 적어 둔 셈입니다. 내용 전체가 이미지인 메뉴 항목은 다시 빌드하고 나면 아무것도 없는 상태로 그려집니다. 소스 코드는 한 줄도 바뀌지 않았습니다. 방아쇠를 당기는 것은 컴파일 대상으로 삼은 SDK입니다.
아이콘만 있는 메뉴 항목은 생각보다 특이한 사례가 아닙니다. 서식 메뉴의 색상 견본처럼 견본 자체가 선택지인 경우가 그렇습니다. 각 항목을 아바타나 상태 기호로 구분하는 기기 선택기나 계정 선택기도 마찬가지입니다. 이미지만 있는 항목을 가로로 늘어놓아 만든 리액션이나 이모지 줄도, 파일 형식 아이콘을 보여주고 이름은 따로 렌더링하는 최근 문서 목록도 여기에 해당합니다. 이 모든 경우에 이미지는 레이블에 붙은 장식이 아니라 레이블 그 자체입니다.
그런 메뉴는 클릭에는 여전히 반응하지만 빈 줄만 늘어선 모양으로 무너집니다. 메뉴의 높이도, 구분선도, 클릭 영역도 그대로라서 자동화된 눈에는 렌더링 실패로 읽히지 않습니다. 메뉴에 항목이 여섯 개 있는지 검사하는 UI 테스트는 여전히 통과합니다. 스크린샷 비교는 이걸 잡아내지만, 항목 개수를 검사하는 단언은 잡아내지 못합니다.
이 변경들이 서로 닮은 지점은 조용함입니다. macOS 27은 묻지도 않고 팀 간 컨테이너 접근을 거부하기도 하는데, 여기서도 API는 멀쩡해 보이는 URL을 돌려주고 실패는 읽기 시점까지 기다립니다. 두 변경 모두 눈에 보이는 신호를 침묵으로 바꿔 놓고, 실제 원인과는 전혀 다른 모습으로 드러납니다.
세 프레임워크, 세 가지 해결책
| 프레임워크 | API | 값 |
|---|---|---|
| AppKit | NSMenuItem.preferredImageVisibility |
.automatic, .visible, .hidden |
| UIKit | UIMenuElement.preferredImageVisibility |
.automatic, .visible, .hidden |
| SwiftUI | labelStyle(.titleAndIcon) |
열거형이 아니라 레이블 스타일 |
AppKit과 UIKit은 형태가 같습니다. 두 속성 모두 .automatic, .visible, .hidden을 갖는 ImageVisibility 열거형을 받고, 둘 다 NSInteger 기반의 RawRepresentable이며, 둘 다 Sendable입니다.67
// AppKit
menuItem.preferredImageVisibility = .visible
// UIKit — also available on the updated initializers
// for UIMenu, UIAction, UICommand, and UIKeyCommand
let action = UIAction(title: "Export", image: exportImage) { _ in export() }
action.preferredImageVisibility = .visible
SwiftUI는 다른 길을 택했습니다. 릴리스 노트는 “메뉴 항목 Label의 아이콘을 항상 표시하도록 지정하려면 labelStyle(_:) 뷰 수정자에 .titleAndIcon 스타일을 사용하라”고 안내합니다.5
Menu("File") {
Button {
openDocument()
} label: {
Label("Open Document", systemImage: "doc")
}
.labelStyle(.titleAndIcon)
}
한 가지 더 짚어둘 점은, SwiftUI의 기본 동작이 27 SDK 동작이 아니라 AppKit의 기준선과 일치한다는 것입니다. 즉 심볼 이미지는 숨기고 심볼이 아닌 이미지는 그대로 표시합니다.5 위의 SDK 링크 표는 AppKit을 설명한 것입니다. 그대로 옮겨 적용된다고 가정하지 마세요.
적용 범위는 들리는 것보다 좁습니다
항목마다 표현이 다르므로 플랫폼 관련 문구를 꼼꼼히 읽어야 합니다.
UIKit 항목은 iPadOS 27.0과 macOS 27.0의 “메뉴 막대와 컨텍스트 메뉴”를 다룹니다.4 SwiftUI 항목은 더 구체적입니다. iPadOS 27.0과 macOS 27.0의 메뉴 막대, 그리고 “macOS 27.0의 컨텍스트 메뉴”라고 적고 있습니다.5 iPadOS의 SwiftUI 컨텍스트 메뉴는 언급되지 않습니다.
UIMenuElement.preferredImageVisibility는 iOS, iPadOS, Mac Catalyst, tvOS, visionOS 27.0에서 사용할 수 있습니다.7 어떤 플랫폼에 API가 제공된다고 해서 그곳에서 숨김 동작이 활성화되어 있다는 뜻은 아닙니다. Apple의 릴리스 노트는 iPadOS와 macOS에 대해서만 그 동작을 설명합니다. tvOS와 visionOS는 확인된 것이 아니라 언급이 없는 상태로 취급하세요.
Interface Builder 쪽 사각지대
코드로는 대응할 수 없는 항목이 하나 있습니다. xib 파일에서 만들어진 메뉴 항목의 경우, NSMenu는 메뉴 항목 인스펙터의 “macOS 26.0 only” 체크박스를 참조합니다. 체크를 해제하면 이미지가 계속 보이고, 체크하면 숨겨집니다.1
이제 Interface Builder의 속성 하나가 런타임의 이미지 표시 여부를 바꿉니다. 메뉴가 xib에서 나온다면 이 점검은 코드 검색으로 끝나지 않습니다. 누군가 인스펙터를 직접 열어봐야 합니다.
일부 아이콘이 살아남는 이유
AppKit과 UIKit은 설정, 공유, 프린트처럼 시스템 전역에서 흔히 쓰이는 메뉴 항목에 대해서는 기본 이미지를 계속 표시합니다.14 SwiftUI도 마찬가지입니다.5
실제로는 진단을 헷갈리게 만드는 효과가 있습니다. 업데이트하고 메뉴를 열면 설정과 공유 옆에는 아이콘이 있는데 내가 만든 항목 옆에는 없습니다. 그러면 이미지 로드에 실패했거나, 에셋 카탈로그가 망가졌거나, 심볼 이름이 틀렸다고 생각하는 게 자연스럽습니다. 그중 어느 것도 사실이 아닙니다. 시스템이 잘 알려진 소수의 항목만 예외로 두는 정책을 적용하고 있을 뿐입니다.
어떤 아이콘을 남길지 판단하기
다섯 개 릴리스 노트 항목 모두 어떤 메뉴 항목에 이미지를 계속 표시할지 판단하려면 갱신된 Human Interface Guidelines를 확인하라고 권합니다.145 그 지침의 내용은 제가 확인하지 못했습니다. HIG 메뉴 페이지는 클라이언트 측에서 렌더링되어 가져오기 도구에는 텍스트가 거의 반환되지 않고, API 레퍼런스와 달리 HIG 콘텐츠에는 JSON 엔드포인트가 없습니다. 요약본의 말을 믿지 말고 직접 확인하세요. 이 글도 요약본입니다.
릴리스 노트 자체에 담긴 구체적인 판단 기준은 SwiftUI 항목에서 나옵니다. 메뉴 항목이 “동작이 아니라 객체나 개념을 나타낼 때” 아이콘을 표시하라는 제안입니다.5
이 기준은 쓸 만합니다. 열려 있는 문서, 사용 가능한 기기, 저장된 필터를 나열하는 메뉴는 객체에 이름을 붙이는 일이고, 여기서 아이콘은 정체성을 전달합니다. 반면 동사로 이루어진 메뉴는, 사실 대부분의 메뉴가 그런데, 모든 항목 옆에 아이콘이 있다고 해서 얻는 게 많지 않습니다. Apple은 macOS 26이 이미지를 과하게 적용했다고 판단한 듯하고, 27은 그에 대한 교정으로 보입니다.
27 SDK로 출시하기 전에 할 일
아이콘만 있는 메뉴 항목부터 찾으세요. 이미지가 내용 전체이기 때문에 가장 심하게 망가지는 쪽입니다. 이미지가 있고 제목이 비어 있는 NSMenuItem, 그리고 같은 방식으로 만든 모든 UIMenu 요소에는 .visible을 명시적으로 지정해야 합니다.
전역이 아니라 항목별로 결정하세요. 모든 곳에 .visible을 지정하는 것은 의도적인 플랫폼 변경을 되돌려 macOS 26 시절로 돌아가는 일입니다. 일괄 재정의보다는 객체 대 동작 기준이 더 나은 필터입니다.
xib는 따로 훑으세요. “macOS 26.0 only” 체크박스는 속성 대입처럼 grep으로 잡히지 않으면서 동작을 바꿉니다.
두 SDK 세대를 모두 지원한다면 양쪽에서 테스트하세요. 동일한 소스인데도 26으로 빌드한 결과와 27로 빌드한 결과가 다르게 그려집니다. 그러면 스크린샷과 UI 테스트가 전에 없던 방식으로 SDK에 의존하게 됩니다.
SDK 링크가 동작을 결정하는 구조는 이번 릴리스에서 반복되는 형태가 되어가고 있습니다. iOS 27의 canOpenURL 지원 중단도 같은 축을 중심으로 돌아가며, 실질적인 교훈도 똑같습니다. 사용자가 무엇을 보게 될지는 소스가 아니라 컴파일 시점의 선택이 결정합니다.
릴리스 노트가 또 바뀔 것을 염두에 두세요. AppKit 항목 세 개 중 둘이 수정 사항으로 분류되어 있다는 것은 베타 주기 동안 동작이 이미 한 번 바뀌었다는 뜻입니다. 저는 2026년 8월 1일에 Beta 4 노트를 기준으로 다섯 항목을 모두 다시 확인했고, 여기 인용한 그대로였습니다. 이 중 무엇이든 실행에 옮기기 전에 최신 노트와 대조해 보세요.
기존 코드베이스 점검하기
이 변경은 체계적으로 점검할 수 있을 만큼 기계적이고, 테스터가 빈 메뉴를 신고한 뒤가 아니라 다시 빌드하기 전에 해 두는 편이 낫습니다.
가장 심각한 경우부터 시작하세요. 제목이 비어 있는 상태로 이미지를 가진 NSMenuItem은, 메뉴를 밋밋하게 만드는 정도가 아니라 눈에 띄게 망가뜨리는 유일한 실패 유형입니다. 코드에서는 대응하는 제목 없이 이미지만 대입하는 부분을 찾아보세요.
# Menu items constructed with an image and no title argument
rg 'NSMenuItem\(' --type swift -A3 | rg -B1 'image ='
rg 'setImage|\.image\s*=' --type swift | rg -i 'menu'
두 패턴 모두 완전하지는 않습니다. 제목은 세 줄 아래에서 설정될 수도 있고 지역화 테이블에서 읽어올 수도 있기 때문입니다. 결과는 확정된 발견이 아니라 살펴볼 후보 목록으로 다루세요.
그다음은 xib입니다. “macOS 26.0 only” 체크박스에는 grep이 통하지 않습니다. 빌드가 볼 수 있는 어떤 속성이 아니라 메뉴 항목 인스펙터 안에 들어 있기 때문입니다. 메뉴가 Interface Builder에서 나온다면, 점검이란 곧 메뉴를 하나씩 열어 항목을 하나씩 확인하는 일입니다.
그다음은 UIKit 메뉴 생성 코드입니다. UIMenu, UIAction, UICommand, UIKeyCommand 모두 preferredImageVisibility를 받는 이니셜라이저가 추가되었으므로, 나중에 따로 대입하지 않고 생성 시점에 바로 해결할 수 있습니다.4
그다음은 메뉴 안에서 쓰이는 SwiftUI Label입니다. 이쪽이 가장 놓치기 쉽습니다. 메뉴 안의 Label은 소스만 보면 다른 곳의 Label과 똑같이 생겼기 때문입니다. 수정자는 레이블에 붙이되, 아이콘을 남기고 싶은 곳에만 붙입니다.
두 번 빌드해서 비교하세요. 가장 확실한 확인 방법에는 코드를 읽는 일이 아예 들어가지 않습니다. 26 SDK와 27 SDK로 각각 빌드해 같은 메뉴를 열고 양쪽을 찍어 두세요. 동일한 소스가 서로 다른 메뉴를 만들어 낸다는 것이 이번 변경의 핵심이고, 나란히 놓고 보면 grep으로는 못 찾을 것들이 드러납니다.
이 마지막 단계는 스크린샷도 함께 지켜줍니다. 메뉴가 담긴 마케팅 이미지, 문서, App Store 자료는 누군가 찍던 시점에 최신이던 SDK 아래에서 캡처된 것입니다. 출시 빌드가 더 이상 그리지 않는 아이콘이 거기 남아 있다면 이제 그 자료들은 틀린 것이고, 빌드 과정의 어떤 단계도 그 사실을 알려주지 않습니다.
핵심 정리
AppKit 개발자라면:
- macOS 27 SDK로 링크하면 심볼뿐 아니라 심볼이 아닌 이미지도 숨겨집니다. SF Symbols만 점검하면 절반을 놓칩니다.
- 아이콘만 있는 메뉴 항목은 27 SDK에서 자동 보호를 잃고 빈 상태로 그려집니다. 항목마다 preferredImageVisibility = .visible을 지정하세요.
- xib에 정의된 메뉴에는 “macOS 26.0 only” 체크박스가 있고, 이것이 어떤 코드 경로와도 무관하게 표시 여부를 바꿉니다.
UIKit 개발자라면:
- preferredImageVisibility는 UIMenuElement에 있고, UIMenu, UIAction, UICommand, UIKeyCommand의 갱신된 이니셜라이저에도 있습니다.
- 이 속성은 tvOS와 visionOS에도 존재하지만, Apple이 동작을 문서화한 것은 iPadOS와 macOS입니다. 가정하기 전에 확인하세요.
SwiftUI 개발자라면:
- preferredImageVisibility는 여러분이 쓸 API가 아닙니다. Label에 labelStyle(.titleAndIcon)을 사용하세요.
- SwiftUI의 기본 동작은 심볼 이미지를 숨기고 심볼이 아닌 이미지는 유지하는 것으로, 27 SDK 동작이 아니라 AppKit 기준선과 일치합니다.
자주 묻는 질문
설정과 공유에는 왜 여전히 아이콘이 보이나요?
시스템이 흔히 쓰이는 일부 메뉴 항목을 예외로 두기 때문입니다. AppKit, UIKit, SwiftUI 모두 설정, 공유, 프린트 같은 항목에는 기본 이미지를 계속 표시합니다.145 자기 항목은 숨겨졌는데 그 아이콘들만 보이는 것은 예상된 동작이며, 로드 실패가 아닙니다.
이전 SDK에 머무르면 이 문제를 피할 수 있나요?
일부는 피할 수 있고, 그 구분이 중요합니다. macOS 26.0 이상으로 링크된 앱은 이미 심볼 이미지를 숨기고 있습니다.1 macOS 27 SDK 아래에 머무르면 심볼이 아닌 이미지의 표시 상태가 유지되고, 아이콘만 있는 항목에 대한 자동 보호도 남습니다.23 하지만 심볼 이미지가 되살아나지는 않습니다.
이미지만 있고 제목이 없는 메뉴 항목은 어떻게 되나요?
macOS 27 이전 SDK에서는 제목과 속성 제목이 모두 비어 있기 때문에 NSMenu가 이미지를 자동으로 표시합니다.3 macOS 27 SDK에서는 그 보호가 적용되지 않아 이미지가 숨겨지고, 보이는 내용이 하나도 없는 메뉴 항목만 남습니다. preferredImageVisibility = .visible을 지정하세요.
tvOS와 visionOS에서도 똑같나요?
UIMenuElement.preferredImageVisibility는 양쪽 모두 27.0에서 사용할 수 있습니다.7 릴리스 노트 항목들이 숨김 동작을 설명하는 대상은 iPadOS와 macOS입니다. 어떤 플랫폼에 API가 존재한다는 사실이 그곳에서 그 동작이 활성화되어 있다는 확인은 아닙니다.
어떤 아이콘을 남겨야 하나요?
릴리스 노트는 Human Interface Guidelines를 가리키는데, 저는 그 내용을 직접 읽지 못했습니다. Apple이 SwiftUI 항목에서 밝힌 판단 기준은 메뉴 항목이 “동작이 아니라 객체나 개념을 나타낼 때” 아이콘을 표시하라는 것입니다.5
출처
-
Apple, “macOS 27 Golden Gate Beta 4 Release Notes,” AppKit. Radar 170477566:
NSMenu가 메뉴 항목의 모든 심볼 이미지를 기본적으로 숨기고 심볼이 아닌 이미지는 계속 표시함, macOS 26.0 이상으로 링크된 애플리케이션에 적용됨, xib의 “macOS 26.0 only” 체크박스 동작,preferredImageVisibility속성, 설정·공유·프린트에 대한 기본 표시 이미지. 기계 판독용 사본은developer.apple.com/tutorials/data/documentation/macos-release-notes/macos-27-release-notes.json. 2026년 8월 1일 재확인. ↩↩↩↩↩↩↩↩↩ -
Apple, macOS 27 Golden Gate Beta 4 Release Notes, AppKit, Resolved Issues. Radar 179374305 (FB23070183): “macOS 27 SDK로 링크된 애플리케이션에서는 심볼 이미지와 심볼이 아닌 메뉴 항목 이미지가 모두 자동으로 숨겨집니다. 이전 SDK로 링크된 애플리케이션에서는 심볼이 아닌 이미지가 계속 자동으로 표시되어 기존 애플리케이션 동작과의 호환성이 유지됩니다.” ↩↩↩
-
Apple, macOS 27 Golden Gate Beta 4 Release Notes, AppKit, Resolved Issues. Radar 179936632: 27 이전 SDK에서 제목과 속성 제목이 모두 비어 있는 메뉴 항목의 이미지를 자동으로 표시하는 동작, 그리고 macOS 27 SDK로 링크할 때 그 동작이 사라지는 것에 관한 내용. ↩↩↩↩
-
Apple, “iOS & iPadOS 27 Beta 4 Release Notes,” UIKit. Radar 170479084: iPadOS 27.0과 macOS 27.0의 메뉴 막대와 컨텍스트 메뉴가 메뉴 요소에 설정된 이미지를 기본적으로 표시하지 않음,
UIMenuElement의preferredImageVisibility및UIMenu,UIAction,UICommand,UIKeyCommand의 갱신된 이니셜라이저. 같은 Radar가 macOS 27 노트에도 등장합니다. ↩↩↩↩↩↩ -
Apple, iOS & iPadOS 27 Beta 4 Release Notes, SwiftUI. Radar 170480710: SwiftUI가 대부분의 맥락에서 메뉴 항목의 모든 심볼 이미지를 기본적으로 숨기고 심볼이 아닌 이미지는 계속 표시함,
.titleAndIcon과 함께 쓰는labelStyle(_:), 메뉴 항목이 “동작이 아니라 객체나 개념을 나타낼 때” 아이콘을 표시하라는 지침, 일반적인 시스템 항목에 대한 기본 표시 이미지. ↩↩↩↩↩↩↩↩↩ -
Apple, “NSMenuItem.preferredImageVisibility” 및 “NSMenuItem.ImageVisibility.” 케이스
.automatic,.visible,.hidden,NSInteger기반RawRepresentable, macOS 27.0부터 사용 가능. ↩ -
Apple, “UIMenuElement.preferredImageVisibility” 및 “UIMenuElement.ImageVisibility.” 케이스
.automatic,.visible,.hidden, iOS 27.0, iPadOS 27.0, Mac Catalyst 27.0, tvOS 27.0, visionOS 27.0에서 사용 가능. ↩↩↩