현재 HttpURLConnection 객체를 생성해 에타 API에 접근하고 있습니다. 해당 클래스는 BufferedReader 및 StringBuilder를 통해 직접 문자열 객체로 변경하는 과정이 필요합니다.
해당 객체 대신 ResponseEntity를 반환하는 등 추상화 레벨이 높은 RestTemplate를 사용해 에타 API에 접근하도록 변경합니다.
현재 페이지에서 폼을 작성해 POST /calendar로 이동 후 ics를 다운로드 후 리프레쉬를 하면 서버에서는 다시 로직을 실행합니다.
이를 방지하기 위해서 PRG 패턴을 적용해 form submit -> POST /calendar -> (redirect) -> GET /success의 순서로 PRG 패턴을 적용합니다.
이때 RefreshAttributes Bean을 통해 redirect시 ics 문자열을 넘겨줍니다. 이때, ics 문자열의 크기가 매우 크기 때문에 flashAttribute로서 추가하도록 합니다. (RefreshAttributes.addFlashAttribute 사용)
현재 createIcsString()을 ics 문자열을 생성하는 그 역할에 맞추어 generateCalendar()로 메서드명을 변경합니다.
generateCalendar()는 EventDTO를 바탕으로 Calendar 객체를 직접 내부에서 생성하는 로직이 포함됩니다. 해당 메서드의 책임을 최소화하기 위해 해당 로직을createWeeklyCalendarBetween()으로 분리합니다.
getLecturesFromEverytime()은 메서드 내부에서 외부 API를 요청해 시간표를 가져오는 역할을 하고 있습니다. 해당 역할에 맞추어 메서드명을 requestTimetable()로 변경합니다.
requestTimetable()에서 파싱 테스트의 용이성을 위해 파싱 로직을 parseTimetable()로 분리합니다.
requestTimetable()은 외부 API에서 데이터를 받아와 파싱하는 역할만을 수행해야 합니다. 따라서 ResponseDTO.convertToEvents()의 호출을 제거하고 generateCalendar()에서 호출해 EventDTO 리스트로 변환하도록 하기 위해 requestTimetable()이 ResponseDTO를 반환하도록 합니다.
위 코드에서 Locale 설정됨에도 불구하고, UTC 기준 0시로 초기화되어서 KST 기준이 아닌 UTC 기준으로 날짜가 설정됩니다.
따라서 다음 코드를 통해 cal.setTimeZone(TimeZone.getTimeZone("Asia/Seoul")); timezone을 명시적으로 정해줍니다.