iOS 개발자라면,,한번쯤은 공부하고 싶던 부분인 컴파일 - 아카이빙 까지의 모든 과정을 공부해봐요.
목차는 다음과 같아요.
오늘은 ABI에 대해 알아보아요.
ABI (Application Binary Interface) 를 쉽게 비유하자면, API 가 ‘소스 코드 수준’에서의 약속 이라면, ABI는 ‘이미 컴파일된 바이너리 수준’에서의 약속이에요.
우리가 만든 앱은 혼자 돌아가지 않아요. iOS 운영체제에 내장된 라이브러리(Foundation, UIKit 등)와 끊임없이 소통해야 하죠. 이때 “데이터를 어떤 메모리 위치에 놓을지”, “함수를 호출할 때 파라미터를 어떤 순서로 전달할지”에 대한 엄격한 규칙이 필요한데, 이것이 바로 ABI 에요.
주요 포함 사항은 다음과 같아요.
조금 더 자세히 알아볼게요.
ABI의 핵심 중 하나는 함수를 호출할 때 CPU 레지스터와 스택을 어떻게 나눠 쓸지에 대한 약속이에요. 이 규칙은 CPU의 성능을 최대로 끌어올리기 위함이에요. 메모리(RAM)에 접근하는 것 보다 레지스터를 쓰는게 훨씬 빠르기 때문이죠.
func calculate(a: Int, b: Int, c: Int) -> Int {
return a + b + c
}
// ABI 약속 (x86_64 아키텍처 예시)
// 1. a는 %rdi 레지스터에 담아라
// 2. b는 %rsi 레지스터에 담아라
// 3. c는 %rdx 레지스터에 담아라
// 4. 결과값은 %rax에 담아서 돌려줘라
%rdi 레지스터에, 두 번째는 %rsi 에 넣는다는 식의 규칙이에요.self 는 보통 특정 레지스터에 고정적으로 담겨요.이게 왜 중요하냐면, 만약 Swift와 C++이 서로 대화한다면 이 규칙이 서로 다르기 때문에 중간에 Bridge 역할을 하는 코드가 필요하게 돼요.
Swift ABI 문서에 따르면, Swift는 구조체나 Enum이 작을 경우 이를 여러 개의 레지스터에 나누어 담는 'Physical Lowering' 과정을 거쳐요.
또한, Enum이 비트 최적화를 통해 8바이트 안에 모든 정보를 담았다면, ABI는 이를 하나의 64비트 레지스터 (ex. %rdi ) 에 담아 보낼 수 있게 돼요. 만약 최적화 규칙이 ABI에 고정되어 있지 않다면, 컴파일러는 이 데이터를 레지스터에 어떻게 효율적으로 나눠 담을지 결정할 수 없어요.
ABI는 구조체나 클래스가 메모리에 어떤 모습으로 누워있을지를 결정해요.
struct MixedData {
var a: Int8 // 1 byte
var b: Int // 8 bytes (64-bit 시스템 기준)
var c: Int8 // 1 byte
}
print(MemoryLayout<MixedData>.size) // 실제 데이터 크기: 10 bytes
print(MemoryLayout<MixedData>.stride) // 실제 차지하는 공간: 24 bytes (Padding 발생!)
Int64는 8바이트 단위로 시작하는 주소에 배치해야 CPU가 빨리 읽어요. ABI는 데이터 사이에 Padding(빈 공간)을 얼마나 넣을지 규칙을 정해요.아까 SIL에서 본 @$s8ViewTypeAAO... 같은 이름이 기억나시나요? 이것도 ABI의 영역이에요.
이게 가장 마법 같은 부분이에요. 라이브러리가 업데이트되어 프로퍼티가 추가되어도, 그 라이브러리를 쓰는 앱을 다시 컴파일하지 않아도 되는 기능이에요.
Swift 4까지는 이 ABI가 버전마다 계속 바뀌었어요. 이게 왜 문제였을까요?
2019년 Swift 5가 발표되면서 드디어 ABI가 고정되었습니다. Apple은 “앞으로 나올 모든 iOS 버전은 Swift 5의 바이너리 규약을 따를게!” 라고 선언한 것이죠.
이로 인해 얻은 이점
여기서 헷갈리기 쉬운 개념이 하나 더 있어요.
import 할 수 있게 해줘요. (이건 .swiftinterface 라는 파일을 통해 해결해요.)이전에 알아본 PWT. PWT는 함수 주소록이라고 했죠. ABI가 안정화되었다는 것은 “PWT의 구조가 바뀌지 않는다”는 약속도 포함돼요.
만약 ABI가 바뀌어서 “PWT의 3번째 칸은 이제 함수 주소가 아니라 타입 크기를 넣기로 했어!”라고 해버리면 기존 앱들은 3번째 칸에서 주소를 찾으려다 엉뚱한 곳을 찌르고 크래시가 날 거에요. ABI Stability 는 이런 ‘메모리상의 지도’를 영구히 고정한 것이에요.
ABI는 “이진법 대화의 예의범절”
공부를 하면서 제 회사의 Xcode 호환성 문제를 다시 생각해볼 수 있었어요.
저희 회사는 Xcode 16으로 빌드를 진행했었는데, 이번에 Xcode 26으로 빌드를하게 되었죠. 근데 Module Stability의 개념을 모른 상태로 SDK를 빌드하였고, 이를 알게 된 이후에 코드를 확인 해보았는데,

앗차차..저희 SDK 자체가 Build Libraries for Distribution 값이 NO로 되어있었습니다.
이 값을 YES로 바꾸면 호환성 문제가 해결된다고 해요.
왜 그런거죠?
프레임워크 안에 .swiftinterface 가 포함되어 있기 때문이에요. Xcode 26의 컴파일러가 이 텍스트 파일을 읽고 “아, 이전 버전 혹은 미래 버전은 이런 함수를 만들었구나!” 라고 이해하며 연결(Bridge)해 줘요.