/ PROJECT, 디어코퍼레이션, WECODE, WANTED

백엔드 프리온보딩 3주차 두번째 프로젝트 회고


원티드 3주차 디어코퍼레이션 기업과제


진행기간

21.11.18 ~ 21.11.21


구현해야 하는 기능

  • 유저 Auth

    • 회원가입 API
    • 로그인 API
    • 할인 / 벌금 CRUD
  • 할인 조건 추가 API
  • 벌금 조건 추가 API
  • 할인 조건 변경 API
  • 벌금 조건 변경 API

  • 킥보드 대여 및 반납
    • 킥보드 대여 API
    • 킥보드 반납 요금 정책에 따른 요금 계산 API
  • 위치 정보 CRUD
    • 서비스 지역 생성 API
    • 지역에 추가되는 할인 / 벌금 추가 API
    • 지역에 추가되는 할인 / 벌금 삭제 API

나의 역할

  • 할인/벌금 추가 API
  • 지역에 추가되는 할인/벌금 추가 API
  • Unit Test 코드 작성
  • README.md 작성
  • EC2 배포

프로젝트 회고

개인적으로 지금까지 진행했던 프로젝트 중에 가장 쉽지 않은 과제였던 것 같다. 서비스 지역마다 할인/벌금/주차구역 등 적용해야 하는 조건이 달랐기 때문에 어떻게 이 조건들을 지역에 맞게 적용시켜야 하는지 처음에는 감도 잘 오지 않았다. 과제가 주어지고 이후 팀원들과 가장 오랜시간동안 회의를 진행했었다.

다행히 과제 기한이 다른 과제보다는 길었기 때문에 시간적 압박은 덜했다. :-) 첫번째 회의에서는 지역의 위도와 경도는 어떻게 얻을것인가, 모델링 설계는 어떻게 진행해야 하는가 이 2가지를 중심으로 진행했다. 다행히 모델링 설계는 과제 조건에 기본적으로 나와 있어서 이를 토대로 설계를 진행했다.

사용자가 이용하는 킥보드 모델, 킥보드 모델, 서비스 지역 모델, 피킹존 모델, 반납금지 구역 모델이 기본적으로 나와있었기 때문에 아래를 토대로 모델링 설계를 진행했다.

[모델링 설계]

  • 킥보드가 사용 될 때마다 usages 즉 킥보드 사용 내역에 정보가 저장된다 (1:N 관계)
  • 킥보드는 여러 서비스 지역에서 사용된다 (1:N관계)
> vehicle 모델 (사용자가 이용하는 킥보드 모델)

deer_name (킥보드의 이름으로 고유한 값)
deer_area_id (킥보드가 현재 위치한 지역의 아이디)


  • 한명의 유저는 여러 킥보드 사용내역을 가질 수 있다(1:N관계)
> usages 모델 (사용자 킥보드 사용 내역 모델)   

use_deer_name (사용자가 이용한 킥보드의 이름)
use_end_lat, use_end_lng (사용자가 이용을 종료할 때 위도 경도)
use_start_at, use_end_at (사용자가 이용을 시작하고 종료한 시간)


  • 서비스 지역마다 여러 할인/벌금 조건이 추가/수정된다 (1:N관계)
  • 서비스 지역마다 여러 주차지역/반남금지 구역이 존재한다 (1:N관계)
> service_area모델(서비스 지역 모델)   

area_id (지역 아이디로 고유한 값)
area_bounday (지역을 표시하는 MySQL spatial data로 POLYGON)
area_center (지역의 중심점)
area_coords (지역의 경계를 표시하는 위도, 경도로 이루어진 점의 리스트)
> parking_areas(주차 지역 모델)

parkingzone_id (파킹존 아이디로 고유한 값)
parkingzone_center_lat, parkingzone_center_lng (파킹존 중심 위도, 경도)
parkingzone_radius (파킹존의 반지름)
> forbidden_areas(반납 금지 구역 모델)

forbidden_area_id (반납금지구역 아이디로 고유한 값)
forbidden_area_boundary (반납금지구역을 표시하는 MySQL spatial data로 POLYGON)
forbidden_area_coords (반납금지구역의 경계를 표시하는 위도, 경도로 이루어진 점의 리스트)


