[API] URL을 통한 클라이언트 - 서버 통신 과정 : URL 구성부터 URLConnection과 HttpURLConnection의 API 사용법까지

민지·2024년 1월 10일

API

목록 보기
2/2

URL을 통한 클라이언트 - 서버 통신 과정

이 포스팅은 전에 배운 샘플코드를 공부하는 과정과 코드를 리팩토링하는 과정을 담은 포스팅이다. 먼저 샘플코드는 다음과 같다.

/* Java 1.8 샘플 코드 */

package test;

import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.io.BufferedReader;
import java.io.IOException;

public class ApiExplorer {
	public static void main(String[] args) throws IOException {
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode("65526b696f6f6c693833424b6f586c","UTF-8") ); /*인증키 (sample사용시에는 호출시 제한됩니다.)*/
		urlBuilder.append("/" +  URLEncoder.encode("xml","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("CardSubwayStatsNew","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("5","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
		// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
		
		// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
		urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		URL url = new URL(urlBuilder.toString());
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setRequestProperty("Content-type", "application/xml");
		System.out.println("Response code: " + conn.getResponseCode()); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		BufferedReader rd;

		// 서비스코드가 정상이면 200~300사이의 숫자가 나옵니다.
		if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
				rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		} else {
				rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
		}
		StringBuilder sb = new StringBuilder();
		String line;
		while ((line = rd.readLine()) != null) {
				sb.append(line);
		}
		rd.close();
		conn.disconnect();
		System.out.println(sb.toString());
	}
}

배운 내용들

  • StringBuilder를 굳이 사용하는 이유?
    - 덧셈연산을 보완한 StringBuilder의 장점
    • URL객체의 input인 String을 하나로 연결하기 위한 StringBuilder의 쓰임새
  • URL 객체 및 연결 설정 - URLConnection과 HttpURLConnection의 API 사용법
    - URL 클래스
    • URLConnection, HTTPURLConnection클래스들과 URL클래스와의 관계
    • URL을 통한 클라이언트 - 서버 통신 과정

📌 0. 전체적인 API 흐름

API 중, 웹에서 주로 사용하는 HTTP API에 대해서 살펴보겠다.

우리동네날씨에 대한 앱을 만드는 예시에 대해 생각해보자. 날씨정보앱은 날씨정보를 얻기 위해, 기상청API 서버로부터 날씨 정보를 얻어와야 한다. 이때, 그 정보를 얻기 위한 사용법이 API이다.

날씨 정보어플은 API request를 통해 얻고자 하는 정보를 API서버로 보내고, API서버는 API response를 보내 API request에 맞는 정보를 응답해준다.

📌 1. StringBuilder 클래스를 굳이 쓰는 이유?

1-1. StringBuilder 클래스란?

