Bolt.new를 사용해서 웹페이지에 카카오 지도 붙여보기

소개

아직 기획 중이라 개발에 대한 기술 조사를 하고 있었습니다

Bolt.new 를 써서 지도를 붙여봤어요.

진행 방법

회원 가입 후 프롬프트를 다음과 같이 입력했습니다.
Kakao Developers에서 앱을 추가하고 키를 받아서 같이 넣어줬어요.

위와 같이 파일을 생성해줍니다

지도가 안보이고 로딩바만 보이고 있었는데, 그렇다고 에러도 뜨지 않아서

개발자 도구에 들어가서 확인해보니 콘솔에도 찍힌게 없었습니다.

네트워크탭 보니깐 sdk를 내려받는데 실패한 걸 알 수 있어서

프롬프트를 주고 받으며 삽질을 많이 했어요.

플랫폼에 도메인 주소를 등록해줘야하는데, 알려준 localhost로는 안되고, 새탭을 띄워보니 https://zp1v56uxy8rdx5ypatb0ockcb9tr6a 이런 형태로 url이 보여서 저걸로 등록하니 지도가 보입니다.

한국 음식 가이드 - 스크린샷

목데이터로 구현해 달라고 했던 부분도 잘 나옵니다.

목업으로 구현되어 있는 부분을 실데이터로 교체해달라고 요청해봤습니다.

에러가 발생했는데, 에러 밑에 있는 버튼을 눌렀더니 알아서 해결했습니다.

이런 작업도 쉽게 해줄 수 있네요

한국판 게임 스크린샷

오늘은 여기까지;;

Azure의 지도 서비스 스크린샷

시키지 않았는데, 컴포넌트도 관심사에 따라 잘 나눠놨네요.

코드

import React from 'react';
import { Star } from 'lucide-react';
import { Restaurant } from '../types';

interface RestaurantCardProps {
  restaurant: Restaurant;
}

export function RestaurantCard({ restaurant }: RestaurantCardProps) {
  return (
    <div className="bg-white rounded-lg shadow-md overflow-hidden">
      <img 
        src={restaurant.imageUrl} 
        alt={restaurant.name}
        className="w-full h-48 object-cover"
      />
      <div className="p-4">
        <h3 className="text-lg font-bold mb-2">{restaurant.name}</h3>
        <p className="text-gray-600 text-sm mb-2">{restaurant.address}</p>
        <div className="flex items-center mb-2">
          <Star className="w-4 h-4 text-yellow-400 mr-1" />
          <span className="text-sm">{restaurant.rating}</span>
        </div>
        {restaurant.kCultureConnection && (
          <div className="mt-2 p-2 bg-pink-50 rounded-md">
            <span className="text-xs font-semibold text-pink-600 uppercase">
              {restaurant.kCultureConnection.type}
            </span>
            <p className="text-sm text-gray-600 mt-1">
              {restaurant.kCultureConnection.description}
            </p>
          </div>
        )}
      </div>
    </div>
  );
}
import React, { useEffect, useRef } from 'react';
import { Restaurant } from '../types';
import { KAKAO_MAPS_API_KEY } from '../config/env';

declare global {
  interface Window {
    kakao: any;
  }
}

interface MapProps {
  restaurants: Restaurant[];
  currentLocation: { latitude: number; longitude: number } | null;
  onMarkerClick: (restaurant: Restaurant) => void;
}

const KAKAO_MAPS_SCRIPT_ID = 'kakao-maps-script';

