์•ž์œผ๋กœ ๊ทธ๋ฆผ์—์„œ ๋‚˜์˜ค๋Š” Swift version์€ ๊ฐ€์ƒ์ด๋‹ค. ์ดํ•ด๋ฅผ ์œ„ํ•ด์„œ ๊ฐ€์ƒ์œผ๋กœ ์ ์—ˆ๋‹ค.

์‚ฌ์ „ ์ง€์‹

otool

Object๋ฅผ dumpํ•ด์„œ ๋‚ด์šฉ๋“ค์„ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋Š” utility

๊ทธ ์ค‘ otool -L์€ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋””ํŽœ๋˜์‹œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…๋ น์–ด์ด๋‹ค. ์ฆ‰, ์ด ๋ช…๋ น์–ด๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์ด ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ์™ธ๋ถ€ ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ path๋ฅผ ๋‚˜์—ดํ•ด์ค€๋‹ค. ๋‚ด๊ฐ€ ๋งŒ๋“  testFramework ์‹คํ–‰ํŒŒ์ผ์— ํ•ด๋‹น ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž. (์ด๊ฑด Swift 2.0 ๋ฒ„์ „์ด๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‹ค. ๋’ค์— ๋‚˜์˜จ๋‹ค.)

$ otool -arch arm64 -L testFramework
testFramework:
    /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1673.126.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
    /System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
    @rpath/libswiftCore.dylib (compatibility version 1.0.0, current version 1100.2.255)
    @rpath/libswiftFoundation.dylib (compatibility version 1.0.0, current version 0.0.0)
    @rpath/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 0.0.0)

์‹œ์Šคํ…œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Foundation๊ณผ UIKit์ด ๋ณด์ธ๋‹ค. @rpath๋ผ๊ณ  ๋‹ฌ๋ ค์žˆ์ง€ ์•Š์€ ๊ฒฝ๋กœ๋Š” system library์ด๋‹ค.

@rpath๋Š” ์‹คํ–‰๋˜๋Š” binary์˜ ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ(์ฆ‰ ์ƒ๋Œ€ ๊ฒฝ๋กœ๋กœ) dynamic library๋‚˜ framework์˜ ์œ„์น˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. Run-Path๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค. ๋ณดํ†ต ์„ค์น˜๋˜๋Š” App Bundle์— dynamic library๊ฐ€ ํฌํ•จ๋˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•œ๋‹ค. Xcode Project file์—์„œ๋Š” ๋‹ค์Œ์˜ ๊ฒฝ๋กœ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Xcode > Build Settings > Linking > RunPath Search Paths

๊ทธ๋Ÿฐ๋ฐ ์ด์ƒํ•œ ๊ฒŒ ์žˆ๋‹ค. dynamic library๋‚˜ framework๋Š” ์™ธ๋ถ€์—์„œ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์•„๋‹Œ๊ฐ€? ์ง€๊ธˆ์€ ์™ธ๋ถ€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์•„์˜ˆ ์—†์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  @rpath๊ฐ€ ์žˆ๋‹ค. ์•„๋ฌด๋ž˜๋„ ์‹œ์Šคํ…œ์— ๊ด€๋ จ๋œ ๋…€์„ ์ฆ‰, Swift, Foundation, ObjectiveC์— ๊ด€๋ จ๋œ ๋…€์„์ธ ๊ฒƒ ๊ฐ™์€๋ฐ ์™œ Bundle ๋‚ด๋ถ€์— ์ถ”๊ฐ€๋˜์–ด ์žˆ์„๊นŒ?

์—ฌ๊ธฐ์„œ ์˜๋ฌธ์ ์ด ๋“ค์—ˆ๋‹ค๋ฉด ์ž˜ ์ฐพ์•„์™”๋‹ค.

App Package Inside

