카테고리 없음

19주차 (2)

jaeoun0238 2025. 3. 5. 20:29

 

 

<!doctype html>
<html lang="ko">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>홈 | PinkTopia</title>
    <link rel="stylesheet" href="./styles.css">
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f9f9f9;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }

        .nav {
            display: flex;
            justify-content: space-between;
            align-items: center;
            background-color: #ff69b4;
            padding: 15px;
            color: white;
            font-weight: bold;
            position: relative;
            height: 50px;
            /* 네비게이션 바 높이 고정 */
        }

        /* 햄버거 메뉴 아이콘 스타일 */
        .menu-icon {
            position: absolute;
            left: 15px;
            height: 100%;
            display: flex;
            align-items: center;
            cursor: pointer;
            z-index: 2;
        }

        .menu-icon .hamburger {
            width: 25px;
            height: 20px;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .menu-icon .hamburger span {
            display: block;
            height: 3px;
            width: 100%;
            background-color: white;
            border-radius: 3px;
            transition: all 0.3s ease;
        }

        /* 로고 컨테이너 위치 수정 */
        .nav .logo-container {
            position: absolute;
            left: 50px;
            /* 햄버거 메뉴 옆으로 이동 */
            height: 100%;
            display: flex;
            align-items: center;
        }

        .nav img {
            width: 45px;
            /* 이미지 크기 증가 */
            height: 45px;
            border-radius: 0;
            /* 네모 모양으로 변경 */
            object-fit: cover;
        }

        /* 로고 텍스트 */
        .nav .logo-text {
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            font-size: 24px;
        }

        #authMenu {
            margin-left: auto;
            z-index: 1;
            /* 로고 텍스트 위에 표시되도록 */
        }

        .nav a {
            color: white;
            text-decoration: none;
            margin: 0 10px;
        }

        .menu {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
            margin-top: 20px;
        }

        .menu a {
            display: block;
            width: calc(33.333% - 20px);
            padding: 20px;
            text-align: center;
            background: white;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            text-decoration: none;
            color: black;
            font-weight: bold;
        }

        .nav>div:first-child {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        /* 사이드바 스타일 */
        .sidebar {
            height: 100%;
            width: 0;
            position: fixed;
            z-index: 1000;
            top: 0;
            left: 0;
            background-color: #ff69b4;
            overflow-x: hidden;
            transition: 0.5s;
            padding-top: 60px;
            box-shadow: 3px 0 10px rgba(0, 0, 0, 0.2);
        }

        .sidebar a {
            padding: 15px 25px;
            text-decoration: none;
            font-size: 18px;
            color: white;
            display: block;
            transition: 0.3s;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        .sidebar a:hover {
            background-color: #ff4da6;
        }

        .close-sidebar {
            position: absolute;
            top: 15px;
            right: 25px;
            font-size: 36px;
            cursor: pointer;
            color: white;
        }

        .sidebar-header {
            padding: 20px;
            color: white;
            font-size: 24px;
            font-weight: bold;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        /* 지도 컨테이너 스타일 */
        #map {
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            border: 2px solid #ff69b4;
        }

        /* 길찾기 폼 스타일 */
        .route-finder input {
            width: 100%;
            padding: 8px;
            margin-bottom: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
        }

        .route-finder label {
            display: block;
            margin-bottom: 5px;
            color: #666;
        }

        .route-button:hover {
            background: #ff4da6 !important;
        }

        /* 반응형 디자인을 위한 미디어 쿼리 */
        @media (max-width: 768px) {
            .map-section {
                flex-direction: column;
            }

            #map {
                height: 300px;
            }

            .route-finder {
                width: 100%;
            }
        }

        #overlay {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 999;
        }

        #popup {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 20px;
            background-color: #ff84c1;
            border: 1px solid #ff84c1;
            z-index: 1000;
            text-align: center;
        }

        #userProfileBox {
            display: flex;
            align-items: center;
            background-color: white;
            /* 배경을 흰색으로 설정 */
            padding: 10px 15px;
            border-radius: 20px;
            /* 둥근 네모 */
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            color: #ff5faf;
            /* 기본 글자색 */
            font-weight: bold;
            font-size: 16px;
        }

        #userProfileBox img {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            margin-right: 10px;
            object-fit: cover;
            border: 2px solid #ff7fbf;
            /* 핑크 테두리 */
        }

        #userProfileBox .welcome-text {
            color: #ff78bc;
            /* 핑크색 */
            font-weight: bold;
        }
    </style>
    <!-- "https://cdn.socket.io/4.3.2/socket.io.min.js" -->
    <script src="https://cdn.socket.io/4.3.2/socket.io.min.js"></script>
