지난 2주간 카카오VX의 골프 관련 굿즈를 판매하는 사이트, 카카오 프렌즈 골프를 클로닝해보았다.
클론 프로젝트는 2주간 진행되었고, 프론트엔드 4명, 백엔드 2명으로 이루어진 팀이 함께 합을 맞추었다.
나는 백엔드 파트를 맡았으며, 모델링부터 장바구니 기능 구현까지 Django와 함께 보낸 흥미로운 2주를 여기 정리해보고자 한다.
사실 클론 프로젝트 타겟을 고를 때, 백엔드의 입장에서 후보군을 살펴보니 그리 튀는 선택지가 존재하지는 않았다. 실시간으로 DB 업데이트가 많이 일어나야 하는 어렵거나 구현하기 힘든 기능들 있는 사이트는 처음부터 제외해서 그랬던거 같다.
그럼에도 불구하고 카카오 프렌즈 골프는 흥미로운 클론 타겟이다. 아래는 내가 느낀 카카오프렌즈 골프 사이트가 가진 특징이다.
제품의 캐릭터별 분류가 중요하게 작용하는 쇼핑몰이다.
기성 골프 제품을 판매한다기 보다는 카카오 프렌즈 캐릭터가 들어간 굿즈를 판매하는 쇼핑몰이 이 쇼핑몰의 아이덴티티이다.
그만큼 각 제품에 특정 캐릭터가 반드시 들어가있으며 캐릭터별 분류와 유저의 특정 캐릭터 선호도에 따른 추천이 무척 중요해보였다.
이를 방증하듯, 회원가입시에 선호하는 프렌즈 캐릭터도 선택해야 한다.
쇼핑몰에 블로그와 프로모션 페이지가 따로 달려있다.
메인페이지와 동떨어진 다른 카테고리로 골프 제품에 대한 블로그와 이벤트 프로모션 페이지가 따로 달려있었다. 우리팀의 목적은 쇼핑몰 기능의 구현이었기에 이부분은 클론 타겟에서 제외하기로 했다.
카카오 쇼핑몰에 보이는 데이터를 기반으로 구현에 필요한 DB 테이블을 모델링 하고 그것들 간의 관계를 생각했다.
모델링 한 결과 테이블이 유저에 대한 부분 / 상품에 대한 부분 / 주문에 대한 부분으로 크게 세 갈래로 나뉘었다.
가장 중요한 세 가지 테이블만 소개해보자면,
유저 테이블은 기본적으로 유저에 대한 정보를 담고 있으며, 유저가 선호하는 캐릭터를 담을 수 있게 캐릭터 테이블과 연결된다.
가장 중요한 상품 테이블은 상품 기본 정보 / 가격 / 할인이나 이벤트 여부 / 연계된 캐릭터 / 매진 / 할인율과 같은 정보를 모두 포함한다.
우리는 서브카테고리를 상품에 달고, 서브카테고리 테이블이 또 메인 카테고리 테이블을 가리키게 모델링 했는데, 이 부분 때문에 나중에 View 로직을 짤 때 조금 힘이 들었다.
주문 관련 모델링을 하는 부분이 사실 가장 고민을 많이 하게 만들었다.
처음에 장바구니와 주문 관련 데이터를 어떤 식으로 구성해야 할 지 감이 안와서 시간을 많이 쓰다가, 결국 위의 사진처럼 세 테이블로 나누고 그들간의 관계를 설정해 두었다.
위와 같이 나누어 관리해주면 주문의 상태 변경 - 주문 자체의 정보 변경 - 주문의 추가 및 삭제를 독립적으로 수행할 수 있어 효율적이다.
본격적으로 View 로직을 구현하기 전에 우리가 구현할 API의 전체적인 구조를 설계하였다.
위의 DB 모델을 크게 세 부분으로 나누었듯, API 엔드포인트도 세 부분으로 나누어 진행하기로 했고, 최대한 Restful하게 설계하려 노력했다.
너무 미리 세세하게 설계하기 보다는 커다란 필요 기능과 관련 HTTP 메서드로 각 엔드포인트를 정의했다.
<id>
<id>
장바구니 API는 설계할때 특히 고민을 많이 했는데 그 이유는 다음과 같다.
결과적으로 아래와 같은 상태 관리 로직을 염두해 두고 API 구조를 짠 후 View 로직을 작성하기 시작했다.
위에서 Aquery Tool을 통해 설계한 테이블을 Django를 통해 구현한 후에는 각 API에 해당하는 View 로직과 각각 필요한 헬퍼 함수 또는 데코레이터를 작성했다.
여기에서는 전체 코드 중 기억에 남는 코드를 소개해보고자 한다.
ProductListView와 ProductDetailView를 동료와 함께 작성하다보니, 공통적으로 각 상품의 상세 정보를 연계된 여러 테이블에서 긁어와 예쁜 딕셔너리 형태로 변환해 줄 일이 잦다는 것을 알게 되었다.
하지만 경우에 따라 다른 키가 필요할 때가 있었고, 또, User가 존재할 경우 추가적인 키 값을 넣어 줄 때가 있었다.
각 경우에 일반적으로 대응 가능한 메서드를 만들기 위해 제외할 키 값을 exclude에 리스트 형태로 받고, 유저 정보가 있다면 받아서 처리 가능한 메서드를 위와 같이 구현했다.
이 데코레이터는 View 클래스의 메서드에 붙여서 request 헤더에 token이 존재하는지 검사해준다.
더불어, 토큰 유효성과 유저 유효성에 대한 예외 검사까지 데코레이터와 함께 처리할 수 있어 메인 코드가 매우 깔끔해질 수 있어서 좋았다.
참고로 일반 데코레이터와는 달리 세 겹으로 함수가 싸여있는데, 이는 클래스 메서드에 붙이기 위해 아래와 같이 django의 method_decorator
와 함께 쓰기 위함이다.
이 부분은 일반적으로 Django 모델에서 중복되면 안되는 unique
속성을 갖는 필드의 중복성을 자동으로 검사해주는 함수를 구현한 것이다. (오버엔지니어링이고 가독성이 똥망이라는 평을 받긴 했지만) 나름 Django 모델의 하부 메서드를 뒤져가면서 만들어낸 기능이라 빼고 싶지 않아 고집부리며 머지시켰다.
이 함수는 어떤 모델과 데이터를 받아, 모델에서 중복될 수 없는 unique 필드를 자동으로 찾아낸 후, 이러한 비 중복 필드의 값이 DB에 존재하는지 검사하고, 만약 존재한다면 예외를 발생시킨다.
이와같이 Django 모델 클래스의 _meta
밑으로 들어가면 생각보다 일반적으로 많이 쓸 수 있는 메서드와 기능이 많아 흥미로웠다.
프로젝트 동안 팀은 애자일의 스크럼 개발방법론을 따라 개발을 진행했다.
따라서 매 주 시작일에 함께 Backlog를 작성하며 한 Sprint 내에서 해결할 목록을 작성했다.
또, 매일 아침에 Scrum meeting을 가지며 진행 상황을 서로 추적하고 Blocker를 확인하며 우선순위를 조절했다.
나는 개인적으로 구현되는 API를 최대한 상세하게 문서화해서 FE 팀원들에게 제공하고 실시간으로 업데이트해 FE 개발을 돕고자 하는 작은 목표가 있었다.
이를 위해 두 가지를 실천했다.
Postman에 무료 Team을 개설하고 (3명까지 무료) 툴을 가지고 백엔드 팀원과 함께 같은 API 문서를 함께 작성할 수 있었다. 또, 퍼블리싱 툴을 통해 체계화된 API 문서를 아주 쉽게 만들어 낼 수 있었다.
문서화된 API는 옆에 쿼리 예시까지 둘 수 있어서 특정 경우에 어떤 API 에러가 전달되고, 또 어떤 방식으로 API를 써야 하는지 FE에게 그나마 쉽게 전달해 줄 수 있었다. (하지만 이 툴이 실제로 프론트 동료들에게 충실히 도움이 되었는지는 잘 모르겠다. 내 생각엔 팀 내에서의 툴 공유는 툴에 대한 교육이 선행되어야 하는 것 같다.)
아무래도 백엔드와 프론트엔드가 같은 시작점에서 함께 개발되다보니, FE는 백엔드 엔드포인트가 메인에 머지되거나 할 때까지 기다리면서 목업데이터를 만들어 써야 하는 불편함이 있었다.
이를 조금이라도 해소해주고자 나는 dev
브랜치를 따로 파서 merge를 기다리는 PR을 미리 merge 시키고 이를 AWS Light Sail에 미리 호스팅해 개발 API 서버를 팀원들에게 따로 제공했다.
이 부분은 유효하게 FE팀원들에게 도움이 되었던 것 같아 돌아보니 기쁘다.
또, dev
브랜치를 유지 관리 한 점은 나의 git 사용 능력을 많이 향상시켜 주었고, 새로운 기능 개발 시 PR을 넣기 전에 미리 테스트를 하고 PR을 넣어 리뷰어의 번거로움을 조금 줄여줄 수 있는 것 같아 다음에도 이 방법을 쓰고자 한다.
프로젝트 진행하면서 내가 만난 가장 큰 Blocker는 아무래도 저작권과 데이터에 대한 부분이었다.
클론 프로젝트이고, 아무래도 캐릭터 특화 굿즈 판매 쇼핑몰이라는 특성을 살리고자 하니, 카카오 프렌즈 캐릭터 자체의 저작권은 물론이고 그것이 붙어있는 굿즈마저 클론 사이트에 가져오지 못하는 엄청난 벽이 있었다.
그렇다고 아무 사진이나 들고 붙이자니, 성에 차지 않았다.
우리는 그래서 일단 저작권이 없는 최대한 귀여원 캐릭터를 골라와, 목업 이미지 생성을 도와주는 사이트에서 캐릭터가 붙은 상품을 최대한 많이 만들었다.
또, Python의 Faker 라이브러리를 통해 Fake 유저와 제품 이름 및 특성을 생성하였다.
이를 csv 파일로 저장하고 다시 DB에 Populate 시키는 코드를 만들어 빠르게 목업 데이터 변화를 실제 DB에 적용할 수 있게 했다.
FE와의 소통에서 나는 API 문서를 만드는데 시간을 많이 썼지만, 그 효용은 그렇게 높지 않았다.
나는 앞으로 팀 내 문서화에 신경 쓰는 만큼 그것을 설명하는 시간 또한 그만큼 할당해야만 문서가 빛을 발한다는것을 배웠다.
처음으로 타인과 함께 개발 협업을 진행한 2주간 코드 자체를 떠나 배운 것들은 정말 값진 것들이 많았다.
Git을 통한 협업은 사실 그렇게 어렵지 않다. 제대로 알고 쓰는 git 명령어는 두려운 것이 아니라 너무나 효과적이고 재밌는 것이다.
개발은 키보드로만 하는 것이 아니다. 설명하고 이해하고 이해시키는 부분이 최소 30% 이상은 차지한다. 개발자는 오히려 사회적이고 남이 모르는 부분을 잘 캐치하고, 또 내가 모르는 부분을 잘 질문할 수 있는 능력을 가져야만 수행할 수 있는 직업이다.
개발자 간의 소통은 감정을 배제하고 로직에 충실할 때 빛이 난다. 서로간에 합당한 근거 제시와 수긍이 있다면 어떤 Blocker도 함께 넘어갈 수 있다.
저작권 때문에 진짜 고생 많으셨어요 🥲 해결 방법 듣고 대단하다 생각했었는데
최종 발표 때 사이트 보고 👍👍👍 역시 갓준식 짱짱! 남은 2차도 화이팅입니당!!