1주차 (8/1 ~ 8/6)
주제 정하기
우리 팀은, 다행히 1주차에 주제를 빠르게 정했다.
1) 카테고리 기준으로 나눠서 검색 결과 보여주기 + 2) 라이프스타일이 비슷한 유저에 기반해 제품 추천 이다.
1) 카테고리에 기준해 검색 결과를 보여주는 방식은 마켓컬리의 원재료나 신선함을 잘 보여줄 수 있고, 경쟁사보다 제품 수가 적음에도 검색 결과를 한 눈에 확인하기 어려운 마켓컬리의 단점을 보완할 수 있을 것이다.
2) 라이프스타일이 비슷한 유저에 기반해 제품 추천은 박리다매, 타겟층 불분명한 타 커머스와 달리 명확하게 라이프스타일에 기준하여 나와 비슷한 사람들이 애용하는 제품을 추천받는다는 느낌이 들어 상대적으로 세련되고 고급화된 이미지의 마켓컬리의 이미지와 맞다고 판단했다.
(그간 광고홍보학과에서 공부도 하고, UX 스터디도 한 효과인지, 기능이나 서비스 개발 시에 기술적 측면 뿐 아니라 마케팅 부분을 살펴서 제안할 수 있게 되었다. 이런 부분이 나중에 프론트엔드 개발자가 돼서 진짜 서비스를 제작할 때 큰 도움이 되어줄 수 있을 것이라 생각했다.)
팀 노션도 만들었다. 이전에 SSAFY에서 노션으로 문서화 작업을 하며 팀 프로젝트를 진행한 경험이 있어서, 템플릿을 만드는 것은 어렵지 않았다.
추천 방식, DB 저장되는 방식 정하기
라이프스타일이 비슷한 유저가 구매한 제품을 추천하는 방식을 구현하기 위해 사용자 협업 필터링을 공부하였다. 그런데 이 때 우리는 한 가지 문제를 발견했다. 마켓컬리는 누적 사용자 수가 천 만 가까이 되는 서비스이고, 지금도 계속해서 가입자가 늘어나는 서비스이다. 그런데 일반적인 유사도 계산 방식을 사용하면, 사용자가 1명 추가될 때, 다른 모든 사용자들의 해당 사용자에 대한 유사도를 계산해서 업데이트를 해야 한다. 이렇게 되면 우리가 만들 데모 프로그램은 물론 마켓컬리 시스템에 부하가 심할 것이라고 생각하게 됐다.
게다가 일반적인 유사도 계산 결과는 행렬로 나오므로, DB에 행렬(Matrix) 형태로 저장해야 하는데 이 행렬을 관계형 DB에 저장하는 방식이 상당히 애매하다! 우리는 게다가 파이썬이나 R이 아니라 서버로 자바 기반의 Spring을 사용하는 중이여서, pandas를 이용해 DataFrame을 만들거나 하는 것처럼 행렬 데이터 저장이 어려웠다. 그래서 이걸 어떻게 해야할 지 잘 모르는 난항 상태였다.
여기저기서 묻고, 검색하면서 우리가 찾은 해결안 후보는 다음과 같았다.
1. Matrix 형태를 관계형 DB에 저장할 때 'key-value' 형태로 DB에 저장한다. (참고: https://sunshout.tistory.com/1318)
Matrix를 Key, Value 쌍으로 저장하는 방법
Matrix는 테이블 형식의 데이터를 저장하는 효율적인 방법이다. 하지만 <예1>과 같은 sparse matrix를 N*N 테이블에 넣으면 메모리 손실이 너무 많다. n1 n2 n3 ... n100,000 n1 1 1 n2 n3 1 1 ....
sunshout.tistory.com
이 방식의 경우, 새로 사용자가 추가될 때마다, 모든 사용자에 대한 레코드가 업데이트가 돼야 하기 때문에 시스템 부하 문제를 해결할 수 없었다.
2. 문항 그 자체를 열(column)으로 두어 1번부터 마지막 수까지 자신과 같은 문항에 같은 답을 한 개수가 가장 비슷한 사람을 찾는다.
장점: 이렇게 하면 새롭게 사용자가 추가됐을 때, 모든 사용자들의 유사도를 다시 구할 필요는 없이 겹치는 개수만 구해주면 된다.
단점: 각각의 사용자가 다른 사용자에 대한 모든 겹치는 개수를 저장해야 하므로 (EX. 재석 : 명수와 겹치는 개수 0, 하하와 겹치는 개수 3, 준하와 겹치는 개수 1 이걸 모두 저장해야 함) DB에서 차지하는 용량이 크다. 그리고 1번부터 끝까지 모든 문항을 다 흝어야 하는 과정이 필요해 시스템에 추가적인 부담을 준다.
3. 선택할 수 있는 문항 수를 지정해두고, 각 문항을 선택한 '우선순위'를 반영해 서로에 대한 가산점을 매기는 방식으로 하자.
장점: 2번처럼 모든 문항을 흝으며 맞춘 개수를 세지 않아도 되며, 유저가 새롭게 추가될 때 각 사용자가 선택한 우선순위 기준으로 점수만 계산해 추가해주면 된다.
단점: 2번처럼 각 사용자들이 다른 사용자에 대한 점수를 모두 저장하고 있어야 하므로 (Ex. 하하: 재석의 우선순위 기반 유사도 점수 19, 준하의 우선순위 기반 유사도 점수 10, 세형의 우선순위 기반 유사도 점수...) DB에서 차지해야 하는 용량이 크다.
이처럼 다양한 해결안 후보들을 살펴본 후, 우리는 3번의 우선순위가 반영된 가산점 계산 방식을 좀 더 발전시켜 '순열 기반의 유사도 계산 방식'이라는 것을 생각해냈다. 모든 문항 중 3개를 우선순위에 따라 다르게 선택할 모든 경우의 수(우선순위가 반영된 것이므로 (2, 1, 4)와 (4, 1, 2)는 다르다.)로 컬럼을 미리 만들어두고, 각 사용자가 속한 컬럼에 대한 다른 사용자들의 점수를 흝어 해당 사용자 다음으로 높은 점수를 얻은 사용자를 찾는 유사도 계산 방식이었다.
가령 위의 사례처럼 사용자 A가 (1, 6, 2) 순열로 라이프스타일을 선택했다면 해당 순열의 컬럼에서 사용자 A의 점수는 최고점인 22점이다. 그리고 사용자 B와 C의 (1, 6, 2) 순열에 대한 점수를 살펴보니 A 다음으로 높은 점수를 얻은 사용자는 사용자 C이다. 그렇다면 이 경우, A와 유사도가 높은 사용자는 C인 것이다. 그래서 A는 C의 구매내역에 기반해 추천을 받는다.
만일 동점으로 유사도가 높은 사용자가 여러 명인 경우에는 해당 사용자들 모두의 구매내역을 기반으로 추천을 하게 되는 방식이다.
이렇게 순열을 기준으로 컬럼을 정의하니 사용자가 새롭게 추가되는지 여부에 상관 없이, 7개 중 3개를 고르는 총 210개의 컬럼 내에서 모든 사용자의 점수만 미리 계산해 저장해놓으면 유사도를 구할 수 있다는 장점이 있었다.
라이프스타일 설문 문항 선정
사람들의 라이프스타일은 너무나 다양해 모든 라이프스타일을 알아낼 수는 없었다. 그래서 우리는 마켓컬리 제품들을 흝어보며 현재의 마켓컬리 제품 구매시에 중요해질 수 있는 라이프스타일(비건, 친환경, 반려견 유무 ...) 을 설문 문항으로 뽑았고, 그 중 선택하는 제품이 아예 달라질 수 있는 항목들은 라이프스타일 선택 시에 그룹이 달라지도록 하였다. (가령 강아지를 키우는 사용자와 고양이를 키우는 사용자에게 추천되는 제품은 아예 달라야 하므로, 그쪽은 그룹을 분리하도록 했다.)
2주차 (8/7 ~ 8/14)
생각해낸 아이디어 기반으로 과제계획서를 작성하는 기간이었다.
만들 것이 많았기 때문에 각자 역할을 분배한 후, 각자가 1차적으로 만들어온 것에 대해 서로 피드백을 더해 완성하였다.
ERD & 아키텍쳐
라이프스타일 설문 문항 중 영유아 자녀 유무, 반려견.묘.식물, 가구원 수로 그룹을 분류할 수 있도록 user 테이블에 컬럼을 넣었다. 그리고 다른 라이프스타일 문항은 순열 기반 유사도를 계산하기 위해 Similarity 테이블을 두어 유저의 selectionCombo(3개를 우선순위대로 선택함)에 따른 각 컬럼에 대한 유사도들을 구해서 저장했다.
나중에 DB를 만들어 직접 저장한 형태는 이렇다.(ERD 상의 selectionCombo가 실제 DB 개발 시에는 selection_set_id로 컬럼명이 바뀌었다.) user_id 1번이 1~210번까지 각각의 행렬에 대한 value를 가지고 있고, 그 뒤로 다시 user_id 2번이 1~210번까지, 이런 식으로 각각의 selection_set_id에 대해 유저가 선택한 행렬에 기반해 유사도를 구해 value에 저장해두어 특정 사용자가 선택한 순열과 일치하는 컬럼(== 사용자가 최고점(value) 22점을 가지는 컬럼)에 대해 그 다음으로 높은 점수(value)를 가지는 사용자를 찾는 것이다.
본선 진출 시 제출할 데모 프로그램은 새롭게 개선한 기능이 포함된 마켓컬리 웹 서비스 형태로 만들기로 했다. 프론트엔드는 React, 서버는 java Springboot, DB는 MySQL을 사용했다. 기술스택은 아무래도 대부분의 팀원이 기존에 웹 서비스를 만들어본 경험이 있는지라, 자신이 사용하기 편리한 것을 선택하게 되었다. (나는 React를 이용한 프론트엔드를 맡았다.)
화면설계
5일 안에 개발을 해야 하기 때문에, 우리는 많은 페이지를 만들기보다는 우리가 보여줄 기능을 잘 표현할 수 있는 두 세 개의 페이지만 만들기로 결정했다. 그래서 추천상품 캐러셀이 포함된, 카테고리 기반으로 정렬된 검색 결과 페이지와 설문 조사 페이지, 2가지만 디자인하였다. 화면 설계는 피그마를 이용하였다.
특히 설문조사 화면의 경우 우리 4명 모두가 각각의 디자인을 하여, 가장 나은 디자인 1개를 뽑았다.
기획서
기획서는 내 담당이었다. (이전에 프로젝트 진행할 때 기획서, PT 자료를 많이 만들어 본 경험이 있어서). 기획서 작성 시에는 1) 최대한 두괄식으로 질문에 대한 답을 먼저 제시한 후, 설명을 적었고, 2) 중요한 부분을 굵은 글씨로 표시했고, 3) 사진 자료 등을 첨부해 내용 전달이 쉽게 될 수 있도록 노력했다.
이렇게 과제 계획서를 완성해 제출하였고, 이틀 뒤에 본선 진출이 확정되었음을 알리는 메일이 왔다!
(이제 5일간의 빡센 개발의 헬게이트가 열렸는데, 그건 다음 글에서 더 이야기하도록 하겠다)
++) 팀 이름 Kurvey는 (Kurly + Survey)의 합성어로, 설문에 기반한 라이프스타일 추천을 하는 팀이기에 그렇게 지었다. 그런데 어감이 '커비'랑 비슷하게 느껴져서 깃허브 팀 마스코트로 커비를 그려놓았다.(실제론 커비라고 아무도 읽지 않는다)
'개발 공부 > 2022 마켓컬리 해커톤' 카테고리의 다른 글
[마켓컬리 해커톤 회고] 5주차: 결선 진출, 그리고 최종 우승! (0) | 2022.09.06 |
---|---|
[마켓컬리 해커톤 회고] 3-4주차: 5일 간 바쁘게 개발한 본선 (0) | 2022.09.05 |