상세 컨텐츠

본문 제목

네이버 오늘 날씨 한번 가져와 보깅깅

자바스크립트

by e7e 2025. 3. 12. 20:03

본문

이건 그냥 재미지만, Cross-Origin에 대한 이해가 필요하당. 

 

일단 스프링 백엔드 없이 결과를 확인 할 수 있게 웹 스토어에서 cross origin으로 검색

아래 그림 모양 플러인을 설치 하도록 하장. 왱? ( cross-origin 제약을 넘기 위해 필요!)

설치 했다면 디폴트로 기능이 꺼져있다.

(Cross-Origin 플러그인이 활성화되어 있는 경우 해킹될 수 있다하니,

꼭 사용시에만 활성화하고, 평상시에는 비활성화하여 놓도록 하장.

활성화 되어 있는 경우 daum이나 naver메일등이 제대로 동작하지 않을 수도 있당)

 

ON 시키면 준비 완료.

이제 백엔드 추가 작업 없이도 Naver URL에 요청 ajax로 응답을 받을 수 있었당.

 

아래 html 소스를 복사/붙여넣기로 실행해 보장.

(꼭 서버위에서 하장.  vscode라면 live 서버 또는 preview 서버 등등 초간단 웹서버...

 Vite React라면 public 폴더에 만들고, npm run dev로 개발서버 구동후  접근 등등) 

 

justTest.html

<!DOCTYPE html>
<meta charset="UTF-8" />
<style>
#merong {
font-size: 0.8em;
color: slategrey;
}
h3 {
margin-left: 50px;
}
#sater {
color: skyblue;
}
#title {
margin-left: 30px;
background-color: blueviolet;
color: white;
animation: yurimAny 5s ease-in-out 1s infinite alternate;
}
@keyframes yurimAny {
0% {
padding-left: 10%;
color: white;
}
50% {
padding-left: 50%;
color: yellow;
}
100% {
padding-left: 10%;
color: white;
}
}
</style>
<body>
<h1 id="title">E7E Naver 오늘 날씨만 가져오깅</h1>
<hr />
<div id="disp"></div>
<script>
const myDisp = document.querySelector("#disp");
let imgArr1, imgArr2;
function fGetWeather() {
let schURL = `https://weather.naver.com`;
myDisp.innerHTML = "";
let xhr = new XMLHttpRequest();
xhr.open("get", schURL, true);
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
let cont = xhr.responseText;
// console.log(cont);
myDisp.innerHTML = "";
// 날씨 정보
let startIndex = cont.indexOf("blockApiResult");
let endIndex = cont.indexOf('"regionTalk~~1"', startIndex + 500) - 1;
//console.log("체로롱",cont.substring(startIndex+16,endIndex));
let needJson = JSON.parse(
cont.substring(startIndex + 16, endIndex) + "}}}"
);
//console.log("체킁1:",needJson);
let headerInfo = needJson.results.choiceResult["talkHeader~~1"];
let naverInfo =
needJson.results.choiceResult["selectedRegion~~1"].naverRegion;
let aInfo = headerInfo.airNowInfo;
let nfInfo = headerInfo.nowFcastInfo;
let rInfo = headerInfo.regionInfo;
//console.log("체킁킁1",aInfo);
//console.log("체킁킁2",nfInfo);
//console.log("체킁킁3",rInfo);
let curPos = `${rInfo.lareaNm} ${rInfo.mareaNm} ${rInfo.sareaNm}`;
/*
console.log("현 위치: ",curPos);
console.log("날씨:",nfInfo.wetrTxt);
console.log("기온:",nfInfo.tmpr);
console.log("바람:",nfInfo.windSpd);
console.log("1시간내 비 확률:",nfInfo.oneHourRainAmt);
console.log("미세먼지:",aInfo.stationPm10Legend);
console.log("초미세먼지:",aInfo.stationPm25Legend);
*/
const e7eWeInfo = {
["현위치"]: `${curPos} <span id=merong>경도:${naverInfo.longitude} 위도:${naverInfo.latitude}</span>`,
["날씨"]: nfInfo.wetrTxt,
["기온"]: nfInfo.tmpr + " ℃",
["바람"]: nfInfo.windSpd + " m/s",
["비(1시간내)"]: nfInfo.oneHourRainAmt + " %",
["미세먼지"]: aInfo.stationPm10Legend,
["초미세먼지"]: aInfo.stationPm25Legend,
};
console.log("final; ", e7eWeInfo);
for (let wKey in e7eWeInfo) {
let h3 = document.createElement("h3");
h3.innerHTML = `${wKey}: ${e7eWeInfo[wKey]}`;
myDisp.appendChild(h3);
}
myDisp.innerHTML += `<h3 id=sater>아래 위성사진</h3><hr>`;
// 위성사진1
startIndex = cont.indexOf('["https://search.pstatic.net/common?');
endIndex = cont.indexOf('"]', startIndex);
imgArr1 = JSON.parse(cont.substring(startIndex, endIndex + 2));
// console.log(imgArr1);
myDisp.innerHTML += `<img id="img1" width=400 height=400 src="${imgArr1[0]}">`;
// 위성사진2
startIndex = cont.indexOf(
'["https://search.pstatic.net/common?',
endIndex
);
endIndex = cont.indexOf('"]', startIndex);
imgArr2 = JSON.parse(cont.substring(startIndex, endIndex + 2));
// console.log(imgArr2);
myDisp.innerHTML += `<img id="img2" width=400 height=400 src="${imgArr2[0]}">`;
imgRotate();
}
};
xhr.send();
}
fGetWeather();
let pIndex1 = 0,
pIndex2 = 0;
function imgRotate() {
myDisp.querySelector("#img1").src = imgArr1[pIndex1];
myDisp.querySelector("#img2").src = imgArr2[pIndex2];
pIndex1++;
if (pIndex1 > imgArr1.length - 1) pIndex1 = 0;
pIndex2++;
if (pIndex2 > imgArr2.length - 1) pIndex2 = 0;
setTimeout(imgRotate, 500);
}
</script>
</body>
</html>

 