</head>

<body>
    <!-- 카카오맵 API 스크립트 추가 -->
    <script
        src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=5dc1bc6ffb574e60204390643bad8557&libraries=services,clusterer,drawing"></script>
    <div id="overlay"></div>
    <div id="popup">
        <p id="popupMessage"></p>
        <button id="confirmButton">확인</button>
        <button id="cancelButton">취소</button>
    </div>
    <div class="nav">
        <!-- 햄버거 메뉴 아이콘 추가 -->
        <div class="menu-icon" onclick="openSidebar()">
            <div class="hamburger">
                <span></span>
                <span></span>
                <span></span>
            </div>
        </div>
        <div class="logo-container">
            <img src="./images/123.jpg" alt="PinkTopia Logo" />
        </div>
        <div class="logo-text">
            <a href="/public/home.html" style="text-decoration: none; color: white">PinkTopia</a>
        </div>
        <!-- 로그인 상태에 따라 변경될 영역 -->
        <div id="authMenu" style="margin-left: auto; display: flex; align-items: center;"></div>
    </div>
    <div class="container">
        <h1>홈</h1>

        <!-- 지도와 길찾기 섹션을 감싸는 컨테이너 -->
        <div class="map-section" style="display: flex; gap: 20px; margin: 20px 0">
            <!-- 길찾기 폼 (왼쪽으로 이동) -->
            <div class="route-finder" style="
            flex: 1;
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            border: 2px solid #ff69b4;
          ">
                <h3 style="color: #ff69b4; margin-bottom: 20px">길찾기</h3>
                <div class="route-input">
                    <div class="mb-3">
                        <label for="start" class="form-label">출발지</label>
                        <input type="text" class="form-control" id="start" placeholder="출발지를 입력하세요" />
                    </div>
                    <div class="mb-3">
                        <label for="end" class="form-label">도착지</label>
                        <input type="text" class="form-control" id="end" placeholder="도착지를 입력하세요" />
                    </div>
                    <button class="route-button" onclick="findRoute()" style="
                width: 100%;
                padding: 10px;
                background: #ff69b4;
                color: white;
                border: none;
                border-radius: 5px;
                cursor: pointer;
              ">
                        길찾기
                    </button>
                </div>
                <div id="route-result" style="margin-top: 20px">
                    <!-- 길찾기 결과가 여기에 표시됩니다 -->
                </div>
            </div>

            <!-- 지도를 표시할 div (오른쪽으로 이동) -->


            <div id="map" style="flex: 2; height: 400px; border-radius: 10px;">
                <script>
                    // document.addEventListener("DOMContentLoaded", function () {

                    let mapContainer = document.getElementById('map'),
                        mapOption = {
                            center: new kakao.maps.LatLng(0, 0),
                            level: 5,
                        };
                    let map = new kakao.maps.Map(mapContainer, mapOption);

                    // 현재 위치 표시
                    if (navigator.geolocation) {
                        navigator.geolocation.getCurrentPosition(function (position) {
                            let lat = position.coords.latitude,
                                lon = position.coords.longitude;
                            let locPosition = new kakao.maps.LatLng(lat, lon),
                                message = '<div style="padding:5px;">현재 위치</div>';
                            displayMarker(locPosition, message);
                        });
                    } else {
                        let locPosition = new kakao.maps.LatLng(0, 0),
                            message = 'geolocation을 사용할 수 없어요..';
                        displayMarker(locPosition, message);
                    }
                    function displayMarker(locPosition, message) {
                        let marker = new kakao.maps.Marker({
                            map: map,
                            position: locPosition,
                        });
                        let infowindow = new kakao.maps.InfoWindow({
                            content: message,
                            removable: true,
                        });
                        infowindow.open(map, marker);
                        map.setCenter(locPosition);
                    }

                    let geocoder = new kakao.maps.services.Geocoder();

                    // 로컬 스토리지에서 저장된 좌표 정보 불러오기
                    let savedStart = JSON.parse(localStorage.getItem('startLocation'));
                    let savedEnd = JSON.parse(localStorage.getItem('endLocation'));

                    // 확대/축소 컨트롤 추가
                    let zoomControl = new kakao.maps.ZoomControl();
                    map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);


                    // 마커 정보 배열 (출발지, 도착지)
                    let markers = [
                        {
                            key: 'start',
                            info: '출발지',
                            position: savedStart
                                ? new kakao.maps.LatLng(savedStart.lat, savedStart.lng)
                                : new kakao.maps.LatLng(36.3275, 127.4268),
                            imageUrl: 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/red_b.png',
                            storageKey: 'startLocation',
                        },
                        {
                            key: 'end',
                            info: '도착지',
                            position: savedEnd
                                ? new kakao.maps.LatLng(savedEnd.lat, savedEnd.lng)
                                : new kakao.maps.LatLng(36.340309, 127.389999),
                            imageUrl: 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/blue_b.png',
                            storageKey: 'endLocation',
                        },
                    ];

                    // 마커를 지도에 추가하고 드래그 이벤트 등록
                    markers.forEach(function (data) {
                        let markerImage = new kakao.maps.MarkerImage(
                            data.imageUrl,
                            new kakao.maps.Size(50, 50),
                        );

                        let marker = new kakao.maps.Marker({
                            position: data.position,
                            image: markerImage,
                            map: map,
                            draggable: true, // 드래그 가능하도록 설정
                        });

                        // 정보창 생성
                        let infowindow = new kakao.maps.InfoWindow({
                            content: `<div style="padding:5px;">${data.info}</div>`,
                        });

                        // 마커에 정보창 표시
                        infowindow.open(map, marker);

                        // 마커 드래그 종료 시 좌표 및 정보창 위치 업데이트
                        kakao.maps.event.addListener(marker, 'dragend', function () {
                            let position = marker.getPosition();

                            // 정보창도 마커의 새 위치로 이동
                            infowindow.setPosition(position);

                            // 새로운 좌표를 localStorage에 저장
                            localStorage.setItem(
                                data.storageKey,
                                JSON.stringify({ lat: position.getLat(), lng: position.getLng() }),
                            );

                            console.log(`${data.info} 위치 저장됨:`, position.getLat(), position.getLng());
                        });

                        // 각 마커 및 정보창을 객체에 저장
                        data.marker = marker;
                        data.infowindow = infowindow;
                    });

                    // 전역 변수로 출발지, 도착지 마커 지정
                    let startMarker = markers.find(m => m.key === 'start').marker;
                    let endMarker = markers.find(m => m.key === 'end').marker;

                    // 길찾기 버튼 클릭 시 링크 새 창 열기
                    function openDirection() {
                        let startPos = startMarker.getPosition();
                        let endPos = endMarker.getPosition();
                        let url = `https://map.kakao.com/link/to/도착지,${endPos.getLat()},${endPos.getLng()}/from/출발지,${startPos.getLat()},${startPos.getLng()}`;
                        window.open(url, '_blank');
                    }

                    // 입력창의 주소를 검색하여 마커 이동 및 좌표 저장
                    function setMarkerPosition(marker, addressInputId) {
                        let inputElement = document.getElementById(addressInputId);
                        geocoder.addressSearch(inputElement.value, function (result, status) {
                            if (status === kakao.maps.services.Status.OK) {
                                let coords = new kakao.maps.LatLng(result[0].y, result[0].x);
                                marker.setPosition(coords);
                                map.setCenter(coords);
                                localStorage.setItem(
                                    addressInputId + 'Location',
                                    JSON.stringify({ lat: result[0].y, lng: result[0].x }),
                                );
                            } else {
                                alert('검색 결과가 없습니다.');
                            }
                        });
                    }
                    ///////////////////////////////////////////////////////////////////////
                    // 마커 이동 시 입력창에 좌표 업데이트
                    function updateInputValue(marker, addressInputId) {
                        let inputElement = document.getElementById(addressInputId);
                        let position = marker.getPosition();
                        inputElement.value = `${position.getLat()}, ${position.getLng()}`;
                    }

                    // 입력창 변경 시 해당 마커 이동
                    document.getElementById('start').addEventListener('change', function () {
                        setMarkerPosition(startMarker, 'start');
                    });

                    document.getElementById('end').addEventListener('change', function () {
                        setMarkerPosition(endMarker, 'end');
                    });

                    // 마커 드래그 후 입력창 값 업데이트
                    kakao.maps.event.addListener(startMarker, 'dragend', function () {
                        updateInputValue(startMarker, 'start');
                    });

                    kakao.maps.event.addListener(endMarker, 'dragend', function () {
                        updateInputValue(endMarker, 'end');
                    });


                    // 입력창의 주소를 기반으로 마커 위치를 이동시키는 함수
                    function setMarkerPosition(marker, addressInputId) {
                        let inputElement = document.getElementById(addressInputId);
                        geocoder.addressSearch(inputElement.value, function (result, status) {
                            if (status === kakao.maps.services.Status.OK) {
                                let coords = new kakao.maps.LatLng(result[0].y, result[0].x);
                                marker.setPosition(coords);
                                map.setCenter(coords);
                                // 변경된 좌표를 로컬 스토리지에 저장 (옵션)
                                localStorage.setItem(addressInputId + 'Location', JSON.stringify({ lat: result[0].y, lng: result[0].x }));
                            } else {
                                alert('검색 결과가 없습니다.');
                            }
                        });
                    }

                    // 출발지 입력창 값이 바뀌면 startMarker의 위치 업데이트
                    document.getElementById('start').addEventListener('change', function () {
                        setMarkerPosition(startMarker, 'start');
                    });


                    /////////////////////////////////////////////////////////
                    //         function checkLoginStatus() {
                    // const accessToken = localStorage.getItem("accessToken");
                    // const authMenu = document.getElementById("authMenu");

                    document.addEventListener("DOMContentLoaded", function () {
                        geoBookmark()
                    });
                    function geoBookmark() {
                        fetch('http://localhost:3000/direction/bookmark')
                            .then((response) => {
                                if (!response.ok) {
                                    throw new Error(`HTTP error! Status: ${response.status}`);
                                }
                                console.log('✅ 패치 성공');
                                return response.json();
                            })
                            .then((data) => {
                                console.log('📌 북마커 데이터 로드 성공:', data);
                                let markerDataB = [];
                                if (data) { // 북마커 데이터 호출 및 지도에 추가

                                    data.forEach(bookmark => {
                                        console.log('이번 북마커는 : ', bookmark)
                                        markerDataB.push({
                                            // markerData.data.map((bookmark) => ({
                                            position: new kakao.maps.LatLng(bookmark.latitude, bookmark.longitude),
                                            imageUrl:
                                                bookmark.sub_achievement_images ||
                                                'https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnZWDr%2FbtsMxEa1tat%2Fd4s5w26JdYrq0b7Qp9wDt1%2Fimg.png',
                                            size: new kakao.maps.Size(40, 40),
                                            info: bookmark.title || '이름 없음',
                                            draggable: false,
                                        });
                                        console.log("북마커 좌표 확인:", bookmark.latitude, bookmark.longitude);
                                    })
                                }
                                addMarkersToMap(markerDataB)
                            })
                            .catch((error) => console.error('Error fetching data:', error));
                    }
                    function addMarkersToMap(markerData) {
                        if (!markerData || markerData.length === 0) {
                            console.warn('📢 북마커 데이터 없음');
                            return;
                        }
                        console.log("다와간다 북마커 : ", markerData)
                        var bounds = new kakao.maps.LatLngBounds();

                        markerData.forEach(function (data) {
                            var markerImage = new kakao.maps.MarkerImage(data.imageUrl, data.size);
                            var marker = new kakao.maps.Marker({
                                position: data.position,
                                image: markerImage,
                                map: map,
                                draggable: data.draggable,
                            });
                            console.log("다와간다2 마커 : ", marker)

                            var infowindow = new kakao.maps.InfoWindow({
                                content: `<div style="padding:5px;">${data.info} <br>
                                      <a href="https://map.kakao.com/link/map/${data.info},${data.position.getLat()},${data.position.getLng()}" target="_blank" style="color:skyblue">큰지도보기</a> 
                                      <a href="https://map.kakao.com/link/to/${data.info},${data.position.getLat()},${data.position.getLng()}" target="_blank" style="color:blue">길찾기</a></div>`,
                            });

                            kakao.maps.event.addListener(marker, 'mouseover', function () {
                                infowindow.open(map, marker);
                            });

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

                            bounds.extend(data.position);
                            // infowindow.open(map, marker);
                            //  bounds.extend(data.position);
                        });
                        map.setBounds(bounds);
                    }


                </script>
            </div>
        </div>
    </div>
    <script>
        // 사이드바 열기 함수
        function openSidebar() {
            document.getElementById('sidebar').style.width = '250px';
        }

        // 사이드바 닫기 함수
        function closeSidebar() {
            document.getElementById('sidebar').style.width = '0';
        }

        // 페이지 로드 시 로그인 상태에 따라 메뉴 표시
        document.addEventListener('DOMContentLoaded', function () {
            const accessToken = localStorage.getItem('accessToken');
            const authMenu = document.getElementById('authMenu');

            if (accessToken) {
                // 사이드바 메뉴 업데이트
                document.getElementById('loggedInMenu').style.display = 'block';
                document.getElementById('loggedOutMenu').style.display = 'none';

                // 상단 네비게이션 바 메뉴 업데이트
                authMenu.innerHTML = `
                    <a href="/public/mypage.html">마이페이지</a>
                    <a href="#" onclick="logout()">로그아웃</a>
                `;

                // 메인 메뉴에 로그인 상태에서만 보이는 메뉴 추가
                const menuList = document.getElementById('menuList');
                if (menuList.querySelectorAll('a').length === 5) {
                    // 기본 메뉴만 있는 경우
                    menuList.innerHTML += `
                        <a href="/public/chattingrooms.html">채팅</a>
                        <a href="/public/pinkmong-dex.html">핑크몽 개인 도감</a>
                        <a href="/public/inventory.html">인벤토리 아이템</a>
                        <a href="/public/achievements.html">업적</a>
                    `;
                }
            } else {
                // 사이드바 메뉴 업데이트
                document.getElementById('loggedInMenu').style.display = 'none';
                document.getElementById('loggedOutMenu').style.display = 'block';

                // 상단 네비게이션 바 메뉴 업데이트
                authMenu.innerHTML = `
                    <a href="/public/log-in.html">로그인</a>
                    <a href="/public/sign-up.html">회원가입</a>
                `;
            }
        });

        document.addEventListener("DOMContentLoaded", function () {
            checkLoginStatus();
        });

        function checkLoginStatus() {
            const accessToken = localStorage.getItem("accessToken");
            const authMenu = document.getElementById("authMenu");

            if (accessToken) {
                fetch("http://localhost:3000/user/me", {
                    headers: { "Authorization": accessToken }
                })
                    .then(response => response.json())
                    .then(userData => {
                        const profileImage = userData.profile_image || "./images/default-profile.png"; // 기본 이미지

                        authMenu.innerHTML = `
                    <div id="userProfileBox" onclick="goToProfile()" style="cursor: pointer;">
                    <img src="${profileImage}" alt="프로필 사진">
                    <span><span class="welcome-text">환영합니다!</span> <strong>${userData.nickname}</strong>님!</span>
                    </div>
                    <a href="#" onclick="logout()" style="margin-left: 15px; color: white; text-decoration: none;">로그아웃</a>
                `;
                    })
                    .catch(error => {
                        console.error("유저 정보 불러오기 실패:", error);
                        authMenu.innerHTML = `<a href="/public/log-in.html" style="color: white;">로그인</a> / <a href="/public/sign-up.html" style="color: white;">회원가입</a>`;
                    });
            } else {
                authMenu.innerHTML = `<a href="/public/log-in.html" style="color: white;">로그인</a> / <a href="/public/sign-up.html" style="color: white;">회원가입</a>`;
            }
        }

        function goToProfile() {
            window.location.href = "/public/mypage.html";
        }


        async function logout() {
            try {
                const accessToken = localStorage.getItem('accessToken');
                if (!accessToken) {
                    console.warn('🚨 로그아웃 시도: 이미 로그아웃된 상태');
                    window.location.href = '/public/log-in.html';
                    return;
                }

                // 🔹 서버에 로그아웃 요청 보내기
                const response = await fetch(
                    'http://localhost:3000/user/auth/logout',
                    {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            Authorization: accessToken,
                        },
                        credentials: 'include', // 쿠키도 함께 보내기
                    },
                );

                if (!response.ok) {
                    throw new Error('서버에서 로그아웃 처리 실패');
                }
                localStorage.removeItem("accessToken");
                console.log("✅ 로그아웃 성공! 페이지 이동");
                window.location.href = "/";
            } catch (error) {
                console.error('❌ 로그아웃 실패:', error);
                alert('로그아웃 중 오류가 발생했습니다.');
            }
        }

        // 길찾기 함수 (나중에 구현)
        function findRoute() {
            const start = document.getElementById('start').value;
            const end = document.getElementById('end').value;

            // 임시 알림
            alert(
                '길찾기 기능은 현재 개발 중입니다.\n출발지: ' +
                start +
                '\n도착지: ' +
                end,
            );

            // 나중에 여기에 실제 길찾기 로직을 구현하면 됩니다.
            const routeResult = document.getElementById('route-result');
            routeResult.innerHTML = `
                <div style="padding: 10px; background: #f8f9fa; border-radius: 5px;">
                    <p>검색 결과가 여기에 표시됩니다.</p>
                </div>
            `;
        }
    </script>
    <!-- 사이드바 추가 -->
    <div id="sidebar" class="sidebar">
        <div class="sidebar-header">
            <span class="close-sidebar" onclick="closeSidebar()">&times;</span>
        </div>
        <div class="sidebar-content">
            <a href="/public/home.html">홈</a>
            <a href="/public/event.html">이벤트</a>
            <a href="/public/store-item.html">아이템샵</a>
            <a href="/public/board.html">게시글 (커뮤니티)</a>
            <a href="/public/ranking.html">랭킹</a>
            <a href="/public/pinkmonglist.html">핑크몽 전체 조회</a>
            <!-- 로그인 시 표시될 메뉴들 -->
            <div id="loggedInMenu" style="display: none">
                <a href="/public/chattingrooms.html">채팅</a>
                <a href="/public/collection.html">핑크몽 개인 도감</a>
                <a href="/public/inventory.html">인벤토리 아이템</a>
                <a href="/public/achievements.html">업적</a>
                <a href="/public/mypage.html">마이페이지</a>
                <a href="#" onclick="logout()">로그아웃</a>
            </div>
            <!-- 로그인 안 된 경우 표시될 메뉴들 -->
            <div id="loggedOutMenu">
                <a href="/public/log-in.html">로그인</a>
                <a href="/public/sign-up.html">회원가입</a>
            </div>
        </div>
    </div>
    <script src="./locationUpdates.js"></script>
    <!-- public\locationUpdates.js -->
