프로젝트 트러블슈팅

Jeom·2025년 11월 6일

StepProject

목록 보기
2/2

🚀 StepProject 개발일지 - SSL, 로그인, 코인 API 연동 (2025.11.06)

🧩 1. SSL 인증 문제 해결 과정

처음 서버와 통신할 때 아래 오류가 발생했다:

❌ 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 우회이므로, 정식 배포 시 반드시 제거해야 한다.


🔐 2. 로그인 API 수정 (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이 반환된다.


💰 3. 코인 API 연동 (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를 반드시 사용해야 함)


📊 4. UI 연동 (MyStocksViewController)

서버에서 불러온 데이터를 RxSwift로 테이블뷰에 바인딩:

viewModel.coins
    .bind(to: tableView.rx.items(cellIdentifier: "CoinCell", cellType: CoinCell.self)) { _, coin, cell in
        cell.configure(with: coin)
    }
    .disposed(by: disposeBag)
  • 상단엔 총자산 및 변동률
  • 하단엔 보유 종목(최대 3개)
  • 그 아래엔 전체 코인 리스트 가 보이도록 구성

⚙️ 5. 트러블슈팅 요약

문제원인해결 방법
SSL Error자체 서명 인증서URLSession.insecure로 임시 우회
500 Error (로그인)"timezone""timeZone"대문자 Z로 수정
Unauthorized (코인 API)헤더 누락Authorization, X-TimeZone 추가
데이터 표시 안됨JSON 구조 불일치CoinResponse 모델 디코딩 수정

✨ 마무리

오늘은 API 명세 불일치, SSL 검증, 대소문자 문제
서버-클라이언트 간 통신에서 자주 겪는 문제를 집중적으로 다뤘다.

profile
iOS 개발노트

0개의 댓글