모바일 개발의 보안: 정의, 위협 및 방어 방법

저자: IT Sectr 게시일: 2026-03-28 읽는 시간: 12 분

모바일 보안은 애플리케이션, 사용자 데이터 및 서버 인프라를 공격과 유출로부터 보호하기 위한 일련의 조치입니다.OWASP Mobile Top 10 (2024)에 따르면, 안전하지 않은 데이터 저장은 모바일 애플리케이션에서 가장 흔한 취약점으로 남아 있습니다. 이 기사에서는 주요 위협, 암호화 방법, 안전한 저장, 인증 및 코드 보호에 대해 다룹니다 — 초보 개발자가 알아야 할 모든 것입니다.

핵심 요점

  • OWASP Mobile Top 10 — 2~3년마다 업데이트되는 모바일 애플리케이션의 주요 취약점 목록입니다.
  • AES — 기기에서 데이터 저장을 위한 대칭 암호화, RSA — 전송을 위한 비대칭 암호화.
  • iOS는 토큰과 비밀번호의 안전한 저장을 위해 Keychain을 사용하고, Android는 Keystore를 사용합니다.
  • OAuth 2.0 및 JWT — 애플리케이션과 서버 간의 인증 및 토큰 교환 표준.
  • ProGuard / R8 — 리버스 엔지니어링을 어렵게 만드는 난독화 도구, RASP는 런타임 공격으로부터 보호합니다.

주요 위협: OWASP Mobile Top 10

OWASP Mobile Top 10이란?

OWASP(Open Web Application Security Project)는 가장 위험한 모바일 보안 취약점 순위를 발표하는 비영리 조직입니다. OWASP Mobile Top 10은 개발자가 무엇에 먼저 집중해야 하는지 이해하는 데 도움이 되는 목록입니다. 2024 버전에서는 안전하지 않은 저장, 약한 인증 및 안전하지 않은 네트워크 통신과 관련된 문제가 순위의 선두를 차지하고 있습니다.

M1: 안전하지 않은 데이터 저장 — 가장 흔한 문제: 비밀번호, 토큰 및 개인 데이터가 암호화 없이 SharedPreferences, NSUserDefaults 또는 로컬 파일에 남아 있습니다. M2: 약한 인증 — 서버 측 검증 부족, 약한 비밀번호. M3: 안전하지 않은 네트워크 통신 — HTTPS 부족 또는 잘못된 SSL 인증서 검증. M4와 M5는 암호화 및 잘못된 API 사용과 관련됩니다.

M6: 안전하지 않은 권한 부여 — 사용자가 요청에서 ID를 대체하여 다른 사용자의 데이터에 액세스할 수 있습니다. M7: 코드 인젝션(SQL Injection, XSS). M8: 앱 조작 — 리패키징, 코드 대체. M9 및 M10 — 타사 라이브러리를 통한 데이터 유출 및 리버스 엔지니어링. 이러한 각 위협에 대해 입증된 대응책이 있으며, IT Sectr에서는 2017년부터 모든 프로젝트에 이를 적용하고 있습니다.

Man-in-the-Middle(MITM) 공격

MITM 공격은 공격자가 애플리케이션과 서버 간의 트래픽을 가로챌 때 발생합니다. 이는 DNS 스푸핑, ARP 스푸핑 또는 보호되지 않은 Wi-Fi 네트워크에 연결을 통해 가능합니다. 보호를 위해 SSL/TLS 인증서 및 Certificate Pinning이 사용됩니다.

Certificate Pinning은 애플리케이션이 서버 인증서가 애플리케이션 코드에 미리 저장된 것과 일치하는지 확인하는 메커니즘입니다. 공격자가 프록시(예: Burp Suite)를 통해 인증서를 대체하더라도 애플리케이션은 연결을 거부합니다. Pinning에는 공개 키 피닝(Public Key Pinning)과 인증서 해시 피닝(Certificate Hash Pinning)의 두 가지 유형이 있습니다.

암호화 및 해싱: AES, RSA, SSL/TLS

대칭 암호화: AES

AES(Advanced Encryption Standard)는 대칭 암호화 알고리즘으로, 기기에서 데이터 보안의 기초입니다. AES는 데이터 암호화 및 복호화에 동일한 키를 사용합니다. AES는 128, 192 또는 256비트 키를 지원합니다. 모바일 개발에서 AES-256은 기기에서 데이터(파일, 캐시, 로컬 데이터베이스 레코드)를 암호화하는 데 사용됩니다.

