Tuist로 프로젝트를 모듈화 할 때, 외부 패키지를 어떻게 활용해야 할까? (feat. static/dynamic & mangled name)
최근 진행하고 있는 프로젝트와 직전에 수행한 프로젝트에서는 Tuist를 이용해서 역할별로 모듈을 구분했다. 앱 구성을 위해 기능 단위로 모듈을 구분하고, 모듈간의 연결이 필요한 곳에만 Target을 지정해 의존성을 관리했다. 외부 패키지(라이브러리)를 활용할 때도, Tuist를 통해 모듈별로 필요한 라이브러리를 주입할 수 있어 프로젝트 관리가 수월했다. 문제는 코드를 런타임에 빌드하였을 때 마주할 수 있었다. Tuist CLI로는 프로젝트가 문제없이 구성되었는데, 지정한 스킴에서 앱 빌드가 성공하지 못했다. 콘솔에서 RxSwift 패키지와 관련된 처음보는 에러를 확인할 수 있었다. 외부 패키지 설정과 관련된 문제일 것이라 판단하고 프로젝트 설정부터 톺아봤다. 문제 인식 Tuist 설정 파일에서 Package.swift 파일에 외부 패키지들을 static framework로 등록하고, 외부 패키지를 활용해야 하는 여러 모듈의 프로젝트 파일에서 external 타겟으로 중복되게 지정하여 tuist generate 로 프로젝트를 생성했더니 콘솔에서 "여러 타겟에서 동일한 외부 타겟이 링크(linked)되었기 때문에 static product 환경에서 예기치 못한 사이드이팩트가 발생할 수 있다"는 Warning을 마주할 수 있었다. 우선은 Warning 정도라고 생각하고, 일단 앱 구성을 위한 모듈별 코드를 작성했다. 그리고 나서 여러 모듈(CommonUI, Domain, Data 모듈)을 조합해서 Feature 모듈을 개별 App Scheme으로 빌드했다. 그 순간 아래와 같은 에러 메시지와 함께 런타임 에러가 발생했다. 문제 서칭 이전에 다른 프로젝트를 진행하면서는 마주한 적 없던 에러였기 때문에 빠르게 서칭하였고, Tuist로 모듈화할 때, 외부 패키지를 static하게 등록하여 활용하여 발생한 문제임을 파악하게 되었다. 그러면 왜 모듈로 구분한 서로 다른 프로젝트에서 동일한 외부 패키지를 활용할 때, static framework로 등록하면 side effect가 발생하여 빌드 과정에 demangle ~ 에러가 발생했던 것일까? 이 궁금증에 조금 더 접근하기 위해서는 static/dynamic framework에 대해 이해를 하는 것이 좋다. 그리고 failed to demangle ~ 로 작성된 에러 메시지의 demangle이 무엇인지도 알아야 한다. Swift 프로젝트에서 Static, Dynamic framework 앱 실행 파일(excecutable file)을 생성하는 시점에 컴파일러가 외부 패키지 파일을 소스 코드 파일과 함께 바이너리 실행 파일로 링킹하는지 여부로 Static, Dynamic 프레임워크를 구분할 수 있다. 쉽게 생각해서, 아래의 두 가지 경우를 구분하는 것이 Static 또는 Dynamic한 프레임워크를 구분하는 기준이라는 것이다.
- 한결