SlideShare a Scribd company logo
생산성을 높여주는
iOS 개발 방법들
홍성호
iOS 개발 생산성
투입대비 결과
“낭비란 자원을 쓰면서
아무 가치도 창조하지 못하는
인간의 활동을 말한다.”
Lean Thinking
Lean
시간 낭비 줄이기
뜻: 군살없는, 기름기 없는, 낭비가 없는
낭비되는 작업의 원인을 찾고 해결
Todo list
빌드시간 최적화
UI 개발속도 향상
XcodeGen
테스트
빌드시간 최적화
UI 개발속도 향상
XcodeGen
테스트
Todo list
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
생산성을 높여주는 iOS 개발 방법들.pdf
클린빌드 vs 증분빌드
Incremental Build
XCFramework
Carthage
Swift Package Manager
CocoaPods
CocoaPods binary
Dependency Manager
XCFramework
Carthage
Swift Package Manager
Dependency Manager
XCFramework
Carthage
Swift Package Manager
Dependency Manager
XCFramework
https://developer.apple.com/videos/play/wwdc2019/416/
https://blog.embrace.io/xcode-12-and-xcframework/
Building for iOS Simulator, but the linked and embedded framework
'MyFramework.framework' was built for iOS + iOS Simulator.
XCFramework
https://developer.apple.com/videos/play/wwdc2019/416/
https://blog.embrace.io/xcode-12-and-xcframework/
XCFramework
https://developer.apple.com/videos/play/wwdc2019/416/
XCFramework
Carthage
Swift Package Manager
Dependency Manager
➜ manhwakyung-ios git:(main) cat Cartfile
github "Swinject/Swinject"
github "airbnb/lottie-ios" "master"
github "cbpowell/MarqueeLabel"
github "BranchMetrics/ios-branch-deep-linking"
github "amplitude/Amplitude-iOS" ~> 7.2.0
github "facebook/facebook-ios-sdk"
github "onevcat/Kingfisher" ~> 6.2.0
github "Alamofire/Alamofire" ~> 5.2
github "grohong/HTTPNetworking"
github "ReactiveX/RxSwift" "6.2.0"
Carthage
https://github.com/Carthage/Carthage
➜ manhwakyung-ios git:(main) carthage update --use-xcframeworks --platform ios
Carthage/Build/Kingfisher.xcframework
Carthage
https://github.com/Carthage/Carthage
Carthage/Build/Kingfisher.xcframework
-create-xcframework
https://developer.apple.com/videos/play/wwdc2019/416/
xcrun lipo -i NaverThirdPartyLogin.framework/NaverThirdPartyLogin
Architectures in the fat file: NaverThirdPartyLogin.framework/NaverThirdPartyLogin are: armv7 i386 x86_64 arm64
xcrun lipo -remove i386 -remove x86_64 -remove armv7
xcodebuild -create-xcframework -framework
NaverThirdPartyLogin.xcframework
AppLogObjC
https://developer.apple.com/videos/play/wwdc2019/416/
XCFramework
Carthage
Swift Package Manager
Dependency Manager
Braze iOS SDK : Appboy
Swift Package Manager
Carthage 를 지원하면 !
Fat Binary XCFramework
Cocoapods 만을 지원하면 코드에서 직접 XCFramework 생성
혹은 SPM
외부 디펜던시 관리
https://github.com/Carthage/Carthage
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
프로젝트 모듈화
https://swift.org/package-manager/
Local Packages
4s
4.2s
4s
Incremental build 시간 줄이기
Package.swift
https://swift.org/package-manager/
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MHKShared",
defaultLocalization: "ko",
platforms: [
.iOS(.v13),
],
products: [
.library(name: "MHKShared", targets: ["MHKShared"]),
.library(name: "MHKUI", targets: ["MHKUI"]),
.library(name: "MHKEntities", targets: ["MHKEntities"]),
],
dependencies: [
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1")),
.package(url: "https://github.com/onevcat/Kingfisher.git", .upToNextMajor(from: "6.3.0"))
],
targets: [
.target(name: "MHKShared", dependencies: []),
.target(name: "MHKEntities", dependencies: []),
.target(
name: "MHKUI",
dependencies: ["MHKShared", "MHKEntities", "SnapKit", "Kingfisher"],
resources: [.process("Resources")]
)
],
swiftLanguageVersions: [.v5]
)
Package.swift
https://swift.org/package-manager/
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MHKShared",
defaultLocalization: "ko",
platforms: [
.iOS(.v13),
],
products: [
.library(name: "MHKShared", targets: ["MHKShared"]),
.library(name: "MHKUI", targets: ["MHKUI"]),
.library(name: "MHKEntities", targets: ["MHKEntities"]),
],
dependencies: [
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1")),
.package(url: "https://github.com/onevcat/Kingfisher.git", .upToNextMajor(from: "6.3.0"))
],
targets: [
.target(name: "MHKShared", dependencies: []),
.target(name: "MHKEntities", dependencies: []),
.target(
name: "MHKUI",
dependencies: ["MHKShared", "MHKEntities", "SnapKit", "Kingfisher"],
resources: [.process("Resources")]
)
],
swiftLanguageVersions: [.v5]
)
Package.swift
https://swift.org/package-manager/
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MHKShared",
defaultLocalization: "ko",
platforms: [
.iOS(.v13),
],
products: [
.library(name: "MHKShared", targets: ["MHKShared"]),
.library(name: "MHKUI", targets: ["MHKUI"]),
.library(name: "MHKEntities", targets: ["MHKEntities"]),
],
dependencies: [
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1")),
.package(url: "https://github.com/onevcat/Kingfisher.git", .upToNextMajor(from: "6.3.0"))
],
targets: [
.target(name: "MHKShared", dependencies: []),
.target(name: "MHKEntities", dependencies: []),
.target(
name: "MHKUI",
dependencies: ["MHKShared", "MHKEntities", "SnapKit", "Kingfisher"],
resources: [.process("Resources")]
)
],
swiftLanguageVersions: [.v5]
)
Package.swift
https://swift.org/package-manager/
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MHKShared",
defaultLocalization: "ko",
platforms: [
.iOS(.v13),
],
products: [
.library(name: "MHKShared", targets: ["MHKShared"]),
.library(name: "MHKUI", targets: ["MHKUI"]),
.library(name: "MHKEntities", targets: ["MHKEntities"]),
],
dependencies: [
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1")),
.package(url: "https://github.com/onevcat/Kingfisher.git", .upToNextMajor(from: "6.3.0"))
],
targets: [
.target(name: "MHKShared", dependencies: []),
.target(name: "MHKEntities", dependencies: []),
.target(
name: "MHKUI",
dependencies: ["MHKShared", "MHKEntities", "SnapKit", "Kingfisher"],
resources: [.process("Resources")]
)
],
swiftLanguageVersions: [.v5]
)
Carthage + SPM "
Package.swift
https://swift.org/package-manager/
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MHKShared",
defaultLocalization: "ko",
platforms: [
.iOS(.v13),
],
products: [
.library(name: "MHKShared", targets: ["MHKShared"]),
.library(name: "MHKUI", targets: ["MHKUI"]),
.library(name: "MHKEntities", targets: ["MHKEntities"]),
],
targets: [
.binaryTarget(name: "Kingfisher", path: "Carthage/Build/Kingfisher.xcframework"),
.binaryTarget(name: "SnapKit", path: "Carthage/Build/SnapKit.xcframework"),
.target(name: "MHKShared", dependencies: []),
.target(name: "MHKEntities", dependencies: []),
.target(
name: "MHKUI",
dependencies: ["MHKShared", “MHKEntities", "SnapKit", "Kingfisher"],
resources: [.process("Resources")]
)
],
swiftLanguageVersions: [.v5]
)
Carthage + SPM #
Carthage + SPM #
$ 답장도 없었습니다
• 바이너리 프레임워크
• 관리비용 있음
• SwiftUI 프리뷰 깨짐 #
Carthage + SPM vs Only SPM
• 빌드 필요
• 관리하기 쉬움
• SwiftUI Preview 잘됨 ✅
다른 모듈에서 사용되는 코드에는 모두 public 해줘야 함
struct implicit initializer 사용할 수 없음
모듈화 단점
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
빌드 할 때마다 호출됨
대부분은 매번 호출될 필요 없음
스크립트 폴더에서 관리
빌드 스크립트 최적화
Localizable.strings I18N.swift
빌드 스크립트 최적화
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
Storyboard vs Code
BEFORE AFTER
라이브러리 수 줄이기
바이너리 프레임워크 사용
프로젝트 모듈화
빌드 스크립트 최적화
코드레벨 최적화
빌드시간 최적화
눈감고 배포하기
빌드시간 최적화
UI 개발속도 향상
XcodeGen
테스트
Todo list
별도의 모듈에서 작업
SwiftUI Preview
최소 의존성 관리
UI 개발
Package.swift
https://swift.org/package-manager/
targets: [
.target(name: "MHKShared", dependencies: []),
.target(name: "MHKEntities", dependencies: []),
.target(
name: "MHKUI",
dependencies: ["MHKShared", "MHKEntities", "SnapKit", "Kingfisher"],
resources: [.process("Resources")]
)
],
SwiftUI Preview
생산성을 높여주는 iOS 개발 방법들.pdf
SwiftUI
SwiftUI
⚡ 적은 의존성의 별도 모듈에서 개발
' SwiftUI 를 이용해 빠른 피드백 받기
⚙ 조립 가능한 UI 컴포넌트화
UI 개발
빌드시간 최적화
UI 개발속도 향상
XcodeGen
테스트
Todo list
XcodeGen
https://github.com/yonaskolb/XcodeGen
XcodeGen
XcodeGen
Merge Conflict
라이언 가르시아
레퍼런스만 제거된 파일들
XcodeGen
https://github.com/yonaskolb/XcodeGen
⚠
import os
import collections
cwd = os.getcwd()
all_files_in_dir = []
for path, subdirs, files in os.walk(cwd + "/Classes"):
for name in files:
if name.endswith(".swift"):
all_files_in_dir.append(name)
count = collections.Counter(all_files_in_dir)
for item in count:
if count[item] > 1:
print(item, "exist ", count[item])
pbxproj = open("Beadal.xcodeproj/project.pbxproj", 'r')
files_in_pbxproj = set([])
for line in pbxproj.readlines():
if line != "n":
for str in line.split():
if str.endswith(".swift"):
files_in_pbxproj.add(str)
# fine reference remove files
for swift_file in all_files_in_dir:
if swift_file not in files_in_pbxproj:
print(swift_file, "# ")
project.pbxproj
https://git.baemin.in/appservice/baemin-ios/-/merge_requests/7248
No more
merge conflicts! ✈
빌드시간 최적화
UI 개발속도 향상
XcodeGen
테스트
Todo list
XCTest
Nimble
xUnit
네트워크 모듈 테스트
비즈니스 로직 테스트
뷰컨트롤러 로직 테스트
단위 테스트
작은 실수 방지
리팩터링 용이
빠른 개발
테스트 장점
단위 테스트
Unit Tests
Bugs
라이언 가르시아
테스트 주도 개발
정리
✅ 빌드시간 최적화
✅ UI 개발속도 향상
✅ XcodeGen
✅ 테스트
Q & A
+

