-
2년 전에 해보고 싶었던 도전에 발을 내딛다카테고리 없음 2022. 9. 16. 21:05
이번 주 퀘스트 과제 중 주요 컨텐츠 중 하나에는 '나만의 메뉴 만들기'가 있었다. 말 그대로 내가 직접 추가해보고 싶은 콘텐츠를 직접 구상해 React 퀘스트 과제의 컴포넌트 중 하나로 작성하는 것이다.
예전에 카카오 개발자 홈페이지에 들어가서 계정을 생성해본 적이 있었다. 지도는 좋아하고, API라는 걸 직접 써보는 경험이 중요하다고 말로만 듣던 시절에 카카오맵 홈페이지를 둘러보던 중 웹 지도 API를 제공한다는 것을 보았다. '일단 들어가면 이렇게든 저렇게든 쓸 수 있는 방법이 어떻게든 있지 않을까? 싶어 일단 들어가 계정을 생성했었다. 물론 그 시절에는 JavaScript의 J자나 HTTP의 H자도 모르던 시절이었기 때문에 설명서의 내용을 읽어도 도저히 이해를 할 수가 없었다.동료분이 이번에 외부 기관에서 제공하는 API를 이용해 환율 정보를 가져와 컴포넌트로 구현했다는 이야기를 듣고, 그때 기억이 다시 떠올랐다. 이 때가 금요일 오전 6시였다. 금요일 오후 3시가 시연인데, 그 안에 할 수 있겠나 싶었다. 두세 시간 정도 시도해 보고 안 되면 원래 하려던 계획을 그냥 하기로 마음먹고 일단 제공하는 기능을 빠르게 훑기 시작했다.
먼저 실제 지도를 그리고 그 위에서 원하는 작업을 수행할 수 있는 기능을 제공하는 Kakao Maps API가 제공되고 있었다.
그리고 주소 정보나 좌표 정보를 요청해 받아올 수 있는 로컬 API가 있었다.
로컬 API 가이드를 둘러보던 중 좌표값을 담아 요청하면 해당 좌표의 행정구역 명칭을 반환받을 수 있는 요청 명령이 있었는데, 그걸 보면서 퀘스트 과제에 적용해볼 만한 생각이 떠올랐다.
먼저 우리나라의 영토 내의 랜덤한 좌표를 생성하고, 해당 좌표를 전송하여 주소를 요청한 뒤, 주소를 반환받아 친구 객체를 생성할 때 속성으로 추가한다. 그리고 '친구 집 찾기' 같은 부가기능을 추가하는데, 해당 컴포넌트를 실행하면 컴포넌트의 영역 안에서 지도를 그려주고, 그 지도에 주소에 해당하는 좌표를 찍어서 보여주는 기능을 넣어보면 재밌겠다 싶었다.
물론 아쉽게도 금요일 오전 기준으로 내가 만든 퀘스트 과제 웹 페이지에 CSS는 하나도 적용이 안 되어있었고, 부가기능도 원래 계획조차도 이제 구현을 시작하려던 마당에다가, React에서 요청과 응답을 위해 사용하는 axios나 useSWR도 제대로 알지 못하고 있었는데 시작하면 진행이나 할 수 있을까 싶었다.
그럼에도 이것만큼은 포기하고 싶지 않다는 생각이 강하게 들었다.
오전 9시까지만 되는 데까지만이라도 해 보고, 막히면 접지 뭐 싶은 마인드로 시작했다. 가장 먼저 좌표 값을 요청하면 주소 값을 반환받아올 수 있는지 확인해보기로 했다.
좌표로 행정구역을 받기 위해서는 이런 식으로 예시 요청을 보내야 한다고 했다. 그래서 9주차 때 했었던 axios와 useSWR 소스코드를 잠깐 참고해 소스코드를 작성해 보았다. 인가를 위한 header 부분이 새로 추가되어야 했기 때문에 axios에 header를 추가하는 법을 찾아 소스코드에 반영해보았다.
import axios from 'axios'; import useSWR from 'swr'; const fetcher = (url) => ( axios.get(url, { headers: { Authorization: `KakaoAK ${REST_API_KEY}`, }, }).then((response) => response.data) ); export default function App() { const url = `https://dapi.kakao.com/v2/local/geo/coord2regioncode.json?x=129&y=37.5`; const { data } = useSWR(url, fetcher); const handleClick = () => { console.log(data); } return ( <button type="button" onClick={handleClick} > 주소 불러오기 </button> // ... ); }
사용법을 찾는 과정에서 잘못된 정보를 찾는 등의 약간의 혼선이 있기는 했지만 결국에는 다음과 같이 결과를 가져오는 것을 확인할 수 있었다.
나도 모르게 물개박수가 나왔다. 이게 바로 누가 만들어놓은 데이터를 이용할 수 있게 해주는 API라는 것이구나... 이렇게 배운 것을 또 한번 새로운 영역에 사용했구나...
그 다음 과정으로 랜덤한 값의 x좌표나 y좌표를 넣은 뒤 요청을 시도했다. x좌표와 y좌표의 범위는 바다가 아닌 내륙만이 포함되도록 했고, 해당 좌표를 받아 국내의 임의의 주소를 정상적으로 반환해 주는 것을 기대했다.
const randomCoordinate = ({ max, min }) => { const coordinate = Math.random() * (max - min) + min; return coordinate.toFixed(7); }; const x = randomCoordinate({ max: 129, min: 127 }); const y = randomCoordinate({ max: 37.5, min: 35.1 }); const url = `https://dapi.kakao.com/v2/local/geo/coord2regioncode.json?x=${x}&y=${y}`;
그러나 url을 이렇게 지정해주자 요청이 아래 캡쳐처럼 빠른 속도로 반복적으로 계속해서 수행되는 문제점이 발생했다.
fetch를 한 번만 수행되게 하는 법을 찾아야 하나, useEffect를 사용해봐야 하나... 여러 방법들을 찾으며 고민하던 중 url을 state로 관리하게 해볼까 생각이 들었고, 실행에 옮겨보았다.
import { useState } from 'react'; // ... export default function App() { const [url, setUrl] = useState(''); const randomCoordinate = ({ max, min }) => { const coordinate = Math.random() * (max - min) + min; return coordinate.toFixed(7); }; const updateUrl = () => { const x = randomCoordinate({ max: 129, min: 127 }); const y = randomCoordinate({ max: 37.5, min: 35.1 }); setUrl(`https://dapi.kakao.com/v2/local/geo/coord2regioncode.json?x=${x}&y=${y}`); }; const { data } = useSWR(url, fetcher); const handleClick = () => { updateUrl(); console.log(data); } return ( <button type="button" onClick={handleClick} > 주소 불러오기 </button> // ... ); }
그러자 다행이 다음 화면처럼 무시무시한 속도로 반복해서 요청을 시도하지 않고, 이제는 친구추가 버튼을 누를 때만 요청해서 가져온 데이터를 보여주는 것을 확인할 수 있었다.
첫 번째 친구 추가 버튼을 눌렀을 때 발생한 문제는 url state의 최초 값이 공백 문자열이기 때문에 최초로 fetch해오는 데이터가 없을 것으로 생각되었다. 그래서 첫 번째 친구추가 클릭을 하기 전에도 url에 값을 부여해 data를 fetch해오도록 하기 위해 화면이 최초로 렌더링된 순간에 원하는 동작을 수행할 수 있도록 useEffect를 사용하였다.
import { useEffect, useState } from 'react'; // ... const updateUrl = () => { const x = randomCoordinate({ max: 129, min: 127 }); const y = randomCoordinate({ max: 37.5, min: 35.1 }); setUrl(`https://dapi.kakao.com/v2/local/geo/coord2regioncode.json?x=${x}&y=${y}`); }; useEffect(() => updateUrl(), []); const { data } = useSWR(url, fetcher); const handleClick = () => { updateUrl(); console.log(data); } // ...
최종적으로 문제없이 API 서버로부터 데이터를 가져오고, 친구추가 버튼을 누를 때마다 가져왔던 데이터를 보여주는 것을 확인할 수 있었다.
사실 이 글은 9월 16일 오전 10시에 무한 요청이 이루어지는 부분의 원인을 결국 그 시간 안에 찾지 못해 잠시 일시 중단시켰었다가, 10일 오전 1시부터 이 글을 계속 써 나가면서 나머지 부분들의 오류를 찾아 해결한 과정을 기록한 모양새가 되었다.
글을 쓰는 과정이 굉장히 재미있었다. 스스로 새로운 시도를 해 보고, 여러 시도 끝에 하나의 실마리가 풀리면서 원하는 기대값이 나오고, 다음을 기약할 수 있게 되는 기분이 참 좋은 것 같다. 물론 아직 다음 과정들이 어떻게 흘러갈지는 알 수 없다. 웹 지도 영역을 임베딩하는 과정에서는 또 어떤 문제가 날 기다리고 있을 것인지...
Task의 홍수 속에 빠져 살고 있지만, 이 작업만큼은 가능하다면 주말과 다음 주중에도 꾸준히 시간을 투자해서 꼭 원래 계획했던 기능을 구현해보고 싶다. 이번에 과정 디스코드에 나만의 작품 자랑하기 코너가 생겼다고 한다. 나도 그곳에 글을 쓸 수 있는 날이 반드시 올 것이다.