[Xcode] workspace란 무엇인가

workspace에 대해 알아보고 만들어봅시다. 그런데 약간의 혼란을 곁들인,,

naljin
15 min readNov 27, 2021

들어가기 전에

개-하! 오랜만이에여..!! 오늘은 workspace 에 대해 알아보러 왔습니다. 왜냐면 제가 아무것도 모른다는 걸 깨달았기 때문 ㅋ

나 : workspace 는.. pod install 등으로 라이브러리 설치하면 생기는..거요..? ㅎ

ㅎㅎ 어..느정도 맞는 말이기도 하지만 그게 다가 아니기 때문에 더 알아보러 길을 떠나봅시다 흑흑

workspace 란

  • workspace는 프로젝트 및 기타 문서를 그룹화하여 함께 작업할 수 있는 Xcode document입니다
  • workspace 에 원하는 수의 Xcode 프로젝트 및 다른 파일들을 포함할 수 있습니다
  • 각 Xcode 프로젝트의 파일을 구성하는 것 외에도 workspace는 포함된 프로젝트와 target 간의 암시적(implicit) 및 명시적(explicit) 관계를 제공합니다.

아니 그러니까,, 한개의 프로젝트가 아닌 여러개의 프로젝트를 한군데 모아 작업하고 싶으면 workspace 를 이용해라! 이거군요..? (사실 예전 어디선가 본거 같은데 잘 기억 안남. 또 까먹은 듯 ㅎ)

workspace를 한글로 직역하면 작업 공간인데,, 지금보니 이름을 꽤나 잘지었다? 싶기도 하고,,

제가 처음에 workspace를 “나 : pod install 등으로 라이브러리 설치하면 생기는..거요..?” 라고 했잖아여? 라이브러리를 설치한다는건 다른 사람이 작업해놓은 프로젝트를 내 프로젝트에서도 쓸 수 있게 가져온다는거고, 이는 둘 이상의 프로젝트를 모아 한 군데서 작업하는 상황이 되니 workspace 에서 작업을 해야했던거네염.

그럼 pod install 은 workspace 를 자동으로 생성하고 추가로 필요한 프로젝트를 모아모아 workspace에 넣어주는 작업을 하는건가봐여? CocoaPods 가이드 문서를 가보죠.

프로젝트에 대한 dependency 들은 Podfile에 저장됩니다. 코코아팟은 라이브러리 간의 의존성을 해결하고, 결과 소스 코드를 가져온 다음, 프로젝트를 빌드하기 위해 Xcode workspace에 함께 link 합니다.

흠 대충 맞는듯여?? (아님 알려주세욤)

👉🏻 알려주신 Boram Jeong님 압도적 감사를 드리며,, 잠깐 “cocoapods에서 pod install 하면 벌어지는 일” 을 짚고 가봅시다. 저는 각각의 라이브러리에 해당하는 xcodeproj 를 받아서 workspace 에 집어 넣는건가??했는데 그게 아니었구요?

cocoapods에서 pod install 하면 벌어지는 일

  1. Pods.xcodeproj 생성 (Pods 도 프로젝트!!!)
  2. Podfile에 명시된 모든 소스를 다운로드를 받아서 Pods.xcodeproj 에 각각의 폴더로 넣음
Pods.xcodeproj

3. 라이브러리가 들어가있는 Pods.xcodeproj 이랑 원래 내 프로젝트 (EmojiCommit.xcodeproj)랑 같이 묶어서 workspace로 만듦

내 로컬에 프레임워크 소스가 다 다운로드 되어 있기 때문에 수정도 가능함

cocoapod이 빌드가 느리다는 이유가 Project Clean하면 저 Pods.xcodeproj도 다 Clean되어서, 빌드 시 Pods.xcodeproj 도 다시 빌드되야하기 때문

근데 그 와중에 “흠,, 근데 SPM은 xcodeproj만으로도 작업할 수 있잖아?? 라이브러리 쓰려면 이런 식으로 workspace를 이용해야하는게 필수가 아니란 말이여,,??”라는 생각이 들었는데요! 또 짱보람님께서 도움을 주셨습니다.

spm 은 github 주소로 해서 프레임워크를 추가하면 다운로드 받는 작업 같은게 진행이 됩니다. 다운로드 받는 경로는 내 앱 폴더 내가 아닌 다른 path 로 다운이 진행되는데, 이렇게 받은 프레임워크 소스를 단순히 읽기만 가능하도록 링크 한거라 생각하면 돼요. 그냥 소스 보여주기 위한 미리보기? 같은거라고 해야하나..

흠냐리 SPM 으로 다운 받은거는 여기 Package Dependencies 부분에 표시가 되잖아요??