</body>

</html>

🔥 오늘 해결한 오류들 & 원인 분석

1️⃣ a.Lf is not a function 오류

✅ 원인

  • kakao.maps.LatLng(latitude, longitude)에 잘못된 값이 들어감.
  • latitude와 longitude가 undefined, null, NaN 등의 값으로 전달됨.
  • geo service에서 latitude, longitude 순서가 반대로 되어 있었음.

🛠️ 해결 방법

✔ latitude와 longitude를 parseFloat()로 숫자로 변환
✔ isNaN(lat) || isNaN(lng) 체크하여 유효한 값만 사용
✔ geo service에서 latitude, longitude 올바른 순서로 수정


2️⃣ 북마커가 지도에 표시되지 않음

✅ 원인

  • fetch()로 받아온 데이터가 문자열(string) 형태여서 kakao.maps.LatLng()에서 오류 발생.
  • addMarkersToMap()에서 position: new kakao.maps.LatLng(bookmark.latitude, bookmark.longitude) 부분에서 잘못된 좌표 처리.

🛠️ 해결 방법

✔ latitude와 longitude를 parseFloat()로 변환하여 숫자로 처리
✔ isNaN() 검사하여 잘못된 좌표는 추가하지 않도록 설정
✔ console.log()로 데이터 흐름을 체크하며 디버깅