์ผ๋‹จ ๋‹ค์–‘ํ•œ ์•„ํ‚คํ…์ณ์— ๋Œ€์‘๋˜๋Š” ์‹คํ–‰ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ณด์ž. Xcode์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ Any iOS Device target์œผ๋กœ ๋นŒ๋“œํ•œ๋‹ค. ๋นŒ๋“œํ•œ Product๋ฅผ ๋ณด๋ ค๋ฉด DerivedData(ํŒŒ์ƒ ๋ฐ์ดํ„ฐ)์— ์ ‘๊ทผํ•˜๋ฉด ๋œ๋‹ค. ์ด์ „์—๋Š” project navigator์— products๋ผ๋Š” group์ด ์žˆ์—ˆ๋Š”๋ฐ, ์—†์–ด์ง„ ๋“ฏ ํ•˜๋‹ค.

  • ๊ฒฝ๋กœ: ~/Library/Developer/Xcode/DerivedData

Xcode์—์„œ ํ•ด๋‹น ๊ฒฝ๋กœ๋ฅผ ๋ฐ”๋กœ ์ฐพ์•„๊ฐ€๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Xcode > Preference > Locations > Derived Data

  • Xcode > File > Project Settings > Derived Data

ํ•ด๋‹น ๊ฒฝ๋กœ ์•ˆ์—๋Š” ๋‚ด๊ฐ€ ๋นŒ๋“œํ•œ ํ”„๋กœ์ ํŠธ๋“ค์ด ๋ชจ์—ฌ ์žˆ๋‹ค. ํ”„๋กœ์ ํŠธ ์ด๋ฆ„ + ํ•ด์‹œ๊ฐ’์˜ ํ˜•ํƒœ์˜ ํด๋”๋“ค์ด ๋ณด์ผ๊ฑฐ๋‹ค.

App์„ ๋นŒ๋“œํ•œ ๊ฒฝ์šฐ์—๋Š” Package ํ˜•ํƒœ๋กœ ๋ฌถ์—ฌ์žˆ์–ด ์˜ค๋ฅธ์ชฝ ํด๋ฆญ ํ›„ โ€œํŒจํ‚ค์ง€ ๋‚ด์šฉ ๋ณด๊ธฐโ€๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ Framework๋ผ๋ฉด Opaque directory๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ํด๋” ํ˜•ํƒœ์ธ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ์„ค๋ช…์ด ์–ด๋ ต๋‹ค๋ฉด Package, Bundle์„ ์ฝ๊ณ  ์˜ค๋ฉด ์ข‹๋‹ค.

ABI

์ผ๋‹จ ๋‹จ์–ด๋ถ€ํ„ฐ ๋ฌด์Šจ์†Œ๋ฆฌ์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค. ์ผ๋‹จ ABI๋ผ๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ผ๊นŒ?

Application Binary Interface

ํ”ํžˆ ์•„๋Š” API(Application Programming Interface)์™€ ๋น„์Šทํ•˜๋‹ค. API์˜ ๊ฒฝ์šฐ ํŠน์ • ํ•จ์ˆ˜๋‚˜ property๋ฅผ ๊ณต๊ฐœํ•˜๊ณ , ํƒ€ ํ”„๋กœ๊ทธ๋žจ ํ˜น์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” cheat sheet?์˜ ๊ฐœ๋…์ด๋‹ค. ๋ง ๊ทธ๋ž˜๋„ interface์ธ ๊ฒƒ.

ABI ์—ญ์‹œ interface์ด๋‚˜, ์˜์—ญ์ด binary์ธ ๊ฒƒ์ด ๋‹ค๋ฅด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ , ์ปดํŒŒ์ผํ•˜๋ฉด ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ๋กœ binary code๊ฐ€ ๋‚˜์˜จ๋‹ค. ๊ฒฐ๊ตญ ์ด ์นœ๊ตฌ๋“ค๊ณผ ์ƒํ˜ธ ์†Œํ†ตํ•˜๋ฉฐ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์ฝ”๋“œ๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ์ดํ•ดํ•˜์—ฌ product๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ. ๊ทธ๋Ÿผ ์ด ํ™˜๊ฒฝ์—์„œ ์—ญ์‹œ ์„œ๋กœ ์–ด๋–ป๊ฒŒ ์†Œํ†ตํ• ์ง€์— ๋Œ€ํ•œ ๊ทœ์•ฝ์ด ํ•„์š”ํ•˜๋‹ค. ๊ทธ๊ฒƒ์ด ABI์ด๋‹ค.