  • 문자열인 String을 더하는 여러 방법 중 하나.

1-2. String을 잇는 여러 방법들

1. '+' 기호 이용 - but 단점 존재..

public static void main(String[] args) {
		String year = "2024 -";
		String month = " 01 -";
		String day = " 09";
		
		String result = year + month + day;
		System.out.println(result);
	}

콘솔창 결과는 다음과 같다.

코드는 간단하게 잇고 싶은 문자열끼리 덧셈연산을 통해 더해줬다. 하지만 이 방식은 String 객체들을 더할 때마다 메모리 할당과 해제를 반복하게 되어, 성능이 좋지 않았다.

그런데, 왜 성능이 좋지 않은 것일까?

문자열의 덧셈 연산은 기본적으로 불변성(immutable) 을 가진다. 즉, 새로운 문자열을 만들 때마다 기존 문자열의 내용을 복사해, 새로운 객체를 생성한다는 이야기다. 이로 인해 문자열을 더할 때마다 메모리에 새로운 객체가 할당되고, 기존의 객체는 garbage collector에 의해 해제된다.
이런 불변성의 특징은 문자열의 안정성을 제공하지만, 동시에 덧셈 연산을 반복하는 과정에서 성능 문제가 발생할 수 있다는 치명적인 단점이 존재한다. 특히, 문자열의 크기가 엄청나게 클 경우나 덧셈 연산이 많은 횟수로 일어난다면 그 단점은 더더욱 극대화된다.

그렇다면 String의 불변성의 단점을 보완해주는 해결책은 없는 것일까? 이에 대한 대안으로 등장한 것이 바로 StringBuilder클래스이다.

2. 1번의 문제점을 보완하는 'StringBuilder'의 등장

StringBuilder는 변경불가능한 String과 달리 변경 가능한 문자열을 만들어준다. 그렇기에 StringBuilder를 이용하면, 덧셈 연산이 발생할 때마다 새로운 객체를 생성하지 않고, 내부 버퍼를 효율적으로 활용해 문자열을 빠르게 조작해 성능 이슈를 해결해준다. 즉, 불필요한 메모리의 할당과 해제를 방지해준다!! (반면, 안정성은 조금 떨어진다는 단점은 있겠지만...)

이해를 돕기 위해 앞선 String 예제와 똑같은 기능을 하되, StringBuilder를 이용한 예제 코드를 작성해보았다.

public static void main(String[] args) {

		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append("2024 -").append(" 01 -");
		stringBuilder.append(" 09");
		
//		String result = stringBuilder; // String에 StringBuilder를 할당하려면 그대로 넣을 순 없고, toString()을 이용해야 한다.
		String result = stringBuilder.toString();

		System.out.println(result);
		
	}


결과 역시 일치함을 확인할 수 있었다!

1-3. 샘플 코드로 돌아오기

// StringBuilder 사용하는 코드 일부 발췌
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode("65526b696f6f6c693833424b6f586c","UTF-8") ); /*인증키 (sample사용시에는 호출시 제한됩니다.)*/
		urlBuilder.append("/" +  URLEncoder.encode("xml","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("CardSubwayStatsNew","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("3","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
		// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
		
		// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
		urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		URL url = new URL(urlBuilder.toString());
		// 1. URL 객체 생성 완

위의 샘플코드를 다시 보자면, API request를 보내기 위한 URL 객체를 만들기 위해, StringBuilder 클래스를 사용했음을 이해할 수 있다.

API의 기본 URL인 "http://openapi.seoul.go.kr:8088"에 필요한 파라미터들을 추가하여 완전한 URL을 만들었다.

주어진 코드 중, urlBuilder.append("/" + URLEncoder.encode("1","UTF-8"));가 요청시작위치를, urlBuilder.append("/" + URLEncoder.encode("5","UTF-8"));가 요청종료위치를 나타낸다. 이때, 요청시작위치가 1로 설정되었다면 조회 시작을 1에서 한다는 것이고, 요청종료위치가 5로 설정되었다면 조회종류값이 5라는 뜻이다. 요청시작위치는 1이상이어야 하고, 요청종류위치의 최댓값은 API에 명세되어 있다.
해당 코드에서 request종료위치를 5로 했더니 row가 총 5개가 나왔고, 3으로 했더니 row가 총 3개가 나온 것을 확인할 수 있었다.

참고로 API request를 위한 URL 구성은 어떤 API를 사용하느냐에 따라 다르며, 해당 API의 명세를 따라 설정해주면 된다.

근데 위에서 Http request를 보내기 위한 URL을 만들었는데, 이때 URL 객체란 뭘까?

참고로, URL을 통해 클라이언트와 서버가 통신을 할 수 있다!

  • 클라이언트는 Http Request를 생성하고 해당 Request에 필요한 정보를 URL에 포함시켜 서버로 전송한다.
  • 서버는 받은 Http Request를 해석하고 요청된 작업을 수행한 후, Http Response를 만들어 클라이언트에게 전송해준다.
  • 클라이언트는 받은 Http Request를 해석하고, 필요한 동작을 수행해준다. 가령, 받은 정보를 브라우저에 표시하는 등의 예시를 들 수 있다.

📌 2. URL 객체 및 연결 설정 - URLConnection과 HttpURLConnection의 API 사용법

2-1. URL 클래스

URL(String spec)
// 문자열 spec이 지정하는 자원에 대한 URL 객체 생성

URL(String protocol, String host, int port, String file)
// 프로토콜 식별자 protocol, 호스트 주소 host, 포트번호 port, 파일 이름 file이 지정하는 자원에 대한 URL 객체 생성

URL클래스는 2가지로 오버로딩되었다.

샘플코드에서는 첫 번째 String만을 input값으로 갖는 함수를 통해 URL 객체를 만들었다.

URL url = new URL(urlBuilder.toString());

StringBuilder를 통해 여러 문자열을 하나로 모은 urlBuilder를 toString 메서드로 String으로 바꿔주고, URL객체를 생성했다.

2-2. URLConnection, HTTPURLConnection클래스들과 URL클래스 와의 관계

Java에서의 네트워크 연결, 즉 서버 - 클라이언트 간의 소통은 URLConnection 및 그 하위 클래스들로 구현할 수 있다. URLConnection클래스는 모든 종류의 URL과 통신하기 위한 일반적인 클래스고, URLConnection의 확장이자 주로 HTTP 프로토콜을 사용할 때 사용하는 것은 HTTPURLConnection클래스다.
이때, URLConnection과 HttpURLConnection은 abstract class라서 직접적으로 새 인스턴스를 만들 수 없다.

그렇다면 URLConnection과 HttpURLConnection은 어떻게 인스턴스를 만들 수 있을까?

정답은 URL객체를 이용하는 것이다. URL 객체와의 연결을 통해 각 클래스에 맞는 인스턴스를 얻을 수 있다.

구체적인 코드는 2-3에서 이어서 정리하겠다!

2-3. URL을 통한 클라이언트 - 서버 통신 과정

1. URL 객체 만들기

URL url = new URL("http://www.naver.com");

2. URL을 이용해 URLConnection 또는 HttpURLConnection 인스턴스 얻기

URLConnection urlCon = url.openConnection();
// URLConnection 인스턴스는 URL객체의 openConnection 메서드로 얻어진다

HttpURLConnection httpCon = (HttpURLConnection)url.openConnection();
// 프로토콜이 http:// 인 경우, 반환된 객체를 HttpURLConnection 객체로 캐스팅할 수 있다.

참고로, URL클래스의 멤버함수인 openConnection의 선언부분은 다음과 같다.

public URLConnection openConnection();

그렇기에 위 코드에서 디폴트로 URLConnection으로 받고, HttpURLConnection으로 받고 싶으면 캐스팅하는 것이다.

이때, 주의할 점은 openConnection메서드는 실제 네트워크와의 연결과는 전혀 관계가 없다는 것이다.
단지, 해당 추상클래스들의 인스턴스를 반환하는 역할을 한다.

실제 네트워크 연결, 즉 서버 - 클라이언트와의 연결을 다루는 작업은 connect()메서드나, 헤더필드를 읽거나, 입력스트림 / 출력스트림을 가져올 때 암시적으로 다뤄진다. 앞서 언급했듯이 서버 - 클라이언트의 소통은 URLConnection클래스 혹은 HTTPURLConnection 클래스의 멤버함수로 이뤄지니 사용법을 배워보도록 하자.

3. URL 연결 설정하기

URLConnection과 HttpURLConnection클래스에서는 네트워크 연결을 위해 다양한 메서드를 제공한다.
그 중, 샘플코드에 나온 메서드들을 보자.

void setRequestMethod(String method);
// HTTP 메소드 GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE 중 하나인 URL request에 대한 메소드를 설정한다. 기본값은 GET
void setRequestProperty(String key, String value);
// key==value쌍으로 지정한 일반 request 속성을 설정한다. 이미 해당 키가 있는 속성이 존재한다면, 이전 값을 새 값으로 update한다.
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-type", "application/");
System.out.println("Response code: " + conn.getResponseCode());

예제코드의 일부분이다.
위 코드는 클라이언트가 URL을 통해 서버에 HTTP GET request를 보내고 서버의 response code를 출력하는 부분이다. URLConnection과 HttpURLConnection클래스를 이용해 서버와 클라이언트간의 연결의 특정 부분을 설정하고, 연결해준다!

4. 헤더 필드 읽기

서버와 클라이언트와의 연결이 이루어졌다. 이제 서버는 URL request를 해석해 처리하고, 메타데이터와 실제 콘텐츠로 구성된 response 메세지를 다시 보내야 한다.

이때 메타데이터는 헤더필드라고 하는 키-값 쌍의 모음이다. 헤더필드(메타데이터)는 서버에 대한 정보, 상태코드, 프로토콜 정보 등을 담는다. 실제 내용은 문서 내용에 따라 텍스트, HTML, 이미지 등이 될 수 있다.

URLConnection클래스에서 제공한 메서드로 헤더 필드를 읽어보겠다.

// 3. 헤더필드 읽기 실습 
	System.out.println("첫번째 헤더필드 값 : " + conn.getHeaderField(1));
	System.out.println("세번째 헤더필드 값 : " + conn.getHeaderField(3));
	System.out.println("콘텐츠 유형 : "+conn.getContentType());
	System.out.println("명명된 헤더필드의 값 : "+conn.getHeaderField("Content-type"));

실행결과는 다음과 같다.

위 코드에서 conn.setRequestProperty("Content-type", "application/"); 가 실제로 잘 실행이 되었는지 getHeaderField()메서드를 이용해 이중체크했다.

5. 입력 스트림 가져오기 및 데이터 읽기 (read)

실제 내용을 읽으려면, 연결(URLConnection, HttpURLConnection)에서 InputStream을 얻은 다음, inputStream의 read()메서드를 이용해 데이터를 읽을 수 있다.

InputStream inputStream = conn.getInputStream();
byte[] data = new byte[1024];
inputStream.read(data);

실제 코드와 실행결과를 보자.


잘 처리된 것을 확인할 수 있다.

하지만, InputStream의 read메서드는 데이터를 바이트로 읽는 low-level메서드로 실제로 사용하기 복잡하고 불편했다.. 🤔
이에 문자열데이터를 읽을 때는 BufferedReader를 사용해 InputStream으로부터 데이터를 읽어온다는 방법을 사용했다.

public InputStreamReader(InputStream in); // InputStreamReader의 생성자
public InputStream getInputStream(); // URLConnection의 멤버함수
public BufferedReader(Reader in); // BufferedReader생성자

InputStream은 데이터를 바이트 단위로 읽어오는 스트림. (앞의 내용에서도 그랬음) InputStreamReader는 이 바이트 단위의 데이터를 문자로 변환해주고,
BufferedReader는 문자열 스트림을 효율적으로 읽어오기 위해, readline()메서드를 통해 한줄씩 읽어온다.

따라서 BufferedReader를 통해 읽어온 데이터를 readline()메서드를 이용해 데이터를 문자열 형태로 처리한다!!

예제코드
BufferedReader reader;
reader =  new BufferedReader(new InputStreamReader(conn.getInputStream()));

String line = reader.readLine(); // reads a line
실제 코드 및 실행결과
// 1. URL 객체 생성 (이하 생략)
// 2. HttpConnection 클래스 - URL 객체를 통해 사용자와 API 서버간의 연결 설정 (이하 생략)
 
// 3. 입력스트림 가져오기 및 데이터 읽기 - BufferedReader를 사용해 inputStream으로부터 데이터를 읽어온다.
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

String line = reader.readLine();
System.out.println(line);

reader.close();
conn.disconnect();


근데 여기서 의문점이 들었음.
readine을 통해 읽어온 것을 sysout을 통해 출력했더니, 앞선 URL 설정에서 요청종류위치를 3으로 설정으로 해서 row가 3개가 나오면 다 잘 나온건데, 진짜로 row가 3개로 모두 기대된대로 출력됐다.

근데 6번에서 배울, 출력스트림을 통해 데이터를 가져와서 쓰는 이유가 뭘까? 🤔

참고로 출력스트림은 공공데이터 API 예제코드에서는 사용되지는 않았지만.. 그 쓰임새만 정리해보고 가자.

6. 출력 스트림 가져오기 및 데이터 쓰기 (write)

앞서, BufferedReader를 사용해 InputStream에서 데이터를 읽어오는 부분은 서버로부터 받은 데이터를 읽어오기 위한 부분이다. 즉, 서버의 response 내용을 읽어오는 부분이다.
반대로, 출력 스트림은 주로 서버에 데이터를 전송하기 위해 사용된다.
네트워크에서는, 데이터의 입출력 방향을 기준으로 "입력"은 read이기에 데이터를 받아오는 쪽이고, "출력"은 write이기에 데이터를 보내는 쪽이다.

클라이언트에서 서버로의 HTTP request를 보낼 때출력 스트림을 사용해, 요청 데이터를 서버에게 전송한다. 이때 HttpURLConnection에서는 getOutputStream() 메서드를 사용해 출력 스트림을 이용할 수 있다.

간단한 예제를 보자.

HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true); // 출력 스트림을 사용하도록 설정

// 출력 스트림 얻기
OutputStream outputStream = conn.getOutputStream();

// 데이터 전송 (예: JSON 문자열 전송) - 서버로 전송
// 예 : String data = "{\"key\":\"value\"}";
String data = "{\"date\":\"2024-01-10\"}";
outputStream.write(data.getBytes("UTF-8")); // 서버로 데이터를 전송

// 출력 스트림 닫기
outputStream.close();

이렇게 클라이언트에서는 getOutputStream()으로 얻은 출력 스트림을 사용해 서버에게 데이터를 보낼 수 있다.

7. 연결 닫기 - 모든 사용된 자원들 해제하기

연결을 닫으려면 InputStream 또는 OutputStream 객체에서, close() 메서드를 호출해야 한다. 이렇게 하면, URLConnection인스턴스와 연결된 네트워크 리소스들이 해제된다!

📌 3. 코드 마지막 부분 리팩토링


BufferedReader reader;		

// 서비스코드가 정상이면 200~300사이의 숫자가 나옵니다. - conn을 이용해 데이터 읽고 쓰기 
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
	reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} 
else { // 서비스코드 에러 
	reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
} 
			
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
	sb.append(line);
}

