티스토리 뷰
안녕하세요. Web Frontend팀 이민하입니다.
지난 빅스마일데이에 첫 론칭한 꿀템 피드 서비스! 이 서비스를 만들기 위한 여정을 여러분께 소개드리려고 합니다.
Intro
시작은 디지털 빅세일이 끝난 2월 말.. 저희 팀장님의 한마디에서 시작했습니다.
"챗GBT를 우리만 보기에 아깝지 않아..!?"
챗GBT(Gmarket Best iTem)는 임직원분들이 직접 추천하는 상품을 모아둔 페이지로 하나하나가 진짜 꿀템입니다!
아깝다고 생각했습니다. 저도 GBT를 보며 많이 샀기 때문에 고객도 이 페이지를 같이 보면 구매가 많이 일어날 것이라고 생각했습니다.
추가로 고객들이 게시글을 작성할 수 있다면..? 그러면 고객들이 우리 사이트에서 놀 수 있는 공간이 되지 않을까?
또한 사내에서도 우리 프러덕에 커뮤니티 기능을 넣어보자는 니즈가 있었다고 들었습니다.
자신감이 생기기 시작했습니다. 우리 사이트에 새로운 활기를 불어넣어 줄 수 있을 것 같은 그런 자신감이 생겼습니다.
만들 수 있을 것 같은 기대감에 하나 잊어버린 것이 있었습니다.
"아 맞다 나 신규 서비스 만들어 본 적 없지!"
네. 저는 입사하고 이벤트 플랫폼, 한반도 기획전, 패턴6를 담당하면서 기존 서비스의 개선 작업을 주로 해왔고 "쇼룸"이라는 서비스를 준비 중이었으나 아직 신규 서비스를 론칭해 본 경험은 없었습니다. 그렇기 때문에 어디서부터 무엇을 작업해야 할지 머릿속에 그려지지 않았습니다.
이 발표는 신규 서비스를 개발하려고 할 때 무엇을 준비해야 할지 막막한 "개발자"분들이 시행착오를 줄일 수 있도록 도움을 드리고자 준비하게 되었습니다.
지속 가능한 개발을 위한 설계
지속 가능한 설계란 보통 환경의 수용능력 범위 내에서 개발하는 것을 말하는, 도시설계에서 사용하는 개념인데요, 어플리케이션 개발에 있어서 개발 비용이 너무 많이 소모되지 않으면서 꾸준히 디벨롭하고 개선할 수 있는 프러덕을 만드는 것과 일맥상통한다고 생각합니다. 그리고 이를 위해 확장성을 고려한 설계가 필요했습니다.
첫 번째로 고민한 것은 "네이밍"이었습니다.
개발자에게 가장 어려운 일들
개발자에게 있어 이름을 짓는다는 행위는 단순히 부르기 위한 목적보다 더 큰 의미가 있습니다. 이름만 듣고도 직관적으로 만드는 의도를 이해하는데 도움이 되어야 합니다. 저희도 구현하고자 하는 개념을 포괄할 수 있어야 한다고 생각했습니다. 또한 기존 개념과 헷갈리지 않도록 사내에서 사용되지 않는 단어를 선택해야 했습니다. 그러다 문득
우리 사이트에서 놀 수 있어야 한다.. → 즐길 거리!? 그러면 게시글을 "놀이 기구"에 비유하면 어떨까?
챗GBT는 Padlet이라는 공유 게시판 서비스를 이용하였는데 그 padlet안에 게시글을 포스팅할 수 있는 빈 보드에 해당하는 영역을 "Attraction"이라 명명했습니다. 어트랙션은 놀이 공원의 놀이 기구라는 뜻으로 사용되곤 하지만 실제로는 매력, 즐길 거리, 명소 등의 뜻을 가지고 있습니다. 부동산 개발 업계에서는 도시의 랜드마크나 코엑스의 별마당 도서관처럼 상업 시설 내 차별화를 두는 장소를 어트랙션이라고 부르기도 합니다.
Attraction에 들어갈 게시글 하나하나는 놀이기구, 탈 것을 의미하는 "Ride"로 부르기로 하였습니다. Attraction 하위에 존재하며 등록, 수정이 가능한 컨텐츠입니다.해당 프로젝트에서 가장 중요한 개념이며 Ride의 퀄리티에 따라 이 서비스의 흥행이 정해질 것이라 생각했습니다.
마지막으로 Ride를 업로드할 수 있는 사람을 지칭하는 개념이 필요했습니다. 이 사람은 지마켓, 옥션의 회원 일 수도, 셀러 고객일 수도, 임직원 일 수도 있기 때문에 이를 포괄하는 개념이어야 했습니다.
그러므로 Ride의 탑승객을 의미하는 "Passenger"로 명명했습니다. 그렇게 핵심 개념인 Attraction, Ride, Passenger 가 탄생했고 자연스레 이 프로젝트의 이름은 지마켓의 놀이공원, "G-world"가 되었습니다.
확장성을 염두에 두고 하위 속성을 정의하기 시작했습니다.
프로젝트 이름을 정하고나서 머릿속에 있는 내용을 화이트보드에 정리해봤습니다.
팀원들과 본격적으로 G-world의 얼개를 짜기 시작했습니다. 개발자가 기획하는 것이다 보니 어떤 식으로 접근해야 할지 몰랐습니다. 해당 페이지를 어디에 노출시킬 것이며 어떤 속성이 필요한지를 고민했습니다.
Attraction은 챗GBT처럼 저희 영업본부 임직원 분들이 올릴 수도 있고, 고객들도 업로드할 수 있어야 했고 상품을 공유했을 때 구매 적립받을 수 있도록 Linkrew 와의 연동이 필요하다고 생각했습니다. (Linkrew 란 누구나 상품 링크를 공유해 수익을 셰어 받는 지마켓의 신규 제휴서비스입니다.)
Ride는 상품은 구매 내역에서 불러오거나, 구매 내역 없이 단순히 상품을 추천하거나, 임직원이 올릴 수 있는 3가지 형태가 있을 수 있다고 판단했습니다. 그리고 구매 기록에 기반한 태그(첫 구매시기, 재구매 횟수 표시 등)를 게시하여 Ride의 리뷰 신뢰도를 높일 수 있는 방안을 생각해 보았습니다. 또한 Ride 내에 승객이 직접 해시태그를 넣고 이를 필터링할 수 있는 기능, 좋아요 표시를 통한 인기 Ride에 대한 리스팅 기능 등 정말 다양한 방안이 나왔습니다.
Ride의 상품 카테고리를 통해 특정 기획전 콘셉트에 맞는, 혹은 유저가 원하는 상품의 Ride를 모아볼 수 있는 필터링 기능도 넣었습니다. 댓글 기능도 들어가야 커뮤니티로써 기능한다고 생각했습니다.
Content Quality에 대한 우려가 가장 큰 고민이었는데, 이용약관 동의 하기 위한 동선, 동일 상품의 Ride가 올라올 경우 모아서 보여준다던지, 콘텐츠가 활발하게 업로드될 수 있도록 승인 대신 선 게시 후 모니터링이 필요하다고 생각했고 이를 위한 신고 기능도 개발할 필요가 있음을 인지했습니다.
사흘 동안 얼추 구상한 내용을 팀장님께 말씀드리고 피드백을 받았습니다. 최초 아이디어를 팀장님이 주신만큼 개발 가능한 범위와 설계 타당성에 대한 검증을 해주시고 조언에 따라 수정을 거쳤습니다.
이번 빅스마일데이(5월)에 적용할 POC(Proof of Concept)를 만들어보자!
이 때는 3월 초. 그리고 저는 3월 중순에 오랜 기간 염원해 오던 미국 여행을 앞두고 있었습니다....
여행 가서 노트북을 펼치지 않으려면 지금 빠르게 설계를 마쳐야 한다는 위기의식이 생겨났습니다. (네? 다음 달까지요?)
본격적으로 테이블을 설계할 때가 됐습니다.
저는 개인적으로 PostgreSQL을 자주 사용해 왔습니다.
가장 먼저 해야 할 일은 “어떤 DBMS를 선택해야 하는가?”입니다. 사내에선 다양한 DBMS를 이용해 다양한 프러덕을 만들고 있습니다. 각 DB는 저마다의 장단점을 가지고 있습니다.
저장할 데이터 양이 많지는 않으면서도 POC 끝나고 데이터의 사용성을 고려했을 때 정합성이 가장 중요하다고 생각했습니다. 따라서 팀 내에선 성능과 안전성을 고려하면 Oracle을 사용하는 데에 이견이 없었습니다. 더불어 이번 BSD는 지마켓만 오픈하지만 옥션으로 확장할 수 있다는 생각도 있었습니다.
테이블 명은 ATTRACTION, RIDE, PASSENGER가 정해졌지만 테이블 내 속성을 의미하는 칼럼은 해당 키워드를 사용하기에 길다고 느껴졌습니다. 그래서 각 단어의 축약형이 필요했는데 보통 개발자들은 영어 단어의 첫 글자를 제외한 모음을 지워서 3~5글자로 만듭니다. Attraction의 모음을 없애면 Attr이죠. 제가 방금 네이밍에 있어서 기존 개념과 헷갈리지 않아야 한다고 말씀드렸습니다. 해당 단어를 현재 사내에서 사용하고 있는지 먼저 찾아볼 필요가 있습니다.
사내 메타 데이터 관리 사이트
사내 Meta data를 관리하는 사이트에서 표준 단어로 검색을 해봅니다. 이는 "속성"을 뜻하는 Attribute의 축약형과 동일합니다. 따라서 이 경우에는 "ATRC"로 축약형을 정하였습니다.
Ride는 글자 수가 적기 때문에 Ride 그대로 사용해도 무방하다고 판단했고, Passenger는 탑승객의 항공업계 공식 약어인 "PAX"를 사용하기로 하였습니다.
테이블의 논리적인 칼럼명은 주로 한글 표기하고 물리적인 칼럼명은 영문으로 표기합니다. 칼럼의 Data Type은 DBMS 별로 조금씩 달라지긴 하나 보편적인 타입을 선언하였습니다. 그리고 해당 칼럼의 길이를 러프하게 정하고 Null 여부와 초기값 등을 설정하는 표를 만들었습니다.
Attraction을 기획하면서 구상한 내용을 담기 위해 테이블에 콘텐츠의 생성, 조회 권한 칼럼을 두었습니다. 이는 추후 유니버스 클럽 고객 만을 위한 Attraction을 만들 수도 있게 하였습니다.
디지털, 신선식품 등 특정 카테고리 상품군 만을 Ride로 올릴 수 있도록 Attraction Category 테이블을 설계했습니다. Attraction 테이블에 칼럼으로 넣지 않고 Category 테이블을 별도로 만든 이유는 Attraction이 기획전, 상품평, 코너 등에 사용될 수 있다고 판단하여 확장성을 고려한 설계가 필요하다고 느꼈기 때문입니다.
데이터를 구조화하는 작업을 테이블의"정규화"라고 합니다. 중복 데이터를 없애기 위한 용도로도 사용되지만 여기서는 데이터베이스의 구조 확장 시 재 디자인 하는 것을 최소화하기 위한 목적으로 사용되었습니다.
Ride는 우리 사이트의 상품과 연동할 수 있어야 했습니다. 이번 BSD에서는 BSD 기간에 태그가 붙은 상품을 구매한 경우에만 구매 내역에서 불러와 Ride Goods로 등록할 수 있게 하였습니다. 그 외 좋아요를 저장하는 Ride Recommend 테이블과 신고할 수 있는 Ride Report 테이블, 댓글을 저장할 Ride Comment 테이블을 설계하였습니다.
Passenger의 경우에는 여태까지 사내에 없던 정말 생소한 개념이기에 테이블 설계하는데 애를 먹었습니다.
기본적으로 아래의 문제 상황이 존재했습니다.
- Gmarket의 id 중복 문제 → 기본 id들이 있기 때문에 Gmarket은 유니크한 id 식별자를 봐야 함
- G/A 간 회원 식별자가 다른 것 → Auction 에는 회원 식별자가 없음
- Admin도 참여할 수 있는 서비스 → Admin id가 G/A와 중복될 수 있음
MyG, MyA 등의 내 정보와 연동하기 위해선 타 팀과의 논의가 필수불가결합니다. 하지만 커뮤니케이션 비용 절감 및 확장 가능성을 고려해 (지마켓 그 너머..) 유저아이디, 회원 식별자, 사이트 종류 세 가지 속성을 이용해 기존 지/옥/Admin 계정 정보와 논리적인 Relation을 맺는 것이 합리적이라 판단했습니다. 지마켓, 옥션, Admin 계정의 유저 id는 중복될 수가 있으므로 pax의 id 칼럼을 만들어 유저 id로 넣어두되 사이트 종류 칼럼으로 구분할 수 있습니다
따라서 Passenger 테이블의 pk 만을 보고 유일한 탑승객임을 보장할 수 있게 되었습니다.
추후 해당 승객의 등급, 뱃지 등 게이미픽케이션 요소를 넣기 위한 칼럼도 정의하였습니다. 해당 탑승객에 대한 정보는 Passenger 테이블에만 저장됩니다.
이 모든 속성은 G-world 서비스에서만 이용하는 것이기 때문에 개인정보를 저장하지 않는다는 것이 중요했습니다. (개인정보 보호테이블이 되면 Meta System 내에서 별도로 관리되어 관리 포인트가 많아집니다.)
기본적으로 모든 테이블에는 Insert Operator, Update Operator와 관련한 칼럼이 포함되어야 합니다. 그래서 해당 칼럼에 생성 승객과 수정 승객 번호를 넣으려고 했습니다. 그러나 담당 DA분께서 아래와 같은 가이드를 주셨습니다.
Insert Operator, Update Operator는 이 데이터를 (ROW) 만들거나 수정한 시스템(또는 플랫폼) 정보여야 합니다.
즉, 시스템명, Application명, Host 정보명(Pod명) 등을 뜻하며, 고객의 개인정보(로그인 ID 등)를 저장해서는 안됩니다.
따라서 별도로 공통 칼럼을 만들어 모든 테이블에 전부 넣어주었습니다.
설계는 항상 꼼꼼해야 하지만 칼럼 추가나 수정은 개발되는 기간 내내 발생할 수 있기 때문에 너무 완벽함을 추구해선 안됩니다.
설계를 마치고 테이블을 생성했습니다.
사내에서 주제영역으로 불리는 개념이 있는데 Database의 schema라고 생각해 주시면 이해가 잘 될 것 같습니다. 물리적인 스키마명을 통일해 사용하지만 실제 주제영역은 Meta 데이터 관리 시스템을 통해 관리됩니다.
G-world는 신규 서비스이므로 Attraction이라는 이름의 새로운 주제영역을 신청하였습니다.
위처럼 Entity를 선언하고 Entity끼리의 Relationship을 맺어주면 ERD가 완성됩니다. 물리적, 논리적 ERD를 각각 구성해야 합니다.
참고로 사내에서는 실제 테이블이 생성될 때 외래키(FK)를 반영하지 않습니다. 외래키 라고 하는 것은 두 테이블을 연결시켜 주는 다리라고 생각하면 이해가 빠른데 Ride 테이블에 상위 테이블인 Attraction의 키 값이 있거나 Ride Goods 테이블에 Ride의 키 값이 들어있는 것을 말합니다. 보통 관계형 데이터베이스에 대해 배울 때는 PK와 FK 설정을 통한 데이터 무결성, 정합성 보장을 한다고 하지만 성능, 개발, 유지보수에 있어서 trade off 관계이기 때문에 현업에서는 물리적인 fk는 정의하지 않는 편입니다. 그러므로 Meta 시스템을 통해 정합성을 보장하려고 하죠.
이제 G-World를 소개하기로 했습니다.
지난 일주일 간의 개발자들이 기획 / 설계한 것을 가지고 기획팀, 디자인팀과 자리를 마련해 팀장님이 처음으로 G-World에 대해 말씀드렸습니다.
걱정반 기대반이었습니다. 기획 / 디자인 리소스가 부족하면 이번 BSD에 보여주기는 힘들 것 같았습니다.
해봅시다!
다행히 긍정적으로 검토해 주시고 챌린지 해보자는 뜻이 모아졌습니다.
이번 BSD는 5월 7일부터 시작했으므로 2달이 남아있었지만 QA 기간까지 끝내려면 한 달 안에 기획 / 디자인 / 퍼블리싱 / 개발을 모두 마쳐야 했습니다. (네?! 다음 달 까지요!?)
BSD에 진행하는 것이 확정이 되고 전 예정대로 휴가를 가게 되었습니다. 그 사이 팀원분들이 울퉁불퉁한 설계도에 필요한 테이블과 칼럼을 추가해 주시면서 무사히 G-world의 데이터베이스가 생성될 수 있었습니다.
다음 편에는 전체적인 Data Flow와 기술스택에 대해 소개해드리겠습니다.
'Backend' 카테고리의 다른 글
오픈마켓 여행 플랫폼의 실전 API 연동 노하우 (20) | 2024.07.23 |
---|---|
조회 속도 개선하기 (ESM '문의하기' 기능 개편) (36) | 2024.06.28 |
Gmarket Mobile Web Vip 악성 봇 대침투 사건 (3) | 2024.05.11 |
설계란 고민의 연속이다 2편 (1) | 2024.04.04 |
설계란 고민의 연속이다 1편 (1) | 2024.03.14 |