스토리보드 파일 내의 충돌은 해결하기가 매우 복잡하니, 어떻게든 해결되겠지라는 생각은 버리고 최대한 충돌 자체가 안나게끔 예방을 해야 한다.
사실 그냥 code based로 협업하는게 제일 좋다. 🥹
1. 문제 상황
- 스토리보드를 통한 iOS 프로젝트
- '스토리보드를 통해 협업을 하면 충돌을 해결하기 복잡하다' 정도만 인지하고 협업을 시작했다.
- 충돌을 최대한 피하기 위해 서로 다른 view contorller를 작업하기로 한다.
- 나중에 알았지만, 하나의 스토리보드 파일에서 각자 다른 뷰컨트롤러 UI를 만지면 충돌을 해결하기 쉬울 거라고 착각했다.
- 상대방이 merge한 master 브랜치를 pull
- Main.storyboard 파일에서 conflict가 발생했다.
- xml 코드로 작성되어 있었고 스토리보드 상의 컴포넌트가 어떤 코드로 변환된 건지 알 수가 없어서 해결 불가능
2. 해결 방법
정 스토리보드로 작업하기로 했다면, 2가지 예방 조치를 해야한다.
.xcuserstate
파일은 스토리보드를 클릭만 해도(어쩌면 숨만 쉬어도) 수정되니, 미리 .gitignore
에 넣어 쓸데없는 commit을 줄인다.
스토리보드 레퍼런스(Storyboard Reference)
를 사용해 스토리보드 파일을 분리한다.
2.1. xcuserstate 파일 관리
UI 상태를 저장하는 이 파일은, 정말 자주 수정되기 때문에 아예 git이 추적하지 못하도록 하는 것이 좋다.
-
만약 이미 git에 올라간 상태라면 아래 명령어를 통해 지워준다.
git rm --cached [Project Name].xcworkspace/xcuserdata/[User Name].xcuserdatad/UserInterfaceState.xcuserstate
-
그리고 .gitignore
파일에 아래 파일을 추가해준다.
*.xcuserstate
2.2. Storyboard Reference 사용하기
Main.storyboard
파일을 분리해서, 하나의 뷰 컨트롤러 당 하나의 스토리보드 파일을 갖도록 한다.
즉, 협업 시 서로 작업하는 파일 자체가 달라지기 때문에 충돌 걱정을 할 필요가 없다. 나는 이 개념을 하나의 스토리보드 파일에서 각자 다른 뷰컨트롤러 UI를 만지면 될 거라고 착각했던 것이다.
➡️ 이렇게 분리된 스토리보드들은 storyboard references
를 통해 서로 연결된다.
여러 스토리보드 파일 사용시의 장점
스토리보드 파일을 분리했을 때의 장점은 apple 공식 문서에도 아래와 같이 나와있다.
- Improved readability (가독성 개선): 뷰 컨트롤러 연결이 더 명시적이게 되며, segue 연결을 추적하기가 더 쉬워진다.
- Reuse (재사용성): 뷰 컨트롤러 scene들이 앱의 여러 부분에서 references를 통해 연결하고 재사용할 수 있다.
- Easier to manage (관리 용이): 팀 협업시 각 멤버가 자신의 UI를 관리할 때 더 효율적으로 작업할 수 있게 된다. 즉, 스토리보드를 분할하면 Git과 같은 소스 코드 버전 관리 시스템을 사용할 때 병합 충돌을 피하는 데 도움이 된다.
스토리보드 연결 방법
Storyboard Reference 를 통해 두 스토리보드를 연결하는 방법은 자동과 수동 두 가지(공식 문서 튜토리얼 참고)가 있다.
내 경우에는 이미 작업된 뷰 컨트롤러가 많았기 때문에 xcode 상의 refactor 기능을 사용했으면 편했을텐데, 그걸 모르고 이미 스토리보드 파일을 만들어놔서 수동으로 VC를 분리해 연결하는 방법을 사용했다. 방법을 간략하게 요약하자면,
1) 새로 만들 스토리보드 파일을 이름은 main에서 분리할 뷰 컨트롤러 클래스 이름과 같게 설정했다.
- 스토리보드 파일 이름이 ViewController 클래스 이름과 동일하다면, 스토리보드 이름을 하드 코딩하는 것이 아니라 VC 클래스 이름을 얻어서 설정할 수 있다 !
2) Main.storyboard 에서 분리 할 ViewController를 복사한 뒤, 새로 생성한 파일에 붙여넣기 한다.
- 잘 복사 됐다면 이제 main에서는 과감히 지워주자 !
3) 새로 생성한 스토리보드의 Identity 인스펙터에서 Storyboard ID
를 설정한다.
- 이 ID를 통해 다른 스토리보드에서 이 뷰를 참조할 수 있게 된다.
4) Main.storyboard 파일에서, 스토리보드 레퍼런스를 생성한다.

- UI Library에서 드래그&드랍으로 생성한다.
- 이 스토리보드 레퍼런스가 우리가 참조할 스토리보드 파일의 뷰 컨트롤러가 된다고 생각하면 된다.
5) 생성한 Storyboard Reference 를 클릭한다. 인스펙터 설정에서 Storyboard
는 스토리보드 파일 명으로 적어주고, Referenced ID
는 이동할 스토리보드에서 설정한 스토리보드 ID로 설정한다.
설정을 잘 완료했다면, 스토리보드 레퍼런스가 아래처럼 귀여운 뷰 컨트롤러로 바뀌게 된다.

- segue 연결 등을 똑같다. 코드로 하던지, 스토리보드 상에서 하던지 말이다.
- 하나의 스토리보드 파일에는 하나의 뷰 컨트롤러만 존재하게끔 관리하면 된다.
3. 참고
스토리보드로 어떻게 협업하나 걱정만 했었는데 이런식으로 하는거군요 잘봤습니다!