SSL(Secure Sockets Layer)과 TLS(Transport Layer Security)는 네트워크를 통해 클라이언트와 서버 간의 안전한 데이터 전송을 보장하는 암호화 프로토콜입니다. 이들은 모든 트래픽을 암호화하여 공격자가 데이터를 가로채거나 변조하는 것을 방지합니다. Google Transparency Report(2025)에 따르면 전 세계 모바일 트래픽의 95% 이상이 TLS 암호화를 사용합니다. 이 프로토콜이 없으면 공개 Wi-Fi나 모바일 네트워크를 통해 전송된 모든 정보를 제3자가 읽을 수 있습니다. Cloudflare, 2024
주요 사항
SSL(Secure Sockets Layer)은 1995년 Netscape가 웹 트래픽을 보호하기 위해 개발한 프로토콜입니다. 첫 번째 버전인 SSL 1.0은 공개적으로 출시된 적이 없으며, SSL 2.0(1995)과 SSL 3.0(1996)은 2000년대 초까지 사용되었지만 심각한 취약점을 포함하고 있었습니다. SSL의 뒤를 이어 TLS(Transport Layer Security)가 등장했습니다. 이는 IETF가 표준화한 개선된 버전입니다. TLS 1.0(1999)은 SSL 3.0을 기반으로 했지만, 이후 버전인 TLS 1.1(2006), TLS 1.2(2008), TLS 1.3(2018)은 점차 원래 아키텍처에서 벗어나 새로운 암호화 알고리즘을 추가하고 취약점을 수정했습니다. 오늘날 SSL은 구식으로 간주되며 모든 최신 시스템은 TLS를 사용하지만, 두 프로토콜 모두 관성적으로 SSL/TLS로 함께 언급되는 경우가 많습니다.
SSL/TLS의 역사는 초기 웹에서 안전한 데이터 전송의 필요성에서 시작되었습니다. 1994년 Netscape는 Navigator 브라우저용 SSL 1.0을 개발했지만 심각한 보안 문제로 인해 공개되지 않았습니다. SSL 2.0은 1995년에 출시되어 실제로 사용되었지만 수많은 취약점을 포함하고 있었습니다: 중간자 공격에 대한 보호 부족, 취약한 암호화 알고리즘, 자르기 공격에 대한 취약성 등이 있습니다. SSL 3.0(1996)은 대부분의 문제를 해결했지만 2014년까지 POODLE 취약점이 발견되었고, 이후 IETF는 모든 SSL 버전을 공식적으로 구식으로 선언했습니다. TLS 1.0~1.3은 암호화 강도, 성능 및 개인정보 보호를 점진적으로 개선했으며, TLS 1.3은 핸드셰이크를 2회 왕복에서 1회로 줄여 불안정한 연결을 가진 모바일 애플리케이션에 매우 중요합니다.
핸드셰이크는 클라이언트와 서버 간의 보안 연결을 설정하는 프로세스입니다. 이는 여러 순차적 단계로 구성되며, 동안 양측이 프로토콜 버전에 동의하고, 암호화 알고리즘을 선택하고, 키를 교환하고, 서로를 인증합니다. TLS 1.3에서는 핸드셰이크가 단 한 번의 네트워크 왕복(1-RTT)만 필요하지만, TLS 1.2에서는 두 번(2-RTT)이 필요했습니다.
첫 번째 단계는 클라이언트가 ClientHello를 보내는 것입니다. 이는 지원되는 TLS 버전, 암호 제품군 및 난수 목록을 포함하는 메시지입니다. 서버는 선택된 버전과 암호, X.509 인증서 및 디지털 서명이 포함된 ServerHello로 응답합니다. 클라이언트는 인증 기관(CA) 체인을 통해 인증서를 확인하고, 세션 키를 생성하여 인증서의 서버 공개 키로 암호화하여 보냅니다. 서버의 확인 후 안전한 데이터 전송이 시작됩니다. 전체 핸드셰이크는 최신 기기에서 1~3밀리초가 소요되어 사용자가 인지할 수 없습니다.
TLS 인증의 기반은 X.509 형식의 인증서를 기반으로 구축된 공개 키 기반(PKI)입니다. 각 인증서에는 도메인 이름(Common Name 또는 Subject Alternative Name), 서버의 공개 키, 발급자 이름(인증 기관), 만료 날짜 및 CA의 디지털 서명이 포함됩니다. 클라이언트는 신뢰 체인을 따라 서버 인증서를 확인합니다: 서버 인증서에서 운영 체제에 내장된 루트 CA까지입니다. Android 기기에서는 루트 인증서가 시스템 키스토어에 저장되며 Google Play Services를 통해 업데이트됩니다. iOS에서는 iOS 업데이트를 통해 업데이트됩니다. 체인의 연결이 끊어지면(만료된 인증서, 도메인 불일치, 알 수 없는 CA) 클라이언트는 연결을 종료합니다. 자체 서명된 인증서(개발에 사용)의 경우 명시적 신뢰가 필요합니다. Android에서는 Network Security Config를 통해, iOS에서는 Info.plist의 NSExceptionDomains를 통해 이루어집니다. 인증서 체인 검증 프로세스에는 CRL(인증서 폐기 목록) 또는 OCSP(온라인 인증서 상태 프로토콜)를 통한 폐기 상태 확인도 포함되지만, 모바일 기기에서는 연결 속도를 높이기 위해 OCSP 요청이 생략되는 경우가 많습니다. 이는 아키텍트가 고려해야 할 보안과 성능 간의 절충점입니다.
SSL과 TLS라는 용어는 종종 같은 의미로 사용되지만, 모바일 애플리케이션의 보안과 성능에 영향을 미치는 근본적인 기술적 차이점이 있습니다.
| 특성 | SSL 3.0 | TLS 1.2 | TLS 1.3 |
|---|---|---|---|
| 출시 연도 | 1996 | 2008 | 2018 |
| 상태 | 구식(RFC 7568) | 활성(권장) | 최신(최고) |
| 왕복 횟수 | 2 | 2 | 1 |
| 키 교환 알고리즘 | RSA | RSA, ECDHE | ECDHE(전용) |
| 인증된 암호화 | 아니요 | GCM, CCM | AEAD 필수 |
| 완전 순방향 비밀성(PFS) | 아니요 | 선택 사항 | 필수 |
TLS 1.3과 이전 버전의 주요 차이점은 ECDHE 프로토콜을 통한 완전 순방향 비밀성(PFS)의 필수 사용입니다. 이는 공격자가 서버의 개인 키에 접근하더라도 이전에 가로챈 트래픽을 복호화할 수 없음을 의미합니다. 서버 손상이 실제 위협인 모바일 애플리케이션의 경우 PFS가 포함된 TLS 1.3은 필수 보안 요구 사항입니다.
이전 버전의 SSL과 TLS는 프로덕션 사용에 부적합하게 만드는 잘 문서화된 취약점이 있습니다. POODLE(CVE-2014-3566)은 패딩 오라클을 통해 SSL 3.0을 공격하여 256개의 요청으로 세션 쿠키를 복호화할 수 있습니다. BEAST(CVE-2011-3389)는 예측 가능한 IV를 통해 TLS 1.0 CBC 모드의 취약점을 악용합니다. Heartbleed(CVE-2014-0160)는 프로토콜 취약점이 아닌 OpenSSL 구현의 버그로 서버 메모리 읽기를 허용합니다. Netcraft에 따르면 2014년에 500,000개 이상의 서버가 취약했습니다. Android 10(API 29) 및 iOS 13부터 이러한 모든 프로토콜은 시스템 수준에서 비활성화됩니다. 그럼에도 불구하고 개발자는 애플리케이션을 출시하기 전에 SSL Labs Test(qualys.com)를 통해 서버 구성을 확인하여 구식 암호 제품군이 없고 TLS 1.3이 지원되는지 확인해야 합니다.
모바일 애플리케이션에서 TLS는 세 가지 수준에서 데이터를 보호합니다: 콘텐츠 암호화(서버 외에는 누구도 데이터를 읽을 수 없음), 무결성 검증(전송 중 데이터 변경 불가), 서버 인증(클라이언트가 올바른 서버에 연결하고 있음을 확신). 인증은 특히 중요합니다. 이것이 없으면 공격자가 DNS 스푸핑이나 가짜 Wi-Fi 액세스 포인트를 통해 서버를 사칭할 수 있습니다.
Google Play Protect(2024)의 연구에 따르면 Android 애플리케이션의 76%가 인증서 확인과 함께 TLS를 올바르게 사용합니다. 나머지 24%는 실수를 범합니다: 테스트를 위해 인증서 확인을 비활성화하고(프로덕션에서 다시 활성화하는 것을 잊음), 검증 없이 자체 서명된 인증서를 사용하거나, SSL 3.0 및 TLS 1.0과 같은 구식 프로토콜을 허용합니다. iOS의 Apple App Transport Security(ATS)는 2017년부터 최소 TLS 1.2를 요구하며, iOS 15부터는 모든 네트워크 요청에 기본적으로 TLS 1.3을 사용합니다. 추가 보호를 위해 Certificate Pinning(특정 서버 인증서에 바인딩)을 구현하는 것도 권장됩니다.
Android에서 가장 인기 있는 네트워킹 라이브러리 중 하나인 OkHttp를 사용하여 보안 HTTPS 연결을 구성하는 예를 살펴보겠습니다. 올바른 구성에는 TLS 1.3 사용 강제 및 인증서 확인이 포함됩니다.
val client = OkHttpClient.Builder()
.connectionSpecs(
listOf(
ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_3, TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_AES_128_GCM_SHA256,
CipherSuite.TLS_AES_256_GCM_SHA384,
CipherSuite.TLS_CHACHA20_POLY1305_SHA256
)
.build()
)
)
.hostnameVerifier { hostname, session ->
SSLSession.DefaultHostnameVerifier.verify(hostname, session)
}
.build()
이 예에서는 지원되는 TLS 버전 세트를 1.3 및 1.2로만 제한하고 구식인 TLS 1.0/1.1을 제외합니다. 암호 제품군은 AEAD 모드와 필수 완전 순방향 비밀성을 갖춘 최신 알고리즘에서 선택됩니다. HostnameVerifier는 호스트 이름이 인증서와 일치하는지 확인합니다. iOS에서는 tlsMinimumSupportedProtocolVersion 매개변수를 .TLSv13으로 설정하여 URLSession 구성을 통해 유사한 구성을 수행합니다. 추가로 iOS에서는 tlsMaximumSupportedProtocolVersion을 설정하여 상위 버전을 제한할 수 있습니다. 이는 아직 TLS 1.3으로 마이그레이션하지 않은 레거시 서버와의 호환성에 유용합니다. 이러한 구성은 모바일 애플리케이션에서 데이터 전송을 위한 최대 수준의 보안을 보장합니다.
자주 묻는 질문
TLS는 프로토콜의 더 새롭고 안전한 버전입니다. SSL은 구식이며 사용해서는 안 됩니다(RFC 7568). 실제로 두 용어 모두 HTTPS 암호화를 의미하지만, 기술적으로 모든 최신 시스템은 TLS 1.2 또는 1.3으로 작동합니다.
Burp Suite 또는 Charles Proxy와 같은 프록시 도구를 설치하고 앱의 트래픽을 가로채세요. 연결이 HTTPS를 사용하고 인증서가 유효하면 앱이 TLS를 사용하는 것입니다. 트래픽이 HTTP로 간다면 암호화가 없는 것입니다.
프로덕션 빌드에서는 TLS 1.2와 TLS 1.3만 허용됩니다. SSL 3.0, TLS 1.0, TLS 1.1 프로토콜은 서버와 클라이언트 애플리케이션 모두에서 비활성화되어야 합니다. 2020년부터 주요 플랫폼(Android, iOS, 브라우저)은 최소 TLS 1.2를 요구합니다.
네, 권장됩니다. TLS는 인증 기관 체인을 통해 인증서를 확인하지만, CA가 손상된 경우(2011년 DigiNotar의 경우처럼) 공격자가 가짜 인증서를 발행할 수 있습니다. Pinning은 추가 검증 계층을 추가합니다.
TLS 1.3은 연결 설정 시간을 2회 왕복에서 1회로 줄여 첫 연결 시 30~50%의 개선을 제공합니다. 불안정한 연결(지하철, 기차)을 가진 모바일 애플리케이션의 경우 데이터 로딩 속도에 매우 중요합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.