More Related Content

PDF
iOS Modular Architecture with Tuist
PDF
Let'Swift 2023 iOS 애플리케이션 개발 생산성 고찰
- 정시 퇴근을 위해 우리는 어떻게 해야할 것인가?
PDF
ReactorKit으로 단방향 반응형 앱 만들기
PDF
InjectionIII의 Hot Reload를 이용하여 앱 개발을 좀 더 편하게 하기.pdf
PDF
20220716_만들면서 느껴보는 POP
PPTX
MVC, MVVM, ReactorKit, VIPER를 거쳐 RIB 정착기
PDF
DI Container를 이용하여 레거시와 모듈화를 동시에 잡기
PDF
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
iOS Modular Architecture with Tuist
Let'Swift 2023 iOS 애플리케이션 개발 생산성 고찰
- 정시 퇴근을 위해 우리는 어떻게 해야할 것인가?
ReactorKit으로 단방향 반응형 앱 만들기
InjectionIII의 Hot Reload를 이용하여 앱 개발을 좀 더 편하게 하기.pdf
20220716_만들면서 느껴보는 POP
MVC, MVVM, ReactorKit, VIPER를 거쳐 RIB 정착기
DI Container를 이용하여 레거시와 모듈화를 동시에 잡기
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들

What's hot (20)

