[TIL] 10주차 화요일. 팀플 - 아웃소싱 프로젝트, 카카오 맵 API 사용해보기

Minji Kim·2024년 6월 18일

내배캠TIL

목록 보기
42/73
post-thumbnail

Task

  • KAKAO MAP API 사용하여 지도 화면에 띄우기
  • Tanstack Query로 supabase DB에서 필요한 데이터만 fetch
  • DB에서 가져온 정보를 지도에 마크업 하기

Problem

카카오 맵 API를 사용해 지도를 불러와야 하는데 역시 혼자서는 무리고 이미 비슷한 작업을 해본 선배님들(구글링)의 도움을 받아보려고 노력했는데 잘 풀리지 않았다. 우리의 작업 환경과 과제 수행 조건에 딱 맞는 걸 찾기가 쉽지 않았다. React, JavaScript, Tanstack Query를 사용하는 게 목표.

Solution

팀원 분께서 라이브러리를 추천해주셨고, 라이브러리를 사용해 간단히 해결할 수 있었다… 세상 참 좋다.

Tanstack Query로 관리해야 한다 ← 이게 과제의 필수 구현 사항 중 하난데.

생각해보니 단지 Map을 불러오는 것만 사용한다면 딱히 필요도 없고, supabase 사용할 때 이미 다 하고 있으니까 괜찮겠다 싶었다!

라이브러리를 사용하니까 정말 간단했다…

라이브러리

react-kakao-maps-sdk : https://react-kakao-maps-sdk.jaeseokim.dev/

라이브러리 설치:

yarn add react-kakao-maps-sdk
or
npm install react-kakao-maps-sdk

코드

설치한 다음 html 안에 script 태그를 넣어줘야 한다.

  • VITE_KAKAO_API_KEY = 우리가 설정한 .env 안에 있는 api key 이름
  • key를 직접 붙여 넣는다면 %%를 빼고 바로 …appkey=키값… 따옴표도 없이
  • html을 건드리지 않고 컴퍼넌트에서 하는 방법부터 찾아봤는데 그 한 줄을 대체하기 위해 코드가 너무 길어져서 그냥 html을 건드리는 것을 택했다. 우리는 페이지 세 개 중 두 개에서 사용하니까 그래도 괜찮을 듯 하다.
  • VITE 버전이 4.몇 이상이어야 이렇게(%사이에두기%) 작성 가능하다고 함. 사용 전에 package.json을 보고 버전 업데이트가 필요한지 확인해보자.
// index.html
// .env를 사용하지 않을 때
<script
	type="text/javascript"
	src="//dapi.kakao.com/v2/maps/sdk.js?appkey=우리가발급받은카카오APIkey&libraries=services,clusterer"
></script>
// index.html
// .env를 사용할 때
// 프로젝트 코드가 공개적이면 .env 사용은 필수
<script
	type="text/javascript"
	src="//dapi.kakao.com/v2/maps/sdk.js?appkey=%.env에적어놓은APIkey이름(우리는VITE_KAKAO_API_KEY)%&libraries=services,clusterer"
></script>
// src/compoents/List/ListPageMap.jsx

import { Map, MapMarker } from "react-kakao-maps-sdk";
import { fetchMenuItems } from "../../api/pharmacy";
import { useQuery } from "@tanstack/react-query";
import { useLocation } from "react-router-dom";

function ListPageMap() {
	const location = useLocation();
	const lastFourDigits = location.pathname.slice(-4);

	const {
		data: pharmacies = [],
		isLoading,
		error
	} = useQuery({
		queryKey: ["pharmacies", lastFourDigits],
		queryFn: () => fetchMenuItems(lastFourDigits)
	});

	if (isLoading) return <p>Loading...</p>;
	if (error) return <p>Error fetching pharmacies</p>;
	if (pharmacies.length === 0) return <p>No pharmacies found</p>;

	const centerLatLon = { lat: pharmacies[0].lat, lng: pharmacies[0].lon };

	const locations = pharmacies.map((pharmacy) => ({
		placeName: pharmacy["place-name"],
		latlng: { lat: pharmacy.lat, lng: pharmacy.lon }
	}));

	return (
		<div>
			<Map
				center={centerLatLon}
				style={{
					width: "100%",
					height: "100vh"
				}}
				level={7}
			>
				{locations.map((loc, idx) => (
					<MapMarker
						key={`${loc.placeName}-${loc.latlng.lat}-${loc.latlng.lng}`}
						position={loc.latlng}
						image={{
							src: "https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png",
							size: { width: 24, height: 35 }
						}}
						placeName={loc.placeName}
					/>
				))}
			</Map>
		</div>
	);
}

export default ListPageMap;
// src/api/pharmacy.js

import supabase from "../supabase/supabase";

export const fetchMenuItems = async (lastFourDigits) => {
	try {
		const { data, error } = await supabase
			.from("pharmacy")
			.select("id, place-name, address, phone-number, place-area, lat, lon")
			.eq("place-code", Number(lastFourDigits));

		if (error) {
			throw new Error(error.message);
		}

		return data;
	} catch (error) {
		console.error("Error fetching menu items:", error.message);
		throw new Error("Failed to fetch menu items");
	}
};
// src/supabase/supabase.js

import { createClient } from "@supabase/supabase-js";

const SUPABASE_PROJECT_URL = import.meta.env.VITE_SUPABASE_URL;
const SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_KEY;

const supabase = createClient(SUPABASE_PROJECT_URL, SUPABASE_ANON_KEY);

export default supabase;

완성본


다짐

간단한 리팩토링 끝내고 추가 기능까지 구현 완성하면 이번주에 카카오맵 사용한 사이드 프로젝트 한 번 만들어보자.

0개의 댓글