AES 모드: GCM(권장) — 데이터 인증 제공, CBC — 블록 체인이 있는 기본 모드, ECB — 안전하지 않으므로 사용하지 마십시오. iOS에서 AES는 CommonCrypto(CCOptions)를 통해 사용 가능하며, Android에서는 Java Cryptography Architecture(JCA)의 Cipher를 통해 사용 가능합니다. 중요: 암호화 키는 애플리케이션 코드에 저장해서는 안 됩니다 — Keychain/Keystore를 사용하세요.

비대칭 암호화: RSA — 공개 키와 개인 키 쌍을 사용합니다. RSA는 소량의 데이터 암호화에 사용됩니다 — 일반적으로 클라이언트와 서버 간에 대칭 키를 교환하기 위해서입니다. 최소 RSA 키 길이는 2048비트(4096 권장)입니다. iOS에서 RSA는 Security Framework(SecKeyCreateRandomKey)를 통해 사용 가능하며, Android에서는 Android Keystore의 KeyPairGenerator를 통해 사용 가능합니다.

해싱 및 SSL/TLS

해싱(SHA-256, SHA-3)은 데이터를 고정 길이 문자열로 되돌릴 수 없게 변환하는 것입니다. 해시는 데이터 무결성 검증 및 비밀번호 저장에 사용됩니다. 비밀번호에는 반드시 bcrypt, scrypt 또는 Argon2를 사용하세요 — 일반 SHA-256은 레인보우 테이블 공격에 취약합니다. SSL/TLS는 클라이언트와 서버 간의 네트워크 트래픽을 암호화하는 프로토콜입니다. 최신 표준은 TLS 1.3으로, Perfect Forward Secrecy(PFS)를 제공합니다.

TLS 1.3은 이전 버전보다 빠릅니다: 핸드셰이크가 2회 대신 1회 왕복으로 완료됩니다. Android에서는 최소 TLS 버전이 SSLSocket을 통해 구성되며, iOS에서는 ATS(App Transport Security)를 통해 구성되며 기본적으로 TLS 1.2 이상이 필요합니다. ATS는 특정 도메인에 대해서만 정당한 사유로 비활성화할 수 있습니다.

안전한 저장: Keychain 및 Keystore

iOS: Keychain

Keychain(키체인)은 iOS / macOS에서 비밀번호, 암호화 키, 인증서 및 토큰을 위한 안전한 저장소입니다. Keychain의 데이터는 각 기기에 고유한 하드웨어 키로 암호화됩니다. Keychain에 대한 액세스는 Security Framework(SecItemAdd, SecItemCopyMatching)를 통해 제어됩니다. Keychain은 기기가 잠기면 자동으로 잠기고 Secure Enclave를 사용하여 암호화됩니다.

Android: Keystore

Android Keystore는 애플리케이션으로부터 격리된 암호화 키를 위한 시스템 저장소입니다. Android 6.0(API 23)부터 Keystore는 보안 칩이 있는 기기에서 하드웨어 지원(TEE — Trusted Execution Environment)을 사용합니다. Keystore의 키는 보안 영역을 절대 떠나지 않으며, 애플리케이션은 암호화 및 서명 작업을 위한 핸들만 받습니다.

Keychain(iOS)과 Keystore(Android) 비교
매개변수 iOS Keychain Android Keystore
저장 데이터 유형 비밀번호, 토큰, 키, 인증서 암호화 키
하드웨어 지원 Secure Enclave(A7+ 탑재 모든 iPhone) TEE(Android 6+, 칩에 따라 다름)
암호화 AES-256 하드웨어 하드웨어 키를 사용한 AES/GCM
생체인식 액세스에 Face ID / Touch ID 액세스에 BiometricPrompt
iCloud / 백업 iCloud Keychain으로 동기화 클라우드와 동기화되지 않음
성능 느림(하드웨어 암호화) 빠름(TEE)

