Skip to content

선아_네트워크 Endpoint 분석, Moya 네트워크 예제

sunnyCookie edited this page May 1, 2023 · 2 revisions

Endpoint

  • ✅ API가 두 시스템(어플리케이션)이 상호작용(소통) 할 수 있게 하는 프로토콜의 총집합이라면 Endpoint는 API가 서버에서 리소스에 접근가능하게 하는 URI다.
  • ex) 지하철 최단 거리 경로를 제공하는 서비스가 있을 때, 사용자는 출발역과 도착역을 설정하고 최단 경로를 찾는 버튼을 터치한다.
    이 때 최단경로를 구하는 서비스를 이용하려는 요청 URI가 엔드포인트이다.


URLSession을 이용할 때 Endpoint 요소

  • baseURL + path + queryParameters => URL 만들고
  • URLhttpBody, httpMethod, header를 사용해 => URLRequest를 만들어서 요청
// Endpoint 구현: Requestable, Responsable의 성격을 가지고 있는 클래스

class Endpoint<R>: RequesteResponsable {
    // 응답 타입 제네릭 명시
    typealias Response = R

    var baseURL: String
    var path: String
    var method: HttpMethod
    var queryParameters: Encodable?
    var bodyParameters: Encodable?
    var headers: [String: String]?
    var sampleData: Data?

    init(...) {...}
}
  • baseURL: endpoint의 root 입니다.
  • path: 리소스의 경로. 데이터의 실제 위치를 나타냅니다
  • method: 리소스에 접근하는 방법입니다. (ex. GET, POST, DELETE...)
  • queryParameters: 물음표로 URL과 구분해서 사용하는 매개변수로 데이터를 정렬, 필터링해줍니다.
  • bodyParameters: 해당 request 혹은 response의 실제 메시지 혹은 내용이 담겨 있다.
    //bodyParameters json 형식의 예
    {
        "userId": "keepcalm",
        "message": "hello, world",
        "status": "noraml"
    }
    
  • headers: key:value 형태로 돼있으며, 추가 정보를 담고 있는 부분이다. (Host / User-Agent(request) or Server(response) / Connection / Content-Type / Content-Length...)

  • 예) body와 header로 완성된 HTTP메세지
    POST /userAccount/login HTTP/1.1                                    // (1) 라인
    Host: swiftapi.rubypaper.co.kr:2029.                                // (2) 헤더
    Content-Type: application/x-www-form-urlencoded                     // (2) 헤더
     
    account=swift%40swift.com&passwd=1234&grant_type=password           // (3) 바디
    


⚙️ Moya 라이브러리

  • URLSession 기반인 Alamofire를 한번 더 추상화한게 Moya다

  • 개발자는 Response, Request만 신경쓰면된다.

  • 장점

    • 깔끔한 네트워크 계층구조를 갖게할 수 있고, 계층을 템플릿화해 재사용성이 높고 가독성이 좋다.
    • API Endpoint 가 올바른지 컴파일시 확인해준다
    • Enum 연관값 사용으로 다양한 endpoint들에대해 명확한 사용법 정의가 가능하다.
    • 유닛테스트가 쉽다.
  • 사용예제

    • endpoint는 Moya의 TargetType 프로토콜을 채택해 구성할 수 있다.
    import Foundation
    import Moya
    
    /*
     Test IPA 제공 : https://reqres.in/
     */
    
    enum TestService: TargetType {
        case readUserList(page: Int)  // https://reqres.in/api/users?page=2
        case registerUser(user: User) // https://reqres.in/api/users
        case updateUser(name: String, id: Int)   // https://reqres.in/api/users/2
    }
    
    extension TestService {
        var baseURL: URL {
            guard let url = URL(string: "https://reqres.in") else {
                fatalError("fatal error, invalid baseURL")
            }
    
            return url
        }
    
        var path: String {
            switch self {
            case .readUserList(_), .registerUser:
                return "/api/users"
            case .updateUser(_, let id):
                return "/api/users/\(id)"
            }
        }
    
        // Http method
        var method: Moya.Method {
            switch self {
            case .readUserList:
                return .get
            case .registerUser:
                return .post
            case .updateUser:
                return .put
            }
    
        }
    
        var task: Moya.Task {
            switch self {
            case .readUserList(let page):
                return .requestParameters(parameters: ["page": page], encoding: URLEncoding.queryString)
            case .registerUser, .updateUser:
                return .requestPlain
            }
            // 1. requestPlain : 기본적으로 어떤 값을 넣지 않을 때 사용합니다. (주로 GET)
            // 2. requestData : Body에 데이터를 담아서 보낼 때 사용합니다. (주로 POST)
            // 3. requestParameters : 파일을 다운로드 할 때 다운로드 링크를 담습니다. (주로 GET)
        }
    
        var headers: [String : String]? {
            return nil
        }
    }
    • endpoint를 이용한 네트워크 통신은 Moya의 MoyaProvider객체를 생성해 사용한다. 이 때, 요청,응답에 쓰이는 데이터타입을 명시해준다
    struct APIManager {
    
        private let provider: MoyaProvider = MoyaProvider<TestService>()
    
        func requestList(page: Int) {
            provider.request(.readUserList(page: page)) { result in
                switch result { ... }
            }
        }
        // ...
    }

참고문서
iOS-Moya를 이용한 API통신처리
[iOS - swift] Moya를 사용한 network 구조 설계 (무료 API 테스트, REST)
[Moya] Moya프레임 워크 (RESTFul API)
Moya test code 참고: 우아한형제들 기술블로그 - iOS Networking and Testing