https://developer.apple.com/videos/play/wwdc2018/411/
목차
Why a package manager for Swift?
- Swift는 크로스 플랫폼 언어이다.
- 따라서, Swift 코드 빌드를 위한 거대한 크로스 플랫폼 툴이 필요했다.
- SwiftPM은 자체적인 complete build system을 포함하고 소프트웨어를 구성, 테스트, 실행할 수 있도록 한다.
- Swift 프로젝트에 표준 패키지 관리자(canonical package manager)를 제공하여 Swift 라이브러리를 쉽게 누구나 공유할 수 있도록 했다. ➡️ Swift 생태계 확장
- 신중하고 엄선된 API를 유지하기 위해 core 라이브러리에 어떤 것이 추가될지에 주의하고 싶다.
- 따라서, 좋은 패키지 관리자는 이러한 아이디어를 core 라이브러리에 저장할 필요 없이 패키지로 쉽게 배포할 수 있도록 한다.
- SwiftPM은 Swift로 작성되었으며 이 자체로 Swift 패키지이다.
https://www.swift.org/package-manager/
How to use it
- SwiftPM은 위와 같이 4개의 command line tools로 구성된다.
- 패키지들은 깃 레포지토리에 저장되며 git tag로 버저닝된다.
패키지 만들기 실습!
패키지로 만들 디렉토리를 생성하고 swift package init을 통해 필요한 파일들을 자동 생성한다.
swift run을 실행하면 "Hello, world!"가 출력된다!
Package 주요 구성 요소 3가지
- Dependencies
- Targets
- Products
Dependencies
- Dependencies는 원하는 기능을 개발할 때 사용할 수 있는 Swift 패키지이다.
- 각 디펜던시는 패키지에서 사용할 수 있는 하나 이상의 라이브러리와 같은 products를 제공한다.
- Swift manifest 파일에서 디펜던시는 위와 같이 표기된다.
- 소스의 location과 버전을 포함한다.
Targets
- 타겟은 패키지의 Basic building blocks이다.
- 타겟은 소스 파일 뭉치를 모듈 또는 테스트 제품군에 빌드하는 방법을 기술한다.
- 타겟은 동일한 패키지의 다른 타겟과 디펜던시로 선언된 다른 패키지에서 추출된 Products에 의존할 수 있다.
Products
- Product는 라이브러리에서 실행할 수 있으며 Products는 하나 이상의 target의 build artifacts로 부터 조립된다.
- 패키지는 프로덕트를 정의하여 다른 패키지에 대한 라이브러리를 제공한다
- 기본적으로는 라이브러리 유형을 명시할 필요가 없지만 필요한 경우 라이브러리를 static 또는 dynamic으로 명시할 수 있다.
예시
- Targets
- targets 부분을 먼저 보면 libdealer 타겟이 선언되어 있고 이 타겟이 주요 기능 구현을 포함한다.
- 이 타겟은 DeckOfPlayingCards 프로덕트에 의존하고 있는데 이 것은 앞서 추가한 디펜던시에서 나온 프로덕트이다.
- 두 번째 타겟인 dealer는 libdealer에 의존한다. (command line tool을 제공하기 위해)
- 테스트 타겟 또한 존재한다.
- Products
- 2개의 프로덕트를 구성한다.
- 첫번째로 libdealer 타겟에 해당하는 라이브러리이다. 이것은 외부 소비를 위한 라이브러리로서 우리의 구현을 제공한다.
- 두번째는 command line tool 사용을 위한 실행 파일을 제공하는 dealer 타겟에 해당하는 executable 프로덕트이다.
The design of SwiftPM
- SwiftPM은 Swift의 철학을 따른다.
- 빠르고, 안전하며 표현력(expressive)을 가진다.
- Safe: 고립된 빌드 환경과 빌드가 임의 명령을 실행할 수 없기 때문에 안전하다.
- Fast: 대규모 디펜던시 그래프로 확장 가능한 빌드 엔진을 사용하기 때문에 속도가 빠르다.
- Expressive: 패키지 매니페스트에 친숙한 언어인 스위프트를 사용하기 때문에 표현력이 풍부하다.
The Design of SwiftPM - Configuration
- 우측의 코드가 더 선언적이다.
- 문자열 상수를 사용하여 타겟이 무엇인지 쉽게 이해하고 확인할 수 있다
- Package Manager 및 기타 빌드 도구는 종종 사용자가 명시적으로 구성(configured)한 항목과 package Manager가 적용한 conventions 사이에 주의를 기울인다.
- 소스 파일(위 사진의 좌측 부분)은 디스크의 컨벤션 기반 위치에서 자동으로 픽업되므로 패키지 매니페스트를 편집하지 않고도 소스 파일들을 쉽게 추가, 제거할 수 있다.
- 그러나 Product와 Target은 디스크의 레이아우소가 상호 참조할 필요 없이 패키지 및 패키지가 정의하는 내용을 쉽게 이해할 수 있도록 명시적으로 구성할 가치가 있다.
- 클라이언트는 매니페스트만 봐도 패키지가 제공하는 내용을 쉽게 확인할 수 있다.
- SwiftPM은 C, C++, Objective-C와 같은 다른 프로그래밍 manager 언어에 대한 소스 코드 구축을 지원한다. 이를 통해 기존 코드와 통합할 수 있다.
- 그러나 동일한 Target에서 이러한 언어를 Swift와 혼합하는 것을 지원하지는 않는다. (다른 타겟으로 관리하자)
The Design of SwiftPM - Dependencies
- 패키지가 지속적인 변경 없이 버그 수정의 혜택을 받을 수 있도록 하려면 Swift 패키지는 의미론적 버전 관리를 준수해야 한다.
- 버전 넘버에 특정한 semantic meaning을 부여한다.
Dependency Resolution
- SwiftPM은 패키지 그래프에 있는 모든 패키지의 정확한 버전을 확인한 후 빌드할 수 있어야 한다.
- 이것을 의존성 해결(Dependency Resolution)이라는 프로세스로 수행한다.
- SwiftPM은 패키지에 지정된 모든 요구 사항을 살펴보고 패키지와 호환되는 최신 버전을 찾는다.
- 디펜던시 확인 후에는 pacakge.resolved 라는 파일에 확인 내용이 기록된다.
- 이 파일의 목적은 다른 팀원들 또는 지속적인 통합 인프라와 resolve 버전을 공유하여 신뢰할 수 있는 빌드 결과를 얻고 디펜던시를 업데이트할 시기를 의도적으로 선택할 수 있도록 하는 것이다.
- 업데이트를 할 준비가 되었다면 Swift Package Update를 실행한다.
The Design of SwiftPM - Building
- SwiftPM은 llbuild를 기본 빌드 엔진으로 사용한다.
- llbuild는 빌드 시스템을 빌드하기 위한 라이브러리 집합이다.
- 범용 및 재사용 가능한 빌드 엔진을 기반으로 제작되었다. ➡️ 빠르게 작업 수행이 가능하고 증분 빌드를 수정할 수 있다.
- 모든 디펜던시가 명시적으로 선언된 상태에서 소프트웨어를 독립적(isolation)으로 개발하면 복잡한 요구사항을 가진 패키지도 서로 다른 환경에서 안정적으로 구축 및 사용할 수 있다.
- 시스템에 패키지를 global 하게 설치하는 대신 SwiftPM은 명시적으로 의존하는 패키지만 사용할 수 있다.
- 빌드 샌드박스를 활용하여 빌드하는 동안 파일 시스템의 임의 위치에 아무 것도 write 할 수 없다.
- SwiftPM은 빌드의 일부로 임의 명령 또는 셸 스크립트를 실행할 수 없다.
- 이로 인해 빌드 그래프와 모든 입출력을 완전히 이해하여 올바른 증분 빌드를 신속하게 수행할 수 있다. (모든 의존성을 볼 수 있기 때문)
Testing
- SwiftPM은 테스트를 지원한다.
- 익숙한 XCTest 프레임워크를 기반으로 한다.
- 테스트 결과를 더 빨리 얻을 수 있도록 병렬 테스트도 지원한다.
- 또한 테스트 필터링을 지원하므로 테스트의 하위 집합을 실행하고 단일 기능에서 반복할 수 있다.
The Design of SwiftPM - Workflow Features
- SwiftPM을 발전시키면서 워크플로우 기능에 대해 생각하고 있다.
- 특히 Command Line 에서 모든 개발 작업을 수행할 수 있도록 하는 것이다.
- 이러한 기능 중 하나가 편집 모드이다.
- 편집 모드는 임시 편집을 수행할 수 있도록 로컬에서 체크아웃된 복사본으로 특정 패키지의 모든 전이 발생 항목을 덮어쓸 수 있으며 그래프의 모든 패키지를 미리 전달하지 않고도 전이 종속성에 대한 변경 사항을 테스트할 수 있다.
- 브랜치 디펜던시를 사용하면 엄격한 버전 관리 요구 사항 없이 패키지에 의존할 수 있다.
- 이것은 여러 패키지를 함께 개발할 때 유용하다.
- 이 기능은 개발 전용 기능이므로 태그를 게시하기 전에 특정 버전 종속성으로 변경해야 한다.
- 로컬 패키지를 사용하면 git 레포지토리 대신 파일 시스템에서 직접 패키지를 사용할 수 있다.
- 이 기능은 초기 생성 중에 여러 패키지를 불러 올 수 있도록 하는 데 유용하다.
The Design of SwiftPM - Tools Evolution
- Swift의 새 버전은 package.swift 매니페스트 API의 새 버전을 가져올 수 있다.
- 패키지를 업데이트하거나 기존 패키지에 액세스하지 않고도 새로운 소스 도구를 활용할 수 있도록 이전 API를 계속 사용할 수 있다.
- 사용 중인 API 버전을 지정하기 위해 package.swift 파일 맨 위에 Swift Tool Version을 명시하고 있다.
- Swift tool의 최소 필수 버전을 지정한다.
Evolution ideas
- 위와 같은 4가지 측면에서 SwiftPM을 발전시킬 수 있을 것 같다. (wwdc18 당시에는 구현되지 않았던 기능들 -> 지금은 존재할 수도 있다.)
Evolution ideas - Great integration with other tools
- 애플에서는 이미 SwiftPM의 라이브러리 기반 아키텍쳐와 함께 이를 위한 토대를 마련했다.
- 개발자 도구에서 SwiftPM 지원을 권장한다
- 사용자가 항상 소스 코드를 직접 편집하는 것 대신 자동화된 도구에서 package.swift 매니페스트를 편집하는 방법을 제시했다.
- libSyntax를 사용하면 가능할 것으로 생각된다.
- libSyntax는 Swift 오픈소스 프로젝트에서 개발 중인 라이브러리로 다른 도구에서 Swift 구문을 쉽게 이해하고 조작할 수 있다.
- 앞서 package.swift는 선언적으로 작성해야 한다고 했는데 이것이 그 이유 중 하나이다.
- 해당 파일을 선언적으로 작성하면 컴퓨터가 이해하기 더 쉬워지고 자동으로 package.swift를 수정하는데 도움이 된다.
Evolution ideas - Publish and deploy
- 현재 패키지의 새 버전을 게시하려면 git로 수동으로 태그를 지정해야 한다. 게시된 태그를 검사하려면 git를 직접 사용한다.
- 이 프로세스를 자동화 + 간소화한 워크플로우의 일부로서 housekeeping, validation, other auxiliary tasks 를 수행하는 새로운 기능을 추가할 수 있다.
- 자동으로 올바른 semantic versioning을 관리하는 기능을 추가할 수도 있다.
Evolution ideas - Support complex packages
- SwfitPM이 정교한 요구사항을 가진 복잡한 패키지를 지원할 수 있기를 원한다.
- 가장 큰 격차는 아마도 Resources일 것이다. (이미지, 데이터 파일 등)
- SwiftPM은 이러한 제품을 번들로 제공하지 않는다.
- 일부 사용자는 compiler flags, linker flags 및 Swift의 기타 속성을 지정하기를 원하지만 SwiftPM은 이를 지원하지 않는다.
- 조건부 설정이나 패키지의 어떤 부분에서 어떤 설정 값을 얻을 수 있는지에 대한 세부적인 제어 등을 포함하여 강력한 빌드 설정 모델을 추가하면 정말 좋을 것이다.
- 임의 셸 스크립트를 실행할 수 없다.
- 그러나 많은 사용자들이 맞춤형 언어 또는 프로세스를 지원하는 등 빌드에 대한 어느정도의 사용자 지정을 원할 수 있다.
- SwiftPm은 새로운 도구를 빌드 프로세스에 도입하는 실제 도구 패키지를 통해 이를 안전하게 지원할 수 있다.
- 다만, 빌드 프로세스에 도입된 모든 세로운 툴이 입출력 디펜던시를 올바르게 선언해야 한다.
Evolution ideas - Trust, Manage, and Find Packages
- Git 자체는 TLS와 같은 보안 메커니즘을 지원한다.
- 그러나 악의적인 행위자는 여전히 원격 레포지토리를 손상시키고 악의적인 콘텐츠를 넣을 수 있다.
- 타사 코드를 사용할 때마다 이러한 위험을 인식해야 한다.
- 그러나 SwiftPM은 사용자가 예상한 패키지 콘텐츠를 실제로 얻을 수 있도록 보안 기능을 구축할 수 있는 좋은 기회를 제공한다.
- SwiftPM은 빌드에서 package.swift 평가가 빠져나가 파일 시스템에 내용을 쓰거나 네트워크에 엑세스 하는 것을 방지한다.
- macOS의 샌드박스 기술을 사용하고 있다.
- 그러나 이러한 보안을 다른 플랫폼에도 적용하고 싶다.
- 그래프에 있는 패키지 중 하나를 프라이빗 커스텀하기 위해 fork를 원할 수 있다.
- 또는 각 패키지가 어디서 왔는지에 대한 origin URL을 재정의하여 원래 패키지가 항상 존재하는지에 의존하지 않고 제어하는 개인 미러를 가리킬 수 있기 때문이다.
- 언젠가 스위프트 패키지에 대한 실제 인덱스를 가지고 싶다.
- 표준화된 네임스페이스를 제공하고 새로운 패키지를 더 쉽게 검색할 수 있도록 하는 것 외에도 패키지에 대한 품질 메트릭과 같은 것도 지원할 수 있다.
Open source process
https://github.com/apple/swift-evolution
- SwiftPM은 오픈소스 프로젝트이기 때문에 다양한 아이디어와 피드백이 필요하다! (언젠가 이런 큰 오픈소스 프로젝트에 기여해보고 싶다..!)
'iOS > Swift' 카테고리의 다른 글
Adopting Swift Packages in Xcode (0) | 2023.06.14 |
---|---|
Creating Swift Packages (1) | 2023.06.07 |
Swift의 디자인 프로토콜 인터페이스 (0) | 2023.04.27 |
ARC in Swift: Basics and beyond (0) | 2023.04.13 |
Understanding Swift Performance (2) | 2023.03.13 |
댓글