NEXTERS 3주차 

HttpRequest 사용하기.

8기 개발자 권기호. 

  


서론 

Android 환경에서 서버와 통신을 해야 하는 경우가 종종 있습니다.  여러분들은 어떤 모듈을 사용하여 서버와 통신하시나요? 

제가 처음 맞이했던 API는 Apache의 HttpClient였어요! 그래서 이번 3주차 활동에서는 Apache의 HttpClient를 이용한 서버와 통신하는 원리, 사용 방법 등을 알려드리고 싶었는 데... 오랜만에 보니…  


* deprecated…. 가슴이 아프네요… 

그러므로 이번 주는 HttpClient에서 HttpRequest로 주제가 변경되었습니다.  

*** 

그래도 혹시 사용해보고 싶으신 분들이 있을 것 같아 몇몇 자료를 첨부합니다! HttpClient를 사용하기 위해선 먼저 API를 설치해야 합니다. 아래 링크로 이동하여 소스를 다운로드 합시다. (전 4.5.2버전 사용합니다.)  아! 혼자 공부하시는 분들을 위하여 API 문서 링크를 따로 첨부했습니다.  

 다운로드 링크

 http://hc.apache.org/downloads.cgi

 API문서 링크

 https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/ 

 튜토리얼 링크

 %다운로드경로%\httpcomponents-client-4.5.2\tutorial\pdf

 Gradle

  android { useLibrary ‘org.apache.http.legaccy’ } 추가 dependencies { compile group: ‘org.apache.httpcomponents’ , name: ‘httpclient-android’, version: ‘4.3.5.1’ } 추가



HttpRequest 시작하기 

처음부터 코드를 보기보단 조금 이론적인 부분을 보고 가는 것이 좋겠죠?  

Hyper-Text Transfer Protocol(HTTP)은 오늘날 인터넷에서 사용되는 가장 중요한 프로토 콜입니다. (다 아는 사실이죠) HTTP에 사용하는 여러 가지 메소드가 있습니다. HTTP/1.0 스 펙에 기재되어 있는 요청 방법에는 GET, HEAD, POST 방ㅇ식이 있으며 1.1 스펙에서 추가 된 PUT, DELETE, TRACE 방식이 있습니다. (다음 링크에 HTTP/1.1 스펙이 잘 설명되어 있네 요. – mindseye.tistory.com/145 ) 

우리는 서버의 자원을 어떻게 사용하는지에 따라 GET, POST 방식를 많이 사용합니다. GET 방식은 “서버의 자원을 가져올 때 사용”합니다. 더 정확히는 한 트랜잭션이 진행되면 서 동기화 이슈를 불러 일으키지 않는 선에서만 사용됩니다. GET 방식의 사용법을 정확히 알게 되는 오늘은 서버의 자원을 가져올 때만 사용하는 것이 아니라 ‘한 트랜잭션에 대해 서 동기화 이슈에 위반되지 않을 경우’에 사용하면 됩니다. (GET 방식을 쓸 때 다양한 이 슈들이 존재합니다. 쿼리 스트링에 제한이 있기도 하죠!! 보안적인 문제도 있고~ㅋ 하지 만 웹 브라우저가 쿠키를 거부한다면…? 즉 스크릿 모드라면..? 등등? 이에 대해 고민하는 것은 여러분의 몫! ) 

POST는 1.1스펙에 멱등 방식이 아닌, 즉 정확한 트래잭션을 가지고 있는 방식입니다. 그래서 GET방식과 다르게 POST는 동기화 이슈에서 안전합니다(Thread safe). 그렇기 때문 에 서버에 데이터를 insert, update, delete의 요청을 할 때에 POST 방식을 이용합니다.  

 이와 같이 HttpRequest는 이 요청 방식들과 관련된 get, post, head, put 등 모든 메소드 들을 정적(static)으로 제공합니다! HttpRequest를 new 하지 않고도 사용할 수 있는 것이 죠~! 멋있어… 더 자세한 내용은 다음 페이지에서 설명하겠습니다. 

HttpRequest는 모두들 “단 하나만의 클래스이며, 무척 가볍다”라고 이야기를 합니다. 저 는 “무척 가볍다”라는 말에는 동의하지만 단 하나의 클래스라는 말에는 동의하지 않습니 다. 외부에서 보기엔 단 하나의 클래스인건 맞지만 단 하나의 클래스 속에 여러 개의 정 적 네스티드 클래스(nested class)와 인터페이스(interface)가 정의되어 있기 때문이죠. 

참고로 소스를 확인해보시면 아시겠지만, HttpRequest는 java.net 패키지의 HttpURLConnection을 기반으로 하여 작동합니다. 이를 개발한 팀 역시 HttpURLConnection을 사용하는 Android 개발자들을 위하여 혹은 가벼운 성능의 HTTP 요청을 전송하는 개발자들을 위해 개발했습니다.  

 

HttpRequest를 이용한 코드 작성 

HttpRequest는 여러 개의 네스티드 클래스와 인터페이스를 가지고 있습니다. 여러 개의 네스티드 클래스 중 제가 관심 있게 보고 있는 인터페이스가 있습니다. 바로 ConnectionFactory라는 인터페이스인데요~!! 이 인터페이스는 HttpRequest가 내부적으로 빌더(Builder) 디자인 패턴을 적용시키기 위하여 설계되어 있습니다. 또한 내부적으로 URL 클래스의 openConnection메소드를 호출하는 등 여러 모로 관심 덩어리입니다. 

