HttpClient

haribo·2021년 2월 27일
1

Java

목록 보기
16/17

들어가기에 앞서

  • 통신 : 서로 다른 두 프로그램간의 데이터 교환. (내적갈등은 통신이 아님)
  • 한 쪽에서 원하는 데이터를 다른 한쪽에 요청하고, 이에 대한 응답 결과를 받는 과정으로 진행된다.

<구조도>

응용프로그램 ————(요청)————→ 서버프로그램

(클라이언트) ←———-(응답)—————

통신방식의 종류

  • socket 통신 : 모든 데이터 교환이 byte배열로 이루어지는 원초적 형태. 서버 프로그램을 직접 개발해야하고, byte 배열의 구조를 설계해야하는 어려움 존재. java.net.Socket 클래스를 이용하여 구현한다. (식당의 화덕. 직접 가마도 만들어야하고, 어떻게 요리할지도 생각해야하고...)
  • Http 통신 : 웹 브라우저와 웹 서버간의 통신 원리를 구현한 형태. 이미 수많은 웹사이트를 통해 성능이 검증된 서버를 활용한다. 웹 프로그래머 역할이 서버개발자에 해당하게 되므로 소켓통신보다 개발이 쉽고 빠르며, 오픈소스 라이브러리를 사용한다. (식당의 가스레인지. 그냥 사오면 그만이고, 공산품이니 안전함도 확보 되어있고, 사용도 간단하다.)

<실습>

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

public class Main01 {
	public static void main(String[] args) {
		
		/********** (1) 접속 설정 **********/
		// 접속할 웹 페이지 주소
		String url = "http://itpaper.co.kr/demo/java/hello.txt";
		// 데이터를 읽기 위한 인코딩 형식
		String encType = "UTF-8";
		// 접속 대기에 대한 제한시간 --> 밀리세컨드 단위
		int timeout = 30000;
	
		// 통신객체 - 웹브라우저에 해당
		HttpClient client = null;
		// 접속을 하기 위한 기본 환경설정 객체 - 인터넷 옵션값 저장
		HttpParams params = new BasicHttpParams();
		// 프로토콜 버전 설정
		params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
				HttpVersion.HTTP_1_1);
		// 요청 제한 시간
		HttpConnectionParams.setConnectionTimeout(params, timeout);
		// 응답 제한 시간
		HttpConnectionParams.setSoTimeout(params, timeout);
		// 통신에 사용할 인코딩 값 설정
		HttpProtocolParams.setContentCharset(params, encType);
		// 접속 기능을 하는 객체 생성 - 옵션값 넘겨줌 
		client = new DefaultHttpClient(params);
		
		
		/********** (2) 읽은 값을 복사할 변수 선언 및 초기화 **********/
		String result = null;
		
		/********** (3) 접속하기 **********/
		// 응답 결과가 저장될 객체
		InputStream is = null;
		
		// 통신에 필요한 요청 정보 설정 --> URL을 주소표시줄에 입력하기
		HttpGet httpget = new HttpGet(url);
		try {
			// 요청을 보낸 후, 응답 받기
			HttpResponse response = client.execute(httpget);
			
			// 웹 서버의 응답결과 코드 받기
			// 404 : Page Not Found (주소 오타, 파일 없음)
			// 500 : Server Error, 200 : OK
			int resultCode = response.getStatusLine().getStatusCode();
			
			// 서버 응답이 정상일 경우에만 처리
			if (resultCode == HttpURLConnection.HTTP_OK) {
				// 수신된 응답에서 실 데이터 추출
				HttpEntity entity = response.getEntity();
				BufferedHttpEntity buffer = new BufferedHttpEntity(entity);
				
				//추출한 데이터를 InputStream으로 변환
				is = buffer.getContent();
			}
			
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 통신 해제
			client.getConnectionManager().shutdown();
		}
		
		/********** (4) 받은 응답에 대한 결과 처리 **********/
		
