/daejeonplace

인스타그램 기반 지역 트렌드 지도 웹/앱 (BE)

Primary LanguageJavaScript

대전 위치기반 서비스(BE)

Table of Contents

📽️ 상세 프로필

Github 프로젝트


HyunAm0225/daejeonplace

필수 평가 요소


  • CI/CD 전략 수립 여부

    None

  • Mircroservice 아키텍처 설계 여부

    %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled.png

    1. 프론트는 리액트를 이용했습니다.
    2. 백엔드로는 장고에서 지원하는 Django REST Framework를 사용했습니다. DRF의 장점은 파이썬으로 RESTful API를 쉽게 구현 할 수 있고 어드민 페이지를 이용할 수 있어서 선택하게 되었습니다 또한 크롤링을 하기 편해서 백엔드로 선택하게 되었습니다.
    3. 데이터베이스는 RDS종류 중 하나인 PostgreSQL을 선택했습니다.
  • 대용량 트래픽 핸들링 여부

    ec2 인스턴스 :

  • 특정 아키텍처 사용 여부 (Spring MVC, Serverless 등)

    None

  • 특정 기능 구현 (결제 기능, 로그인/로그아웃 기능, 실시간 채팅 기능 등..)

    관련 commit

    • 세션 관리 → JWT 활용

      <login을 할때 JWT를 사용한이유>

      • 간편합니다. 세션/쿠키는 별도의 저장소의 관리가 필요합니다. 그러나 JWT는 발급한 후 검증만 하면 되기 때문에 추가 저장소가 필요 없습니다. 이는 Stateless 한 서버를 만드는 입장에서는 큰 강점입니다. 여기서 Stateless는 어떠한 별도의 저장소도 사용하지 않는, 즉 상태를 저장하지 않는 것을 의미합니다. 이는 서버를 확장하거나 유지, 보수하는데 유리합니다.
  • 특정 기술 숙련도 (지도 기술, 추천 기술, AI 등)

    카카오 맵 API 적용 commit

    # post/serializer.py
    
    def address_to_latlon(place, addr):
        url = 'https://dapi.kakao.com/v2/local/search/keyword.json?query={}'.format(
            place)
        headers = {
            "Authorization": f"KakaoAK {KAKAO_KEY}"
        }
        no_val = {}
        try:
            result = requests.get(url, headers=headers).json()['documents'][0]
            val = [result['address_name'], result['y'], result['x']]
        except:
            no_val['address_name'] = addr
            url = 'https://dapi.kakao.com/v2/local/search/keyword.json?query={}'.format(
                addr)
            result = requests.get(url, headers=headers).json()['documents'][0]
            val = [no_val['address_name'], result['y'], result['x']]
        return val
  • 특정 데이터 숙련도 (지도 데이터, 스트림 데이터 등)

    지도 데이터 활용 commit (위와 동일한 commit)

    # post/serializer.py
    
    def address_to_latlon(place, addr):
        url = 'https://dapi.kakao.com/v2/local/search/keyword.json?query={}'.format(
            place)
        headers = {
            "Authorization": f"KakaoAK {KAKAO_KEY}"
        }
        no_val = {}
        try:
            result = requests.get(url, headers=headers).json()['documents'][0]
            val = [result['address_name'], result['y'], result['x']]
        except:
            no_val['address_name'] = addr
            url = 'https://dapi.kakao.com/v2/local/search/keyword.json?query={}'.format(
                addr)
            result = requests.get(url, headers=headers).json()['documents'][0]
            val = [no_val['address_name'], result['y'], result['x']]
        return val
  • 데이터 모델링

    %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/9.png