그렇다면 이 소스는 어디에 있을까요? Show in Finder 를 클릭해봅시다

오호 여깄었구나 ㅎㅇㅎㅇ

풀 경로를 찍어보면 /Users/kangsujin/Library/Developer/Xcode/DerivedData/EmojiCommit-gzqcsqsqauilaqckmmlxjdpopzkj/SourcePackages/checkouts 요렇게 나오네요. DerivedData 에서 타겟내의 SourcePackages 하위에 있단 말이쥐,,,

그렇다면 빌드한 결과물은 어디에 있을까요? 바로바로 라이브러리와 연결된 타겟의 Products 폴더 내에 있다고 합니다.

??? 여기가 대체 어디라고??

ㅇㅋㅇㅋ 전체 경로를 다시 찍어 볼게요. /Users/kangsujin/Library/Developer/Xcode/DerivedData/EmojiCommit-gzqcsqsqauilaqckmmlxjdpopzkj/Build/Products/Debug-iphonesimulator

여기에 만들어진 .o 파일이 SwiftPM으로 빌드된 결과물으로, 이게 앱 바이너리에 들어간다고 하네요 (출처 — 민소네님 블로그)

이야기가 새긴 했는데, 어쨌거나 workspace를 통해 Xcode에서 작업의 범위를 확장할 수 있습니다. 왜냐면 워크스페이스는 각 Xcode 프로젝트의 파일에 대한 액세스를 제공하기 때문에, 하나의 프로젝트는 workspace에 있는 다른 프로젝트의 기능을 마구마구 사용할 수 있으니까요!

인덱싱 또한 전체 workspace에서 수행되기 때문에 코드 완성, Jump to Definition 및 기타 모든 콘텐츠 인식 기능은 workspace의 모든 프로젝트에서 원활하게 작동합니다. 리팩토링 작업도 workspace의 모든 콘텐츠에 대해 작동합니다.

이렇게 각 Xcode 프로젝트가 서로의 파일에 접근할 수 있는 이유는 기본적으로 workspace의 모든 Xcode 프로젝트는 workspace build directory 라고 하는 동일한 디렉토리에 빌드되기 때문입니다.

마지막으로 프로젝트는 둘 이상의 workspace에 속할 수 있습니다.

이제 슬슬 워크스페이스를 만들어서 직접 확인을 해볼때가 됐져??? 만들러 가봅시다 ㄱㄱ

workspace 만들기

Xcode에서 File > New > Workspace 를 클릭합니다. (혹은 control + command + N)

그리고 이름을 저장해주면?

지정된 위치에 덩그러니 생겨있는데

열어보면 당황스러울 정도로 아무것도 없어요

여기에 이제 내가 원하는 프로젝트들을 넣어줄건데 일단 저는 MainProject.xcodeproj 를 생성 후 드래그 & 드롭으로 워크스페이스에 넣어주겠습니다

그러면 잘 들어갔네여 ㅎㅇㅎㅇ

여기서 SubProject.xcodeproj 라는 프로젝트를 한개 더 생성해서 워크스페이스에 넣어줄겁니다. 해당 프로젝트에는 postfixNaljin() 이라는 String extension 함수를 추가해줬어요

extension String {
func postfixNaljin() -> String {
return self + "naljin"
}
}

SubProject 프로젝트도 똑같이 드래그 & 드롭으로 추가해줬는데, 이때 프로젝트의 depth 는 MainProject 의 depth 와 같아야합니다

요렇게 어떤 프로젝트들이 추가되어있는지는 워크스페이스를 열어서 확인할 수도 있고, .xcworkpace 우클릭 👉🏻 패키지 내용 보기 👉🏻 contents.xcworkspacedata 에서 확인할 수도 있습니다

그리고 MainProject에서 SubProject에 정의된 postfixNaljin 함수를 사용하려고하면?

ㅋ 어림도 없지 ㅋ 에러가 납니다

엥?? 이렇게 하라는거 아니었어요? ㅎ 아아 import 를 안했군요

기껏 import 를 해줬는데 이번에는 No such module 에러가 납니다 ㅋㅋ

ㅋ 약 한시간 넘게 삽질 결과 import 하려는 모듈이 한번은 빌드가 되어야 정상적으로 import 된다는 걸 발견했습니다 ㅎ 이럴때마다 엑코 미친건가 싶기도하고,, 그냥 저렇게만 에러를 때리면 내가 어떻게 안단 말이야 ㅋㅋ,,

위처럼 타겟을 SubProject로 바꿔서 한번 빌드한 다음에 MainProject로 돌아와 import 를 했더니 잘 뜹니다ㅋ,,

