Trip Or Travel: 이제야 올리는 TOT 프로젝트 완성글

여는 말


이 프로젝트를 완성한 것은 2021년 11월 말인데…ㅎ;; 이제야 프로젝트 완성했던 글을 쓴다…
사실, 이 프로젝트를 통해 새롭게 알게 된 내용 정리하고 그래야 하는데, 너무 오래 지났다보니 정확하게 새롭게 배웠던 내용이 뭐 였는지 기억이 안난다…!!
~~사실 새롭게 알게 된 내용이 많기도 했고

결론은, 게으름 피운 나의 업보..랄까…? 일단 (나름)최근에 끝냈던 동아리 프로젝트 관련 내용이 기억날때 다 적어둬야 겠다고 판단했다. 그래도 이 프로젝트의 완성본과 약간 기억나는 점들을 작성하자는 생각에 다시 이 프로젝트 관련 글을 작성한다!

결과물



지도

지도

21년도 11월에 완성하고 서버를 열어뒀는데 22년 2월즈음, 혹시 서버 비용 나올까봐 닫아주면서… 지도 API연결된게 요롷게 사라졌다. 2월에는 멀쩡했는데, 최근에 사진이라도 남기자 생각해서 로컬 서버를 열어서 보니 연결이 끊긴 걸 확인했다. 아마 새롭게 업데이트가 되서 더이상 안되는 걸지도…? 사실 백엔드는 잘 모른다

  • 기능
    지도의 기능은 다음과 같다.
    포스트를 작성할 때 지도에서 위치를 선택한다. 그러면 자동으로 위도와 경도로 변환되어 작성된다. (위도와 경도는 데이터베이스로 넘어간다.)
    포스트를 포스팅하면 해당 글의 위도와 경도가 지도에 마커로 표시된다.
    해당 표시로 인해, 그간 내가 어디를 여행다니고 기록을 남겼는 지 한 눈에 알 수 있어서 좋다.
  • TIL
    지도 API를 불러오는 것, 마커 찍는 방법, 지도의 기본 위치를 설정 등 지도를 활용하는 백엔드 기술을 배울 수 있었다.
    구글에서 무료로 배포하는 지도 API를 활용하는 법 (구글에서 친절하게 예시와 함께 설명을 해두었다. 영어로 되어있는게 함정)
    • 구글 지도 API 링크
          <!-- Google Map  -->
          <script
          src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAlc1cmKgefcHGoKjAL5FUUjXGrAlRvwN0&callback=initMap&v=weekly"
          async></script>
          <script src="https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js"></script>
          <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/exif-js"></script>
      
    • 지도 API 연결하기
        function initMap() {
          map = new google.maps.Map(document.getElementById("map"), {
              center: {lat: 37.5642135, lng: 127.0016985},
              zoom: 8,
          });
        }
      
    • 지도에 마커 찍기
        function showArticles() {
        $.ajax({
            type: "GET",
            url: "/trip",
            data: {},
            success: function (response) {
                const articles = response["articles"];
                console.log(articles);
                for (let i = 0; i < articles.length; i++) {
                    // 마커 지도에 저장하기
                    let marker = new google.maps.Marker({
                        map: map,
                        position: {
                            lat: Number(articles[i]['lat']),
                            lng: Number(articles[i]['lng']),
                        }
                    });
                    makeCard(articles[i]["writer"], articles[i]["img"], articles[i]["date"], articles[i]["place"], articles[i]["content"]);
                }
            }
          })
        }
      
    • 솔직히 말하자면 정확히 어떻게 사용했는지 지금은 잘 기억이 안나긴 한다. 하지만 다음번에 다시 할때는 조금 더 수월하게 할 수 있을 것 같다! 이거 처음 만들때는 멘토님 계셨어도 며칠동안 했던 것 같다..

포스팅