๋Ÿฐํƒ€์ž„์— Swift ํ”„๋กœ๊ทธ๋žจ์˜ binary๋Š” ๋‹ค๋ฅธ library์™€ ABI๋ฅผ ํ†ตํ•ด ์†Œํ†ตํ•œ๋‹ค. API๋ฅผ ์ •์˜ํ•  ๋•Œ๋Š” ๋ณดํ†ต ํ•จ์ˆ˜์˜ ์ด๋ฆ„, ํƒ€์ž…, ์ธ์ž, ๋ฐ˜ํ™˜ ํƒ€์ž…๋“ฑ์„ ์ •์˜ํ•œ๋‹ค. ABI์˜ ๊ฒฝ์šฐ์—๋Š” ํ•จ์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœํ• ์ง€, ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ• ์ง€, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋””์— ๋†“๊ณ  ์–ด๋–ป๊ฒŒ ์ ‘๊ทผํ• ์ง€ ๋“ฑ์„ ์ •์˜ํ•œ๋‹ค.

  • CPU instructions (registers, stack organization, memory access type) CPU๋ช…๋ น์–ด
  • calling convention(ํ•จ์ˆ˜ ํ˜ธ์ถœ, argument์ „๋‹ฌ, ๊ฐ’ ๋ฆฌํ„ด)
  • OS์— ๋Œ€ํ•œ ์‹œ์Šคํ…œ ํ˜ธ์ถœ
  • Data Layout
  • Type Metadata
  • Mangling
  • Runtime
  • Standard Library

์ดํ•ด๋ฅผ ์œ„ํ•ด์„œ! Dynamic library๋ฅผ ๋กœ๋“œํ•˜์—ฌ ์‚ฌ์šฉํ•  ๋•Œ ํ•„์š”ํ•œ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•˜์ž. Dynamic library์˜ ๊ฒฝ์šฐ ์ด๋ฏธ ์ปดํŒŒ์ผ๋œ ์‹คํ–‰ํŒŒ์ผ ์ž์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์™€์„œ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ ค ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, Binary ์˜์—ญ์—์„œ์˜ interface๊ฐ€ ํ•„์ˆ˜์ ์ด๋‹ค.

ABI Stability (Binary Compatibility)

ABI Stability๋Š” Swift 5.0์—์„œ ํ™•๋ณด๋œ ๊ธฐ๋Šฅ์ด๋‹ค. ์ด๊ฒŒ ๋„๋Œ€์ฒด ์™œ ํ•„์š”ํ• ๊นŒ? ์‰ฝ๊ฒŒ API๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ƒ๊ฐํ•ด๋ณด์ž. ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ด์•„๋‘” ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š” API version 1.0์„ ๋ฐฐํฌํ•ด์„œ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๋‹ค๊ณ  ํ•˜์ž. ๊ทธ๋Ÿฐ๋ฐ version 2๋กœ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋˜๋ฉด์„œ, ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋˜ interface์˜ ์ด๋ฆ„์ด ๋ฐ”๋€Œ์—ˆ๋‹ค! ํ˜น์€ ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ์กฐํšŒํ•˜๋Š”๋ฐ, ์•ˆ์ „๋ชจ๋“œ(?)์—์„œ ์ ‘๊ทผํ•˜๋Š”์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ์ธ์ˆ˜๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค๊ณ  ํ•˜์ž. ๊ทธ๋Ÿผ client์ชฝ์€ (ํ•ด๋‹น API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ชฝ) ์•„์˜ˆ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•˜๊ฒŒ ๋œ๋‹ค.