SharedPreferences와 NSUserDefaults는 민감한 데이터 저장용으로 설계되지 않았습니다 — 평문으로 정보를 저장합니다. 데이터 보호를 위해 EncryptedSharedPreferences(Android)를 사용하거나 UserDefaults(iOS)에 저장하기 전에 데이터를 암호화하세요. IT Sectr에서는 액세스 토큰과 비밀번호에 항상 Keychain과 Keystore를 사용합니다.

인증: OAuth 2.0, JWT 및 생체인식

OAuth 2.0 및 OpenID Connect

OAuth 2.0은 비밀번호를 전송하지 않고 사용자 리소스에 대한 안전한 액세스를 제공하는 위임 권한 부여 프로토콜입니다. 모바일 애플리케이션에서는 PKCE(Proof Key for Code Exchange)를 사용한 Authorization Code Flow가 가장 일반적으로 사용됩니다. PKCE는 권한 부여 코드의 가로채기를 방지합니다 — 이는 모바일 애플리케이션의 필수 요구 사항입니다.

OpenID Connect(OIDC)는 사용자 인증을 위한 OAuth 2.0 위의 확장 기능입니다. OIDC는 사용자 정보(이름, 이메일, ID)를 포함하는 JWT 형식의 ID Token을 추가합니다. OAuth 2.0 + OIDC 흐름에는 다음이 포함됩니다: 사용자를 로그인 페이지로 리디렉션, 권한 부여 코드 획득, 코드를 토큰(access + refresh + id)으로 교환, API 요청에 액세스 토큰 사용.

JWT: 액세스, 리프레시 및 세션 토큰

JWT(JSON Web Token)는 JSON 형식의 클레임을 포함하는 컴팩트하고 URL에 안전한 토큰 형식입니다. JWT는 세 부분으로 구성됩니다: 헤더(유형 및 서명 알고리즘), 페이로드(데이터), 서명. 액세스 토큰은 API 액세스를 위한 단기 토큰(15~60분)입니다. 리프레시 토큰은 재로그인 없이 새 액세스 토큰을 얻기 위한 장기 토큰(일/주)입니다.

세션 토큰은 서버가 데이터베이스나 Redis에 세션을 저장하고 클라이언트가 무작위 식별자를 받는 전통적인 접근 방식입니다. 모바일 개발에서는 JWT가 선호됩니다: 서버 측 세션 저장이 필요하지 않고, 모든 정보를 내부에 포함하며, 검증이 쉽습니다. 그러나 JWT는 즉시 취소할 수 없습니다 — 이는 액세스 토큰의 짧은 수명과 리프레시 토큰 사용으로 해결되는 절충안입니다.

생체인식 인증

iOS의 Face ID 및 Touch ID, Android의 지문 인증 — 사용자의 고유한 물리적 특성을 사용하는 생체인식 인증 방법입니다. iOS에서 생체인식은 LocalAuthentication(LAContext)을 통해 작동하고, Android에서는 BiometricPrompt(Android 9+) 또는 FingerprintManager(비권장)를 통해 작동합니다. 생체인식은 앱 잠금 해제, 결제 확인 및 보호된 데이터 액세스에 사용됩니다.

중요한 주의사항: 생체인식은 편리한 UX이지만 서버 인증의 대체 수단이 아닙니다. 생체인식 확인 성공 후 애플리케이션은 서버에서 액세스 토큰을 가져와야 합니다. Android에서는 기기가 카메라 기반 얼굴 인식(Class 1)이 아닌 Class 3(강력) 생체인식을 사용하는지 확인하세요.

코드 보호: ProGuard, R8 및 Root Detection

난독화: ProGuard 및 R8

ProGuard는 Android용 Java 바이트코드의 난독화, 압축 및 최적화 도구로, 리버스 엔지니어링에 대한 코드 보안을 향상시킵니다. R8은 그 후속 제품으로, Android Studio 3.4부터 Gradle에 내장되어 있습니다. R8은 4가지 작업을 수행합니다: 압축(사용되지 않는 클래스와 메서드 제거), 최적화(메서드 인라인화, 코드 단순화), 난독화(클래스와 메서드를 짧은 이름으로 변경), 사전 검증(바이트코드 확인).

DexGuard는 향상된 보호 기능을 갖춘 ProGuard의 상용 버전입니다: 문자열 암호화, 리소스 난독화, 리패키징 방지, APK 무결성 제어. 대부분의 프로젝트에서는 R8로 충분하지만, 금융 및 은행 애플리케이션의 경우 DexGuard가 추가 보안 계층을 제공합니다. R8은 build.gradle을 통해 활성화됩니다: minifyEnabled = trueproguardFiles.

