항해99 - 실전 프로젝트 04(외부 API, DB에 저장하기)

2021. 12. 7. 21:09항해99/실전프로젝트

728x90

모든 API를 관리하는 Class 만들기

https://eating-salmon.tistory.com/74

 

항해99-실전프로젝트 02(공공데이타포털 api 사용하기)

E-R 다이어그램 e-r 다이어그램이 나타내고 있는 날씨, 천문 데이터 엔티티 정보들은 모두 외부 api를 통해서 데이터를 가져와야 한다. 그렇기 때문에 백엔드에서 외부 api를 사용하여 데이터를 가

eating-salmon.tistory.com

지난 포스팅에서 하나의 외부 api를 가져오고 객체로 저장하는 방식을 포스팅하였다.

이번에는 이런 외부 api를 여러 개 엮어서 db에 저장해보겠습니다.

 

1. 의존주입 받기

@Component
@RequiredArgsConstructor
@Slf4j
public class API {
    private final AccuWeatherApi accuWeatherApi;
    private final DustApi dustApi;
    private final MoonAPI moonAPI;
    private final WeatherApi weatherApi;
    private final AddressToGps addressToGps;
    
    private final LocationRepository locationRepository;
    private final StarRepository starRepository;
    private final WeatherRepository weatherRepository;
}
  • @Component : Spring Beaan 객체로 등록하기 위해서 애노테이션을 등록하였다.
  • @RequeiredArgsConstructor : 하위의 의존 클래스에 자동주입을 받기위해 등록하였다.
  • @Slf4j : 프로젝트 로그를 출력하기 위해서 등록

2. 모든 api의 응답데이터를 가져오는 findInfoByAddress method

2.1) api를 보내기 전 각 api마다 필요로하는 도시 id 찾기

public LocationStarMoonDustDto findInfoByAddress(String address, int count) throws Exception {
    List<String> location = processAddress(address);
    
    WeatherCity weatherCity = WeatherCity.getWeatherCityByString(location.get(0));
    MoonCity moonCity = MoonCity.getMoonCityByString(location.get(0), location.get(1));
    DustCity dustCity = DustCity.getDustCityByString(location.get(1));
    StarGazingCity starGazingCity = StarGazingCity.getStarGazingCityByString(location.get(0));

 }
public List<String> processAddress(String address){
    List<String> result = new ArrayList<>();

    for (City value : City.values()) {
        if(address.contains(value.getKorName())){
            result.add(value.getKorName());
            result.add(value.getState());
            return result;
        }
    }
    return result;
}
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum City {
    서울("서울", "서울특별시" ),
    부산("부산", "부산광역시"),
    대구("대구", "대구광역시" ),
    인천("인천", "인천광역시"),
    광주("광주", "광주광역시"),
    대전("대전", "대전광여시"),
    울산("울산", "울산광역시"),
    //경기
    세종("세종", "경기도"),
    수원("수원", "경기도"),
    성남("성남", "경기도"),
    의정부("의정부","경기도" ),
    안양("안양", "경기도"),
    부천("부천", "경기도"),
    광명("광명", "경기도"),
    평택("평택", "경기도"),
    동두천("동두천","경기도"),
    .....
}
  • 저번 weatherApi 포스팅과 같이 각 api마다 도시가 가지고 있는 id 값이나 좌표 값이 들어있다.
  • weatherApi 같은 경우 도시이름을 좌표로 바꾸어서 요청메시지에 담아 보내주어야 한다.
  • 위 과정은 그와 같이 각 api에 맞게 도시 정보를 바꾸는 과정이다.
  • List<String> location = processAddress(address)
    • 해당하는 주소가 담고 있는 도시 이름을 가져온다.
    • City Enum 데이터를 한번 씩 돌면서 해당하는 도시 이름이 포함되어있으면 그 도시 데이터를 가져온다.
  • WeatherCity weatherCity = WeatherCity.getWeatherCityByString(location.get(0));
    • 각각의 api마다 도시가 가지고 있는 id값 목록들을 enum화 시켰고
    • 해당하는 api의 해당하는 도시의 id 값을 찾는 함수이다.
public LocationStarMoonDustDto findInfoByAddress(String address, int count) throws Exception {
    List<String> location = processAddress(address);
    
    WeatherCity weatherCity = WeatherCity.getWeatherCityByString(location.get(0));
    MoonCity moonCity = MoonCity.getMoonCityByString(location.get(0), location.get(1));
    DustCity dustCity = DustCity.getDustCityByString(location.get(1));
    StarGazingCity starGazingCity = StarGazingCity.getStarGazingCityByString(location.get(0));
	
    List<StarGazingDto> starGazing = accuWeatherApi.getStarGazing(starGazingCity, count);
    SunMoonDto moon = moonAPI.getMoon(moonCity);
    List<WeatherApiDto2> weather = weatherApi.getWeather(weatherCity);
    DustApiDto dust = dustApi.getDust(dustCity);
    GeographicDto geographicDto = addressToGps.getAddress(address);
    
    
    LocationStarMoonDustDto result = new LocationStarMoonDustDto(
            starGazing,
            moon,
            weather,
            dust,
            address,
            geographicDto
    );
    
    return result;
}
  • 각각 api마다 필요한 도시정보들을 구한 뒤
  • 각 api마다 데이터를 가져오는 getAPI 함수를 실행하여 데이터를 가져온다.
  • 가져온 데이터는 모든 데이터를 묶어 주는 dto인 LocationStarMoonDustDto 객체에 담아서 return 한다.

3. 객체 저장하기, saveStarLocationWeather method

 @Transactional
    public Location saveStarLocationWeather(LocationStarMoonDustDto result ) {
        List<String> location = processAddress(result.getAddress());
        Location newLocation = new Location(location.get(0));

        Location saveLocation = locationRepository.save(newLocation);

        Star newStar =
                new Star(
                    result.getMoon().getMoonrise(),
                    result.getMoon().getMoonSet(),
                    Long.valueOf(result.getStarGazing().get(0).getValue().longValue()),
                    saveLocation
                );
        starRepository.save(newStar);

        for (WeatherApiDto2 weatherApiDto2 : result.getWeather()) {
            Weather newWeather = new Weather(
                            weatherApiDto2.getHumidity(),
                            weatherApiDto2.getWeather(),
                            weatherApiDto2.getTemperature(),
                            weatherApiDto2.getMaxTemperature(),
                            weatherApiDto2.getMinTemperature(),
                            weatherApiDto2.getPrecipitationProbability(),
                            weatherApiDto2.getFcstTime(),
                            result.getDust().getPm10Value(),
                            weatherApiDto2.getBaseDate(),
                            saveLocation);

            weatherRepository.save(newWeather);
        }

        return saveLocation;
    }
  • 위에서 가져온 데이터를 토대로
  • location table, weather table, star table의 정보를 저장한다.
  • 위 메소드는 데이터 베이스를 변경하는 작업을 함으로 @Transitional 어노테이션을 사용하여
  • 트랜잭션은 4가지의 성질을 가지고 있다.

4. DB 상태

location Table
star Table
weather Table