08_Spring_240524(금)_89일차(0) - 공공데이터 API 활용 - 날씨

soowagger·2024년 5월 26일

8_Spring

목록 보기
38/38

config.properties에 인코드, 디코드 인증키 등록

# 공공데이터 포털 ServiceKey encode
my.public.data.service.key.encode=인코드값

# 공공데이터 포털 ServiceKey decode
my.public.data.service.key.decode=디코드값

mainController에서 키값 꺼내서 리턴

	@Value("${my.public.data.service.key.decode}")
	private String decodeServiceKey;
    
    
	/* 공공데이터 서비스키 리턴하기
	 */
	@GetMapping("/getServiceKey")
	@ResponseBody
	public String getServiceKey() {
		return decodeServiceKey;
	}

header.js

// 공공 데이터

// async & awiat : 비동기 처리 패턴
// 비동기를 마치 동기처럼(실행 순서를 지켜서) 사용하는 방법
// async : 비동기가 수행되는 함수 정의 부분 앞에 붙여 사용하는 키워드 (비동기 요청을 수행할 것이다.)
// await : promise를 리턴하는 비동기 요청 앞에 붙여 사용하는 키워드


// 오늘 날짜를 YYYYMMDD 형식으로 리턴하는 함수
function getCurrentDate() {

    const today = new Date();
    const year = today.getFullYear(); // 2024
    const month = ('0' + (today.getMonth() + 1)).slice(-2);
    const day = ('0' + today.getDate()).slice(-2);
    return `${year}${month}${day}`;

}

// 비동기 요청 1번째 함수
// 서비스키 config.properties에서 얻어오기
async function getServiceKey() {

    try { 
        
        const response = await fetch("/getServiceKey"); // 첫번째 then의 response(Promise) 객체 리턴
        return response.text();

        // const response = fetch("/getServiceKey");
        // const result = response.text();

        // fetch("/getServiceKey")
        // .then(resp => resp.text())
        // .then(result => {
        //     console.log(result);
        // })

    } catch(err) {
        console.log("getServiceKey의 에러 : " + err);
    }
}

// 공공데이터 날씨 API 정보를 얻어올 함수
async function fetchData() {

    const currentDate = getCurrentDate(); // 20240524
    console.log(currentDate);
    const serviceKey = await getServiceKey(); // 비동기 요청 1번째의 응답이 올 때까지 기다림

    console.log("serviceKey : ", serviceKey);

    const url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst';

    // URLSearchParams : URL의 쿼리 문자열을 쉽게 다룰 수 있게 해주는 내장 객체
    // 단, 사용 시 decode 서비스키 사용 -> URLSearchParams이 데이터를 인코딩하기 때문
    const queryParams = new URLSearchParams({
        ServiceKey : serviceKey,
        pageNo : 1,
        numOfRows : 10,
        dataType : 'JSON',
        base_date : currentDate,
        base_time : '0500',
        nx: 60,
        ny: 127
    });

    console.log(`${url}?${queryParams}`);

    // fetch 요청
    try {
        
        const response = await fetch(`${url}?${queryParams}`)
        const result = await response.json();

        console.log(result);

        const obj = result.response.body.items.item.reduce((acc, data) => {
            acc[data.category] = data.fcstValue;
            return acc;
        }, {});
   
        console.log(obj);
        const sky = {
            "1" : "맑음",
            "3" : "구름많음",
            "4" : "흐림"
        }
        // 화면에 뿌리기..
        const weatherInfo = document.querySelector(".weather-info");
       
        // i 요소 생성 (아이콘)
        const icon = document.createElement('i');
       
        // span 요소 생성 (날씨 정보)
        const span = document.createElement('span');
      
        // 첫 번째 p 요소 생성 (기온 정보)
        const p1 = document.createElement('p');
        // 두 번째 p 요소 생성 (비 올 확률 정보)
        const p2 = document.createElement('p');
        // 강수형태(PTY) 코드 : 없음(0), 비(1), 비/눈(2), 눈(3), 소나기(4)
        // 강수 형태에 따라 icon 지정
        if( obj.PTY == 0 ) { // 강수 없음
            switch(obj.SKY) { // SKY 상태에 따라 아이콘 지정
                case "1" : 
                    icon.className = 'fa-solid fa-sun'; break;
   
                case "3" :
                    icon.className = 'fa-solid fa-cloud'; break;
               
                case "4" :
                    icon.className = 'fa-solid fa-cloud-sun'; break;
   
            }
        } else if(obj.PTY == 3) { // 눈 올 때
            icon.className = 'fa-solid fa-snowflake';
        } else { // 그외 비올때
            icon.className = 'fa-solid fa-cloud-rain';
        }
        // 하늘 정보
        span.innerText = sky[obj.SKY];
        // 기온
        p1.innerText = `기온 : ${obj.TMP}`;
       
        // 강수확률
        p2.innerText = `강수 확률 : ${obj.POP}%`;
        // div에 자식 요소들 추가
        weatherInfo.appendChild(icon);
        weatherInfo.appendChild(span);
        weatherInfo.appendChild(p1);
        weatherInfo.appendChild(p2);

    } catch(err) {
        console.log(err);
    }
}

fetchData();

JS에서 날짜 구할 때 getMonth는 1달 전으로 나오고 1자리 수로 나옴
10보다 작으면 앞에 0 붙여서 나오게끔 처리

'0' + (today.getMonth() + 1) 의 경우 공백이 생기기 때문에 slice 처리

profile

0개의 댓글