Skip to content

Conversation

@youn9k
Copy link
Member

@youn9k youn9k commented Nov 19, 2024

🤔 배경

  • HTTP API를 추상화합니다. #51
    스티커 API들을 사용하기 위해 HTTP 통신 메소드가 필요했고, 여러 API가 존재할 수 있어 추상화를 진행했습니다.

📃 작업 내역

  • enum Request 추가
// 사용 방법
Request.requestJSON(IssueAPI.fetchIssues(page: page))

// 구현부
public enum Request {
    public static func requestJSON<E: EndPoint, T: Decodable>(
        _ endPoint: E,
        decoder: JSONDecoder = .init(),
        queue: DispatchQueue = .main
    ) -> AnyPublisher<T, any Error> {
        return URLSession.shared.dataTaskPublisher(for: endPoint.request())
             // 10초의 타임아웃을 적용
            .timeout(.seconds(10), scheduler: RunLoop.main)
            .map { output in
               // 네트워크 로그를 출력
                printNetworkLog(request: endPoint.request(), output: output)
            }
            // Response -> Data 변환
            .tryMap(responseToData)
            // Data -> JSON 변환
            .decode(type: T.self, decoder: decoder)
            // Error 처리
            .mapError(\.asAPIError)
            // Queue 선택 옵션
            .receive(on: queue)
            .eraseToAnyPublisher()
    }
}
  • enum EndPoint 추가

서드파티 라이브러리인 Moya 방식에서 영감을 받아 EndPoint protocol로 추상화했습니다.
EndPoint 프로토콜을 채택하여 구현하고 request() 메소드를 통해 URLRequest 로 변환할 수 있도록 합니다.

public protocol EndPoint {
    var baseURL: URL { get }
    var path: String { get }
    var method: HTTPMethod { get }
    var parameters: [String: Any]? { get }
    var headers: [String: String]? { get }
    var body: Encodable? { get }
}

extension EndPoint {
    public func request() -> URLRequest { ... }

  • enum APIError 추가

네트워킹 중 발생하는 에러를 구분하기위해 Enum으로 관리합니다.

public enum APIError: Error {
    case decodingError(DecodingError)
    case badRequest       // 400번대 오류
    ...
}

extension APIError: LocalizedError {
    public var errorDescription: String? {
        switch self {
        case .unknown:
            return "알 수 없는 오류가 발생하였습니다."
        ...
        }
    }
}

디코딩 에러 메시지를 직관적으로 볼 수 있도록 프로퍼티를 추가합니다.

extension DecodingError {
    var fullDescription: String {
        switch self {
        case let .typeMismatch(type, context):
            return """
                    타입이 맞지 않습니다.\n
                    \(type) 타입에서 오류 발생:\n
                    codingPath: \(context.codingPath)\n
                    debugDescription: \(context.debugDescription)\n
                    underlyingError: \(context.underlyingError?.localizedDescription ?? "none")
                    """
        ...

✅ 리뷰 노트

🎨 스크린샷

  • nil 😨

🚀 테스트 방법

  • nil 🤯

Co-Authored-By: Kiyoung <[email protected]>
Co-Authored-By: 0Hooni <[email protected]>
Co-Authored-By: seuhong <[email protected]>
@youn9k youn9k added the ✨ feat 새로운 기능 추가 label Nov 19, 2024
@youn9k youn9k self-assigned this Nov 19, 2024
@youn9k youn9k linked an issue Nov 19, 2024 that may be closed by this pull request
1 task
Copy link
Member

@Kiyoung-Kim-57 Kiyoung-Kim-57 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@hsw1920 hsw1920 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

라이브 코드리뷰 완료

가독성 개선 및 네트워크 로그 수정
Copy link
Collaborator

@0Hooni 0Hooni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

라이브 코드리뷰함

LGTM 👍

@youn9k youn9k merged commit ac836eb into develop Nov 19, 2024
1 check passed
@youn9k youn9k deleted the feat/#51-http-api branch November 19, 2024 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTP API를 추상화합니다.

5 participants