추가 평가 요소


  • 기능 별 구현 전략

    1번 기능


    • 해당 서비스의 특성을 고려한 DB 선택 및 확장성 고려 :

      장고에서는 먼저 Nosql을 이용하지 않습니다. 또한 현재 사용하는 프로젝트에서 대용량의 데이터를 필요로 하지 않고 외래키 관계를 표현 해야해서 RDBMS를 사용했습니다.

      Php에서는 Mysql을 많이 쓰지만 Django에서는 Postgresql을 많이 쓴다고 합니다. 또한 초기 설정에 있어서도 Postgresql이 더편해서 Postgresql을 사용했고 또 외부 서버를 사용하기 위해서 Aws에 있는 RDBMS를 이용해 postgresql를 사용했습니다.

    • Map 또는 GPS API 를 다뤄 본 적이 있는지. Map data 등 용량이 적지 않은 데이터를 불러오고 처리하는데 Latency 문제에 대한 해결책이 있는지

      <PostGIS?>

      Postgresql을 사용하면 PostGIS라는 맵데이터를 이용하기 쉽게 사용할 수 있는 기능이 있다는것을 조사하면서 처음 알게 되었습니다.

      링크 : https://docs.djangoproject.com/en/3.1/ref/contrib/gis/install/postgis/

      하지만 저는 익숙한 kakaomap API를 이용해서 주소명으로 다양한 정보들을 얻을 수 있게 사용하였습니다.

    2번 기능


    • 추천 알고리즘을 적용 해봤던 도메인이 무엇이 있고, 어떤 특성들에 중점을 두었는지

      <관련 API vs 좌표값을 이용한 설정하기>

      여기서는 현재 자신의 위치를 API로 받아들인다음 그 좌표를 이용하여 주변 500m정도의 거리를 통한 주변에 있는 인싸 플레이스 기능 구현을 하거나 카카오 맵에 있는 기능을 통해 구현하려했는데.. 백엔드 구현이 많이 늦어지고 수정하는 부분이 많아져서 기능구현을 아직 완벽하게 하지 못했습니다..

    3번 기능


    • 크롤링 기능의 multi-thread 사용 여부 :

      <고민 내용>

      지금 웹에서가 아닌 그냥 로컬에서 python 크롤링을 통해 기능 구현을 위한 구상을 하고 어떤 장소들을 필터링 할지 고민중에 있습니다.

      또한 aws람다와 api gateway를 통해 장소들을 자동으로 데이터 베이스에 넣어줄지 파이썬 셀레니움으로 크롤링 값을 가져와서 django내에서 처리할지 고민했는데 생각보다 일반적으로 파이썬으로 처리하는 것 보다 웹이랑 결합하려니 많은 어려움을 겪고 있어서 현재 기능 구현으로 넣지 못했습니다.

      <로컬에서 파이썬으로만 예시 구현>

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%201.png

      #대전을 입력할 시 #대전,#부산,#서울,#제주 이런 식으로 태그를 해서 조회수를 올리려는 사람이 너무 많아서 #대전맛집을 우선으로 해서 검색을 하였습니다.

      이런 식으로 해도 location을 보면 대전이 아닌 장소가 여러가지 나와서 #대전맛집, #대전, #대전핫플 이런 식으로 3가지 해쉬태그를 통해 종류별 2550개 정도 장소를 받아 들여서 count를 통해 상위 35개 정도의 데이터들을 가져오도록 개선 해야하고 멀티 프로세싱을 통해 빠르게 처리 해야할 것 같습니다.

  • 개발 전략

    • 1단계에서 별점을 숫자로 입력받아서 구현할지 or 별같은것을 이용한 API이용할지?
    • 1단계에서 기존에 있는 장소에 대한 위치 표시 및 별점 리뷰 + 만약 지도에 등록 되지 않은 꿀잼 도시를 직접 등록 해서 다른사람도 볼 수 있게 표시하기
    • 2단계에서 주변 위치 검색은 다음 map API를 통해 확인할수 있나 보고 만약 가능하면 쉽게 걸어갈 수 있는 거라 500m~1000m 범위 안에 있는 장소 표시?
    • #대전 태그 기반 자동추가는 해쉬태그안에 있는 장소를 찾아서 할지 아니면 인스타그램에서 어디 에있는 장소를 크롤링하여 그 장소를 보여줄지 생각해보기
    • 수익 모델 위치 기반 광고는 좀 더 생각해보기..
    • 수익 모델을 위한 광고 위치는 지도 오른쪽 하단에 위치

    다음과 같은 유저 플로우를 고려했습니다.

    %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%202.png

    1. 먼저 로그인 페이지에서 로그인을 해야 노잼 대전 페이지에 로그인을 해서 메인페이지를 볼 수 있습니다.
    2. 만약 로그인을 하려는데 아이디가 없으면 일반회원가입 or 소셜 회원가입을 가능하게 해 두었습니다.
    3. 회원가입을 한 후 메인 페이지에 들어가면 해시태그 기반 장소추가, 장소 검색, 현위치 기반 장소 추천 기능이 있습니다.
    4. 만약 검색 기능을 통해 장소가 나오면 별점, 한줄평으로 그 장소에 대한 평가를 할 수 있습니다.
    5. 만약 검색 기능을 통해 장소가 없으면 장소명 입력, 별점/한줄평 입력, 작성자 자동 입력을통해 장소를 등록 시킬 수 있습니다.
  • 배포 전략

    Nginx + uwsgi + django로 구성된 것을 EC2를 통해 배포하였습니다.

    Nginx + uWSGI를 사용한 이유


    먼저 Nginx를 이용하면 장점은 다음과 같습니다.

    • 도메인 라우팅을 관리합니다(리버스 프록시)
    • 정적 파일 제공
    • 한 번에 들어오는 많은 요청을 처리
    • 느린 클라이언트 처리
    • 동적 요청을 wsgi에 전달
    • SSL(https)
    • Python 코드와 비교하여 컴퓨팅 리소스(CPU 및 메모리) 절약
    • 로드 밸런싱, 캐싱 등

    wsgi를 사용한 이유

    • 작업자 프로세스/스레드 풀 실행(코드실행)
    • Nginx에 들어오는 요청을 WSGI와 호환되도록 번역
    • 앱의 WSGI 응답을 적절한 http 응답으로 변환
    • 요청이 들어오면 실제로 파이썬 코드를 호출합니다.

    또한 wsgi를 이용할 시 runserver를 이용할 때 보다 유저가 요청하는 요청이 많아도 견딜수 있다는 점이 있습니다.

    마지막으로 컴퓨팅을 aws에 있는 컴퓨팅 시스템인 ec2를 이용한 이유는

    • 탄력적인 웹 규모 컴퓨팅 Auto Scailing을 통한 자동 확장 및 축소
    • 완전 제어 CLI 제공버
    • 유연한 클라우드 호스팅 서비스 다양한 OS 서버
    • 통합 Storage, RDS, VCP 등과 통합 가능
    • 안정성
    • 보안

    또한 저의 데이터 베이스가 RDS에 있는 Postgresql로 구현했기 때문입니다. 그리고 비용면에서도 aws가 개인적으로는 괜찮고 많이 사용한 클라우드 이기 때문에 사용하였습니다.

  • 기능 별 추가 설명

    • 회원가입 기능

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%203.png

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%204.png

    • JWT Token을 이용한 로그인 기능

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%205.png

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%206.png

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%205.png

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%206.png

    • Token을 이용해 유저정보 잘 받아오는지 확인하기

      현재 접속 유저 확인하기

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%207.png

      현재 유저 비밀번호 바꾸기

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%208.png

    • 장소 추가 기능

      만약 장소가 기존 daum 지도에 있는 경우

      이런식으로 입력하면 주소와 위도, 경도가 자동적으로 입력되는 것을 확인할 수 있습니다.

      <입력하기>

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%209.png

      <post 한 값>

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%2010.png

      <admin에서 본 데이터>

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%2011.png

      만약 지도에 데이터가 없는 경우

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%2012.png

      %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%2013.png

  • 깃 사용 전략

    원래는 기능별 branch를 새로 파서 깃허브를 진행해야 하지만.. 혼자 진행하고 일단은 아직 merge와 깃의 흐름을 잘 몰라서 그냥 커밋하는 내용에 기능별 번호를 추가해서 프로젝트를 진행하였습니다.

    %E1%84%83%E1%85%A2%E1%84%8C%E1%85%A5%E1%86%AB%20%E1%84%8B%E1%85%B1%E1%84%8E%E1%85%B5%E1%84%80%E1%85%B5%E1%84%87%E1%85%A1%E1%86%AB%20%E1%84%89%E1%85%A5%E1%84%87%E1%85%B5%E1%84%89%E1%85%B3(BE)%206194ac77e8f347598c24eb51e35d93d8/Untitled%2014.png

