public interface ApiExecutor {
    String execute(URI uri) throws IOException;
}

public class SimpleApiExecutor implements ApiExecutor {
    @Override
    public String execute(URI uri) throws IOException {
        String response;
        HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();

        /* BufferedReader 를 타고 가면 AutoClosable 타입이란 걸 알 수 있음
         * AutoClosable 인터페에스를 구현한 Object를 `try with resource 문`의 () 안에서 선언을 해두면, 이 블록이 마무리되기 전에 반드시 해당 리소스를 close 해줌
         * - AutoClosable 은 close 라는 메서드를 가지고 있음
         */
        try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
            response = br.lines().collect(Collectors.joining());
        }
        return response;
    }
}

public class WebApiExRateProvider implements ExRateProvider {
    @Override
    public BigDecimal getExRate(String currency) {
        String url = "<https://open.er-api.com/v6/latest/>" + currency;

        return runApiForExRate(url);
    }

    private static BigDecimal runApiForExRate(String url) {
        URI uri;
        try {
            uri = new URI(url);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }

        String response;
        try {
            response = new SimpleApiExecutor().execute(uri);
            System.out.println(response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            BigDecimal exRate = extractExRate(response);
            System.out.println("API ExRate: " + exRate);
            return exRate;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    private static BigDecimal extractExRate(String response) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        ExRateData data = mapper.readValue(response, ExRateData.class);
        return data.rates().get("KRW");
    }
}