루트 및 탈옥 감지

Root Detection(Android) 및 Jailbreak Detection(iOS)은 기기에서 슈퍼유저 권한이 획득되었는지 확인하는 메커니즘입니다. 손상된 기기에서는 프로세스 메모리 읽기, 트래픽 가로채기 및 코드 대체가 가능합니다. Android에서 확인에는 SU 바이너리 파일의 존재, 테스트 서명 키 및 비표준 빌드 플래그가 사용됩니다.

RASP(Runtime Application Self-Protection)는 실행 중에 애플리케이션을 보호하는 기술입니다. RASP는 디버깅, 리패키징, 코드 인젝션 시도를 감지하고 위협이 감지되면 애플리케이션을 종료합니다. RASP 솔루션의 예: Dexter, Guardsquare, Promon. RASP는 런타임에 작동하며 이상 징후에 반응합니다 — 실행 전에 코드를 보호하는 정적 난독화와는 다릅니다.

리버스 엔지니어링은 컴파일된 애플리케이션에서 소스 코드를 복원하는 프로세스입니다. 도구: JADX(APK 디컴파일러), Ghidra, IDA Pro, Hopper. 리버스 엔지니어링에 대한 보호는 난독화, 문자열 암호화, 무결성 확인 및 Root Detection의 조합입니다. 완벽한 보호는 존재하지 않습니다 — 목표는 공격자에게 리버스 엔지니어링을 충분히 비싸게 만드는 것입니다.

자주 묻는 질문

모바일 보안 학습을 어디서 시작해야 하나요?

OWASP Mobile Top 10부터 시작하세요 — 가장 흔한 취약점의 로드맵입니다. 그런 다음 HTTPS와 SSL 인증서를 공부하고, Certificate Pinning을 구성한 후 Keychain / Keystore를 통한 안전한 저장으로 넘어가세요.

대칭 암호화와 비대칭 암호화의 차이점은 무엇인가요?

AES(대칭) — 암호화 및 복호화에 하나의 키, 빠름, 대량 데이터에 적합. RSA(비대칭) — 키 쌍(공개 및 개인), 느림, 대칭 키 교환에 사용.

애플리케이션의 모든 데이터를 암호화해야 하나요?

기밀 데이터만 암호화해야 합니다: 비밀번호, 토큰, 개인 사용자 데이터, 결제 정보. 이미지, 텍스트 및 인터페이스 설정은 암호화가 필요하지 않습니다 — 크기가 증가하고 애플리케이션이 느려집니다.

리프레시 토큰이란 무엇이며 왜 필요한가요?

리프레시 토큰은 비밀번호를 다시 입력하지 않고 새 액세스 토큰을 얻을 수 있는 장기 토큰입니다. 이는 보안을 향상시킵니다 — 액세스 토큰은 15~60분 동안 유효하며, 유출되더라도 공격자가 오래 사용할 수 없습니다.

ProGuard / R8 사용이 필수인가요?

네, Android 릴리스 빌드에서는 R8을 활성화해야 합니다. 이는 리버스 엔지니어링으로부터의 보호뿐만 아니라 APK 크기 감소 및 성능 최적화입니다. R8이 없으면 코드는 단일 JADX 명령으로 읽을 수 있는 형태로 디컴파일될 수 있습니다.

요약

  • OWASP Mobile Top 10 — 주요 위협 목록; 보안 감사를 이것부터 시작하세요.
  • AES-256 — 기기 데이터의 대칭 암호화 표준, RSA — 키 교환용.
  • Keychain(iOS) 및 Keystore(Android) — 토큰과 비밀번호를 저장하는 유일한 올바른 장소.
  • PKCE 및 JWT를 사용한 OAuth 2.0 — 모바일 애플리케이션의 최신 인증 표준.
  • R8 — Android용 필수 난독화 도구, Root/Jailbreak Detection이 손상된 기기로부터 보호합니다.
  • Certificate Pinning은 인증서가 대체되어도 MITM 공격을 방지합니다.
  • 보안은 프로세스이지 기능이 아닙니다: 개발의 각 단계에서 취약점을 테스트하세요.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의