카드 등록

  • 기능
    상단 Trip버튼 클릭시 포스팅 상자가 열린다.
    포스팅 상자 안 작성자,여행날짜,여행장소,사진업로드,내용 을 작성하면 된다. 위도와 경도는 여행장소 선택시 자동으로 입력이 된다.
    모든 내용 작성 완료 후 저장버튼을 누르면 팝업창으로 작성 완료가 뜨면서 포스트가 업로드 된다.
  • TIL
    • 포스팅 박스 열고 닫기
      function openClose() {
        // id 값 post-box의 display 값이 block 이면
        if ($('#posting-box').css('display') === 'block') {
            // post-box를 가리고
            $('#posting-box').hide();
        } else {
            // 아니면 post-box를 보여주기
            $('#posting-box').show();
        }
      }
      
    • 여행장소
      여행장소 검색하는 것과 검색한 것을 위도, 경도로 바뀌게 하는 작업을 했었다. 여행장소를 검색하면 상단 지도에서 위치가 옮겨지고 위도, 경도가 입력된다.
        function initMap() {
          map = new google.maps.Map(document.getElementById("map"), {
              center: {lat: 37.5642135, lng: 127.0016985},
              zoom: 8,
          });
      
      
          let geocoder = new google.maps.Geocoder();
      
          document.getElementById('geo-submit').addEventListener('click', function () {
      
              // 여기서 실행
              geocodeAddress(geocoder, map);
          });
      
          /**
           * geocodeAddress
          *
          * 입력한 주소로 맵의 좌표를 바꾼다.
          */
          function geocodeAddress(geocoder, resultMap) {
      
              // 주소 설정
              let address = document.getElementById("post-trip-place").value;
      
              /**
               * 입력받은 주소로 좌표에 맵 마커를 찍는다.
              * 1번째 파라미터 : 주소 등 여러가지.
              *      ㄴ 참고 : https://developers.google.com/maps/documentation/javascript/geocoding#GeocodingRequests
              *
              * 2번째 파라미터의 함수
              *      ㄴ result : 결과값
              *      ㄴ status : 상태. OK가 나오면 정상.
              */
              geocoder.geocode({'address': address}, function (result, status) {
      
                  if (status === 'OK') {
                      // 맵의 중심 좌표를 설정한다.
                      resultMap.setCenter(result[0].geometry.location);
                      // 맵의 확대 정도를 설정한다.
                      resultMap.setZoom(18);
                      // 맵 마커
                      let marker = new google.maps.Marker({
                          map: resultMap,
                          position: result[0].geometry.location
                      });
      
                      tot.location = {lat: marker.getPosition().lat(), lng: marker.getPosition().lng()}
      
                      $('#post-trip-location').val(tot.location.lat + '/' + tot.location.lng);
                      // // 위도
                      // latitude = marker.position.lat();
                      // // 경도
                      // longitude = marker.position.lng();
                  } else {
                      alert('지오코드가 다음의 이유로 성공하지 못했습니다 : ' + status);
                  }
              });
          }
        }
      
    • 사진 업로드
      파일 선택 버튼을 클릭하면 본인 파일에서 원하는 사진을 선택하여 업로드 할 수 있다. 처음하는 작업이라 엄청나게 서칭한 끝에 성공할 수 있었다… 너무 어려웠다..ㅜ
        function uploadImage() {
        let images = $('#post-img')[0].files[0]
        if (images === undefined) {
            alert('이미지를 선택해주세요.')
            return
        }
      
        let formData = new FormData();
        formData.append("images", images)
      
        $.ajax({
            type: "POST",
            url: "/image",
            processData: false,
            contentType: false,
            data: formData,
            success: function (res) {
                if (res['result'] === 'success') {
                    img_path = res['img_path']
                    alert('사진 업로드 성공!')
                    console.log(img_path);
                } else {
                    alert('사진 업로드 실패!')
                    console.error(res['error'])
                }
            }
        })
      }
      
    • 포스팅 하기
      저장 버튼 클릭시 포스팅이 완료 된다! 백엔드는 완전 처음이었기 때문에 다양한 데이터들을 데이터베이스로 넘기고 빼와서 포스트 보이게 하기 쉽지 않았다.
        function postArticle() {
          const writer = $("#post-writer").val();
          const date = $("#post-trip-date").val();
          const place = $("#post-trip-place").val();
          const content = $("#post-trip-content").val();
      
          // POST 방식으로 카드 생성 요청하기
          $.ajax({
              type: "POST", // POST 방식으로 요청하겠다.
              url: "/trip", // /memo라는 url에 요청하겠다.
              data: {
                  writer_give: writer,
                  date_give: date,
                  place_give: place,
                  lat_give: tot.location.lat,
                  lng_give: tot.location.lng,
                  img_give: img_path,
                  content_give: content
              }, // 데이터를 주는 방법
              success: function (response) { // 성공하면
                  if (response["result"] === "success") {
                      alert("포스팅 성공!");
                      // 3. 성공 시 페이지 새로고침하기
                      window.location.reload();
                  } else {
                      alert("서버 오류!");
                  }
              }
          })
        }
      