์ด์™€ ๋งˆ์ฐฌ๊ฐ€์ง€์˜ ์ƒํ™ฉ์ด๋‹ค! Swift ๋ฒ„์ „์ด ๋ณ€๊ฒฝ๋˜๋ฉด, ํ•ด๋‹น ์–ธ์–ด๋ฅผ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋Š” Compiler์˜ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚˜๊ณ , ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ABI์—ญ์‹œ ๋ณ€๊ฒฝ๋œ๋‹ค. Swift 2.0์œผ๋กœ ๋งŒ๋“ค์–ด๋‚ธ binary file๋ฅผ Swift 3.0์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค. ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Package์— Swift runtime library๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•˜์œ„ ๋ฒ„์ „์˜ OS์™€ ํ˜ธํ™˜์„ ํ™•๋ณดํ•ด์•ผ ํ–ˆ์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด์ „ Swift 2.0 ๋ฒ„์ „์˜ App์„ ๋ณด๋ฉด(ipa๋ฅผ ์—ด๋ฉด) .dylib๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค. (Swift dynamic library) ์ฆ‰, ๋‹ค๋ฅธ ๋ฒ„์ „์˜ binary ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด App Bundle์— ์ด๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ๋ฐฐํฌํ–ˆ๋˜ ๊ฒƒ.

๊ทธ๋ ‡๋‹ค๋ฉด ABI Stability๋ฅผ ์ง€์›ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์–ด๋–ค ๋ง์ผ๊นŒ?

Swift Dynamic library(Swift Runtime library)๊ฐ€ OS์˜ ์ผ๋ถ€๊ฐ€ ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด Swift version์— ์ƒ๊ด€์—†์ด ํ•ด๋‹น binary๋ฅผ ํ•ด์„ํ•˜๋Š” ABI๋Š” OS๊ฐ€ ๋“ค๊ณ  ์žˆ์–ด์„œ App Package์— ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค! ๊ทธ๋ž˜์„œ deployment target 13.0 ์ด์ƒ ์„ค์ • ์‹œ, Swift Runtime Library์˜ ์œ„์น˜๊ฐ€ @rpath์—์„œ system path๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค.

$ otool -arch arm64 -L testFramework
testFramework:
    /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1673.126.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
    /System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
    /usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 1100.2.255)
    /usr/lib/swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 0.0.0)
    /usr/lib/swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 0.0.0)

์•„๋ž˜์˜ 3๊ฐœ ํ•ญ๋ชฉ์ด OS ๊ฒฝ๋กœ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค. ์ด์ œ ์˜๋ฌธ์ ์ด ํ•ด์†Œ๋˜์—ˆ๋‹ค!

์žฅ์ 

์ผ๋‹จ ์• ํ”Œ์˜ ์ž…์žฅ์—์„œ ํ”Œ๋žซํผ ์•ˆ์ •ํ™”๋ฅผ ๊ฐ€์ง„๋‹ค๋Š” ์ ์—์„œ ์ข‹์„ ๊ฒƒ์ด๋‹ค. ํ  ๊ฐœ๋ฐœ ๊ด€์ ์—์„œ๋งŒ ๋ณด์ž๋ฉด,

  • App๊ณผ Library๊ฐ„์˜ Binary Compatibility๋ฅผ ๊ฐ€์ง„๋‹ค.
    • ํŠน์ • ๋ฒ„์ „์˜ Swift Compiler๋กœ ๊ตฌ์ถ•๋œ Product๋ฅผ ๋ฒ„์ „์— ์ƒ๊ด€์—†์ด ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฒˆ๋“ค ํฌ๊ธฐ ๊ฐ์†Œ
    • ์ด์ „์—๋Š” Swift Runtime Library๋ฅผ ์ถ”๊ฐ€ํ•ด์คฌ์–ด์•ผ ํ–ˆ๋Š”๋ฐ ๋นผ๋„ ๋œ๋‹ค. (๊ทผ๋ฐ ํ•œ 5mb ํ•œ๋Œ€..)
  • Migration ๋น„์šฉ ๊ฐ์†Œ
    • ๊ฐœ๋ฐœ์ž์—๊ฒŒ ํ˜ธ์žฌ์š” ํ˜ธ์žฌ

Reference