🚀 StepProject 개발일지 - SSL, 로그인, 코인 API 연동 (2025.11.06)
처음 서버와 통신할 때 아래 오류가 발생했다:
❌ The certificate for this server is invalid.
You might be connecting to a server that is pretending to be “<서버 주소>”.
이는 서버의 자체 서명(Self-Signed) 인증서 때문이었다.
이를 임시로 해결하기 위해, URLSession을 확장하여 SSL 검증을 무시하도록 설정했다.
extension URLSession {
static var insecure: URLSession = {
let config = URLSessionConfiguration.default
let delegate = InsecureSessionDelegate()
return URLSession(configuration: config, delegate: delegate, delegateQueue: nil)
}()
}
final class InsecureSessionDelegate: NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if let trust = challenge.protectionSpace.serverTrust {
completionHandler(.useCredential, URLCredential(trust: trust))
} else {
completionHandler(.performDefaultHandling, nil)
}
}
}
⚠️ 주의:
이는 개발용 SSL 우회이므로, 정식 배포 시 반드시 제거해야 한다.
APIService.swift)처음엔 닉네임만 바디에 담아 전송했지만,
서버가 요구하는 JSON 구조는 다음과 같았다:
{
"nickname": "사용자이름",
"timeZone": "Asia/Seoul"
}
즉, timeZone의 Z가 대문자여야 정상적으로 동작했다.
(소문자 timezone으로 보낼 경우 서버에서 500 에러 발생)
let body: [String: Any] = [
"nickname": nickname,
"timeZone": TimeZone.current.identifier // 대문자 Z
]
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
🛰 [DEBUG] Headers: ["Content-Type": "application/json"]
📦 [DEBUG] Body: {"nickname":"다람쥐","timeZone":"Asia/Seoul"}
📡 [DEBUG] Response Code: 200
🌐 Login Response: {"accessToken": "eyJhbGciOiJIUzI1NiJ9..."}
이제 정상적으로 accessToken이 반환된다.
CoinService.swift)로그인 성공 후 토큰을 이용해 코인 목록을 불러왔다.
/api/coins/top → 상위 거래량 코인 심볼 조회 /api/coins/summaries → 해당 코인들의 요약 데이터 조회request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.setValue(TimeZone.current.identifier, forHTTPHeaderField: "X-TimeZone")
서버 명세에 따라
X-TimeZone헤더를 추가함
(대문자 Z를 반드시 사용해야 함)
서버에서 불러온 데이터를 RxSwift로 테이블뷰에 바인딩:
viewModel.coins
.bind(to: tableView.rx.items(cellIdentifier: "CoinCell", cellType: CoinCell.self)) { _, coin, cell in
cell.configure(with: coin)
}
.disposed(by: disposeBag)
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| SSL Error | 자체 서명 인증서 | URLSession.insecure로 임시 우회 |
| 500 Error (로그인) | "timezone" → "timeZone" | 대문자 Z로 수정 |
| Unauthorized (코인 API) | 헤더 누락 | Authorization, X-TimeZone 추가 |
| 데이터 표시 안됨 | JSON 구조 불일치 | CoinResponse 모델 디코딩 수정 |
오늘은 API 명세 불일치, SSL 검증, 대소문자 문제 등
서버-클라이언트 간 통신에서 자주 겪는 문제를 집중적으로 다뤘다.