3️⃣ 북마커 위치가 반대로 표시됨

✅ 원인

  • geo service에서 latitude와 longitude 순서가 반대로 저장됨.
  • kakao.maps.LatLng(longitude, latitude)로 호출하면서 좌표가 뒤집어짐.

🛠️ 해결 방법

✔ new kakao.maps.LatLng(latitude, longitude) 순서를 올바르게 수정
✔ geo service에서 API 응답 데이터의 latitude, longitude 순서 정리


🚀 최종 해결 과정

✅ geo service에서 latitude, longitude 순서 수정
✅ parseFloat() 사용하여 좌표값을 숫자로 변환
✅ isNaN() 검사하여 유효하지 않은 좌표 제거
✅ console.log()로 데이터 흐름 체크 및 디버깅 완료
북마커가 정상적으로 지도에 표시됨! 🎯🔥


🎯 오늘의 교훈

1️⃣ 데이터를 받을 때 항상 형(type)을 확인하자! (string vs number)
2️⃣ 위도(latitude)와 경도(longitude) 순서를 항상 점검하자!
3️⃣ 콘솔 로그(console.log())를 적극 활용하여 데이터 흐름을 파악하자!
4️⃣ API 응답 데이터 구조를 항상 명확하게 이해하고 사용하자!


🎉 오늘의 성과

🚀 북마커 데이터 정상 로드 성공!
🚀 지도에 북마커가 정상적으로 표시됨!
🚀 좌표 순서 오류 해결 완료!

💡 앞으로 API 데이터를 사용할 때 console.log()로 미리 확인하는 습관을 들이자!
🔥 고생 많았다! 이제 북마커 기능 완벽하게 작동한다! 🔥