[요약] Java URLConnection과 HttpURLConnection 사용 방법
URL(대부분 HTTP 프로토콜 사용)을 통해 서버와 통신하는 Java 프로그램을 개발 하기 위
해 URLConnection 및 HttpURLConnection 클래스를 사용한다. 예를들어 파일, 웹 페이지를 업로드 및 다운로드, HTTP 요청 및 응답 전송 및 검색 등을 위한 코드를 작성할 수 있다.
URLConnection과 HttpURLConnection 클래스
URLConnection은 Java 애플리케이션과 URL 간의 연결 관련한 모든 클래스의 수퍼클래스이다. URLConnection의 클래스는 일반적인 URL에 대한 API를 제공하고, 서브 클래스 HttpURLConnection는 HTTP 고유의 기능에 대한 추가 지원을 제공한다. 이 두 클래스는 모두 추상클래스이다. 그러므로, URLConnection 및 HttpURLConnection의 새 인스턴스를 직접 만들 수 없다 . 대신 URL 객체에서 연결을 통해 URLConnection의 인스턴스를 얻는다. 일반적으로 클라이언트 프로그램은 URL을 통해 서버와 통신할때 다음 단계를 따른다.
- URL 객체 만들기
- URL에서 URLConnection 객체 얻기
- URL 연결 구성
- 헤더 필드 읽기
- 입력 스트림 가져오기 및 데이터 읽기
- 출력 스트림 가져오기 및 데이터 쓰기
- 연결 닫기
3~6단계는 선택 사항이며, 5~6단계는 서로 바꿔 사용할 수 있다. 개발 시에 필요한URLConnection 및 HttpURLConnection 클래스의 API는 아래와 같다 .
1. URL 객체 생성
다음과 같이 주어진 URL 주소에 대해 새 URL 객체를 생성한다.
1 | URL url = new URL("http://www.google.com"); |
이 생성자는 URL 형식이 잘못된 경우 MalformedURLException 을 throw한다 . 이 예외는 IOException 의 하위 클래스다.
2. URL에서 URLConnection 객체 얻기
URLConnection 인스턴스는 URL 객체의 openConnection() 메소드 호출에 의하여 얻어진다.
1 | URLConnection urlCon = url.openConnection(); |
프로토콜이 http://인 경우 반환된 객체를 HttpURLConnection 객체 로 캐스팅할 수 있다.
1 | HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); |
openConnection() 메서드는 실제 네트워크 연결을 설정하지 않고, 단지 URLConnection 클래스의 인스턴스를 반환한다. 네트워크 연결은 connect() 메서드가 호출 될 때 명시적으로 이루어지거나, 헤더 필드를 읽거나 입력스트림/출력스트림을 가져올 때 암시적으로 이루어진다. URL의 openConnection() 메서드는 I/O 오류가 발생하면 IOException을 발생시킨다.
3. URLConnection 구성
실제로 연결을 설정하기 전에 타임아웃, 캐시, HTTP 요청 방법 등과 같이 클라이언트와 서버 간의 다양한 옵션을 설정할 수 있다. URLConnection 클래스는 연결을 구성하기위한 다음과 같은 메소드를 제공한다 :
- setConnectTimeout (int timeout) : 연결 타임아웃 값을 설정한다(단위 : 밀리초). java.net.SocketTimeoutException는 연결이 설정되기 전에 제한 시간이 만료되면 발생한다. 시간 초과가 0이면, 무한대 타임아웃(기본값)을 의미한다.
- setReadTimeout (int timeout) : 읽기 타임아웃 값을 설정한다(단위 : 밀리초). 제한 시간이 만료되고 연결의 입력 스트림에서 읽을 수 있는 데이터가 없으면 SocketTimeoutException이 발생한다. 시간 초과가 0이면, 무한대 타임아웃(기본값)을 의미한다.
- setDefaultUseCaches (boolean default) : URLConnection이 기본적으로 캐시를 사용하는지 여부를 설정한다(기본값은 true). 이 메서드는 URLConnection 클래스의 다음 인스턴스에 영향을 준다.
- setUseCaches (boolean useCaches) : 연결이 캐시를 사용하는지 여부를 설정한다(기본값은 true).
- setDoInput (boolean doInput) : URLConnection을 서버에서 콘텐츠를 읽는 데 사용할 수있는지 여부를 설정한다(기본값은 true).
- setDoOutput (boolean doOutput) : URLConnection이 서버에 데이터를 보내는 데 사용할 수있는지 여부를 설정한다(기본값은 false).
- setIfModifiedSince (long time) : 주로 HTTP 프로토콜에 대해 클라이언트가 검색한 콘텐츠의 마지막 수정 시간을 새로 설정한다. 예를 들어, 서버가 지정된 시간 이후에 정적콘텐츠(이미지, HTML 등)가 변경되지 않았으면 콘텐츠를 가져오지 않고 상태 코드 304(수정되지 않음)를 반환한다. 클라이언트는 지정된 시간보다 최근에 수정된 경우 새로운 콘텐츠를 받게 된다.
- setAllowUserInteraction (boolean allow) : 사용자 상호 작용을 활성화 또는 비활성화한다. 예를 들어 필요한 경우 인증 대화 상자를 표시한다(기본값은 false).
- setDefaultAllowUserInteraction (boolean default) : 이후의 모든 URLConnection객체에 대한 사용자 상호 작용의 기본값을 설정한다.
- setRequestProperty (String key, String value) : key=value 쌍으로 지정된 일반 요청 속성을 설정한다. 키가 있는 속성이 이미 있는 경우 이전 값을 새 값으로 적용한다.
이러한 메서드는 연결을 설정하기 전에 호출해야 한다. 일부 메서드는 연결이 이미 설정된 경우 IllegalStateException을 발생시킨다. 또한 하위 클래스 HttpURLConnection은 HTTP 관련 기능을 사용하여 연결을 구성하기 위한 다음 메서드를 제공합니다.
- setRequestMethod (String method) : HTTP 메소드 GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE 중 하나인 URL 요청에 대한 메소드를 설정합니다. 기본값은 GET이다.
- setChunkedStreamingMode (int chunkLength) : 콘텐츠 길이를 미리 알 수 없는 경우 내부 버퍼링 없이 HTTP 요청 본문을 스트리밍할 수 있다.
- setFixedLengthStreamingMode (long contentLength) : 콘텐츠 길이를 미리 알고 있는 경우 내부 버퍼링 없이 HTTP 요청 본문을 스트리밍할 수 있다.
- setFollowRedirects (boolean follow) : 이 정적 메서드는 HTTP 리다이렉션 뒤에 이 클래스의 미래 개체가 자동으로 따라야 하는지 여부를 설정한다(기본값은 true).
- setInstanceFollowRedirects (boolean follow) : HTTP 리다이렉션 뒤에 이 HttpURLConnection 클래스의 인스턴스가 자동으로 따라와야 하는지 여부를 설정한다(기본값은 true).
위의 메소드는 setter이다. 그리고 URLConnection과 HttpURLConnection 클래스는 해당 getter도 제공한다.
- getConnectTimeout()
- getReadTimeout()
- getDefaultUseCaches()
- getUseCaches()
- getDoInput()
- getDoOutput()
- getIfModifiedSince()
- getAllowUserInteraction()
- getDefaultAllowUserInteraction()
- getRequestProperty(문자열 키)
- getRequestMethod()
- getFollowRedirects()
- getInstanceFollowRedirects()
4. 헤더 필드 읽기
연결이 이루어지면 서버는 URL 요청을 처리하고 메타데이터와 실제 콘텐츠로 구성된 응답을 다시 보낸다. 메타데이터는 헤더 필드라고 하는 키=값 쌍의 모음이다. 헤더 필드는 서버에 대한 정보, 상태 코드, 프로토콜 정보 등을 나타낸다. 실제 내용은 문서의 유형에 따라 텍스트, HTML, 이미지 등이 될 수 있다. URLConnection 클래스는 헤더 필드를 읽기 위한 다음과 같은 방법을 제공한다 :
- getHeaderFields () : 모든 헤더 필드를 포함하는 맵을 반환한다. 키는 필드 이름이고 값은 해당 필드 값을 나타내는 문자열 목록이다.
- getHeaderField (int n) : n 번째 헤더 필드의 값을 읽는다.
- getHeaderField (String name) : 명명된 헤더 필드의 값을 읽는다.
- getHeaderFieldKey (int n) : n 번째 헤더 필드의 키를 읽는다.
- getHeaderFieldDate (String name, long default) : Date로 구문 분석된 명명된 필드의 값을 읽는다. 필드가 없거나 값 형식이 잘못된 경우 기본값이 대신 반환된다.
- getHeaderFieldInt (String name, int default) : 정수로 구문 분석된 명명된 필드의 값을 읽는다. 필드가 없거나 값 형식이 잘못된 경우 기본값이 대신 반환된다.
- getHeaderFieldLong (String name, long default) : 긴 숫자로 구문 분석된 명명된 필드의 값을 읽는다. 필드가 없거나 값 형식이 잘못된 경우 기본값이 대신 반환된다.
위는 헤더 필드를 읽는 일반적인 메서드 이다. 자주 액세스하는 일부 헤더 필드의 경우 URLConnection 클래스는 보다 구체적인 메서드를 제공한다.
- getContentEncoding () : 콘텐츠의 인코딩 유형을 나타내는 콘텐츠 인코딩 헤더 필드의 값을 읽는다.
- getContentLength () : 콘텐츠의 크기(바이트)를 나타내는 콘텐츠 길이 헤더 필드의 값을 읽는다.
- getContentType () : 컨텐츠의 유형을 나타내는 컨텐츠 유형 헤더 필드의 값을 읽는다.
- getDate () : 서버의 날짜 시간을 나타내는 날짜 헤더 필드의 값을 읽는다.
- getExpiration () : 만료 헤더 필드의 값을 읽고 응답이 오래된 것으로 간주되는 시간을 나타낸다. 이는 캐시 제어를 위한 것이다.
- getLastModified () : 컨텐츠의 마지막 수정 시간을 나타내는 last-modified 헤더 필드의 값을 읽는다.
그리고 서브클래스 HttpURLConnection 은 추가 메소드를 제공한다:
- getResponseCode () : 서버에서 보낸 HTTP 상태 코드를 반환한다.
헤더 필드를 읽을 때 connect() 를 호출하지 않고 암시적으로 연결이 설정된다.
5. 입력 스트림 가져오기 및 데이터 읽기
실제 내용을 읽으려면 연결에서 InputStream 인스턴스 를 얻은 다음 InputStream 의 read() 메서드를 사용하여 데이터를 읽어야 힌다.
1 2 3 |
InputStream inputStream = urlCon.getInputStream(); byte[] data = new byte[1024]; inputStream.read(data); |
InputStream의 read ()는 데이터를 바이트의 배열로 읽는 로우-레빌(low-level)의 메서드이다. 문자 데이터를 읽기 위해서는 InputStream을 InputStreamReader에서 보다 편하게 조작하기 위해 래핑 한다 :
1 2 3 4 5 6 |
InputStream inputStream = urlCon.getInputStream(); InputStreamReader reader = new InputStreamReader(inputStream); int character = reader.read(); // reads a single character char[] buffer = new char[4096]; reader.read(buffer); // reads to an array of characters |
또는 데이터를 문자열로 읽기 위해 InputStream을 BufferedReader 로 래핑한다 .
1 2 |
BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String line = reader.readLine(); // reads a line |
getInputStream () 메소드는 다음과 같은 예외를 던질 수 있다 :
- IOException : 입력 스트림을 생성하는 동안 I/O 오류가 발생한 경우.
- SocketTimeoutException : 데이터를 읽을 수 있기 전에 읽기 제한 시간이 만료되는 경우.
- UnknownServiceExcepetion : 프로토콜이 입력을 지원하지 않는 경우.
6. 출력 스트림 가져오기 및 데이터 쓰기
서버에 데이터를 보내려면 먼저 연결에서 출력을 활성화해야 합니다.
1 | urlCon.setDoOutput(true); |
연결과 관련된 OutputStream 객체를 가져온 다음 OutputStream 의 write() 메서드를 사용하여 데이터를 쓴다.
1 2 3 |
OutputStream outputStream = urlCon.getOutputStream(); byte[] data = new byte[1024]; outputStream.write(data); |
OutputStream의 write () 메서드는 바이트의 배열을 기록하는 낮은 수준의 방법이다. 문자 데이터를 쓰기 위해서는 OutputStream을 OutputStreamWriter 에서 보다 편하게 조작하기 위해 래핑한다 :
1 2 3 4 5 6 |
OutputStreamWriter writer = new OutputStreamWriter(outputStream); int character = 'a'; writer.write(character); // writes a single character char[] buffer = new char[4096]; writer.write(buffer); // writes an array of characters |
또는 문자열을 작성하기 위해 PrintWriter 에서 OutputStream 을 래핑한다 .
1 2 3 |
PrintWriter writer = new PrintWriter(outputStream); String line = "This is String"; writer.print(line); |
참고로 getOutputStream () 메소드는 IOException 또는 UnknownServiceException를 throw 할수있다.
7. 연결 종료
연결을 닫으려면 InputStream 또는 OutputStream 객체 에서 close() 메서드를 호출한다. 이렇게 하면 URLConnection 인스턴스와 연결된 네트워크 리소스가 해제된다 .URLConnection과 HttpURLConnection의 API를 사용하는 방법이다.
[글 원문] https://www.codejava.net/java-se/networking/how-to-use-java-urlconnection-and-httpurlconnection