55import org .springframework .beans .factory .annotation .Value ;
66import org .springframework .stereotype .Component ;
77
8- import java .io .BufferedReader ;
9- import java .io .IOException ;
10- import java .io .InputStreamReader ;
8+ import java .io .*;
119import java .net .HttpURLConnection ;
1210import java .net .URL ;
1311import java .text .NumberFormat ;
1412import java .text .SimpleDateFormat ;
15- import java .util .Date ;
16- import java .util .Locale ;
17-
13+ import java .util .*;
1814
1915@ Component
2016public class ExchangeRateUtils {
@@ -23,6 +19,7 @@ public class ExchangeRateUtils {
2319
2420 private static final String dataType = "AP01" ;
2521 private static String authKey ;
22+ private static Map <String , String > cookies = new HashMap <>(); // 쿠키 저장소
2623
2724 @ Value ("${exchange.rate.api.authKey}" )
2825 public void setAuthKey (String value ) {
@@ -41,53 +38,82 @@ public static double fetchExchangeRate(String searchDate, String currency_unit)
4138
4239 // Request 초기 세팅
4340 connection .setRequestMethod ("GET" );
44- connection .setInstanceFollowRedirects (false ); // 리다이렉션 자동 처리 비활성화
41+ connection .setInstanceFollowRedirects (false ); // 리다이렉션 자동 처리 비활성화
4542 connection .setConnectTimeout (5000 );
4643 connection .setReadTimeout (5000 );
4744
45+ // 쿠키 설정
46+ if (!cookies .isEmpty ()) {
47+ String cookieHeader = String .join ("; " , cookies .entrySet ().stream ()
48+ .map (entry -> entry .getKey () + "=" + entry .getValue ())
49+ .toArray (String []::new ));
50+ connection .setRequestProperty ("Cookie" , cookieHeader );
51+ }
52+
4853 int status = connection .getResponseCode ();
4954
50- // API 호출
51- if (status > 299 ) { // 실패한 경우 Exception 발생
52- throw new RuntimeException ("HTTP 요청 실패: 상태 코드 " + status );
53- } else { // 성공했을 경우 환율 정보 추출
55+ // 리다이렉션 처리
56+ if (status == HttpURLConnection .HTTP_MOVED_TEMP || status == HttpURLConnection .HTTP_MOVED_PERM ) {
57+ String newUrl = connection .getHeaderField ("Location" );
58+ // 쿠키 저장
59+ String setCookieHeader = connection .getHeaderField ("Set-Cookie" );
60+ if (setCookieHeader != null ) {
61+ parseCookies (setCookieHeader );
62+ }
63+ return fetchExchangeRate (searchDate , currency_unit ); // 재귀 호출로 리다이렉션 처리
64+ }
65+
66+ // API 호출 성공
67+ if (status == HttpURLConnection .HTTP_OK ) {
5468 reader = new BufferedReader (new InputStreamReader (connection .getInputStream ()));
69+ StringBuilder response = new StringBuilder ();
5570
5671 while ((line = reader .readLine ()) != null ) {
57- JSONArray exchangeRateInfoList = new JSONArray (line );
72+ response .append (line );
73+ }
74+ reader .close ();
5875
59- if (exchangeRateInfoList .isEmpty ()) {
60- // 빈 데이터가 조회된 경우
61- throw new RuntimeException ("빈 데이터가 조회된 경우" );
62- }
76+ // JSON 응답 처리
77+ JSONArray exchangeRateInfoList = new JSONArray (response .toString ());
6378
64- for (int i = 0 ; i < exchangeRateInfoList .length (); i ++) {
65- JSONObject exchangeRateInfo = exchangeRateInfoList .getJSONObject (i );
79+ for (int i = 0 ; i < exchangeRateInfoList .length (); i ++) {
80+ JSONObject exchangeRateInfo = exchangeRateInfoList .getJSONObject (i );
6681
67- if (!exchangeRateInfo .has ("cur_unit" ) || exchangeRateInfo .isNull ("cur_unit" )) {
68- // 비영업일이거나, 영업 시간 전이라 데이터가 없는 경우
69- throw new RuntimeException ("null: 비영업일이거나 영업 시간 전인 경우" );
70- }
82+ if (!exchangeRateInfo .has ("cur_unit" ) || exchangeRateInfo .isNull ("cur_unit" )) {
83+ throw new RuntimeException ("null: 비영업일이거나 영업 시간 전인 경우" );
84+ }
7185
72- if (exchangeRateInfo .getString ("cur_unit" ).equals (currency_unit )) {
73- // 쉼표가 포함된 String을 Double로 파싱
74- NumberFormat format = NumberFormat .getInstance (Locale .getDefault ());
75- exchangeRate = format .parse (exchangeRateInfo .getString ("deal_bas_r" )).doubleValue ();
76- }
86+ if (exchangeRateInfo .getString ("cur_unit" ).equals (currency_unit )) {
87+ // 쉼표가 포함된 String을 Double로 파싱
88+ NumberFormat format = NumberFormat .getInstance (Locale .getDefault ());
89+ exchangeRate = format .parse (exchangeRateInfo .getString ("deal_bas_r" )).doubleValue ();
90+ break ;
7791 }
7892 }
79- reader .close ();
93+ } else {
94+ throw new RuntimeException ("HTTP 요청 실패: 상태 코드 " + status );
8095 }
8196
8297 } catch (IOException | java .text .ParseException e ) {
8398 throw new RuntimeException (e );
8499 } finally {
85- connection .disconnect ();
100+ if (connection != null ) {
101+ connection .disconnect ();
102+ }
86103 }
87104
88105 return exchangeRate ;
89106 }
90107
108+ private static void parseCookies (String setCookieHeader ) {
109+ String [] cookiePairs = setCookieHeader .split (";" );
110+ for (String pair : cookiePairs ) {
111+ String [] keyValue = pair .split ("=" , 2 );
112+ if (keyValue .length == 2 ) {
113+ cookies .put (keyValue [0 ].trim (), keyValue [1 ].trim ());
114+ }
115+ }
116+ }
91117
92118 public static String getPreviousDate (String currentDate ) {
93119 try {
0 commit comments