Side - Project 점심이(2 / 3)

김종찬·2023년 2월 17일
0

프로젝트

목록 보기
2/2

오늘은 저번시간에 기본적인 메시지 전송틀을 이용하여 점심메뉴를 지정된 시간과 현재 날씨를 접목시켜 추천해주는것을 개발해 보겠습니다.

아래 코드는 https://github.com/bellCold/slack-lunch-commend 에서 모두 보실수 있습니다!

  • 학습목표
  • Spring에서 제공하는 스케쥴에 대해서 학습
  • 날씨 api를 사용하여 현재날씨 정보 가져오기

우선 현재 날씨의 관한 정보를 가져오기 위해 검색을 통해, 그나마 접근성이 쉬웠고 해당 사용법에대한 레퍼런스가 많았던 공공기관 데이터를 사용하기로 했습니다. 해당 api를 이용하기 위해 여느 api와 같이 키값이 필요했으므로 사용하고자하는 api의 키값을 받도록 한다.

현재 날씨 정보 받기

로그인을 한 후 공공데이터포털에 접속하여 해당 api의 활용 신청을 해당 서비스를 누르면 이용할수 있다.

마이페이지를 통해 자신의 활용중인 목록을 볼 수 있습니다. 신청 후 아마.. 바로 승인된걸로 기억합니다.

여기서 내가 필요로 하는것은 일반 인증키 이다. 상세설명과 참고문서를 통해 요청값들과 응답 정보를 보다 자세하게 볼 수 있다. 웬만한 api의 사용법은 서비스 제공측에서 상세하게 설명되어있습니다.

전 시간과 마찬가지로 키값은 노출되면 안되므로 관리를 해줍니다.

이제 날씨 정보를 불러올 WeatherService를 구현해보도록 하겠습니다.

@Service
public class WeatherService {

    @Value(value = "${weather.service.key}")
    String serviceKey;

    private final String URL = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst";
    private final String CURRENT_DATE = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
    private final String BASE_TIME = LocalTime.now().minusHours(1).format(DateTimeFormatter.ofPattern("HHmm"));
    private final String NX = "57";
    private final String NY = "124";

    private Weather checkWeather() throws IOException {
        StringBuilder urlBuilder = new StringBuilder(URL);
        urlBuilder.append("?" + URLEncoder.encode("serviceKey", UTF_8) + "=" + serviceKey);
        urlBuilder.append("&" + URLEncoder.encode("dataType", UTF_8) + "=" + URLEncoder.encode("JSON", UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("base_date", UTF_8) + "=" + URLEncoder.encode(CURRENT_DATE, UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("base_time", UTF_8) + "=" + URLEncoder.encode(BASE_TIME, UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("nx", UTF_8) + "=" + URLEncoder.encode(NX, UTF_8));
        urlBuilder.append("&" + URLEncoder.encode("ny", UTF_8) + "=" + URLEncoder.encode(NY, UTF_8));

        URL url = new URL(urlBuilder.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(HttpMethod.GET.toString());
        conn.setRequestProperty("Content-type", MediaType.APPLICATION_JSON_VALUE);

// ...중략
}


아주아주 상세하게 적혀있습니다. 위의 코드는 원하고자하는 날씨를 요청메시지폼에 알맞게 URL을 생성해줍니다.

  • 요청하고자하는 서비스의 end-point
  • 오늘 날짜
  • 원하는 날씨 시간대(위 코드를 보면 현재시간의 1시간 전을 셋팅하였습니다. 이건 아직 발표되지 않은시간을 요청하는것을 방지하기위해)
  • 받고자하는 데이터타입(JSON)
  • 원하는 지역의 위도, 경도 (명세표를 보면 지역별 위도, 경도 확인가능)

정상적인 현재 날씨의 정보를 JSON형태로 응답 받을수 있습니다.
내가 필요한 데이터를 추출하기 위해 JSON형태의 응답을 적절하게 parsing 해줍니다. 점심이 프로젝트에서는 온도와, 강수상태에 따라 음식을 추천해주는쪽으로 고려하여 두 데이터를 추출하였습니다.

현재 온도와, 강수 형태의 따라 현재 날씨의 상태를 분류하였고, 그 상태를 받아올수 있는 로직을 구현하였습니다.

점심 추천 알림 기능 구현

이제 날씨를 접목하여 음식을 추천해주는 알림서비스 기능을 구현해보도록 하겠습니다.
마찬가지로 저번 알림 메시지 보내기가 추상화되어있는 SlackService를 상속받아 구현합니다.

@Service
@RequiredArgsConstructor
public class SlackLunchService extends SlackService {
    private final WeatherService weatherService;

    public void sendLunchMessage() throws IOException {
        String weatherStatus = weatherService.getCurrentWeatherStatus();
        super.postSlackMessage("😀 오늘의 점심 추천 메뉴는 " + Menu.recommendMenu(weatherStatus) + "입니다. 맛있게 드세용!");
    }
}

이때 날씨 상태를 받아와 메뉴추천을 받을때 현재의 날씨 상태를 넣어 추천받도록 구현하였습니다.

날씨 상태에 따라 분류되어있는 음식중 하나를 랜덤하게 반환해줍니다.
아직 이부분은 로직이 뭔가 지저분한 느낌이..너무 많이 드는데 조금더 좋은 생각이 들면 ..리펙토링하는걸로

스케줄을 제외한 점심을 추천받을 모든 로직이 구현되어있습니다. 다시한번 정리하자면

  1. 슬랙 메시지를 보내기 위해 SlackService를 상속받은 SlackLunchService에서 점심 메시지를 생성
  2. 현재 날씨 상태를 호출하여 날씨 정보를 가져옵니다.
  3. 그 날씨 정보를 메뉴에서 날씨상태에 맞게 랜덤으로 추천받은 메뉴를 가져옵니다.
  4. 받아온 메뉴를 postMessage를 호출하여 발송합니다.

이렇게 모든 로직이 완료되었고, 이제 마지막으로 sendLunchMessage()를 원하는 시간, 주기에 자동으로 호출하는 Spring에서 제공하는 Schedule을 설정해보록하겠습니다.

@Configuration
@EnableScheduling
@RequiredArgsConstructor
public class SlackLunchScheduleConfig {
    private static final String LUNCH_ALERT_TIMER = "0/10 * * * * ?"; // <- 10 마다

    private final SlackLunchService slackLunchService;

    @Scheduled(cron = LUNCH_ALERT_TIMER)
    public void todayLunchRecommendMenu() throws IOException {
        slackLunchService.sendLunchMessage();
    }

}

전체적인 구성은 이러합니다. @Configuration 구성정보 어노테이션 @EnableScheduling 애플리케이션 실행시 자동 스케줄링 어노테이션 @Scheduled cron -> 자신이 원하는 특정시간이나 주기를 설정해줄수있다. 정규표현식처럼 cron 표현식에 대해서는 검색을 통해 자신이 원하는 설정을 할 수 있습니다. 설정 정보를 보면 10초마다(cron설정) SlackLunckService의 sendLunchMessage()를 10초마다 호출해라~ 라고 생각하시면됩니다.

모든 설정이 끝났으니 서버를 실행해보겠습니다.

정상적으로 메시지가 발송되는것을 볼수있습니다!

다음시간에는 AWS EC2를 이용하여 배포까지 해보도록 하겠습니다.

profile
봄이 오길

0개의 댓글