PDF
우아한 모노리스
PDF
SwiftUI와 TCA로 GitHub Search앱 만들기
PDF
신입 개발자 생활백서 [개정판]
PDF
Hello, ReactorKit 
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PDF
MvcのFatモデルに立ち向かう
PDF
인프런 - 스타트업 인프랩 시작 사례
ODP
MVC の Model を考える
PDF
GUI アプリケーションにおける MVC
PDF
View customize pluginを使いこなす
PPT
React js
PPTX
나의 이직 이야기
PPTX
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
PDF
이벤트 기반 분산 시스템을 향한 여정
PDF
serviceクラスをやめようサブクラスを使おう
PDF
How to build massive service for advance
PDF
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
PDF
がんばらなくても C# で Single Page Web アプリケーションが書けてしまう「Blazor」とは
PDF
REST API のコツ
PDF
NestJS
우아한 모노리스
SwiftUI와 TCA로 GitHub Search앱 만들기
신입 개발자 생활백서 [개정판]
Hello, ReactorKit 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
MvcのFatモデルに立ち向かう
인프런 - 스타트업 인프랩 시작 사례
MVC の Model を考える
GUI アプリケーションにおける MVC
View customize pluginを使いこなす
React js
나의 이직 이야기
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
이벤트 기반 분산 시스템을 향한 여정
serviceクラスをやめようサブクラスを使おう
How to build massive service for advance
숨겨진 마이크로서비스: 초고속 응답과 고가용성을 위한 캐시 서비스 디자인
がんばらなくても C# で Single Page Web アプリケーションが書けてしまう「Blazor」とは
REST API のコツ
NestJS
Ad