아래와 같은 결과가 나왔을 거당.~~ 그렇당!!~

현 위치에는 접속 대략 주소 와 경도 / 위도 가 나올꺼당. (내껀 지웠당!~~ 내 맘이당!~~ㅋ)

굳이 소스 설명은 생략하겠당. (너무 긴 글이 필요하당.~~, Self Study )

 

암것도 안 주면 서운하다닝, F12를 눌러 console 로그를 보면 아래 그림과 같은 결과가

보일거시당.  해당 결과가 나오는 과정을 소스에서 추적하면 충분히 파악 할 수 

있을거시당. 또 누군가는 console에 찍힌  결과를 충분히 만족할 수도 있겠다.

 

하지만 실제 서비스의 경우 사용자에게 모두 브라우져 플러그인을 설치하라 요구할 수 없으닝.

아래와 같은 절차로 서버 사이드 프로그램이 필요해 진당.

 

아작스에서 네이버 바로 요청시 Cross-Origin(CORS) 문제를 서버 우회로 해결하기

위해서 아래 httpclient5 라이브러리를 추강 (딴거도 써도 됨!,요건 내가 좋아함) 

pom.xml

<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-fluent</artifactId>
<version>5.2.1</version>
</dependency>

 

아작스 요청을 받을 controller 소스 작성!(이름은 일단 내맘...)

HttpClientTest.java

package kr.pe.basic.controller;
import org.apache.hc.client5.http.fluent.Request;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/hyun")
public class HttpClientTest {
@GetMapping("/weather")
public String getWeather() {
return "weather"; // weather.jsp롱
}
//weater.jsp 안 아작스에서 요청하는 URL
@GetMapping(value="/naver", produces = "application/json;chaset=utf-8")
@ResponseBody
public String getWeatherInfo() throws Exception {
return Request.get("https://weather.naver.com").execute().returnContent().asString();
}
}

 

클라이언트 단 작성(이름은 내맘!)

weather.jsp

