Spring/Spring Boot

[Spring] spring boot - 외부 Rest API json으로 받아오기(JAVA)

민돌v 2022. 1. 15. 16:33
728x90

JAVA로 외부 api 값을 받아오는 방법은 3가지가 있다.

  1. httpurlconnection
  2. httpclient
  3. spring resttemplate

 

오늘은 이 3가지 방법에 대해서 알아보고 뭐를 사용할지 알아보고자 한다.

+ 결론은 3가지방법을 대략적으로 파악하고, 최신 트렌드?에 맞는 RestTemplate를 쓰기로했다!

 


자바 Http 통신

위의 3가지 방식이 나오게된 순서를 보면 먼저, 순수 자바로만 HTTP통신을 할 수 있는 1) HttpURLConnection 클래스가 있었고, 

이걸 사용하기 쉽게 추상화해서 만들어진게 2) Apache HttpClient이며 요것이 최근에 버전업을 해서 -> HttpComponents로 사용이 되고있다.

3) Spring RestTemplate는 이런 기술들을 기반으로 작동하는 것이라고 한다... 휴 순서가 요래요래 맞물리니, 한번 집고 넘어가야 공부하기 편할것같다,

 

순서대로 가보자!


 

 1) HttpURLConnection

 HttpURLConnection은 JDK 1.1부터 있는 자바 HTTP통신을 가능하게 하는 클래스이고, java.net 패키지에 포함되어있다.

HttpURLConnection은 기본적으로  GET 요청방식을 가지는데, setRequestMethod()로 다른 요청방식으로 설정할 수 잇다.

사용을해보니, 결과값을 받아오는 방법도 귀찮고(Stream으로 직접 처리 하나씩) 음.. 뭔가 불편하다!

코드도 길어지고,, 하나하나 설정해주는것도 다 따로따로 해줘야하고...

 

간단한 사용법

public class urlconnection {
    public static void run() throws IOException {
        String testurl = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json";

        URL url = new URL(testurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        int resCode = conn.getResponseCode();

        System.out.println(resCode);
        System.out.println(conn.getResponseMessage());
        System.out.println(conn.getContent().toString());

        Object result = conn.getContent();
        int ch;
        while((ch=((InputStream)result).read()) != -1) {
            System.out.print((char) ch);
        }
    }
}

결과 - 키가 없기때문에 API에서 거부된 메세지

 

정말 간단한 사용법이다.. 타임아웃이나, 메소드 설정은 여기로 참고! https://goddaehee.tistory.com/161

 


 

 2) HttpClient

 Apache HttpComponents로 불리며 HttpURLConnection을 사용할 때보다 조금 더 짧고, 직관적으로 코드를 짤수있다는 장점이 있다.

무엇보다 Response값을, URLConnection과 달리 exeute메서드로 요청해서 EntityUtils.tostring()으로 바로 문자열로 받아올 수 있다고 한다. (매우 편해보임)

요청방식도 따로 설정해주지 않고, 각각 메소드로 정의되어있어서, 더 직관적으로 볼 수있다는 장점도 있는것 같다.

 

단점)

  • URLConnection보다 코드가 간결해졌지만 여전히 반복적인 코드가 존재하며 길다!
  • 응답의 컨텐츠 타입에 따라 별도의 로직이 필요하다고한다. (RestTemplate가 이때 유용하다고함)

 

코드 - 참고 https://amagrammer91.tistory.com/65 (by 터프남님)

@RestController
public class ApacheHttpClientController {

    @GetMapping("apachehttpclient")
    public ResponseEntity apacheHttpClient() {

        ObjectMapper objectMapper = new ObjectMapper();
        Object objValue = null;

        try {
            URI uri = new URI("http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json");
            uri = new URIBuilder(uri)
                    .addParameter("key", "key")
                    .addParameter("targetDt", "20210201")
                    .build();

            CloseableHttpClient httpClient = HttpClients.custom()
                    .setMaxConnTotal(100)
                    .setMaxConnPerRoute(100)
                    .build();

            HttpResponse httpResponse = httpClient.execute(new HttpGet(uri));
            HttpEntity entity = httpResponse.getEntity();
            String content = EntityUtils.toString(entity);
            System.out.println("content = " + content);
            objValue = objectMapper.readValue(content, Object.class);
            System.out.println("objValue = " + objValue);

        } catch (Exception e) {

        }

        return ResponseEntity.ok(objValue);
    }
}

 


 RestTemplate!  내 코드에 적용할 방법이다! 하나씩 알아보자

 

3) Spring RestTemplate

org.springframework.http.client 패키지에 있다. httpclient는 HTTP를 사용하여 통신하는 범용 라이브러리이고, 

RestTemplate는 HttpClient를 추상화(HttpEntity의 json, xml 등)해서 제공해준다. 따라서 내부 통신(HTTP 커넥션)에 있어서는  Apache HttpComponents를 사용한다.

RestTemplate가 없었다면, 직접 json이나 xml 라이브러리를 사용해서변환해야 한다고 한다.

 