Similar to 생산성을 높여주는 iOS 개발 방법들.pdf (20)

PDF
효과적인 데브옵스를 위한 AWS 개발 도구 활용하기 - AWS Summit Seoul 2017
PDF
DevOps - CI/CD 알아보기
PDF
[NDC17] 왓 스튜디오 서비스파트
PDF
웹 IDE 비교
PDF
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
PPTX
LetsSwift(강민규스피커,안정민서포터).pptx
PDF
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
PDF
TOAST Meetup2015 - 구름 Cloud IDE (류성태)
PDF
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
PDF
SOSCON 2017 - Backend.AI
PPTX
Continuous Integration
PDF
01.개발환경 교육교재
PDF
클라이드 네이티브 기반 Twelve Factor 앱 개발 - 윤석찬, AWS 테크에반젤리스트 :: AWS Summit Online Kore...
PDF
Lablupconf session8 "Paving the road to AI-powered world"
PPTX
Single-page Application
PDF
[2017 AWS Startup Day] 서버리스 마이크로서비스로 일당백 개발조직 만들기
PPTX
Big Data platform을 위한 Sencha Ext JS 사례.
PDF
AWS Code 서비스 특집 - 아마존 DevOps와 CodeDeploy, CodePipeline (윤석찬)
PPTX
빠르고 지속적으로 전달하기: Continuous Delivery for Android
PPTX
개발 방식을 바꾸는 15가지 기술
효과적인 데브옵스를 위한 AWS 개발 도구 활용하기 - AWS Summit Seoul 2017
DevOps - CI/CD 알아보기
[NDC17] 왓 스튜디오 서비스파트
웹 IDE 비교
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
LetsSwift(강민규스피커,안정민서포터).pptx
NDC13: DVCS와 코드리뷰 그리고 자동화를 통한 쾌속 개발
TOAST Meetup2015 - 구름 Cloud IDE (류성태)
Backend.AI: 오픈소스 머신러닝 인프라 프레임워크
SOSCON 2017 - Backend.AI
Continuous Integration
01.개발환경 교육교재
클라이드 네이티브 기반 Twelve Factor 앱 개발 - 윤석찬, AWS 테크에반젤리스트 :: AWS Summit Online Kore...
Lablupconf session8 "Paving the road to AI-powered world"
Single-page Application
[2017 AWS Startup Day] 서버리스 마이크로서비스로 일당백 개발조직 만들기
Big Data platform을 위한 Sencha Ext JS 사례.
AWS Code 서비스 특집 - 아마존 DevOps와 CodeDeploy, CodePipeline (윤석찬)
빠르고 지속적으로 전달하기: Continuous Delivery for Android
개발 방식을 바꾸는 15가지 기술
Ad

생산성을 높여주는 iOS 개발 방법들.pdf