ConnectionFactory interface는 2개의 추상 메소드를 가지고 있고, 자기 자신을 구현한 멤버필드를 가지고 있습니다. (인터페이스에 싱글톤을 적용시켰네요!) HttpRequest 서버로 요청을 보낼 때 마다 새로운 HttpURLConnection을 생성합니다~!  이런 특별한 구조로 HttpRequest는 HTTP의 다양한 요청 방식을 구현해냅니다. HttpRequest를 파헤쳐 보는 것은 또한 여러분의 몫입니다. 다음 링크에서 소스를 확인해 보세요!(링크) 

이제 그 요청 방식들 중 HttpRequest를 이용하여 어떻게 GET 방식의 요청을 하는지 알 아봅시다.  

GET  

다음과 같이 URL을 설정해준 뒤, HttpRequest에 사용할 요청방식 GET을 나타내는 get 메소드를 호출합니다. HttpRequest에 포함되어 있는 HTTP 요청 방식 메소드들은 모두 static 메소드이므로, 따로 HttpRequest 인스턴스를 생성할 필요가 없습니다.   


get 메소드 내부에선 HttpRequest 객체를 생성해서 리턴해줍니다.   


HttpRequest 생성자에는 인자가 두 개 있습니다. 첫 번째 인자는 요청을 보낼 URL, 두 번째 인자는 요청에 사용할 메소드입니다. (여기에서 java.net 패키지의 URL클래스를 사용합니다.)   

HttpRequest 객체 생성이 완료되었습니다. 이렇게 생성된 HttpRequest 객체는 서버로 요청을 보낼 모든 준비가 완료된 ‘준비된 객체’입니다.   

이제 이 준비된 객체를 서버로 요청을 보내기 위해선 응답(response)을 받을 수 있는 메 소드를 호출하면 됩니다.  

위 그림에선 code()메소드를 호출했습니다. code()내부에선 getConnection()메소드를 호출 합니다.  


getConnection()메소드는 createConnection()메소드를 호출하네요? 이 메소드는 무엇인지 따라가보면~!  


내부적으로 HttpURLConnection 객체를 생성하는 것을 볼 수 있습니다.  


CONNECTION_FACTORY는 ConnectionFactory객체입니다. 

이와 같이 응답의 정보에 따라 다양한 메소드를 이용할 수 있습니다. 서버가 보내주는 응답의 Header 정보를 확인하면 됩니다. Response Code를 확인해보는 code() 메소드, 응 답 메시지를 확인하는 body() 메소드, 통신이 성공했는지 확인하는 ok() 메소드가 있습니 다~!! 이렇게 서버의 응답을 확인하는 첫 메소드를 호출하는 순간 서버와 통신이 시작됩 니다. (두 번째부터 호출되는 메소드는 서버와 재 통신하지 않습니다.)  이제 위의 GET 방식과 더불어 POST 방식으로 요청을 전송하는 코드를 확인하겠습니다. 

  


최종코드   


주의 사항 

· 해당하는 메소드들을 첫 번째로 호출할 당시 호출한 위치가 Android의 UI Thread or runOnUiThread()일 경우 NetworkOnMainThreadException이 발생합니다. 

10  

· code(), ok()와 같은 메소드들은 첫 요청 이후 여러 번 재 호출해도 되지만 body() 메 소드는 한 번 호출 이후 재호출을 할 경우 IOException이 발생합니다. 

· 재 호출이 아니더라도 body() 메소드를 UIThread에서 호출할 경우 IOException이 발생합니다. 

HttpRequest 객체를 이용해서 UIComponent에 직접 데이터를 갱신해 주면 좋지만 모 든 작업은 Worker Thread에서 처리 후, 최종 결과만 UIThread에 전달하시길 권고합니다. 

마치며… POST 방식은 다음 장의 세션 유지하기에서 form data 전송과 함께 다시 한 번 더 보겠습니다. 

HttpRequest의 UML  


아! Multipart 종류들의 메소드들은 HttpRequest.part() 메소드를 사용하시면 됩니다! 

 Maven Central 

</dependency>

     <groupId>com.github.kevinsawicki</groupId>

      <artifactId>http-request</artifactId>

      <version>6.0</version>

</dependency>

 Not Maven environment

 https://raw.githubusercontent.com/kevinsawicki/http-request/master/lib/src/main/java/com/github/kevinsawicki/http/HttpRequest.java

 HttpRequest API

 HttpRequest API - http://kevinsawicki.github.io/http-request/apidocs/index.html

사용된 코드 & 도움된 사이트

HttpRequest - https://github.com/kevinsawicki/http-request

HttpRequest API - http://kevinsawicki.github.io/http-request/apidocs/index.html

HttpRequestProject(Android) – https://github.com/KwonGiho/HttpRequestProject

HttpRequestServer(J2EE) - https://github.com/KwonGiho/HttpRequestServer

HTTP1.1스펙 한글판 - mindseye.tistory.com/145

HTTP1.1 스펙 - https://tools.ietf.org/html/rfc2616#section-2.2

+ Recent posts