안녕하세요! iOS 개발에서 정말 중요한 보안 메커니즘에 대해 정리해보겠습니다.
프로비저닝 프로파일과 샌드박스는 iOS 생태계의 핵심 보안 기둥이라고 할 수 있어요 🔐🔐🔐
프로비저닝 프로파일
왜 애플은 앱스토어 외부에서 앱을 설치하기 어렵게 만들었을까요? 🤔
바로 신뢰성 때문입니다. "이 개발자가 만든 앱을 내 기기에서 실행해도 될까?"라는 질문에 대한 답이 프로비저닝 프로파일이에요.
What is 프로비저닝 프로파일?
프로비저닝 프로파일은 특정 디바이스에서 특정 앱을 실행할 수 있는 허가증입니다. 마치 출입증처럼 "이 사람(개발자)이 만든 이 앱(Bundle ID)을 이 기기(Device UUID)에서 실행해도 됩니다"라고 애플이 보증해주는 거죠
구성요소
- 앱 ID (Bundle Identifier): com.yourcompany.appname 형태의 고유 식별자
- 디바이스 UUID: 앱 실행이 허용된 기기들의 고유 번호
- 인증서: 개발자 신원을 증명하는 디지털 증명서
- 권한 (Entitlements): 푸시 알림, 결제 등 특별한 기능 사용 권한
프로비저닝 프로파일 종류
1. Development 프로파일
개발하면서 "왜 내 앱이 실기기에서 안 돌아가지?" 하는 경험 있으시죠? 바로 이 프로파일이 없어서입니다.
- 용도: 개발 및 디버깅
- 특징: 등록된 개발 기기에서만 실행 가능, 디버거 연결 허용
- 제한: 최대 100대의 기기까지만 등록 가능
2. Ad Hoc 프로파일
베타 테스트할 때 정말 유용해요. 앱스토어에 올리기 전에 선택된 사용자들에게만 배포할 수 있거든요.
- 용도: 내부 테스트, 클라이언트 데모
- 특징: 특정 기기 UUID 목록 포함
- 제한: Development와 동일하게 100대 제한
3. Distribution 프로파일
앱스토어 배포용입니다. 기기 UUID 목록을 포함하지 않아서 전 세계 모든 iOS 기기에서 실행 가능해요.(1과의 차이점이죠)
4. Enterprise 프로파일
회사 내부용 앱을 만들 때 사용합니다. 기기 제한이 없어서 정말 편하지만, Enterprise 개발자 계정이 필요해요 (연간 $299 💸).
(저도 얼른 취업해서 이 Enterprise 써보고 싶네요...ㅠ알차게 쓸 자신 있는데)
인증서 시스템
프로비저닝 프로파일의 핵심은 바로 디지털 서명입니다. 왜 애플은 이렇게 복잡한 시스템을 만들었을까요?
디지털 서명의 원리
공개키 암호화 방식을 사용합니다. 간단히 말하면:
- 개인키: 나만 가지고 있는 열쇠 (서명할 때 사용)
- 공개키: 모든 사람이 볼 수 있는 열쇠 (서명 검증할 때 사용)
인증서 생성 과정
1. 개발자가 XCode나 Keychain Access에서 인증서 서명 요청(CSR) 생성.
2. 이때 개인키와 공개키 쌍이 생성되며, 개인 키는 개발자의 맥에 저장되고 공개키는 CSR에 포함.
3. CSR을 Apple Developer Potal 제출
4. apple이 CSR 검증하여 공개키가 포함된 디지털 인증서를 발급해준다
5. 다운로드하여 더블클릭하면 키체인에 공개키와 함께 등록된다.
협업시에는 개발용 인증서 + 공개키를 .P12(인증서)로 내보내면 끝
코드 서명과 검증
서명 과정(앱 빌드시 XCode에서 자동으로 수행)
1. 앱 바이너리의 해시값 계산
2. 개인키로 해시값 암호화 (디지털 서명 생성)
3. 서명을 앱 패키지에 포함
검증 과정(iOS 기기에서 앱 실행시 자동으로 수행합니당)
1. 앱 바이너리의 해시값 계산
2. 공개키로 서명 복호화하여 원본 해시값 추출
3. 두 해시값 비교 → 일치하면 앱 무결성 확인(변조되지 않았구나~)
팀 협업에서의 인증서 관리
협업할 때 가장 골치 아픈 부분이 바로 이거예요. 팀원이 "제 맥에서 빌드가 안 돼요!" 하면 99% 인증서 문제거든요.
(저 또한 삽질을 한게 한두번이 아니에요..ㅠㅠㅠ)
해결 방법:
- 팀 리더가 .p12 파일(인증서 + 개인키)과 프로비저닝 프로파일 생성
- 팀원들에게 배포
- 각자 Keychain에 설치
- XCode에서 동일한 Apple ID로 로그인
⚠️ 주의사항이자 중요사항⭐️: 개인키를 분실하면 이미 배포된 앱과의 연결이 끊어져서 처음부터 다시 해야 합니다. 백업은 필수!
샌드박스
프로비저닝 프로파일이 "신뢰할 수 있는 앱만 다운로드"하는 외부 보안이라면, 샌드박스는 "다운로드된 앱이 악의적으로 행동하지 못하게"하는 내부 보안입니다.
왜 샌드박스가 필요할까?
앱스토어를 통해 다운받은 앱이라고 해서 100% 안전할까요? 🤔
개발자가 나중에 악의적인 코드를 추가할 수도 있고, 앱에 버그가 있어서 시스템을 위험에 빠뜨릴 수도 있어요.
그래서 iOS는 각 앱을 격리된 감옥(Sandbox)에 가둬놓고 실행시킵니다. (어떤 사람은 모래사장이라고도 비유를 하는데 같은 의미입니다)
샌드박스 컨테이너 구조
/private/var/mobile/Containers/
├── Data/Application/[UUID]/ # 앱 데이터 컨테이너
│ ├── Documents/ # 사용자 문서 (iCloud 백업 O)
│ ├── Library/
│ │ ├── Caches/ # 캐시 데이터 (백업 X)
│ │ ├── Preferences/ # UserDefaults 설정
│ │ └── Application Support/ # 앱 지원 파일
│ └── tmp/ # 임시 파일 (자동 삭제)
└── Bundle/Application/[UUID]/ # 앱 실행 파일 컨테이너
└── [AppName].app/ # 실제 앱 번들
각 디렉토리마다 용도가 다른 이유는 성능과 보안을 동시에 고려했기 때문이에요.
Documents 디렉토리
사용자가 직접 생성한 중요한 데이터를 저장합니다. iCloud를 통해 백업되기 때문에 정말 중요한 파일만 여기에 저장해야 해요.
let documentsPath = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask).first!
Library/Caches 디렉토리
네트워크에서 다운로드한 이미지, 동영상 등을 저장합니다. 시스템이 저장 공간이 부족하면 자동으로 삭제할 수 있어요.
let cachesPath = FileManager.default.urls(for: .cachesDirectory,
in: .userDomainMask).first!
이외에도:
- Library/Preferences/: UserDefaults에 저장되는 앱 설정
- tmp/: 임시파일저장. 앱이 실행 중이 아닐때 시스템이 자동으로 삭제가능
- Bundle/: 실행 파일과 리소스가 잇어요
주요 특징
1. 격리된 파일 시스템
다른 앱의 데이터에 절대 접근할 수 없습니다. 카카오톡이 네이버 앱의 로그인 정보를 볼 수 없는 이유죠.
2. 제한된 리소스 접근
카메라, 마이크, 위치 정보 등에 접근하려면 반드시 사용자 허가가 필요합니다.
3. 제한된 앱 간 통신
앱끼리 직접 통신할 수 없고, iOS가 제공하는 안전한 방법만 사용해야 합니다:
- URL Scheme: myapp://open?param=value
- Universal Links(누르면 재밌어져요): https://boletto.site/invite/sD5Pim7v
- App Groups: 같은 개발자의 앱들끼리 데이터 공유
- App Extensions: 위젯, 키보드 등
4. 네트워크 접근 제한 (ATS)
iOS 9부터 App Transport Security(ATS)가 도입되어 HTTPS 연결만 허용됩니다. HTTP를 사용하려면 Info.plist에 명시적으로 예외 처리해야 해요.
샌드박스의 성능상 이점
보안뿐만 아니라 성능도 고려한 설계예요:
1. 최적화된 I/O 작업
제한된 공간에서 파일을 관리하기 때문에 디스크 I/O가 더 효율적입니다.
2. 자동 메모리 관리
- 앱 종료 시 tmp/ 디렉토리 자동 정리
- 메모리 부족 시 Caches/ 디렉토리 우선 삭제
- 백그라운드 앱의 메모리 자동 해제
자 여기까지 애플의 보안에 대해서 정리해봤어요. 아마 저 프로비저닝 프로파일때문에 하신 분들이 꽤 많을거 같아서 도움이 되었으면 좋겠습니다 !!
'iOS' 카테고리의 다른 글
Metal(1)- 메탈을 알기전에 필요한 것들 (1) | 2025.03.29 |
---|---|
Autolayout 모든 것: 사이클부터 제약조건까지 (0) | 2025.03.26 |
근본으로 돌아가자(6) Image (3) | 2025.03.05 |
근본으로 돌아가자(5) - 프로토콜 (0) | 2025.03.03 |
Dynamic Dispatch는 어떻게 이루어지는가? 클래스 VS 프로토콜 (0) | 2025.03.02 |