reader.close();
conn.disconnect();
System.out.println(sb.toString());
}

근데 굳이 위의 예제코드에서 마지막 결과를 콘솔창에 출력할 때 StringBuilder를 쓸 이유가 없다고 생각했다. StringBuilder는 여러 개의 문자열을 덧셈연산을 통해 합칠 때 주로 사용하는데, 여기서는 어차피 하나의 reader밖에 없기 때문에 굳이 사용할 필요가 없다고 생각했기 때문이다.

BufferedReader reader;

// 서비스코드가 정상이면 200~300사이의 숫자가 나옵니다. - conn을 이용해 데이터 읽고 쓰기 
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
	reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} 
else { // 서비스코드 에러 
	reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
} 
			
String line;
	
while ((line = reader.readLine()) != null) {
	System.out.println(line);
}

reader.close();
conn.disconnect();

그래서 BufferedReader인 reader를 readline메서드를 이용해 리턴값인 String을 System.out.println으로 출력하게 했다.

추가적으로 readline메서드의 정의를 살펴보면, 에러가 발생하면 null값을 리턴하므로 안전하게 while문 조건 안에 null을 추가해줬다.

최종 코드

package test;

import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;

public class ApiExplorer {
	public static void main(String[] args) throws IOException {
		StringBuilder urlBuilder = new StringBuilder("http://openapi.seoul.go.kr:8088"); /*URL*/
		urlBuilder.append("/" +  URLEncoder.encode("65526b696f6f6c693833424b6f586c","UTF-8") ); /*인증키 (sample사용시에는 호출시 제한됩니다.)*/
		urlBuilder.append("/" +  URLEncoder.encode("xml","UTF-8") ); /*요청파일타입 (xml,xmlf,xls,json) */
		urlBuilder.append("/" + URLEncoder.encode("CardSubwayStatsNew","UTF-8")); /*서비스명 (대소문자 구분 필수입니다.)*/
		urlBuilder.append("/" + URLEncoder.encode("1","UTF-8")); /*요청시작위치 (sample인증키 사용시 5이내 숫자)*/
		urlBuilder.append("/" + URLEncoder.encode("3","UTF-8")); /*요청종료위치(sample인증키 사용시 5이상 숫자 선택 안 됨)*/
		// 상위 5개는 필수적으로 순서바꾸지 않고 호출해야 합니다.
		
		// 서비스별 추가 요청 인자이며 자세한 내용은 각 서비스별 '요청인자'부분에 자세히 나와 있습니다.
		urlBuilder.append("/" + URLEncoder.encode("20220301","UTF-8")); /* 서비스별 추가 요청인자들*/
		
		URL url = new URL(urlBuilder.toString());
		// 1. URL 객체 생성 완
		
		// 2. HttpConnection 클래스 - URL 객체를 통해 사용자와 API 서버간의 연결 설정 
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setRequestProperty("Content-type", "application/");
		System.out.println("Response code: " + conn.getResponseCode()); /* 연결 자체에 대한 확인이 필요하므로 추가합니다.*/
		
		// 3. 입력스트림 가져오기 및 데이터 읽기 - BufferedReader를 사용해 inputStream으로부터 데이터를 읽어온다.
		BufferedReader reader;
		
		// 서비스코드가 정상이면 200~300사이의 숫자가 나옵니다. - conn을 이용해 데이터 읽고 쓰기 
			if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
					reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			} 
			else { // 서비스코드 에러 
					reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));

		} // 그 결과, 서비스코드가 정상 작동했다면 "reader"에는 서버의 response 메세지를 읽어온 문자열이, 서비스코드에 에러가 났다면, 에러 메세지가 저장될 것 
			
		// 결과를 각 줄로 출력
		String line;
		while ((line = reader.readLine()) != null) {
		    System.out.println(line);
		}

		reader.close();
		conn.disconnect();
	}
}
profile
배운 내용을 바로바로 기록하자!

0개의 댓글