## PR 타입
어떤 변경에 대한 PR인가요?
<!-- 아래 체크리스트 중 해당 되는 부분에 체크해주세요 "x". -->
- [ ] 버그 수정
- [x] Feature / 신기능
- [ ] 코드 스타일 업데이트 (formatting, local variables)
- [ ] 리팩토링 (no functional changes, no api changes)
- [ ] 빌드 관련 변경사항
- [ ] CI 관련된 변경사항
- [ ] Documentation content changes
- [ ] 구조 변경
- [ ] Other... 추가 설명 요망:
## 배경
- Share 모듈에 SharedThirdParty로 외부 라이브러리 의존성을 부여했지만 FlexLayout이 import 되지 않는 문제가 있었다.
## 목표
- [x] FlexLayout, PinLayout으로 로그인 UI를 그린다
## 결과 (Optional)
<!-- 개발한 내용의 결과를 설명해주세요. !-->
|로그인|
|--|
|<img src="https://hackmd.io/_uploads/BJJcUsVVR.gif" width="300">|
## Trouble or Trouble Shooting(Optional)
<!-- 해당 PR에서 발생한 문제를 해결한 내용을 작성해주세요. !-->
|import FlexLayout 안되는 문제|
|--|
|<img src="https://hackmd.io/_uploads/SyBAOoV4A.gif" width="1000">|
> Missing required modules: 'FlexLayoutYoga', 'FlexLayoutYogaKit'
해당 문제는 `import FlexLayout`을 사용하는 곳에서 FlexLayoutYoga, FlexLayoutYogaKit 필요하다는 문제입니다.
**해결 방법**
문제를 해결하기 위해선 사용하는 모듈 settings에서 전처리기에 대한 정의를 해야합니다.
```swift
.settings(
base: [
"GCC_PREPROCESSOR_DEFINITIONS": "$(inherited) FLEXLAYOUT_SWIFT_PACKAGE=1",
"OTHER_LDFLAGS": "$(inherited) -all_load"
]
)
```
- `GCC_PREPROCESSOR_DEFINITIONS`: 전처리기 정의를 지정합니다.
- `OTHER_LDFLAGS`: Linker Flag를 지정합니다.
- `$(inherited)`: 상위 설정을 상속받도록 설정합니다.
- `-all_load`: static library의 모든 오브젝트 파일을 로드하도록 Linker에 지시합니다
> import 해야하는 모든 모듈에서 위의 설정을 알고 있어야 합니다.
---
|import FlexLayout을 해서 flex 메서드 호출 시 발생하는 문제 1|
|--|
|<img src="https://hackmd.io/_uploads/r1gNuj440.gif" width="1000">|
> Thread 1: "-[UIView yoga]: unrecognized selector sent to instance 0x103e08d80"
해당 문제는 첫 번째 문제를 해결하고 발생한 문제입니다. 이 문제는 사용하는 모듈에서 FlexLayout을 모를 때, 발생합니다.
**해결 방법**
모든 모듈에서 SPM FlexLayout을 알고 있어야 합니다.
```swift
import ProjectDescription
extension TargetDependency {
public struct SPM {}
}
public extension TargetDependency.SPM {
static let Kingfisher = Self.package(product: "Kingfisher")
static let FlexLayout = Self.package(product: "FlexLayout")
static let PinLayout = Self.package(product: "PinLayout")
private static func external(_ name: String) -> TargetDependency {
return TargetDependency.external(name: name)
}
private static func package(product: String) -> TargetDependency {
return TargetDependency.package(product: product)
}
}
```
> SPM 패키지 설정
```swift
let project = Project.makeModule(
name: ModulePath.Coordinator.name + ModulePath.Coordinator.Onboarding.rawValue,
targets: [
.coordinator(
interface: .Onboarding,
factory: .init(
dependencies: [
.feature,
.coordinator(interface: .App),
.SPM.FlexLayout
]
)
),
.coordinator(
implements: .Onboarding,
factory: .init(
dependencies: [
.coordinator(interface: .Onboarding)
]
)
),
.coordinator(
testing: .Onboarding,
factory: .init(
dependencies: [
.coordinator(interface: .Onboarding)
]
)
),
.coordinator(
tests: .Onboarding,
factory: .init(
dependencies: [
.coordinator(testing: .Onboarding)
]
)
)
]
)
```
> CoordinatorOnboarding 모듈
|import FlexLayout을 해서 flex 메서드 호출 시 발생하는 문제 2|
|--|
|<img src="https://hackmd.io/_uploads/SkSdPsEEA.gif" width="500">|
> Undefined symbol: FlexLayout.Flex.alignContent(FlexLayout.Flex.AlignContent) -> FlexLayout.Flex,
호출 1번을 해결하고 다시 flex 메서드를 호출했지만, 해당 문제가 발생했습니다.
**문제해결**

위의 이미지처럼 사용하는 모듈내의 Interface에 Package 자체를 등록했습니다. 이렇게 사용하는 곳에 모두 등록하는 것이 맞는 방법은 아니지만, 문제 해결을 우선적으로 생각하고 설정해봤습니다.
```swift
import ProjectDescription
import ProjectDescriptionHelpers
import DependencyPlugin
let project = Project.makeModule(
name: ModulePath.Coordinator.name + ModulePath.Coordinator.Onboarding.rawValue,
packages: [
.remote(url: "https://github.com/layoutBox/FlexLayout", requirement: .upToNextMajor(from: "2.0.7"))
],
targets: [
.coordinator(
interface: .Onboarding,
factory: .init(
dependencies: [
.feature,
.coordinator(interface: .App),
.SPM.FlexLayout
]
)
),
.coordinator(
implements: .Onboarding,
factory: .init(
dependencies: [
.coordinator(interface: .Onboarding)
]
)
),
.coordinator(
testing: .Onboarding,
factory: .init(
dependencies: [
.coordinator(interface: .Onboarding)
]
)
),
.coordinator(
tests: .Onboarding,
factory: .init(
dependencies: [
.coordinator(testing: .Onboarding)
]
)
)
]
)
```