-
Explore the Swift on Server ecosystem (feat. WWDC 2024)Swift 2024. 12. 2. 18:49
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 WWDC 2024에서 소개된 Explore the Swift on Server ecosystem에 대해 학습해보려 합니다 🙋🏻
Swift 언어는 우리가 애플 생태계의 앱을 개발하는데 주로 쓰이지만 서버 애플리케이션을 위한 언어로도 적합합니다.
그렇기에 생소한 이 개념과 쓰임을 어떻게 애플은 소개하고 사용하라고 하는지 알아봅니다 😃
Explore the Swift on Server ecosystem
Meet Swift on Server
우선, Swift를 서버 애플리케이션에 적합하게 만드는 요소들에 대해 알아봐야 합니다.
Swift를 사용하면 가비지 컬렉션 대신 자동 참조 계산을 통해 낮은 메모리 공간으로 C와 유사한 성능을 얻을 수 있어요.
이는 예측 가능한 리소스 소비와 빠른 시작 시간이 필요한 최신 클라우드 서비스에 아주 적합해요!
또한, Swift는 표현이 풍부하기에 컴파일 타임에 다양한 버그를 제거하여 개발자가 강력하고 안정적인 분산 시스템을 작성할 수 있도록 해줍니다.
이는 해당 서비스가 충돌 및 보안 취약성에서 덜 취약하게 만들어주죠.
클라우드 서비스는 동시 작업량이 많은 작업을 처리해야 하는 경우가 많아요.
이때, Swift의 동시성 기능을 통해서 개발자는 확장 가능하고 응답성이 뛰어난 서버 애플리케이션을 작성하는 동시에 데이터 경합으로 인한 버그의 원천을 제거할 수 있습니다.
실제로 Swift는 iCloud 키체인, 사진, 메모 등 애플 클라우드 서비스 전반에 걸쳐 많은 기능을 지원합니다 😃
거기다 앱 스토어 처리를 위한 파이프라인 및 SharePlay 파일 공유도 있죠.
마지막으로 애플의 새로운 프라이빗 클라우드 컴퓨팅 서비스도 Swift를 사용해 구축되었어요.
애플 서비스 전반에 걸쳐 이는 Swift on Server를 사용하는 애플리케이션에서 처리되는 초당 수백만개의 요청에 해당됩니다.
Swift Server Workgroup, SSWG는 이러한 활동과 더 나은 미래를 위해 다양하게 활약하고 있습니다.
서버 애플리케이션 개발 및 배포에 Swift 사용을 촉진하는데 중점을 두고 있어요.
그럼 이렇게 Swift를 서버 애플리케이션에 적합하게 만드는 요소들과 어떻게 활용되는지 간략히 살펴봤으니 이제는 서버 생태계의 인기 있는 패키지 중 일부를 사용해 서비스를 구축해볼까요?
Build a service
만들어볼 데모 서비스는 두 가지 작업을 지원해야 합니다.
이렇게 누가 어떤 이벤트에 참석할 계획인지 보여주기 위해 모든 이벤트들을 나열해야 합니다.
즉, 정보를 response로 내려주는거죠.
그리고, 새 이벤트를 만들 수 있어야 해요.
정보를 request로 받아 생성하는거죠.
Swift 패키지 작업을 위해서 Xcode, VS Code, Neovim 혹은 언어 서버 프로토콜을 지원하는 기타 편집기와 같은 다양한 편집기를 사용할 수 있어요.
이번 영상에서는 VS Code를 사용해 패키지 작업을 수행해봅니다.
해당 데모 서비스 구축에서는 하단에 있는 VS Code의 내장 터미널을 사용해 서비스의 출력을 확인하고 서비스에 요청을 보냅니다.
패키지는 OpenAPI 생성기에 의존하며 Vapor를 OpenAPI용 서버 전송으로 사용합니다.
패키지엔 두개의 타겟이 있어요.
OpenAPIGenerator 플러그인이 구성된 EventAPI 타겟과 서비스 구현이 포함된 EventService 타겟이죠.
즉 EventService 타겟에서 EventAPI 타겟을 의존성으로 들고 사용하죠.
Swift OpenAPI Generator를 사용하면 서비스를 YAML로 문서화하고 서버 및 클라이언트용 코드를 생성할 수 있어요.
OpenAPI가 무엇인지 모른다면 아래 2023년 WWDC 영상을 참고해보세요!
그럼 이어서 OpenAPI 문서를 검토해봐야합니다.
이벤트는 두개죠.
get 메서드로 리스트 정보를 뿌려주는것과 이벤트를 만드는 post 메서드입니다.
이를 활용하기 위해서 서비스에서는 엔트리 포인트가 있죠.
먼저 Vapor 애플리케이션을 만들죠.
그 후 OpenAPI Vapor Transport를 생성합니다.
그 다음 서비스 인스턴스 생성 후 이를 전송에 등록하죠.
마지막으로 HTTP 서버를 시작하고 들어오는 연결을 수신하는 Vapor 애플리케이션을 실행합니다.
해당 서비스는 생성된 APIProtocol도 구현해요.
이렇게 작업 두개의 메서드를 만들 수 있어요.
이제 서비스를 시작해볼까요?
터미널 하단에 서버가 구축 및 시작됩니다.
curl을 이용해 다른 터미널에서 서비스를 쿼리하여 모든 이벤트를 나열할 수 있어요.
하드 코딩된 이벤트 목록이 포함된 JSON 배열을 반환해줘요.
여기서 우리는 새 이벤트를 동적으로 추가하고 이를 DB에 유지하려고 하기에 Database drivers를 살펴봐야 합니다.
PostgreSQL, MySQL, Cassandra, MongoDB와 같은 DB를 위한 오픈 소스 에코시스템에는 다양한 Datebase driver가 존재합니다.
이 데모 예제에서는 Postgres DB를 이용합니다.
PostgresNIO라는 Vapor와 Apple이 관리하는 Postgres용 오픈 소스 Database driver가 존재합니다.
내부에 PostgresClient 기능이 존재하는데요.
완전히 새로운 비동기식 인터페이스를 제공하고 구조화된 동시성을 활용하는 내장 연결 풀과 함께 제공되어 DB에 대한 간헐적인 네트워킹 오류에 대한 복원력을 제공해준다고 해요!
또한, 더 빠른 쿼리 실행을 위해 여러 연결을 통해 쿼리를 분산하고 연결을 미리 준비해 처리량을 향상시킵니다.
이제 진행할 단계는 이러합니다.
1️⃣ PostgresNIO를 사용해 EventService를 DB에 연결
2️⃣ PostgresClient를 사용해 listEvents 메서드에서 DB를 쿼리
3️⃣ createEvent 메서드를 구현해 새 이벤트를 DB에 삽입
하나씩 보시죠!
먼저 패키지 매니페스트에 PostgresNIO에 대한 종속성을 추가해야 합니다.
그 후 타겟에 종속성을 추가합니다.
이러면 이제 서비스에서 PostgresNIO를 가져올 수 있죠.
이젠 서비스에 PostgresClient 속성을 추가해야 합니다.
클라이언트를 추가했으면, 이를 사용해 listEvents 메서드에서 DB를 쿼리합니다.
쿼리 메서드는 행의 AsyncSequence를 반환합니다.
하드 코딩된 이벤트 목록을 대체하기 위해 행을 반복하고 필드를 디코딩한 후 각 행에 대한 이벤트를 생성해요.
쿼리 메서드에서 반환된 AsyncSequence는 성능 속도를 높이기 위해 DB에 자동으로 행을 프리패치해요.
서비스를 다시 실행하려면 PostgresClient를 생성하여 서비스에 전달해야 합니다.
먼저 로컬에서 이미 시작한 DB에 연결하기 위해 PostgresClient를 생성합니다.
그 후, PostgresClient를 서비스에 전달합니다.
클라이언트를 시작하려면 클라이언트의 run 메서드를 호출해야 해요.
해당 메서드는 완료될때까지 현재 작업을 이어 받습니다.
Vapor 애플리케이션과 PostgresClient를 동시 실행하려고 하기에 작업 그룹을 이용해야 합니다.
요렇게 하위 작업을 만들고 그룹으로 묶어 구현하죠.
이제 DB에 새 이벤트를 추가하기 위해 createEvent 메서드를 구현합니다.
요렇게 DB를 쿼리해 새 이벤트를 삽입하고 이벤트 생성 완료했음을 반환합니다.
해당 코드에서 아래와 같이 매개변수를 다룰 수 있는데요.
문자열 쿼리를 값 바인딩이 있는 매개변수화된 쿼리로 변환합니다.
요러면 SQL 주입 공격으로부터 완벽하게 안전해져요.
이제 서비스를 다시 실행하고 curl을 사용해 이벤트 생성을 해봅니다.
이벤트 생성이 완료되었으니 이제 한번 이벤트를 조회해볼까요?
아주 정상적으로 잘 나열됩니다.
DB에 저장이 잘 되었다는 소리죠.
간혹 이렇게 오류가 발생할 수 있어요.
그러나 오류가 정확히 어떤건지 제대로 알려주지는 않습니다.
이럴때 우리는 서비스에 기능을 추가해 문제를 해결하는데 도움을 받을 수 있습니다.
Observability는 로깅, 메트릭, 추적의 세가지 요소로 구성됩니다.
로깅은 서비스가 수행한 작업을 정확히 이해하는데 도움을 주며 세부 정보를 볼 수 있어요.
메트릭을 사용하면 서비스 상태에 대한 높은 수준의 개요를 한눈에 확인할 수 있어요.
로그와 지표는 단일 서비스가 수행하는 작업을 이해하는데 도움을 주지만 최신 클라우드 시스템은 분산 시스템의 집합인 경우가 많습니다.
여기서 추적은 단일 요청이 시스템을 통해 어떤 경로를 통과했는지 이해하는데 도움을 줍니다.
Swift 생태계는 코드가 Observability 이벤트를 생성할 수 있도록 하는 세 가지 요소 모두에 대한 API 패키지를 제공해줍니다.
이렇게 메서드에 Swift-log를 사용해 로그를 보낼 수 있어요.
Swift-log는 문제 해결 시 추가 컨텍스트를 제공하는 로그 메시지에 메타데이터를 추가해 구조화된 로깅을 지원합니다.
그리고 서비스가 처리한 요청 수를 추적하기 위해 각 요청마다 증가하는 Swift-metrics의 카운터를 추가할 수 있어요.
마지막으로 Swift-distributed-Tracing을 추가해 DB 쿼리 주위에 범위를 생성할 수 있습니다.
이는 시스템 전체에서 end-to-end 요청 문제를 해결하는데 도움을 줄 수 있어요.
Swift의 분산 추적이 어떻게 작동하는지 더 자세히 알아보려면 WWDC 2023의 아래 세션을 참고해주세요.
이제 이렇게 백엔드쪽에서 처리를 할 수 있어요.
세 라이브러리의 부트스트랩 호출을 통해서 수행합니다.
먼저 LoggingSystem을 부트스트랩 하고 그 다음으로 MetricsSystem, InstrumentationSystem을 부트스트랩하는 것이 좋아요.
이유는 메트릭 및 계측 시스템이 해당 상태에 대한 로그를 내보내려고 할 수 있기 때문입니다.
이렇게 간단히 코드 몇 줄로 터미널에 로그 및 추적을 내보낼 수 있어요.
패키지와 EventService 타겟에 대해서 종속성으로 Swift-log도 추가해야 합니다.
그 다음 서비스에서 로깅 모듈을 임포트하고 쿼리 메서드에서 발생하는 오류를 잡아볼 수 있습니다.
요런식으로 로거를 이용하여 터미널로 로그를 보낼 수 있어요.
이제 오류 메시지가 나타나는데 중복 키 위반으로 인해 오류가 발생했다고 자세히 알려줍니다.
이렇게 로깅을 통해 더 구체적으로 오류를 파악하고 해결할 수 있습니다 😃
지금까지 서비스를 구축하는데 사용할 수 있는 Swift on Sever 에코 시스템의 라이브러리 중 일부를 간략하게 살펴봤어요!
Explore the ecosystem
네트워킹, 드라이버, 메시지 스트리밍 등과 같은 다양한 사용 사례를 위해서 더 많은 라이브러리들이 존재합니다.
더 많은 라이브러리를 보고 싶다면 Swift.org 패키지 섹션에서 서버 카테고리를 살펴보면 좋습니다.
또한 패키지를 찾을 수 있는 다른 훌륭한 리소스는 Swift Server Workgroup의 인큐베이션 리스트들입니다.
인큐베이션 프로세스의 패키지는 3단계를 거쳐요.
각 레벨에는 패키지의 생산 준비 상태 및 사용에 따른 다양한 요구 사항들이 있습니다.
Swift.org에서 인큐베이션된 패키지 목록을 찾을 수 있습니다.
마무리
Vapor만 알고 있었는데 그것도 아는거지 심오하게 다뤄본적 없는...
정말 다양하게 Swift가 여러 생태계에서 쓰일 수 있다는걸 느껴봤습니다.
느껴본거하고 완전히 잘 이해한건 다르겠지만!
레퍼런스
'Swift' 카테고리의 다른 글
ETag 캐싱으로 앱 성능 최적화하기 (32) 2024.11.26 Consume noncopyable types in Swift (feat. WWDC 2024) (26) 2024.11.18 Go further with Swift Testing (feat. WWDC 2024) (4) 2024.09.30 Meet Swift Testing (feat. WWDC 2024) (6) 2024.09.26 Swift 6 - @retroactive (7) 2024.09.12