		try {
			byte[] buffer = new byte[is.available()];
			is.read(buffer);
			result = new String(buffer, encType);
			System.out.println(result);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

helper 클래스의 필요성

파일 helper클래스의 이유와 동일하다. 모든 프로그램들은 네트워크를 통해 데이터를 다운로드받고, 저장을 위하여 데이터를 전송하는 기능을 필요로한다. 동일한 기능이 자주 쓰이면 우린 helper로 만들어서 코드를 재사용하는게 효율적이란걸 이미 알고있다.

package study.java.helper;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

public class HttpHelper {
	// ------ 싱글톤 객체 생성 시작 ------
	private static HttpHelper current;

	public static HttpHelper getInstance() {
		if (current == null) {
			current = new HttpHelper();
		}
		return current;
	}

	public static void freeInstance() {
		// 객체에 null을 대입하면 메모리에서 삭제된다.
		current = null;
	}

	// 기본 생성자를 private으로 은닉하게 되면 new를 통한 객체 생성이 금지된다.
	private HttpHelper() {
		super();
	}
	// ------ 싱글톤 객체 생성 끝 ------

	public InputStream getWebData(String url, String encType) {
		// 접속 대기에 대한 제한시간 --> 밀리세컨드 단위
		int timeout = 30000;

		// 통신객체
		HttpClient client = null;
		// 접속을 하기 위한 기본 환경설정 객체
		HttpParams params = new BasicHttpParams();
		// 프로토콜 버전 설정
		params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
		// 요청 제한 시간
		HttpConnectionParams.setConnectionTimeout(params, timeout);
		// 응답 제한 시간
		HttpConnectionParams.setSoTimeout(params, timeout);
		// 통신에 사용할 인코딩 값 설정
		HttpProtocolParams.setContentCharset(params, encType);
		// 접속 기능을 하는 객체 생성
		client = new DefaultHttpClient(params);

		/********** (3) 접속하기 **********/
		// 응답 결과가 저장될 객체
		InputStream is = null;

		// 통신에 필요한 요청 정보 설정 --> URL을 주소표시줄에 입력하기
		HttpGet httpget = new HttpGet(url);
		try {
			// 요청을 보낸 후, 응답 받기
			HttpResponse response = client.execute(httpget);

			// 웹 서버의 응답결과 코드 받기
			// 404 : Page Not Found (주소 오타, 파일 없음)
			// 500 : Server Error, 200 : OK
			int resultCode = response.getStatusLine().getStatusCode();

			// 서버 응답이 정상일 경우에만 처리
			if (resultCode == HttpURLConnection.HTTP_OK) {
				// 수신된 응답에서 실 데이터 추출
				HttpEntity entity = response.getEntity();
				BufferedHttpEntity buffer = new BufferedHttpEntity(entity);

				// 추출한 데이터를 InputStream으로 변환
				is = buffer.getContent();
			}

		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 통신 해제
			client.getConnectionManager().shutdown();
		}
		
		// 통신결과 리턴
		return is;
	}
}
import java.io.IOException;
import java.io.InputStream;

import study.java.helper.HttpHelper;

public class Main02 {
	public static void main(String[] args) {
		/*********** (1) 접속 설정 ***********/
		// 접속할 웹 페이지 주소
		String url = "https://www.naver.com";
		// 데이터를 읽기 위한 인코딩 형식
		String encType = "UTF-8";

		/*********** (2) 읽은 값을 복사할 변수 선언 및 초기화 ***********/
		String result = null;
		
		/*********** (3) 접속하기 ***********/
		InputStream is = HttpHelper.getInstance().getWebData(url, encType);
		
		// 예외처리
		if (is == null) {
			System.out.println("통신 실패");
			return;
		}

		/*********** (4) 받은 응답에 대한 결과 처리 ***********/
		
		try {
			byte[] buffer = new byte[is.available()];
			is.read(buffer);
			result = new String(buffer, encType);
			System.out.println(result);
		} catch (IOException e) {
			e.printStackTrace();
		}
		

		
	}

}

실행하면 네이버 페이지 구성 소스와 동일한 결과를 가져온다.

웹브라우저는 웹서버에서 받은 결과를 그래픽으로 변환해주는 기능을 하는 프로그램이다.

결론

  • 일반 응용프로그램에서는 서버로부터 수신되는 응답결과에 포함된 데이터를 활용하는 형태로 구현된다.
  • 데이터를 구성하기 가장 적합한 구조는 JSON 형식이다.
  • 즉 웹서버에서 JSON형식의 데이터를 생성하고, 클라이언트가 그 데이터를 전송받아 활용하는 형태가 최근 프로그래밍 구현 기법 중에서 기본적으로 사용되고 있다.
  • Http 통신 + JSON 데이터 파서 + DAO 패턴
  • 안드로이드 데이터 통신을 위하여 사용되는 기본 패턴이다.
  • 이 과정이 웹에서 쓰일경우 Ajax라 불린다.
이 포스트는 itpaper.co.kr에서 제공되는 강의자료를 바탕으로 작성되었습니다.
profile
그림 그리는 백엔드 개발자

0개의 댓글