[Swifit]Router로 API 요청하기-Alamafire Advanced Usage

Yungso
8 min readJul 27, 2021

--

이 글은 Alamofire(ver. 5) Advanced Usage의 request routing이 무엇인지 알아보고, router를 통해 request를 하는 방법을 소개합니다.

Photo by Jonathan on Unsplash

Request Routing..?

집에 있는 라우터를 먼저 떠올려보면, 집으로 들어오는 하나의 네트워크 선이 라우터를 통해 여러 컴퓨터에 연결할 수 있고 와이파이도 만들어줍니다. 앱에서의 라우터도 비슷한 느낌이죠. 하나의 앱에선 여러 API 요청이 발생하는데 Reqeust Router을 통해서 모든 요청을 생성할 수 있고, 이를 통해 API 요청 로직을 일관적으로 관리할 수 있습니다. API 요청할 때마다 Reqeust를 정의하는 코드가 여기저기 흩어져서 불안했다면(=It’s me🙋‍♀️) 라우터를 만들어서 내 관리하에 있다는 안정감을 얻을 수 있을 것입니다.

Alamofire의 Advanced Usage 문서에 Request Routing에 대한 내용이 있으며, 다음과 같이 사용하면 좋다는 것을 어필하고 있다.

As apps grow in size, it’s important to adopt common patterns as you build out your network stack. An important part of that design is how to route your requests. The Alamofire URLConvertible and URLRequestConvertible protocols along with the Router design pattern are here to help.

대충, 라우터를 디자인하는게 중요한데 URLRequestConvertible 프로토콜이 그걸 가능하게 해준다는 내용.

연습해볼 API

라우터를 만들어보기 전에 API 주소와 데이터 모델을 저장합니다. 실제로 테스트해 볼 수 있는 API 이니 함께 해보시죠! (전체 코드 Git 저장소는 이 글의 맨 아래 있습니다.)

API의 URL은 “https://httpbin.org/get”, “https://httpbin.org/post” 입니다. 따라서 baseURLAPIPath를 아래와 같이 저장합니다.

🔽 URL

let baseURL = "https://httpbin.org"class APIPath{
static let postPractice = "/post"
static let getPractice = "/get"
}

🔽 Parameter: userNameage를 파라미터로 전달할 것이기 때문에, Codable을 따르는 구조체를 만듭니다.

struct UserInfo: Codable {
var userName: String?
var age: Int?
}

🔽 Response: 응답값으로String타입의 url, UserInfo타입의 json을 받을 것입니다. 이따 확인해보겠지만 요청했던 URL과 파라미터가 그대로 응답값으로 오는 API 입니다.

struct HttpbinResponse: Decodable {
var url: String?
var json: UserInfo?
}

라우터 생성하기 - Routing Request

코드 작성하기 전에 라우터를 설계해 보겠습니다. 라우터는 Reqeust를 만드는 것이라는 컨셉을 기억하면서 라우터의 역할을 적어보면,

  1. base URL을 가변적으로 설정할 수 있다. 앱에서 요청하는 API는 인증 API와 서비스 API로 두 종류가 있고, 이 둘의 baseURL은 다르다고 가정해 본다. 또한, 빌드 환경(개발/스테이징/실서버)에 따라서도 baseURL이 달라진다고 하자. 이처럼 어떤 API에 요청하는지, 빌드 환경은 어떤지에 따라 라우터가baseURL을 설정해 줄 수 있어야 한다.
  2. get 또는 post 요청 방식에 따라 파라미터가 추가되도록 한다. get은 파라미터가 URL 쿼리로 추가되고 post는 body로 추가된다.
  3. URL 인코딩을 적용한다.
  4. 이 외에도 필요에 따라 header 값을 추가할 수 있다.

이렇게 설계한 라우터를 구현해봅시다.

[코드 노트]

URLRequestConvertible 프로토콜을 따르는 APIRouter 클래스를 정의합니다. URLRequestConvertible 프로토콜은 asURLRequest()메소드를 구현해야 하는데, 이 메소드에서 앞서 설계한 Request를 만들어 반환합니다.

1. enum으로APIType 을 정의합니다. APITypeauthservice로 나누고, 케이스에 따른 baseURL 을 저장합니다.

개발환경에 대한 enviroment 변수는 전역에서 접근가능하도록 저장했습니다. ⤵️

enum Enviroment {
case dev
case stage
case real
}
let enviroment: Enviroment = .dev

2. baseURLpath를 연결해서 URLComponent를 생성하고 퍼센트 인코딩을 합니다.

3. get 방식일때 파라미터를 query parameter로 추가해주기 위해, Data 타입인 파라미터를 Dictionary 형태로 타입캐스팅을 한 후에 queryItem으로 추가합니다.

4. 2–4과정으로 baseURLpath, query parameter로를 연결해서 URL을 만들었는데요, 이 URLRequest를 생성합니다.

5. post 방식이면 httpBody를 추가하고, headerContent-Typeapplication/json 으로 설정합니다.

이 외에도 필요한 header 값을 추가할 수 있지만, Authorization값은 RequestInterceptor로 인증 흐름을 구현하는 걸 추천드립니다. 관련 글은 여기에 있습니다.

라우터 사용하기

이제 위에서 만든 APIRouter를 호출할 거예요. 아래와 같이 요청 파라미터를 만듭니다.

var userInfo: UserInfo = {
var userInfo = UserInfo()
userInfo.userName = "yungso"
userInfo.age = 20
return userInfo
}()

Router에 파라미터는 Data 타입이기 때문에, Data 타입으로 형변환 해주는 extesion을 아래와 같이 만듭니다.

extension Encodable {
var toData: Data? {
guard let data: Data = try? JSONEncoder().encode(self) else { return nil }
return data
}
}

이제 드디어 get 요청을 해보자구요! APIRouterRequest를 리턴받아서 요청합니다.

APIRouter를 이용한 get 요청

제대로 요청이 되었는지 콘솔에 프린트된 내용을 확인해보아요.

[REQUEST]
URL: https://httpbin.org/get?age=20&userName=yungso
Body: nil
[RESPONSE]
URL: Optional("https://httpbin.org/get?age=20&userName=yungso")
Response Data: ...

post 요청은 APIRouterinit파라미터에서 pathhttpMethod만 바꿔주면 됩니다. 넘나 편한것..

APIRouter를 이용한 post 요청
[REQUEST]
URL: https://httpbin.org/post
Body: {
"age" : 20,
"userName" : "yungso"
}
[RESPONSE]
URL: https://httpbin.org/post
json body: UserInfo(userName: Optional("yungso"), age: Optional(20))
Response Data: ...

마무리

위의 라우터에는 put방식에서 파라미터 추가하는 내용이 빠져있기 때문에 put 요청이 있다면 이 부분을 꼭 추가해야 합니다. 인터넷에 Alamofire Router로 검색해서 다른 코드들도 살펴보면, get/post/put/delete 방식에 따라 라우터를 따로 만드는 경우도 있었고, APIRouter를 인스턴스화 하는 부분을immutable value로 한 파일에 저장해두고 사용하기도 하더라구요. 편의 또는 상황에 맞게 라우터를 커스텀하여 만드는데 이 글이 도움이 되었으면 좋겠습니다~!

🔽 전체 소스코드를 포함한 데모 프로젝트이니, 실행해보며 테스트해보실 수 있습니다.

🔽 Alamofire Advanced Usage에 대해 더 알아보고 싶다면👇👇 click click!

--

--