logo
logo
언어
Swift
애플의 iOS와 macOS를 위한 프로그래밍 언어
StackOverflow 질문 수: 335360
Github Stars : ★ 67288
사용 기업
이커머스
기타
소셜/컨텐츠
금융/보험
직장
패션
교육
부동산/인테리어
여행
푸드테크
헬스케어
모빌리티
종합
인공지능
techstack-logo
트렌비
techstack-logo
엔라이튼
techstack-logo
큐피스트
techstack-logo
핀다
techstack-logo
드라마앤컴퍼니
techstack-logo
딜리셔스
techstack-logo
뤼이드
techstack-logo
에이블리
techstack-logo
스푼
techstack-logo
크몽
techstack-logo
디셈버앤컴퍼니
techstack-logo
직방
techstack-logo
당근
techstack-logo
마이리얼트립
techstack-logo
버킷플레이스
techstack-logo
버즈빌
techstack-logo
마켓컬리
techstack-logo
에이비일팔공
더 보기
기술 블로그 글
스포카
발전하는 iOS와 Clean Swift Architecture
스포카 iOS 플랫폼에서는 Clean Swift 아키텍처를 기반으로 키친보드와 키친보드 유통사 iOS 앱을 개발하고 있습니다.Clean Swift란, Uncle Bob의 클린 아키텍처를 iOS, MacOS 플랫폼에 맞게 적용한 형태의 아키텍처입니다.이 글에서는 스포카에서 Clean Swift 기반으로 iOS 앱을 개발하며 겪었던 어려움과 이를 어떻게 개선하였는지에 대한 내용을 다루어보겠습니다.왜 Clean Swift를 채택하는가?Clean Swift 아키텍처를 제품 개발에 꾸준히 사용한 이유는 아래와 같습니다.• 키친보드 iOS 앱의 아키텍처는 언제든지 바뀔 수 있다.• 스포카 모바일 챕터는 규모가 크지 않습니다. 그래서 추후 여러 사람과 공동으로 작업하게 되었을때 손쉽게 다른 아키텍처를 결합하거나, 현재의 아키텍처를 개선할 수 있어야한다고 보았습니다.• Clean Swift가 추구하는 프레임워크가 아닌 템플릿으로 만들어지는 아키텍처 구조는 특정 아키텍처에 강하게 결합되지 않도록 도와주었고 이는 개선에도 용이하였습니다.• 키친보드 iOS 앱은 로직의 복잡도가 높다.• 키친보드 서비스는 무거운 도메인들과 관리되어야하는 케이스가 다소 존재하는 편입니다. 저희는 이러한 로직의 복잡도가 UI의 복잡도보다 높다고 판단하였습니다.• 클린 아키텍처를 기반으로 한 Clean Swift는 iOS 플랫폼에 특화된 고수준과 저수준을 분리하는 방식을 제시합니다.• 이러한 고수준 비즈니스 논리의 분리가 키친보드 iOS 앱 코드의 복잡도를 낮출 수 있었습니다.그러나 Clean Swift를 적용하며 마주한 문제가 있었습니다.저희가 마주한 Clean Swift의 문제점은 발전하는 iOS 문제였습니다.iOS 플랫폼은 끊임없이 발전을 거듭했습니다. SwiftUI의 등장, 상태 관리의 중요성 대두, 새로운 비동기 처리 방식의 도입 등 Swift 언어와 패러다임은 다소 많은 변화를 거쳤습니다.iOS 플랫폼의 클린 아키텍처라는 말이 무색하게 2015년에 발표된 Clean Swift는 2024년의 iOS 플랫폼에는 맞지 않게 된 것이었습니다.이러한 Clean Swift의 문제점을 마주하여 새로운 기술 도입에 어려움을 겪었고, 새로운 아키텍처로의 변경을 생각하기도 했었습니다.그러나 앞서 언급드린 프레임워크가 아닌 템플릿, 고수준과 저수준 분리 등 Clean Swift에서 제시하는 방향성은 여전히 유효하여 깊은 고민이 되었습니다.Clean Swift를 만든 Raymond는 블로그에서 아래와 같은 말을 하였습니다.Raymond의 말처럼, 저희는 Swift 언어가 지속적으로 발전하는 만큼 더 나은 방법을 찾아 나아가야한다고 보았습니다. 그래서 Clean Swift를 변형하여 언어와 패러다임의 발전에 맞추는 여러 시도들을 해보았습니다.이 글에서는 저희가 설계한 완벽하진 않지만 더 나은 방법(better ways)의 Clean Swift를 소개해 드려 보고자 합니다.먼저 개선한 Clean Swift의 설계 목표로 기존의 장점들을 포함한 다음의 4가지를 선정하였습니다.• Single Re
swift
라인
Swift Concurrency 성능 조사
안녕하세요. LINE Plus iOS Platform Dev 팀에서 iOS 개발을 하고 있는 김윤재입니다. 2021년에 Swift Concurrency가 등장했을 때 LINE Engineering 블로그에 Swift Concurrency를 소개하는 글(Swift Concurrency에 대해서)을 남겼습니다. 어느덧 글을 쓴 지 2년이 지났네요. 당시에는 주로 Swift Concurrency의 장점을 소개했는데요. 이번 글에서는 최근 팀에서 Swift Concurrency를 적용할 때 성능 관점에서 어떤 점을 주의해야 할지 스터디를 진행하며 알게 된 점을 공유하려고 합니다.Swift Concurrency의 두 가지 특징성능 관점에서 주의해야 할 점을 살펴보기 전에 Swift Concurrency 내부 작동 방식의 두 가지 특징인 TaskPriority와 Suspension points를 먼저 살펴보겠습니다.TaskPriority 작동 방식Swift Concurrency에는 GCD(Grand Central Dispatch)의 QoS(Quality of Service)와 같은 역할을 하는 TaskPriority가 있습니다. 아래는 Swift TaskPriority와 GCD QoS를 서로 상응하는 우선순위에 맞게 배치한 표입니다. 같은 행에 속하면 같은 우선순위입니다.QoS(GCD) TaskPriority(Swift Concurrency) Userinitiated High Default Medium Utility LowSwift Concurrency의 장점 중 하나로 소개된 것이 스레드를 코어 수만큼만 사용해서 콘텍스트 스위칭이 적다는 것이었습니다(참고: WWDC 2021: Swift Concurrency - Behind the Scenes). 그렇다면 스레드 숫자가 코어 수로 제한되는 상황에서 우선순위에 따른 스케줄링을 어떻게 진행하는지 아래와 같은 의문이 들었습니다.우선순위가 다양한 작업이 있을 때 OS는 어떤 방식으로 각 작업에 스레드를 할당할까?우선순위가 더 높은 작업이 많을 때 우선순위가 낮은 작업은 어떻게 실행을 보장받을까?이 의문을 해결하기 위해 우선순위가 높은 작업을 먼저 실행한 뒤 낮은 작업을 실행해 결과를 살펴보고, 다음에는 우선순위가 낮은 작업부터 실행해서 결과를 살펴봤습니다.우선순위가 높은 작업부터 추가했을 때 스레드 할당 방식먼저 TaskPriority가 High인 작업들을 추가한 뒤, 이어서 Low인 작업들을 추가하는 방식으로 테스트를 진행했습니다. 테스트는 코어가 6개인 iPhone 12 Pro 기기로 진행했습니다. 따라서 Swift Concurrency에서 스레드를 6개 사용할 것이라고 판단, High 작업을 6개 추가한 뒤 Low 작업을 6개 추가했습니다.Xcode Instruments에서 Swift Concurrency 프로파일링 템플릿을 이용해 진행한 프로파일링 결과 중 두 가지, 작업 상태(Task states)와 스레드(Threads) 결과를 살펴보겠습니다.먼저 작업 상태는 아래와 같이 나타났습니다. 상위
swift
당근
당근마켓 모바일 실험실: Rust로 공유 라이브러리 만들기
서비스를 개발하다보면 각자 전문적인 개발 영역을 벗어나 공통적인 엔지니어링 문제를 해결해야 하는 경우가 있는데요. 당근마켓에는 이를 “플랫폼”으로 녹여내 효율적으로 풀어낼 수 있도록 고민하며 도와주는 “모바일 플랫폼 팀” 있습니다. 당근마켓 엔지니어들은 모바일 플랫폼 팀과 협력하며 여러 문제를 해결해 나가고 있어요.플랫폼 기능은 한 번 추가되면 모두가 함께 오랫동안 사용하게 되기 때문에 마구잡이로 일단 추가하는 것보다는 테크 스펙부터 사전 실험까지 여러 과정을 거쳐 꼼꼼하게 검토해서 추가하는 편이에요. 그러다 보니 그 중에서는 굉장히 오랜 호흡을 가지고 진행되거나 중간에 버려지는 것들도 있어요.이런 다양한 시도들 중 이미 도입되어 “결과”로써 흥미로운 사례들 뿐만 아니라, “과정”이 흥미로운 실험들을 소개하고 대내외적으로 교훈을 공유하기 위해 “당근마켓 모바일 실험실” 글을 써볼까 해요. 중간 과정을 공유함으로써 비슷한 고민을 가지고 있는 다른 조직과 소통하고 의견을 나누는 데 도움이 되길 바랍니다 :)첫 번째 글에서는 당근마켓 모바일 앱에 크로스 플랫폼 모듈을 도입하기 위한 고민을 소개해 볼게요.장치 플랫폼(Android/iOS/Web) 간 중복 구현 문제개발자들은 플랫폼 기능을 사용할 때 통합된 인터페이스를 통해 구현 디테일이나 장치 플랫폼 간의 차이를 신경쓰지 않고 사용할 수 있기를 기대해요.실제 구현은 Android와 iOS에서 각각 구현(JavaScript Bridge를 사용하지 않는 경우 Web에서도 따로 구현)해야 하기 때문에 일관적인 동작을 보장하기 위해서는 사전에 충분한 협의와 소통, 검증이 필요해요. 모바일 플랫폼 팀에서는 각 플랫폼 개발자들이 모여 스펙을 먼저 리뷰하고, 테스트 코드를 먼저 작성하는 식으로 이런 과정을 수행해왔어요.하지만 이런 방식들은 결국 사람의 개입에 의존하기 때문에 100% 완전함을 보장하기 어렵고, 실제 구현 차이로 인해 예상치 못한 문제를 발생시킬 수도 있어요.무엇보다 구현과 관리에 대한 비용이 플랫폼마다 중복해서 들어가기 때문에 새로운 플랫폼 기능을 제안 할 때 마다 지속적으로 부담을 느끼게 했어요.이런 부담을 줄이기 위해서 여러 플랫폼 간 코드를 공유할 수 있는 방법이 없을까 탐색하기 시작했어요. 혹시 쉬운 방법이 있다면 플랫폼 개발환경을 모르는 개발자가 직접 로직을 구현해서 함께 제안할 수도 있을거라 기대했어요.네이티브 라이브러리를 통한 코드 공유플랫폼 동작에 의존하지 않는 코어 로직을 공유하는 경우라면, 네이티브 라이브러리(.a, .so, .dylib 등)를 빌드할 수 있는 C와 같은 언어로 하나의 코드를 작성해서 공유하면 이런 구현 중복 문제를 줄일 수 있어요.Android의 경우 NDK(Native Development Kit)라는 도구를 사용해서 C 코드나 네이티브 라이브러리를 호출 할 수 있어요.C로 작성된 모듈의 인터페이스 규약이나 메모리 구조가 Java/Kotlin 과 다르기 때문에 상호운용(Interop)을 위해서 FFI(Foreign Function Interface) 작
java
javascript
kotlin
rust
swift
당근
Tuist 를 활용해 확장 가능한 모듈 구조 만들기
배경앱의 규모가 커지면 커질수록 단일 프로젝트로 앱을 개발하기 점점 어려워집니다. 먼저 빌드 속도가 느려지고, 객체간 물리적 의존을 끊을 수 없기 때문에 설계가 오염되는 경우가 많습니다.물리적 의존이란?모듈이 분리되지 않으면, 객체간 접근이 물리적으로 제한되는 것이 아니기에, 객체를 오용하기 쉽습니다. (개인의 의지에 따라 코드를 작성할 수 있다)ex) 추상화된 객체가 구체적인 구현체를 알게되는 상황당근마켓에서는 위 문제를 해결하기 위해 앱 프로젝트를 수많은 모듈로 분리했고, 이를 쉽게 관리하기 위해 Tuist 라는 도구를 활용하고 있습니다.당근마켓) XcodeGen 에서 Tuist 로 전환하기기준 없이 모듈을 분리만 한다면, 프로젝트의 구조는 더 복잡해지고 얻을 수 이점이 줄어듭니다.최근, 모듈 분리를 처음 시도하는 분들을 위해 당근마켓의 앱을 관통하는 Modular Architecture 에 대해 소개했습니다.MVVM, MVI 등 흔히 이야기되는 Presentation Layer 아키텍처와 다른 개념입니다.https://medium.com/media/17a1a4c9b817a6cd5a58500f7eda216f/href발표 내용을 짧게 요약해보면..역할에 따라 모듈 계층을 나눠 설계합니다.계층에는 Feature, Domain, Core, Shared 가 존재합니다.새로운 모듈을 추가할 때 모듈의 역할에 따라 적절한 계층을 지정하고, 인터페이스와 구현체를 분리할지 판단합니다.위 아키텍처를 토대로 당근마켓 프로젝트는 수십개의 모듈에서 수백개의 모듈로 분리되었고, 점차 기존의 방식으로 Xcode 프로젝트를 관리하기 어려워졌습니다.이번 글에서는 당근마켓에서 Tuist 를 활용해 어떻게 Xcode 프로젝트 관리 경험을 개선했는지 소개합니다.모듈이 많아지며 생기는 문제모듈의 수가 점차 늘어나면서 Tuist 에서 기본적으로 제공하는 인터페이스만으로는 프로젝트 관리에 어려움이 발생했습니다.별도의 개선 없이 Tuist 를 사용하면 수백개의 프로젝트 의존성이 존재하더라도, 이를 String 타입에 의존해 모듈을 추가하고 의존성을 구성하게 됩니다.이 때 엔지니어들은 프로젝트 구성에 어려움을 느낄 수 있고, 실수가 발생하기 쉽습니다.구체적인 예시로 살펴보겠습니다.// Project.swiftTarget( name: "FooFeature", platform: .iOS, product: .framework, bundleId: "com.featrues.foo", infoPlist: .default, sources: "Sources", dependencies: [ // 의존성을 String 기반으로 추가해야 함 .project( target: "BarFeatureInterface", path: .relativeToRoot("Projects/Feature/Bar") ), .project( target: "BazFeatureInterface", path: .relativeToRoot("Projects
swift
tuist
Copyright © 2024. Codenary All Rights Reserved.