function loadKakaoMapsScript(): Promise<void> {
  return new Promise((resolve, reject) => {
    if (window.kakao?.maps) {
      resolve();
      return;
    }

    if (document.getElementById(KAKAO_MAPS_SCRIPT_ID)) {
      const checkLoaded = setInterval(() => {
        if (window.kakao?.maps) {
          clearInterval(checkLoaded);
          resolve();
        }
      }, 100);
      return;
    }

    const script = document.createElement('script');
    script.id = KAKAO_MAPS_SCRIPT_ID;
    script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=${KAKAO_MAPS_API_KEY}&libraries=services&autoload=false`;
    script.onload = () => {
      window.kakao.maps.load(() => {
        resolve();
      });
    };
    script.onerror = reject;
    document.head.appendChild(script);
  });
}

export function Map({ restaurants, currentLocation, onMarkerClick }: MapProps) {
  const mapRef = useRef<HTMLDivElement>(null);
  const mapInstance = useRef<any>(null);
  const markersRef = useRef<any[]>([]);

  useEffect(() => {
    async function initializeMap() {
      if (!mapRef.current) return;

      try {
        await loadKakaoMapsScript();

        const center = currentLocation 
          ? new window.kakao.maps.LatLng(currentLocation.latitude, currentLocation.longitude)
          : new window.kakao.maps.LatLng(37.5665, 126.9780); // Default to Seoul

        const options = {
          center,
          level: 3
        };

        mapInstance.current = new window.kakao.maps.Map(mapRef.current, options);

        // Clear existing markers
        markersRef.current.forEach(marker => marker.setMap(null));
        markersRef.current = [];

        // Add markers for restaurants
        restaurants.forEach(restaurant => {
          const position = new window.kakao.maps.LatLng(restaurant.latitude, restaurant.longitude);
          
          const markerImage = restaurant.kCultureConnection
            ? new window.kakao.maps.MarkerImage(
                'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png',
                new window.kakao.maps.Size(24, 35)
              )
            : null;

          const marker = new window.kakao.maps.Marker({
            position,
            map: mapInstance.current,
            image: markerImage
          });

          const infowindow = new window.kakao.maps.InfoWindow({
            content: `<div style="padding:5px;font-size:12px;">${restaurant.name}</div>`
          });

          window.kakao.maps.event.addListener(marker, 'mouseover', () => {
            infowindow.open(mapInstance.current, marker);
          });

          window.kakao.maps.event.addListener(marker, 'mouseout', () => {
            infowindow.close();
          });

          window.kakao.maps.event.addListener(marker, 'click', () => {
            onMarkerClick(restaurant);
          });

          markersRef.current.push(marker);
        });

        // Add current location marker if available
        if (currentLocation) {
          const currentPosition = new window.kakao.maps.LatLng(
            currentLocation.latitude,
            currentLocation.longitude
          );
          
          const marker = new window.kakao.maps.Marker({
            position: currentPosition,
            map: mapInstance.current,
            image: new window.kakao.maps.MarkerImage(
              'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_red.png',
              new window.kakao.maps.Size(24, 35)
            )
          });

          markersRef.current.push(marker);
        }
      } catch (error) {
        console.error('Error initializing map:', error);
      }
    }

    initializeMap();

    return () => {
      markersRef.current.forEach(marker => marker.setMap(null));
      markersRef.current = [];
    };
  }, [restaurants, currentLocation]);

  return (
    <div className="relative w-full h-[600px] rounded-lg shadow-lg">
      <div 
        ref={mapRef} 
        className="absolute inset-0 w-full h-full rounded-lg"
        style={{ background: '#f8f9fa' }}
      />
      {!mapInstance.current && (
        <div className="absolute inset-0 flex items-center justify-center bg-gray-100 bg-opacity-75 rounded-lg">
          <p className="text-gray-600">Loading map...</p>
        </div>
      )}
    </div>
  );
}


결과와 배운 점

직접 개발하면 그래도 시간이 좀 걸릴 작업을 한시간도 안되어서 뚝딱 만들어내는게 신기하고 너무 편하네요.

제가 프롬프트를 잘못 작성해서 그런건지

카카오 지도를 사용하는 부분에서는 생각보다 시행착오가 많았습니다.

직접 디버깅을 해야하는 상황도 있었어요.

7
3개의 답글

👉 이 게시글도 읽어보세요