하지만 성공은 어림없지! 접근 제어 관련해서 에러가 뜨고요?

아아 ㅇㅋㅇㅋ SubProject 에서 해당 함수를 public func postfixNaljin 로 접근제어자 설정을 다시 해줬음니다

근데도 에러가 안없어지는거예요?????????? 음,, 설마,,? 하고 SubProject로 타겟을 바꿔서 다시 빌드를 하고 MainProject 로 돌아왔더니 그제서야 정상 동작이 됐습니다.

아니 그럼 import 하려는 프로젝트에 변경사항 있을때마다 타겟 바꿔서 빌드해줘야한다는 건가????? 이게 맞나요????? 혼란하다 혼란해..

튼 이렇게 workspace 에서 SubProject 를 열어 public 으로 접근제어자를 바꿔주면, 당연히 원래 SubProject.xcodeproj 만 단독으로 열어도 해당 함수의 접근 제어자가 public 으로 변경되어있습니다. 워크스페이스에서 어차피 여기를 참조하고 있는거니까요..?! 반대로 xcodeproj 만 열어서 내용 변경을 하고, workspace 를 열었을때도 동일하게 반영되어 있겠쥬? (저는 처음에 이 개념이 잘 안잡혔었어여)

submodule 로 하위 repository 한번에 관리하기

하 근데 또 이런 생각이 드는거예여

만약 MainProject 가 github 에 따로 레포지토리로 관리되고 있고, SubProject 도 github 에 따로 레포가 있어 ㅇㅇ 이 두 프로젝트 clone 받아와서 workspace에 반영한 다음에 각 레포의 origin 에 변경 사항이 있으면 바로 pull 땡겨오고 내쪽에서 변경 사항 있으면 각 repo 에 push 때리는 식으로 최신화가 가능한가??

흠,, 각 레포지토리를 일일이 열어서 push 하고 pull 하면 최신화가 되긴 하겠지?? workspace에서도 같이 최신화가 유지 되나?? 생각도 들었지만, 어차피 동일한 xcodeproj 를 참조하고 있기 때문에 여기서 보는 내용도 항상 최신화된 버전일테고,,

근데 레포지토리마다 열어서 관리하기 귀찮은데,, 한번에 관리가 안되나,,?? 서브모듈로 어찌 저찌 조질 수 있을 거 같기도 하고,,???

ㅎ 해봅시다

우선 차례대로 xcodeproj 의 프로젝트를 담고있는 MainProject, SubProject 를 레포를 만들었구여, xcworkspace 를 담고있는 WorkSpcae 레포도 만들었습니다

그리고 WorkSpace 디렉토리로 이동해서 아래 명령어를 통해서 MainProjectSubProject 를 submodule 로 추가했습니다

git submodule add https://github.com/sujinnaljin/MainProject
git submodule add https://github.com/sujinnaljin/SubProject

그럼 WorkSpace 디렉토리는 이런 모양이 되는데여

여기서 Naljin.xcworkspace를 열어 위에서 했던대로 MainProject.xcodeprojSubProject.xcodeproj 를 드래그 & 드롭 합니다

이제 워크스페이스 안에서 MainProjectSubProject 를 변경했을때 git 에 어떻게 변경 사항이 일어나는지 봅시다.

저는 Fork 라는 앱을 쓰고 있는데 MainProjectSubProject의 서브모듈에 변경 사항이 있다고 뜨네여

우측 SubModules 를 클릭해서 각각 MainProjectSubProject 를 열어보면 어떤 변경 사항이 있었는지 확인하고 필요시 commit & push 할 수 있습니다.

또 만약 다른 사람이 작업해서 origin 에 변경 사항이 있는 경우, 서브모듈에서 이 변경사항을 감지하고 head 를 최신으로 체크아웃할 수 있습니다.

흠 쓰고 나니 이건 워크스페이스 관련 내용이라기 보다는 그냥 서브모듈 사용법 같네여. 굳이 Naljin.xcworkspace 는 WorkSpace 의 폴더에 없어도 될테니까요.

만약 서브모듈을 이용하지 않는다면 변경 사항이 있을 때마다 각각의 git repository로 가서 push & pull 해야할텐데, 이렇게 사용할 프로젝트들을 서브모듈로 추가한다면 한곳에서 관리할 수 있는 장점이 있는것 같습니다,,?? (더 좋은 방법이 있으면 알려주세염)

마무리

후 오늘도 구구절절하고 길었따 증맬,,!!! ㅋㅎㅜㅜ

그낭 혼란 뿐이었던거 같은데,, 머,, 틀린 내용이나,, 보충해주실 내용 있으면,, 댓글 달아주시겠져,,,?? 제발요,,

참고

--

--