서론
Xcode 15.1 Beta에서 IBDesignable이 Deprecated 되었습니다.
Xcode 15부터 생긴 #Preview 매크로를 적극 권장하기 위한 처리가 아닐까 생각이 들어서 이번 기회에 #Preview를 사용해 보기로 했습니다.
막상 사용해 보니 생각보다 더 편하고 유용해서 이렇게 포스팅까지 하게 되었네요.
특히 무선 Preview가 상상 이상이라 놀라웠습니다.
하나하나 천천히 살펴봅시다!
Preview 관련 WWDC를 다룬 포스팅도 봐주시면 감사하겠습니다 ㅎㅎ
#Preview
#Preview를 사용하는 방법은 정말 간단합니다.
#Preview {
보고 싶은 뷰
}
위 코드만 소스 파일 최상위에 적어주면 됩니다.
그럼 Xcode 화면이 분리돼서 Preview가 보입니다.
Xcode가 가로로 넓으면 좌우로, 세로로 길면 상하로 배치되네요.
#Preview는 매크로 중 하나로 Preview의 생성자를 포함하고 있습니다.
externalMacro로 생성이 되는데 내부적으로 어떤 코드가 수행되는지는 확인할 수 없었어요 :(
Preview 공식문서를 통해 Preview는 구조체로 되어 있고,
Preview 생성자를 직접 호출하면 안 된다는 건 알 수 있었습니다.
또한, 생각보다 많은 생성자가 존재했습니다.
특히 눈에 띄는 건 camera를 파라미터로 받는 생성자들이었는데요.
아직 Beta 생성자라 정확히는 모르겠습니다만, 나중에는 카메라 프리뷰도 Xcode를 통해 볼 수 있지 않을까 싶네요.
참고로 PreviewCamera는 #Preview에서 3D 장면을 보고 싶을 때 전달하는 구조체라고 하네요.
Preview 표시하기
#Preview에 대해 어느 정도 알았으니 직접 사용해 봅시다.
코드 베이스 UI
먼저 코드 베이스로 레이아웃을 잡은 ViewController부터 볼게요.
label 하나를 중간에 배치했습니다.
#Preview {
ViewController()
}
소스파일 최상위에 #Preview 코드를 작성해 주면
이렇게 Preview 화면이 나옵니다.
Preview가 나오는 속도를 보여드리고 싶어서 영상 첨부로 해봤어요 ㅎㅎ
꽤 빠르지 않나요?
이제 Label의 텍스트를 바꿔보겠습니다.
실시간으로 바뀌긴 하는데 "즉시"라고 하기엔 애매한 속도인 거 같아요.
특히 코드 작업을 멈췄다가 다시 할 때 텀이 길다고 느껴졌습니다.
Preview 안에서 뷰를 바꿔도 동작하는지 살펴볼까요?
func update(text: String) {
self.label.text = text
}
ViewController 안에 label의 텍스트를 업데이트하는 메서드를 추가했습니다.
#Preview {
let vc = ViewController()
vc.update(text: "안녕하세요")
return vc
}
Preview 안에서 update를 호출해서 label을 업데이트해 보겠습니다.
이번엔 빠른 속도로 바뀌네요!
ViewController 안의 View를 직접 수정할 때보다 Preview 안에서 메서드로 수정하는 게 체감이 될 정도로 빨랐습니다.
(뇌피셜이지만) WWDC에서 말한 것처럼 최소한의 범위만 컴파일을 하기 때문에 ViewController 안의 view를 다시 컴파일하는 것보다 text만 변경하는 게 가벼워서 Preview 속도도 빨라진 거 같아요.
스토리보드 사용
다음은 스토리보드를 사용한 ViewController의 Preview 표시입니다.
결론부터 말하면 스토리보드와 Preview는 잘 어울리지 않았습니다 ㅠㅠ
코드 베이스와 마찬가지로 Label을 하나 넣고, IBOutlet으로 연결해 줬어요.
#Preview {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")
return vc
}
Preview에서 ViewController를 생성해서 반환해 주는 것으로 Preview를 띄워줬습니다.
스토리보드를 수정하고, Preview에 갱신이 되는지 확인해 보겠습니다.
되긴 하는데 많이 느린 모습입니다.
스토리보드의 수정 범위만 가져오는 게 아니라 전체를 다시 가져와서 느린 걸까요?
(Preview 내부에서 어떻게 동작하는지 몰라서 살짝 답답하네요 ㅎㅎ;)
이번에도 update(text:)를 이용해 label의 텍스트를 변경해 봅시다.
ViewController의 update(text:)를 호출하기 위해 타입 캐스팅을 해줬는데요...
Preview가 죽어버리네요.
스토리보드랑 Preview는 같이 쓰지 말라는 거구나... 확 느껴졌습니다.
하지 말라는 건 안 하는 거로 ㅎㅎ;;
XIB
XIB도 스토리보드처럼 충돌이 있을지 궁금해서 시도해 봤습니다.
저는 보통 CollectionViewCell을 만들 때 XIB를 사용해서 이번 예제도 Cell을 준비했어요.
#Preview {
let dish = Dish(title: "테스트", description: "테스트 인스턴스", normalPrice: "100", salePrice: "200", badges: ["Test"])
let cell = DishListCollectionViewCell.loadNib()
cell.configure(dish: dish)
return cell
}
Cell을 만들고, 테스트 인스턴스로 UI를 확인해 봤습니다.
걱정과는 달리 표시도 잘 되고, 빠르게 업데이트되는 모습을 볼 수 있었습니다. (휴..)
#Preview의 다양한 기능
지금까지 Preview 표시를 알아봤습니다.
Xcode의 Preview 패널에는 다양한 기능이 존재합니다.
1. Pin 기능
2. Preview 모드 설정
3. 디바이스 설정
4. Preview 종류 설정
오른쪽 아래는 확대, 축소 기능이라 너무 뻔해서 따로 다루진 않을게요.
1. Pin 기능
먼저 Pin 기능입니다.
Pin 기능은 #Preview가 적혀 있는 파일을 나가도 Preview 화면이 유지되는 기능입니다.
만약 #Preview 안에서 여러 파일의 UI를 확인한다면 파일을 이곳저곳 돌아다녀도 Preview를 확인할 수 있습니다.
2. Preview 모드 설정
Preview는 동적 모드, 정적 모드가 있습니다.
동적 모드는 실제 앱 구동 화면처럼 UI를 표시하고 터치 이벤트에 반응하는 모드입니다.
그래서 스크롤에 따라 뷰가 바뀌는 걸 확인하는 등의 상황에서 유용하게 쓰입니다.
정적모드는 첫 프레임에서 UI를 디버깅하는 모드입니다.
정적 모드로 바꾸면 첫 프레임으로 고정이 되고 스크롤 같은 이벤트가 무시됩니다.
정적 모드에서 각 View를 누르면 어떤 View인지 코드에 표시됩니다.
지금처럼 ViewController를 반환하면 하나의 View로 처리되기 때문에 무의미하지만,
WWDC 영상에서 시연했던 것처럼 SwiftUI에서는 매우 유용해 보였습니다.
UIKit에서는 어떻게 활용할 수 있을지 잘 모르겠네요.
이렇게 스켈레톤뷰 확인하기에는 유용했습니다 ㅋㅋ
Preview 모드의 세 번째 버튼은 여러 프리뷰를 한 번에 볼 수 있는 기능입니다.
라이트 모드, 다크 모드를 한 번에 확인하거나,
지원하는 화면 방향을 한 번에 모두 확인하거나,
글꼴 같은 동적 타입을 한 번에 확인할 수 있습니다.
이건 Coloe cheme Variants로 설정한 모습니다.
라이트 모드와 다크 모드 프리뷰가 모두 나옵니다.
Orientation Variants는 화면 방향의 모든 preview가 표시되고,
Dynamic Type Variants를 선택하면 모든 동적 타입 UI를 확인할 수 있습니다.
위 그림은 제가 동적 타입 처리를 안 해줘서... 다 똑같이 보이는 거랍니다 ㅎㅎ;;
이 여러 프리뷰를 동시에 확인하는 게 정말 유용하다고 느껴졌습니다.
3. 디바이스 설정
디바이스 설정은 Preview에 떠있는 디바이스의 설정을 조절할 수 있습니다.
컬러 스킴, 방향을 설정할 수 있습니다.
여러 프리뷰를 한 번에 볼 때는 정적 모드만 가능하기 때문에 동적 모드는 확인할 수 없었습니다.
디바이스 설정을 이용하면 동적 모드도 편하게 미리 볼 수 있어요.
4. Preview 종류 설정
마지막은 Preview 종류 설정입니다.
어떤 기기로 Preview를 보여줄지 선택할 수 있습니다.
인상 깊었던 건 아이폰은 다이나믹 아일랜드, 터치 ID 유무를 표시해 주고, 아이패드는 인치를 표시해 주는 점입니다.
아이폰의 하드웨어 스펙을 외우지 않아도 된다는 점이 좋더라고요.
More을 누르면 더 많은 기기로 Preview를 볼 수 있습니다.
실제기기 Preview
#Preview는 실기기 미리 보기도 지원합니다!
디바이스 설정의 Devices 섹션 아이템이 실제 기기인데요.
여기에서 하나를 고르면 그 기기에서 Preview를 볼 수 있습니다. (프로젝트 팀 설정이 필요합니다.)
이게 정말 대박이었어요.
딜레이가 얼마나 발생하는지 보여드리고 싶어서 이것도 영상으로 준비했습니다.
이건 코드 변경 영상이고요,
이건 위 영상과 동시에 촬영한 아이폰 화면입니다.
두 개 동시에 재생하시면 얼마나 빠르게 업데이트가 되는지 확인할 수 있습니다.
Xcode에서 띄워주는 Preview보다 딜레이가 적은 거 같아요.
또 하나 정말 놀란 건 무선 Preview였어요.
엄청 느리겠지 생각했는데 상상 이상으로 빨랐습니다.
무선으로 Preview를 띄우고 코드를 바꾸는 영상입니다.
유선과 큰 차이가 안 느껴질 정도로 빠르지 않나요?
이건 정말 편하고 유용하게 쓰일 거 같네요.
마무리
서론에 적은 WWDC에서 소개된 대로 소스 코드가 수정되면 최소한의 범위가 컴파일되고 Preview가 업데이트됩니다.
컴파일 과정과 뷰를 다시 그리는 과정이 들어가서 "즉시"라고 하기엔 애매했지만, 충분히 빠른 모습을 볼 수 있었어요.
특히 무선 프리뷰는 많이 놀랐을 정도로 빨랐습니다.
무선 빌드는 느려서 답답할 정도인데 무선 프리뷰는 그래도 많이 쓸 수 있을 거 같아요!
#Preview... 당연히 느려서 답답할 줄 알았는데 생각보다 선방해서 좋았습니다.
혹시 머뭇거리고 계시다면 한 번 도전해 보세요!
(맥북 에어에서는 발열이 심할지도...)
감사합니다.
출처
https://developer.apple.com/documentation/developertoolssupport/preview/
https://developer.apple.com/documentation/xcode-release-notes/xcode-15_1-release-notes
https://developer.apple.com/wwdc23/10252
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.