카드

카드

포스팅 버튼에서 저장을 누른 후 해당 카드 모양으로 게시된다.

  • 기능
    최상단에 작성자 이름이 나오고 그 이후로 업로드한 사진, 여행날짜, 여행 장소, 내용이 나온다.
    카드에 margin을 주었으며, 웹 사이즈에 따라 카드가 초과되면 다음 줄로 내려가게 flex-wrap: wrap설정을 하였다.
  • TIL
    • JavaScript
      
      function makeCard(writer, img, date, place, content) {
          const tempHtml = `<div class="cards-box">
                            <div class="card">
                              <span class="card-writer">Writer ${writer}</span>
                              <img class="card-img" src="${img}">
                              <span class="card-trip-date">여행 날짜: ${date}</span>
                              <span class="card-trip-place">여행 장소: ${place}</span>
                              <span class="card-trip-content">${content}</span>
                            </div>
                          </div>`;
          $("#card-bundle").append(tempHtml);
      }
      
      function getImage() {
        $.ajax({
            type: 'GET',
            url: '/trip',
            success: function (res) {
                let images = res['images']
                for (let i = 0; i < images.length; i++) {
                    let image = images[i]
                    console.log(image)
                    let temp = `<img src="${image}" alt="image${i}">`
                    $('.card-img').append(temp)
                }
            }
        })
      } 
      
    • Django
        @app.route('/trip', methods=['POST'])
        def post_article():
          # 클라이언트로부터 데이터를 받기
          writer_receive = request.form['writer_give']
          date_receive = request.form['date_give']
          place_receive = request.form['place_give']
          lat_receive = request.form['lat_give']
          lng_receive = request.form['lng_give']
          img_receive = request.form['img_give']
          content_receive = request.form['content_give']
      
          article = {'writer': writer_receive, 'date': date_receive, 'place': place_receive,
                    'lat': lat_receive, 'lng': lng_receive, 'img': img_receive, 'content': content_receive}
      
          #  mongoDB에 데이터를 넣기
          db.trip.insert_one(article)
          # 성공 여부 & 성공 메시지 반환하기
          return jsonify({'result': 'success'})
      


글 작성을 마치며


굉장히 오랜만에 만들었던 파일을 보면서 기억이 새록새록 떠오른다. 당시에 백엔드 너무 어려웠어서 정말 힘들고 고통받았던… 기억이 있는데. 지금 와서 다시 보니 그래도 그간 참고 열심히 하길 잘했다는 생각이 든다.
처음 배우면서 프로젝트를 진행해서 너무 복잡하고 어떤 순서로 해야 할 지 감이 안 잡혔었는데, 지금 다시 보니 뭔가 좀 알겠는 느낌? (이 프로젝트를 만들 던 당시보다는 머리에 든게 많아져서 그런가 보다. 뿌듯-)
지금 이 글의 내용은 거의 자바스크립트 위주로 작성했지만 Django를 하면서도 새롭게 안 것도 많다. 근데, 이걸 다 넣고 그러기엔 좀 애매하달까…? 그래서 마지막 카드 부분에만 작성하였다.
내가 앞으로 백엔드를 할 일이 있을 지는 모르겠지만, 이 프로젝트 경험 덕분에 백엔드는 어떻게 돌아가는지 이해가 많이 되었다. 역시 글로 읽었을 때와 직접 경험했을 때는 매우 다르달까.
나중에 기회가 된다면, 해당 프로젝트를 참고하여 백엔드를 해보는 걸로! TOT 프로젝트 글 작성 끝!

Comments