RestTemplate 동작원리

https://sjh836.tistory.com/141 - by 빨간색소년님

 

  1. 어플리케이션이 RestTemplate를 생성 -> URI, HTTP메소드 등의 헤더를 담아 요청
  2. RestTemplate는 HttpMessageConverter를 사용하여 requestEntity를 요청메세지로 변환한다.
  3. RestTemplate는 ClientHttpRequestFactory로 부터 ClientHttpRequest를 가져와서 요청을 보낸다.
  4. ClientHttpRequest는 요청메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신한다.
  5. RestTemplate는 ResponseErrorHandler로 오류를 확인하고 있다면 처리로직을 태운다.
  6. ResponseErrorHandler는 오류가 있다면 ClientHttpResponse에서 응답데이터를 가져와서 처리한다.
  7. RestTemplate는 HttpMessageConverter를 이용해서 응답메세지를 java object(class responseType)으로 변환한다.
  8. 어플리케이션에 반환된다.

RestTemplate 사용하기!

Resttemplate 가이드 : https://www.baeldung.com/rest-template

주요 메소드

RestTemplate MethodHTTP Method설명

RestTemplate Method HTTP Method 설명
execute Any  
exchange Any 헤더세팅해서 HTTP Method로 요청보내고 ResponseEntity로 반환받음
getForObject GET get 요청을 보내고 java object로 매핑받아서 반환받음
getForEntity GET get 요청을 보내고 ResponseEntity로 반환받음
postForLocation POST post 요청을 보내고 java.net.URI 로 반환받음
postForObject POST post 요청을 보내고 ResponseEntity로 반환받음
put PUT  
delete DELETE  
headForHeaders HEAD  
optionsForAllow OPTIONS  

출처: https://sjh836.tistory.com/141 [빨간색코딩]

 

 

간단한 사용법

1. RestTemplate 객체를 만들고

2.  URL을 uri로 만든 다음,

3. restTemplate.exchange()메소드로 ResponseEntity<>를 반환받는다.

4. getBody()메소드로 온 결과값을 json데이터 변환해 반환한다.

@Service
public class Service {
    public String getData(String url ) {
        //Spring restTemplate
        HashMap<String, Object> result = new HashMap<String, Object>();
        String jsonInString = "";

       
        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders header = new HttpHeaders();
        HttpEntity<?> entity = new HttpEntity<>(header);
        
        UriComponents uri = UriComponentsBuilder.fromHttpUrl(url).build();

        ResponseEntity<?> resultMap = restTemplate.exchange(uri.toString(), HttpMethod.GET, entity, Object.class);

        result.put("statusCode", resultMap.getStatusCodeValue()); //http status code를 확인
        result.put("header", resultMap.getHeaders()); //헤더 정보 확인
        result.put("body", resultMap.getBody()); //실제 데이터 정보 확인

        //데이터를 제대로 전달 받았는지 확인 string형태로 파싱해줌
        ObjectMapper mapper = new ObjectMapper();
        jsonInString = mapper.writeValueAsString(resultMap.getBody());
                  

        return jsonInString;


    }
}

 

수정 코드

ResponseEntity로 반환하기 

ResponseEntity 그대로 반환하고, 에러 쳌

@Service
public class Service {
    public ResponseEntity<Object> getData(String url ) {
        //Spring restTemplate
        HashMap<String, Object> result = new HashMap<String, Object>();
		ResponseEntity<Object> resultMap = new ResponseEntity<>(null,null,200);

        try {
            RestTemplate restTemplate = new RestTemplate();

            HttpHeaders header = new HttpHeaders();
            HttpEntity<?> entity = new HttpEntity<>(header);

            UriComponents uri = UriComponentsBuilder.fromHttpUrl(url).build();

            ResponseEntity<?> resultMap = restTemplate.exchange(uri.toString(), HttpMethod.GET, entity, Object.class);

            result.put("statusCode", resultMap.getStatusCodeValue()); //http status code를 확인
            result.put("header", resultMap.getHeaders()); //헤더 정보 확인
            result.put("body", resultMap.getBody()); //실제 데이터 정보 확인

            //에러처리해야댐
        } catch (HttpClientErrorException | HttpServerErrorException e) {
            result.put("statusCode", e.getRawStatusCode());
            result.put("body"  , e.getStatusText());
            System.out.println("error");
            System.out.println(e.toString());

			return resultMap;
        }
        catch (Exception e) {
            result.put("statusCode", "999");
            result.put("body"  , "excpetion오류");
            System.out.println(e.toString());
 
 			return resultMap;

        }

        return resultMap;


    }
}

 

 

 

 

 

 

*참고

자바 Http 통신 순서 : https://amagrammer91.tistory.com/65

Spring restTemplate : https://vmpo.tistory.com/27

java urlconnection : https://r-0o0-j.tistory.com/132

java rest api 받는 3가지 방법 : https://dream-kwon.tistory.com/39

httpclient vs httpurlconnection vs spring resttemplate : https://sjh836.tistory.com/141

반응형