Swift 5.7
작년에 발표된 docC
와 Swift.org
웹사이트가 오픈 소스로 제공되어 커뮤니티의 사용성 증가
커뮤니티를 구성원에게 관리 및 지원을 제공하기 위해 Swift on Server
및 Diversity in Swift
에 대한 작업 모델을 사용해왔는데 잘 작동 👍
그래서 두 개의 새로운 작업 그룹 추가
- Swift Website : 커뮤니티 리소스로 만들기
- C++ Interoperability : C++ 상호 운용성을 위한 모델 디자인 형성
작년에 구성원을 지원하기 위해 Swift Diversity 작업 그룹은 Swift Mentorship Program을 도입해 잘 성공했고 올해도 새롭게 진행할 예정
Linux 패키지 형식에 대한 지원 추가
-> Linux 플랫폼용 Swift 도구 체인 배포 프로세스 간소화
새로운 기본 도구 체인 설치 프로그램을 통해 Amazon Linux 2
및 CentOS 7용 RPM
을 다운로드 가능
Swift는 주로 앱 빌드용이지만 여러 수준에서 사용되기 위해 변경 사항을 거침
바이너리에 대한 표준 라이브러리를 적게 만들기 위해 외부 유니코드 지원 라이브러리에 대한 종속성 삭제
=> Swift는 앱에서부터 서버, 제한된 프로세서까지 유용하게 사용
워크플로를 사용자 지정하는 데 도움이 되는 새로운 도구
Trust On First Use
패키지 다운로드 시 패키지 지문이 기록되는 보안 프로그램
이후 다운로드는 지문의 유효성을 검사하고 만약 다른 경우 오류를 보고
명령 플러그인은 Swift 개발자의 작업 흐름을 개선할 수 있는 좋은 방법
사용 예시
- 문서 생성
- 소스 코드 재포맷
- 테스트 보고서 생성
쉘 스크립트에 자동화를 작성하고 별도의 워크플로 유지 대신 Swift를 사용할 수 있음
명령 플러그인은 오픈 소스 도구와 Swift Package Manager 사이 접착제 기능
=> 이제 모든 오픈 소스 도구를 Xcode 및 Swift Package Manager에서 사용 가능
문서를 소스 코드에 통합하는 도구
Objective-C 및 C 지원으로 좋아짐
플러그인은 단순한 Swift 코드
CommandPlugin 프로토콜을 준수하는 구조체로 플러그인을 정의
이후 호출할 도구를 플러그인에 알려주는 함수를 추가하면 끝
빌드 도구를 위한 플러그인으로 빌드 중에 추가 단계를 삽입할 수 있는 패키지로 언제든지 직접 실행하고 패키지 파일을 변경할 수 있는 명령 플러그인과 다름
사용 예시
- 소스 코드 생성
- 사용자 지정 처리
빌드 시스템에 실행 가능한 명령과 결과로 예상되는 출력을 알려주는 빌드 명령(buildCommand)를 정의하여 플러그인을 구현
패키지에 확장성을 제공하는 보안 솔루션
패키지 사용을 확장하면서 모듈 충돌이 발생할 수 있음
ex) 두 개의 패키지가 동일한 이름의 모듈을 정의하는 경우
Swift 5.6에서는 모듈 명확성을 도입
패키지 매니페스트의 종속선 섹션에 moduleAliases
키워드만 추가하면 다른 이름을 사용하여 같은 이름을 가졌던 모듈을 구별 가능
내부 개선 사항
작년에 소스 코드 컴파일을 조정하는 Swift Driver 소개
이제 드라이버를 별도의 실행 파일이 아닌 Xcode 빌드 시스템 내에서 직접 프레임워크로 사용 가능
-> 빌드 시스템과 빌드를 밀접하게 조정하여 병렬화 작업 허용
프로토콜 및 where 절
과 같은 항목에서 제네릭 시스템의 타입 체크 성능 향상
이전에는 관련된 프로토콜이 많아 시간과 메모리 사용량이 확장되는 문제를 개선하여 타입 체크 속도 향상
이전에는 앱을 시작할 때마다 프로토콜을 계산하여 필요한 프로토콜이 많을 수록 실행 시간이 길었음
이제 캐시를 적용하여 iOS16에서 실행할 때 앱 시작 시간을 절반으로 줄일 수도 있음
스레드 안정성을 포함하는 최신 동시성 모델
작년) 콜백 및 수동 대기열 관리보다 안전하고 쉬운 Actor와 async/await을 결함한 새로운 동시성 모델을 도입
동시성은 앱의 근본적이고 중요한 개선 사항이므로 iOS 13 및 macOS Catalina까지 배포 가능하도록 적용
Swift의 중요한 기능 중 하나는 메모리 안전!
값을 수정하는 동안 값을 읽는 동작은 수행할 수 없음
ex) 3을 제거하고나면 count가 줄어서 2도 제거?
-> 배열을 수정하는 동안 count에 접근하는 것이 안전하지 않아 방지
스레드에서도 안전을 위해 예측할 수 없는 동작을 유발할 수 있는 동시성 버그를 방지하자!
Actor는 Data Race를 제거하는 첫 번째 단계
각 actor는 동시성 바다에서 다른 것과 격리된 섬으로 생각할 수 있음
이때 서로 다른 스레드가 actor 각각이 저장한 정보를 읽으려 한다면?
다음 세션에서 자세히 설명~
Memory safety에서 Thread safety으로.
- Swift 6의 목표
이를 위해 Robust concurrency model
과 Opt-in safety checks
를 개선
Opt-in safety checks
- 잠재적인 data race를 식별하는 새로운 안전 검사
- 빌드 설정에서 활성화 가능
distributed actor
는 섬을 네트워크를 통해 다른 시스템에 배치
이제 Swift에서 백엔드를 쉽게 작성할 수 있음
distributed
는 원격 시스템에 있을 수 있는 액터에서 호출이 예상되는 함수에도 추가
endOfRound 메서드 추가
일반 actor와 차이점은 호출이 네트워크 오류로 인해 잠재적으로 실패할 수 있다는 점
따라서 액터 외부에서 함수 호출 시 필요한 await 키워드와 try 키워드를 추가해야 함
서버 측 클러스터 분산 시스템 구축에 중점을 둔 오픈 소스 Distributed Actors
패기지도 구축함 (자세한 내용은 관련 세션)
AsyncSequenece를 처리할 때 간편한 솔루션을 제공하기 위해 오픈 소스 알고리즘 세트를 출시
여러 비동기 시퀀스를 결합하고 컬렉션으로 그룹화하는 방법을 여러 가지가 있고 이는 일부일 뿐 자세한 내용은 관련 세션~
동시성에 새로운 측면
Actor 중 가장 우선순위가 높은 것부터 실행
운영 체제 스케줄러와 긴밀한 통합을 유지하면서 운선순위 모델 역전 방지 기능이 내장되어 있어 덜 중요한 작업이 중요한 작업을 차단하는 것을 방지
이전까지는 앱에서 동시성 성능이 미치는 영향을 시각화하기 어려웠지만 새로운 도구가 생김
Instruments의 Swift Concurrency 보기
는 성능 문제를 조사하는데 도움
단순하고 명확한 제네릭 및 강력한 문자열 처리 등 언어 개선
코드에서 원하는 것을 표현하기 위해 도구 여러 면에서 개선됨
예를 들어 if let
구문에서 변수명을 그대로 사용하는 경우가 일반적
하지만 이름이 길면 사용하기 번거롭고 축약하기엔 문제가 될 수 있다.
Swift 5.7은 이러한 패턴에 대한 속기를 도입하여 옵셔널 언래핑 시 이름을 드롭하면 같은 이름을 갖게 됨 + guard
에서도 작용
또한 이제 여러 명령문 또는 제어 흐름 기능이 있는 복잡한 클로저에서도 클로저의 결과 타입을 수동으로 지정하지 않고도 사용 가능
Swift는 타입 및 메모리 안전에 유의하기 때문에 포인터 타입이 다른 포인터 간에 자동으로 변환하지 않음
하지만 C에서는 특정 변환을 허용하기 때문에 이런 차이가 C API를 Swift로 가져올 때 문제가 될 수 있음
Swift에서는 한 타입의 포인터에서 다른 타입처럼 엑세스하는 것은 위험하므로 명확하게 표현하지만 C에서는 무의미한 작업
이제 Swift는 가져온 함수 및 메서드 호출에 대한 별도의 규칙을 가져 API를 원활하게 사용 가능
올해 문자열에서 정보를 추출하는 새로운 도구 등장
이전에는 일부 정보를 얻기 위해 찾고, 쪼개고, 자르는 구문을 작성해야 했음
일부 구문을 줄인다 해도 작업이 복잡하여 파악하기 어려움
우리가 해야할 것은 코드가 원하는 문자열을 그리고 이를 수행하는 방법을 파악하는 것
-> 명령형 접근 방식이 아닌 선언적 접근 방식
Swift 5.7에서는 이제 정규식을 통해 해결할 수 있음
정규식
문자열의 패턴을 설명하는 방법
이 구문은 Swift의 정규식 리터럴에서 지원되며 다른 개발자 도구에서와 마찬가지로 작동
정규식 리터럴은 기호와 니모닉으로 작성되어 규칙이 조합으로 나타냄 -> 복잡한 리터럴을 이해하는데 1분도 걸릴 수 있음
기호 대신 단어로 규칙을 작성할 수 있으면 이해하기 쉬울 것
이 모든걸 합치면 SwiftUI와 유사한 결과를 얻을 수 있음
-> 이것이 정규식 리터럴의 훌륭한 대안이 될 것
RegexBuilder 라이브러리
는 기존 구문보다 사용하기 쉽고 읽기 쉬운 새로운 SwiftUI 스타일 언어를 제공
SwiftUI 뷰 계층 구조를 뷰로 전환하듯 정규식을 재사용 가능한 정규식 구성 요소로 전환 가능
특별한 이스케이프 없이 문자열 리터럴은 내부 텍스트 (ex "<"
)와 일치하기만 하면 되고 빌더 중간에 정규식 리터럴을 사용할 수도 있음
어떤 구문을 사용하든 강력한 타입의 캡처를 지원
Mailmap 프로토콜을 사용하는 두 가지 방법
컨테이너의 경우 더 많은 공간을 차지하고 작업하는 데 시간이 걸리기 때문에 이러한 구분이 중요
Swfit 5.7에서 컨테이너를 사용하는 경우 any 키워드를 작성
any 키워드를 표시하여 두 함수의 차이를 쉽게 설명 가능
이전에는 프로토콜 자체를 타입으로 사용할 수 없었지만 이제 Collection
과 같은 프로토콜도 모든 타입으로 사용 가능
associatedtype이 있는 경우 프로토콜 이름 뒤에 <>
에 넣어 기본 연관 타입
으로 만들어 제한할 수 있음
근데 이미 AnyCollection이 있는데?
-> 박스 클래스나 클로저 대신 내장된 타입을 사용하여 구현
-> typealias로 대체
그럼에도 여전히 Mailmap이 Equatable을 준수할 때 Mailmap을 사용해도 == 연산자를 사용 못하는 듯 제한이 있음
그렇기 때문에 대부분의 경우 Generic을 사용해야 함
동일한 작업이지만 상단은 제네릭 타입을 사용, 하단은 모든 타입을 사용
제네릭이 더 효율적이고 기능성이 높음 하지만 모든 타입이 읽고 쓰기가 쉬움
제네릭 작성시 <제네릭 이름: 매개변수 형식>
으로 사용해야 해서 any보다 길다
-> some으로 대체
제네릭과 모든 타입 중 선택하는 경우 any
대신 some
을 쓰면 됨
이제 더 이상 제네릭을 피할 이유가 없다!