팀원들과 회의를 하며 추가한 모델은 아래와 같았다.

  • user 모델
    유저의 정보가 저장되어야 해당 유저에게 벌금/할인을 부과하고 해당 킥보드를 어떤 유저가 사용하고 있는지에 대한 정보가 필요했기 때문에 유저 모델을 추가했다

  • roles 모델
    확장성을 고려해 role이라는 모델을 생성했다. 후에 유저를 나이대별로 나누어 사용 금액을 따로 부과할 수 도 있기 때문에 유저에 role을 부과하기 위해 모델을 추가했다

  • types 모델
    할인과 벌금에 대한 조건을 추가하는 모델을 discount_or_penalties라는 모델 하나로 진행하기 위해 할인/벌금에 대한 타입을 부과했다

  • unit 모델
    할인과 벌금이 원이라는 금액으로 추가될 수 있지만 거리에 비례하여 %로 추가할 수 있기 때문에 이를 고려해 unit이라는 모델을 추가했다

  • service_area_discount_or_penalties 모델
    네이밍 짓는게 너무 힘들었다. 최대한 어떤 역할을 하는 모델인지를 추측할 수 있게 길더라도 풀어서 쓰자는 결론이 나왔고 위와 같은 네임이 나오게 되었다.
    여러 서비스 지역마다 여러 할인/벌금 조건이 추가되고 삭제될 수 있기 때문에 M:M의 관계로 구축하게 되었다.

디어erd


[모델링 설계 중 생겼던 문제해결]

모델링 설계가 끝난 뒤 프로젝트의 모델링 초기 세팅을 위해서 작성하는 도중에 PolygonField와 같이 geo 관련 필드에서 에러가 발생했다. 찾아본 결과 geo 관련 (폴리곤, 포인트 등) 필드 사용할 때 django.contrib.gis.db에서 models 임포트하여 사용해야 했다(기존 방식대로 models.Model 임포트하여 사용하면 안된다)

팀원들의 os환경이 우분투와 맥으로 나뉘었었고 우분투 기준으로 아래와 같이 해결했었다

  • 우분투 기준 sudo apt-get install gdal-bin, sudo apt-get install libgdal-dev 명령어 사용install 관련 블로그 참고
  • INSTALLED_APP에 “django.contrib.gis” 추가 후 데이터베이스 ENGINE을 django.contrib.gis.db.backends.mysql로 변경stackoverflow 참고

이후 gdal 문제는 간단하게 conda install gdal 설치로 해결할 수 있다는 것을 알게되었다 :-)


[GDAL 사용]

이 프로젝트에서 가장 큰 관건은 바로 “지역의 위도와 경도는 어떻게 얻을것인가” 였다. 이 부분은 각자 충분히 찾아보고 회의를 진행하기로 하여서 1-2시간의 시간을 가지고 다시 만나 회의를 진행했다. 팀원 중 한명이 지역의 커서를 찍으면 찍은 지역의 필요한 데이터인 POLYGON 정보를 받을 수 있게되었다 !

geojson을 이용하여 GEOSGeometry 객체 저장하기

geojson.io 에서 원하는 지역에 도형(polygon) 및 점(point)을 생성하여 geojson 형식의 파일을 생성하고 unit test에서 geojson 파일을 읽어서 각 feature를 생성하였다.

gdal

두 feature 사이의 거리 계산
haversine 라이브러리를 이용하여 WGS84 좌표계 시스템으로 되어있는 두 좌표간 거리를 계산해 주었고, 지역을 벗어난 킥보드가 해당 지역으로부터 얼마나 떨어져 있는지 계산하기 위해 epsg 5174 좌표로 변환한뒤 킥보드 반납 지점(Point)과 지역(Polygon)의 거리를 계산해 주었다.


진행한 소감

생각해야 할 게 많은 프로젝트였다.. ^^ 기능 구현하는 시간보다 오히려 초반에 더 많이 헤매고 찾아봤던 기억이 난다. polygon이 무슨 역할을 하는지 장고에서 제공되는지도 잘 몰랐기에 polygon을 이해하는데 오랜 시간이 걸렸다. 사실 아직도 조금 헷갈리는 개념이긴 한 것 같다. 다행히 팀원 한분이 커서를 찍으면 이에 맞는 위도, 경도등을 자동으로 계산해서 출력해주는 사이트를 찾게 되어서 다행이 데이터를 세팅 할 수 있었다.

이번 프로젝트는 migrations 파일을 관리하는 팀원을 한명 두어 최대한 마이그레이트 하는 과정에서 문제가 생기지 않게 했다. 화면공유를 통해 다같이 데이터를 세팅하는 과정에 참여했다. 기능구현도 물론 쉽지 않았지만 이번 과제는 초기 모델링 설계 ~ 초기세팅부터 기능 구현후의 데이터 세팅이 더 어려웠던 것 같다. 모델링 설계에 많은 시간을 들여 모든 팀원이 완벽히 이해한 후 진행한게 기능 구현에 가장 큰 도움이 되었다. 진짜 모델링 너무 중요한 것 같다..!

이번 프로젝트는 PR을 적극적으로 활용했던 것 같다 :-) 팀원의 리뷰를 통해 코드가 더욱 나아질 수 있고 다른 방향으로도 생각을 할 수 있게 해주는 시간이였던 것 같아 개인적으로 좋았다(다한증이 생긴건 비밀이다.. ^^)

PR2
PR1