dev_공부일지/Spring 개념 정리

API 호출 기본 (URL, Reader, ObjectMapper)

dev_0hoon 2024. 9. 17. 16:30

 

환율 계산기를 만드려고 한다. 먼저 무료로 제공하고 있는 환율 데이터 API를 통해 환율을 가져오는 코드를 작성하려 한다.

이 부분에서 기존에 애매모호했던 내용을 정리하려한다.

 

1. java.net.URL

URL url = new URL("https://example.com");
URLConnection connection = url.openConnection();

 URL클래스는 원격지원에 대한 연결을 생성할 때 사용된다. 그리고 openConnection() 메서드는 주어진 URL에 대한 URLConnection 객체를 반환한다.

- 연결 객체 생성: URL의 프로토콜에 맞는 URLConnection 객체를 생성한다. 예를 들어, http 프로토콜의 경우 HttpURLConnection 객체가 반환됩니다.

URL url = new URL("https://open.er-api.com/v6/latest/" + currency);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

 

 상속을 통해 형변환이 가능하다.

설정 변경 가능: URLConnection 객체를 통해 시간 초과, 요청 메서드(POST, GET 등), 헤더 등 다양한 설정을 변경할 수 있다.

연결 수행: URLConnection 객체를 사용하여 원격 자원과의 실제 연결이 이루어지며, 이때부터 데이터를 송수신할 수 있다.

 

이번에는 수신의 용도로만 사용할 것이다.

 

1차

- 수신

InputStream inputStream = connection.getInputStream();

- 결과

sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@f79e

뭔가 호출로 가져온 데이터가 주소로만 표시 되어있다. 

 

2차

- 수신

InputStreamReader isr = new InputStreamReader(connection.getInputStream());

InputStreamReader는 InputStream 바이트 스트림을 Reader(문자스트림)으로 변환하는데 사용된다.

 

BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));

BufferedReader는 문자 스트림을 버퍼링하여 성능을 향상시킨다. BufferedReader는 내부 버퍼를 사용해 데이터를 일정량 모아서 처리하기 떄문에 매번 작은 데이터를 읽는 대신 한 번에 큰 데이터를 일겅 들이게 된ㄷ나. I/O 작업이 더 효율적이고 빠르게 이루어진다.

 

        String response = br.lines().collect(Collectors.joining());

데이터를 한줄씩 읽어서 String 형태로 만들어 준다.

참고로 Collectors.joining()는 여러줄의 데이터를 한줄의 형태로 만들어 준다.


2. ObjectMapper

        ObjectMapper mapper = new ObjectMapper();
        ExRateData data = mapper.readValue(response, ExRateData.class);
        BigDecimal exRate = data.rates().get("KRW");

 

그렇게 나온 데이터를 ObjectMapper를 이용해 DTO에 담아 줄 수 있다.

 

record를 사용해 만들어 준다. 파라미터가 필드의 값이 되어 생성자 만들으로도 dto를 생성할 수 있다.

public record ExRateData(String result, Map<String, BigDecimal> rates) {

}

 

참고로 이렇게만 담는다면, 

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "provider" (class com.hellopayment.ExRateData), not marked as ignorable (2 known properties: "rates", "result"])
 at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2914] (through reference chain: com.hellopayment.ExRateData["provider"])

다음처럼 변환을 못한다는 오류가 난다. "provider"를 담을 곳이 없다고 뭐라 하는 것이다.

 

@JsonIgnoreProperties(ignoreUnknown = true)
public record ExRateData(String result, Map<String, BigDecimal> rates) {

}

담을 dto에 @JsonIgnoreProperties를 true로 사용해서 불필요한 json 데이터는 굳이 받지 않게 설정하면 된다.