-
코틀린의 가벼운 http 클라이언트 fuel카테고리 없음 2020. 7. 25. 10:44
자바 진영에서는 주로 스프링의 RestTemplate을 사용하여 http 요청을 했었지만 코틀린 진영에서는 1대장의 자리를 두고 새롭게 여러가지 http클라이언트 라이브러리가 개발되고 있는 것 같다.
그 중 한 가지를 가볍게 소개하고자 한다.
https://github.com/kittinunf/fuel
kittinunf/fuel
The easiest HTTP networking library for Kotlin/Android - kittinunf/fuel
github.com
fuel(발음은 fyool) 이라고 한다.
주요 피쳐로는
- GET, POST, PUT, DELETE, HEAD, PATCH 제공하되 사용하기 편리한 인터페이스가 제공된다.
- 비동기, 블로킹 요청
- 파일 업로드, 다운로드
- 비동기 요청 취소(이것은 뭘까?)
- 로깅 기능
- (De)Serialize
- 코루틴으로 요청 기능(병렬처리할때 좋을 듯)
- 라우팅
가 있다.
사용방법
GET 요청
// blocking mode val (request, response, result) = "http://github.com/hello" .httpGet().response() // async mode "http://http://github.com/hello".httpGet().response { request, response, result -> //response handling }
코틀린의 확장함수를 이용하여 직관적으로 호출하는 모습이고 request, response, result 를 구조분해하여 편리하게 가져다 쓸 수 있다.
블로킹은 값들을 한번에 리턴하고 비동기 호출은 콜백을 저렇게 전달하면 된다.
POST 요청
// blocking mode val (request, response, result) = Fuel.post("http://github.com/hello/post") .body(bodyJson) .response() // async mode "http://github.com/hello/post".httpPost() .body(bodyJson) .response{ request, response, result -> //response handling }
POST도 직관적으로 사용하기 쉽게 되어있다.
fuel의 여러가지 설정은
FuelManager.instance
라는 객체를 사용하여 아래와 같이 전역으로 설정을 등록할 수 있다.
// base path 추가 FuelManager.instance.basePath = "http://github.com/hello" val (request, response, result) = "/get".httpGet().response() // header 전역으로 추가 FuelManager.instance.baseHeaders = mapOf("Content-Type" to "Hello") // interceptor 추가 FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor()) FuelManager.instance.addRequestInterceptor(tokenInterceptor()) fun tokenInterceptor() = { next: (Request) -> Request -> { req: Request -> req.header(mapOf("Authorization" to "Bearer AbCdEf123456")) next(req) } }
아직은 경량으로 만들어서 그런지 조금 불편한 점도 보이는데,
pojo로 객체를 받아오고자 할 때는 여러가지 방법이 제시가 되어 있지만 요 방법이 그나마 깔끔해 보인다.
data class Post(var userId:Int, var id:Int, var title:String, var body:String){ class Deserializer : ResponseDeserializable<Array<Post>> { override fun deserialize(content: String): Array<Post> = Gson().fromJson(content, Array<Post>::class.java) } } val post = Post(1, 1, "Lorem", "Lorem Ipse dolor sit amet") val (request, response, result) = Fuel.post("http://github.com/hello/posts") .header("Content-Type" to "application/json") .body(Gson().toJson(post).toString())
변환하고자 하는 클래스에 직접 내부 Deserializer 클래스를 선언해야 하며,
Gson 말고 jackson 모듈을 추가해서 사용할 수도 있다만 어쨌든 직접 어떤 deserialze 모듈을 사용할지 직접 명시를 해 줘야 하는 것 같다..
그리고 기존 RestTemplate에 친숙했던 자바 진영의 유저들은 커넥션 풀, 타임아웃 등의 추가적인 설정을 하기 위해서 ApachaHttpClient를 사용했는데 fuel은 아직 클라이언트 구현체로 ApacheHttpClient를 갈아 끼우는 확장기능은 제공하지 않고 있다. 심지어 다른 방법으로도 커넥션 풀 설정은 아직은 불가능한 것 같다.
https://github.com/kittinunf/fuel/issues/320
Add explicit connection pooling options · Issue #320 · kittinunf/fuel
I'm using Fuel in a high-concurrency environment, so due to UNIX's usage of sockets as files, I'm encountering issues where I have too many open sockets (due to the TIME_WAIT state of s...
github.com
깃허브의 누가 이슈를 제기했는데 2년동안 아직 open 상태이다. ㅜㅜ
처음의 사용법은 직관적이고 편리하다 했는데 아직 실무에서 사용하는 것은 좀 더 기다려봐야 할 것 같다.