<!DOCTYPE html>
<meta charset="UTF-8" />
<style>
#merong {
font-size: 0.8em;
color: slategrey;
}
h3 {
margin-left: 50px;
}
#sater {
color: skyblue;
}
#title {
margin-left: 30px;
background-color: blueviolet;
color: white;
animation: yurimAny 5s ease-in-out 1s infinite alternate;
}
@keyframes yurimAny {
0% {
padding-left: 10%;
color: white;
}
50% {
padding-left: 50%;
color: yellow;
}
100% {
padding-left: 10%;
color: white;
}
}
</style>
<body>
<h1 id="title">E7E Naver 오늘 날씨만 가져오깅</h1>
<hr />
<div id="disp"></div>
<script>
const myDisp = document.querySelector("#disp");
let imgArr1, imgArr2;
function fGetWeather() {
let schURL = `https://weather.naver.com`;
myDisp.innerHTML = "";
let xhr = new XMLHttpRequest();
xhr.open("get", schURL, true);
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
let cont = xhr.responseText;
// console.log(cont);
myDisp.innerHTML = "";
// 날씨 정보
let startIndex = cont.indexOf("blockApiResult");
let endIndex = cont.indexOf('"regionTalk~~1"', startIndex + 500) - 1;
//console.log("체로롱",cont.substring(startIndex+16,endIndex));
let needJson = JSON.parse(
cont.substring(startIndex + 16, endIndex) + "}}}"
);
//console.log("체킁1:",needJson);
let headerInfo = needJson.results.choiceResult["talkHeader~~1"];
let naverInfo =
needJson.results.choiceResult["selectedRegion~~1"].naverRegion;
let aInfo = headerInfo.airNowInfo;
let nfInfo = headerInfo.nowFcastInfo;
let rInfo = headerInfo.regionInfo;
//console.log("체킁킁1",aInfo);
//console.log("체킁킁2",nfInfo);
//console.log("체킁킁3",rInfo);
let curPos = `\${rInfo.lareaNm} \${rInfo.mareaNm} \${rInfo.sareaNm}`;
/*
console.log("현 위치: ",curPos);
console.log("날씨:",nfInfo.wetrTxt);
console.log("기온:",nfInfo.tmpr);
console.log("바람:",nfInfo.windSpd);
console.log("1시간내 비 확률:",nfInfo.oneHourRainAmt);
console.log("미세먼지:",aInfo.stationPm10Legend);
console.log("초미세먼지:",aInfo.stationPm25Legend);
*/
const e7eWeInfo = {
["현위치"]: `\${curPos} <span id=merong>경도:\${naverInfo.longitude} 위도:\${naverInfo.latitude}</span>`,
["날씨"]: nfInfo.wetrTxt,
["기온"]: nfInfo.tmpr + " ℃",
["바람"]: nfInfo.windSpd + " m/s",
["비(1시간내)"]: nfInfo.oneHourRainAmt + " %",
["미세먼지"]: aInfo.stationPm10Legend,
["초미세먼지"]: aInfo.stationPm25Legend,
};
console.log("final; ", e7eWeInfo);
for (let wKey in e7eWeInfo) {
let h3 = document.createElement("h3");
h3.innerHTML = `\${wKey}: \${e7eWeInfo[wKey]}`;
myDisp.appendChild(h3);
}
myDisp.innerHTML += `<h3 id=sater>아래 위성사진</h3><hr>`;
// 위성사진1
startIndex = cont.indexOf('["https://search.pstatic.net/common?');
endIndex = cont.indexOf('"]', startIndex);
imgArr1 = JSON.parse(cont.substring(startIndex, endIndex + 2));
// console.log(imgArr1);
myDisp.innerHTML += `<img id="img1" width=400 height=400 src="\${imgArr1[0]}">`;
// 위성사진2
startIndex = cont.indexOf(
'["https://search.pstatic.net/common?',
endIndex
);
endIndex = cont.indexOf('"]', startIndex);
imgArr2 = JSON.parse(cont.substring(startIndex, endIndex + 2));
// console.log(imgArr2);
myDisp.innerHTML += `<img id="img2" width=400 height=400 src="\${imgArr2[0]}">`;
imgRotate();
}
};
xhr.send();
}
fGetWeather();
let pIndex1 = 0,
pIndex2 = 0;
function imgRotate() {
myDisp.querySelector("#img1").src = imgArr1[pIndex1];
myDisp.querySelector("#img2").src = imgArr2[pIndex2];
pIndex1++;
if (pIndex1 > imgArr1.length - 1) pIndex1 = 0;
pIndex2++;
if (pIndex2 > imgArr2.length - 1) pIndex2 = 0;
setTimeout(imgRotate, 500);
}
</script>
</body>
</html>

 

테스통 결과는 이전과 똑같을 지어다. 

 

이거슨 일시적 편법이닝, 제대로 하려면 네이버 날씨API등을 사용하는 거시 좋당.

 


그거시 완벽하지 않음을 알지만,

그거시 가치가 있음도 안당.

 

삶에 원하지 않았던 페이지도 많지만,

그거시 필요했었음을 이젠 안당!

 

내가 나여서 부끄러운 적도 많지만,

내가 나여서 당당했음도 이젠 안당.

 

무서워 도망치고 싶은 적도 많지만.

무서워서 용기를 낸 적도 있음도 이젠 안당.

 

그냥 가자.... 화이팅!!

 

https://www.youtube.com/watch?v=Qzuehp-umF4 

 

관련글 더보기