class NetworkManager {
static let shared = NetworkManager()
private init() {}
func getAttractionData(completion: @escaping (String) -> Void) {
guard let url = URL(string: "\(Constants.baseURL)/B551011/KorService1/searchKeyword1?serviceKey=\(Constants.API_KEY)&numOfRows=10&pageNo=1&MobileOS=IOS&MobileApp=AppTest&_type=json&listYN=Y&arrange=A&keyword=%EC%A0%84%EB%B6%81&contentTypeId=12") else { return }
let task = URLSession.shared.dataTask(with: URLRequest(url: url)) { data, _, error in
guard let data = data, error == nil else { return }
do {
let results = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)
print(results)
} catch {
print(error.localizedDescription)
}
}
task.resume()
}
}
위의 코드를 실행하면 아래와 같은 오류가 발생합니다.
SSL, TLS 관련 에러인데, 검색해보니 IOS10부터는 ATS(App Transport Security)가 강화되어 보안이 안전하지 않은 Https 트래픽을 비활성화합니다.
따라서 Info.plist에서 ATS setting을 수정함으로 해결할 수 있습니다.
<plist version="1.0">
<dict>
-- 추가 --
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>apis.data.go.kr</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<true/>
</dict>
</dict>
</dict>
-- 종료 --
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
apis.data.go.kr 도메인에 대한 예외 설정을 추가했습니다.
이는 HTTPS 연결을 사용하지 않는 이 도메인에 대해 HTTP 연결을 허용하는 설정입니다.
근데 여기서 몇가지 중요한 점이 있습니다.
1. NSExceptionRequiresForwardSecrecy - <true/>
Forward Secrecy란?
Forward Secrecy(앞선 기밀성)는 SSL/TLS 암호화 기술의 중요한 부분으로, 각 세션에서 사용되는 암호화 키를 독립적으로 생성하여 과거의 키가 노출되더라도 이전 세션의 암호화 데이터를 보호하는 방법입니다. 이 기술은 보안성을 높이며, 최신 보안 요구 사항에 부합합니다.
NSExceptionRequiresForwardSecrecy의 영향
- 설정: NSExceptionRequiresForwardSecrecy를 false로 설정하면, 일부 보안 수준이 낮은 암호화 방식도 허용됩니다.
- 보안: 이는 앱의 보안성을 약화시킬 수 있습니다. 특히 금융, 건강, 개인정보와 관련된 앱에서는 보안이 중요하므로 Forward Secrecy를 비활성화하는 것은 권장되지 않습니다.
- 앱 심사: Apple은 보안 문제에 대해 매우 엄격한 기준을 가지고 있습니다. Forward Secrecy를 비활성화한 경우, Apple의 심사에서 앱이 거부될 가능성이 높아집니다.
2. 서버의 SSL/TLS 지원 확인
터미널에 위에 이미지처럼 입력한 후에 실행합니다.
실행 결과 TLSv1.3 관련 오류가 발생했다는 걸 확인했습니다.
NSExceptionMinimumTLSVersion = "TLSv1.3";로 설정되어 있는 경우, 서버가 TLS 1.3을 지원하지 않으면 연결이 실패하게 됩니다.
1. TLS 버전 확인 및 조정
- 우선, 서버가 TLS 1.3을 지원하는지 확인하세요. 만약 서버가 TLS 1.3을 지원하지 않거나, TLS 1.2만 지원한다면, NSExceptionMinimumTLSVersion을 TLS 1.2로 낮추는 것이 필요합니다.
https://www.ssllabs.com/ssltest/analyze.html?d=apis.data.go.kr
서버에 대한 SSL을 테스트한 결과 해당 서버는 TLS 1.0을 지원한다고 되어 있습니다.
2. Info.plist에 TLS 버전 설정
서버가 TLS 1.0부터 지원한다고 하기 때문에 NSExceptionMinimumTLSVersion을 TLS 1.0로 설정하여 연결 문제를 해결하려고 했습니다.
info.plist 파일을 아래와 같이 수정했습니다.
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>apis.data.go.kr</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
근데 위의 입력을 하면 아래와 같은 오류가 발생합니다.
The value "TLSv1.0" for 'NSAppTransportSecurity' =>
'NSExceptionDomains' => 'apis.data.go.kr' => 'NSExceptionMinimumTLSVersion'
has been deprecated starting in iOS 15.0, use TLSv1.2 or TLSv1.3 instead.
이 메시지는 iOS 15.0부터 NSExceptionMinimumTLSVersion에서 TLS 1.0을 사용하는 것이 더 이상 지원되지 않고, 대신 TLS 1.2 또는 TLS 1.3을 사용해야 한다는 의미입니다.
자세한 설명
- Deprecated: "Deprecated"는 더 이상 사용되지 않거나 권장되지 않는 기능을 의미합니다. iOS 15.0 이상에서는 TLS 1.0이 보안상의 이유로 사용되지 않도록 권장합니다.
- TLS 버전: TLS (Transport Layer Security)는 데이터 전송의 보안을 제공하는 프로토콜입니다. TLS 1.0은 오래된 버전으로, 보안 취약점이 발견되어 최신 버전으로 업그레이드하는 것이 권장됩니다.
- TLS 1.2 및 TLS 1.3: 이 두 버전은 현재 보안상의 최신 기준을 충족하며, TLS 1.0보다 안전합니다. iOS 15.0부터는 TLS 1.0을 사용하는 것이 지원되지 않고, TLS 1.2 또는 TLS 1.3을 사용해야 합니다.
문제 해결
iOS 15.0 이상에서 NSExceptionMinimumTLSVersion을 설정할 때는 TLS 1.0 대신 TLS 1.2 또는 TLS 1.3을 사용해야 합니다. TLS 1.0 설정이 포함된 경우, iOS에서는 이를 무시하고 최신 버전을 사용해야 합니다.
서버가 TLS 1.0만 지원하는 경우, iOS 15.0 이상에서는 TLS 1.0을 사용하는 것이 보안상 권장되지 않으므로 서버의 업그레이드가 최선의 해결책입니다.
하지만... 앱을 실행시켜야 하기 때문에..
최종적으로 info.plist는 다음과 같이 작성했습니다.
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>apis.data.go.kr</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
'iOS > Swift' 카테고리의 다른 글
Storyboard와 XIB의 차이점은 무엇인가요? (0) | 2024.08.21 |
---|---|
왜 DispatchQueue.main을 tableView(_ : cellForRowAt: )에 안 넣었나? (0) | 2024.08.20 |
iOS 앱의 생명주기(App Life Cycle)에 대해 설명해주세요. (0) | 2024.08.16 |
Swift에서 옵셔널이란 무엇이며, 언제 사용해야 하나요? (0) | 2024.08.16 |
델리게이트 패턴이란? (0) | 2024.07.08 |