api 전체 과정

jeongmuyamette·2025년 2월 25일

TIL

목록 보기
52/72
post-thumbnail
import UIKit


import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

// API 성공 응답 모델
struct LottoAPIResponse: Codable {
    let page: Int64
    let perPage: Int64
    let totalCount: Int64
    let currentCount: Int64
    let matchCount: Int64
    let data: [LottoStore]
}

// API 에러 응답 모델
struct APIError: Codable {
    let code: Int
    let msg: String
}

// 로또 판매점 모델
struct LottoStore: Codable {
    let 번호: Int
    let 상호: String
    let 도로명주소: String
    let 지번주소: String
}

class LottoAPITest {
    static func testFetchLottoStores() {
        // Base URL과 path 설정
         let baseURL = "https://api.odcloud.kr/api"
         let path = "/15086355/v1/uddi:ef7ca84b-c2bc-404a-9743-85752073b61b"
         
         // 인증키는 이미 인코딩된 형태로 사용
         let serviceKey = "S4Z3xung5wpu6TPz1bUEfRu8ln55RTZu4rwIDF61MPCFNDzcfOFIO7N2AFFgrCWLY2DooC%2B0Soo4pSsQ0U%2BIWg%3D%3D"
         
         // URL 문자열 직접 구성
         let urlString = "\(baseURL)\(path)?page=1&perPage=10&serviceKey=\(serviceKey)"
         
         guard let url = URL(string: urlString) else {
             print("❌ URL 생성 실패")
             return
         }
        
        print("🔍 요청 URL: \(url.absoluteString)")
          
          var request = URLRequest(url: url)
          request.setValue("application/json", forHTTPHeaderField: "Accept")
        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            if let error = error {
                print("❌ 네트워크 에러: \(error.localizedDescription)")
                return
            }
            
            guard let httpResponse = response as? HTTPURLResponse else {
                print("❌ HTTP 응답이 아님")
                return
            }
            
            print("📡 HTTP 상태 코드: \(httpResponse.statusCode)")
            
            guard let data = data else {
                print("❌ 데이터 없음")
                return
            }
            
            // JSON 데이터 출력 (디버깅용)
            if let jsonString = String(data: data, encoding: .utf8) {
                print("📦 수신된 JSON 데이터:")
                print(jsonString)
            }
            
            do {
                if httpResponse.statusCode != 200 {
                    let errorResponse = try JSONDecoder().decode(APIError.self, from: data)
                    print("❌ API 에러: 코드=\(errorResponse.code), 메시지=\(errorResponse.msg)")
                } else {
                    let response = try JSONDecoder().decode(LottoAPIResponse.self, from: data)
                    print("\n✅ 파싱 성공!")
                    print("📊 총 데이터 수: \(response.totalCount)")
                    print("📑 현재 페이지: \(response.page)")
                    print("📝 페이지당 항목 수: \(response.perPage)")
                    
                    if let firstStore = response.data.first {
                        print("\n📍 첫 번째 판매점 정보:")
                        print("번호: \(firstStore.번호)")
                        print("상호: \(firstStore.상호)")
                        print("도로명주소: \(firstStore.도로명주소)")
                        print("지번주소: \(firstStore.지번주소)")
                    }
                }
            } catch {
                print("❌ 파싱 에러: \(error)")
                
                if let decodingError = error as? DecodingError {
                    switch decodingError {
                    case .dataCorrupted(let context):
                        print("Data corrupted: \(context.debugDescription)")
                    case .keyNotFound(let key, let context):
                        print("Key '\(key)' not found: \(context.debugDescription)")
                    case .typeMismatch(let type, let context):
                        print("Type '\(type)' mismatch: \(context.debugDescription)")
                    case .valueNotFound(let type, let context):
                        print("Value of type '\(type)' not found: \(context.debugDescription)")
                    @unknown default:
                        print("Unknown decoding error")
                    }
                }
            }
        }
        
        task.resume()
        
        // 비동기 작업이 완료될 때까지 대기
        RunLoop.main.run(until: Date(timeIntervalSinceNow: 5))
    }
}

// 테스트 실행
print("🚀 로또 판매점 API 테스트 시작")
LottoAPITest.testFetchLottoStores()

1. 전체 과정 요약

사용자 앱 → API 서버 요청 → 서버 응답 → 데이터 처리 → 화면 표시

2. 상세 설명

2-1. 데이터 모델 준비

struct LottoAPIResponse: Codable {
    let page: Int64
    let data: [LottoStore]
    // ... 기타 필드들
}

struct LottoStore: Codable {
    let 번호: Int
    let 상호: String
    // ... 기타 필드들
}
  • 서버에서 받을 데이터의 형태를 미리 구조체로 정의
  • Codable 프로토콜을 채택하여 JSON ↔ Swift 객체 간 변환 가능하게 함

2-2. API 요청 준비

let baseURL = "https://api.odcloud.kr/api"
let serviceKey = "발급받은 인증키"
let urlString = "\(baseURL)\(path)?serviceKey=\(serviceKey)"
  • API 서버 주소와 필요한 인증 정보를 준비
  • 마치 실제 주소를 적는 것처럼 URL을 조합

2-3. 네트워크 요청 보내기

var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Accept")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    // 응답 처리
}
task.resume()
  • URLSession을 사용하여 실제 네트워크 통신 수행
  • 마치 편지를 보내고 답장을 기다리는 것과 같은 과정

2-4. 응답 처리

// 1. 에러 체크
if let error = error {
    print("네트워크 에러 발생!")
    return
}

// 2. 응답 데이터 확인
guard let data = data else {
    print("데이터가 없음!")
    return
}

// 3. JSON 변환 및 처리
do {
    let response = try JSONDecoder().decode(LottoAPIResponse.self, from: data)
    print("성공! 데이터 받았음!")
    // 데이터 사용
} catch {
    print("데이터 변환 실패!")
}

3. 실제 동작 과정

1. 앱에서 요청 보내기
   └─ "로또 판매점 정보 좀 보내주세요!"

2. 서버가 요청 받기
   └─ "네, 잠시만 기다려주세요"

3. 서버가 응답 보내기
   └─ "여기 로또 판매점 정보입니다!"
   
4. 앱에서 응답 처리하기
   └─ 받은 정보를 사용자가 볼 수 있게 변환

4. 비유하자면...

  • 전체 과정은 마치 식당에서 주문하는 것과 비슷합니다:
    • 손님(앱)이 주문서(요청) 작성
    • 주문서를 주방(서버)에 전달
    • 주방에서 음식(데이터) 준비
    • 웨이터가 음식을 가져옴(응답)
    • 손님이 음식을 받아서 먹음(데이터 처리)

5. 주의할 점

  1. 네트워크 통신은 시간이 걸립니다
  2. 언제든 실패할 수 있습니다
  3. 받은 데이터가 예상한 형식과 다를 수 있습니다
  4. 적절한 에러 처리가 중요합니다

0개의 댓글