문제 해결 경험


  • EC2 uwsgi-nginx 배포 과정

    1. uwsgi 설치 오류

    2. uwsgi 실행오류

      • 경로들이 다 ~/myproject....이런 형식으로 되어 있어서
      • 경로를 /home/ubuntu/myproject 이런 형식으로 바꾸니 해결되었습니다.
    3. ec2에서 django 배포는 성공했지만 css파일들이 보이지 않는 경우

    4. 소스코드를 수정해서 runserver한 페이지와 ec2상에서 배포된 도메인에서의 페이지가 서로 다르다.

      • 찾아보니 이것은 nginx와 uwsgi를 다시 껐다 키지 않았기 때문에 발생한 문제라고 합니다.
      • 아래의 명령어를 통해 다시 껐다 켜준 후 도메인을 통해 접속해보겠습니다.
      sudo systemctl daemon-reload
      sudo systemctl restart uwsgi nginx
  • 배포된 ec2가 변경 내용 반영 못할 때

    문제 상황 :

    • 소스코드를 수정해서 runserver한 페이지와 ec2상에서 배포된 도메인에서의 페이지가 서로 다르다

    이슈 해결 방법 :

    • 찾아보니 이것은 nginx와 uwsgi를 다시 껐다 키지 않았기 때문에 발생한 문제라고 합니다.

    • 아래의 명령어를 통해 다시 껐다 켜 준 후 도메인을 통해 접속 해보겠습니다.

      sudo systemctl daemon-reload
      sudo systemctl restart uwsgi nginx