요구사항 분석
nomadia는 디지털 노마드를 위한 커뮤니티 서비스로 기획을 했다. 그 이유는 다음과 같다.
- 디지털 노마드를 위한 서비스는 지속적으로 성장하고 있으며, 아직 시장 지배적인 기업이 없기 때문에.
- 이전부터 관심이 있었던 주제이기 때문에.
- 하나의 서비스이지만 다양한 기능들을 필요로 하며 이러한 기능을 구현 해보며 실력을 늘릴 수 있을 것이라 생각 했기 때문에.
좋은 서비스는 고객의 필요에 의해 만들어진다. 이 때 개발 자원은 한정되어 있기 때문에 많은 기능을 넣는 것이 반드시 고객의 필요에 부합한다고 볼 수는 없다.
‘지역’의 주요 관광지는 관광 전문 사이트 혹은 Google map을 이용하면 되고 ‘구인’은 Linkedin을 포함한 사이트에서 찾는 편이 더 적절하다. 따라서 먼저 고객의 니즈가 어디 있는지, ‘왜’ 이 서비스를 이용해야 하는지 먼저 다양한 자료들을 찾아보며 조사 했다.
디지털 노마드의 특징은 다음과 같다.
- 대부분이 IT 노동자이다.
- 대부분이 고학력자이다.
- 디지털 노마드의 세대 분포는 아래의 표와 같다.
- 안정된 커뮤니티의 부재로 정신적 건강에 위협을 받는다.
- 리모트 워커의 경우 시간당 페이 계약이 대부분이지만 업무 단위의 계약도 한다.
디지털 노마드의 연령 분포
연령 | 25세 이하 | 26~41세 | 42~57세 | 58~76세 |
비중 | 21% | 44% | 23% | 12% |
디지털 노마드가 처한 특수한 상황은 다음과 같다.
- 거주 지역의 WIFI 등 통신이 불안정한 상황이 있을 수 있다.
- 높은 임대료와 생활비로 경제적 어려움에 처할 수 있다.
- 여권의 파워에 의해 거주할 수 있는 지역이 제한된다.
- 현지의 사정에 무지한 경우가 많다.
- 현지 생활에 도움을 받을 수 있는 인간관계를 적극적으로 찾는 경향이 있다.
출처:
‘디지털 노마드’ 삶에 대해 아무도 말하지 않는 6가지
위의 사항을 조합해 보았을 때 필수적 기능과 부가적 기능에 대한 내역을 도출할 수 있다.
필수기능
- 커뮤니티 기능.
- 해당 지역의 인터넷 환경, 환율 등 전반적인 정보.
- 향상된 보안 기능.
디지털 노마드는 여러가지 이유에서 현지 사람들 혹은 같은 디지털 노마드 간의 커넥션을 필요로 한다. 따라서 커뮤니티 기능이 필수적이다.
Airbnb나 Google map에서는 얻을 수 없는 디지털 노마드의 관점에서 필요한 정보를 보여줄 필요성이 있다. 예를 들면 해당 지역의 인터넷 통신의 안정성, 속도 및 co-working space에 대한 정보가 있다.
IT 종사자이기 때문에 개인 정보 보호와 보안에 대해서 엄격할 가능성이 높다. 서비스에서 보다 높은 수준의 보안을 제공할 필요성이 있다.
부가 기능
- 자신의 여권으로 이동할 수 있는 지역에 대한 정보.
- 법률적 지식을 가진 사람 연결하는 서비스.
- 해당 지역의 전반적인 생활비, 물가에 대한 정보.
- 수입과 소비에 관한 기록 서비스.
개발의 중요도 순서에 따라 필수 기능을 먼저 개발하고 시간적 여유가 된다면 부가 기능까지 만드는 것을 목표로 한다.
요구사항 설계
위의 분석에 따라 도출한 요구사항은 다음과 같다.
속성 요구사항
유저 | 지역 | 게시글 |
이메일 | 인터넷 속도 | 내용 |
위치 | 환율 | 댓글 |
비밀번호 | 생계비 지수 | 추천 수 |
생년월일 | 관광 지수 | |
국적 | 안전 지수 | |
이름 | 여행 가능 여부 (여권) | |
팔로우 | 대화방 | |
소개 | 추천 수 | |
비추천 수 | ||
종합 평점 | ||
리뷰 | ||
공유 오피스 위치 |
행위 요구사항
유저 | 지역 | 게시글 |
회원가입 하기 | 평점 주기 | 피드 쓰기 |
로그인 / 로그아웃 하기 | 지역 기반 채팅 하기 | 댓글 쓰기 |
개인 정보 수정 하기 | 추천 하기 | 공유 하기 |
팔로우 / 취소 하기 | 비추천 하기 | 추천 하기 |
리뷰 하기 |
예비 테이블 설계
본격적으로 테이블을 만들기 전에 예비 테이블을 만들었다.
- user는 postgreSQL의 예약어이기 때문에 user_profile로 대신했다.
- location은 geo location, address location등으로 쓰일 수 있어 의미가 모호하기 때문에 구체적인 city로 대신했다.
테이블 설계
기본 설계 원칙
1. PK는 어느 것으로 해야 할까?
- 먼저 PK를 인조키로 할지 자연키로 할지의 문제가 있다.
PK를 자연키로 할 경우 성능에서 이점이 있지만 비즈니스의 요구 사항에 의해 변경될 일이 생길 수 있다.
PK를 인조키로 할 경우 테이블의 유연성에서 이점이 있지만 인덱스를 추가로 구성해 주어야 하고 인조키 추가를 위한 필드로 인해 테이블이 커진다.
무결성(데이터베이스 내에 모든 값은 언제나 정확한 값을 유지해야 한다)
유연성(데이터베이스 구조는 요구사항 변화에 대해 수정이 쉬워야 한다)
확장성(데이터베이스 구조는 기능 확장에 대해서 수정이 쉬워야 한다)
위의 3가지를 가장 우선을 고려하고 성능은 정말 문제가 될 때 개선하는 방식으로 설계해야 좋은 데이터베이스를 얻을 수 있다. 따라서 PK는 유연성에서 이점이 있는 인조키를 사용한다.
- 다음으로 PK를 increment pk로 해야 할지 uuid로 해야 할지의 문제가 있다.
uuid는 보안 상의 이점이 있고, 분산 시스템에서 DB에 데이터를 삽입할 수 있다는 이점이 있다. 하지만 길이로 인해 많은 저장 장소를 필요로 하게 되고 성능 상의 문제를 일으킨다. 따라서 외부에 노출되는 데이터가 아니라면 increment pk를 사용한다.
출처: UUID와 increment PK는 언제 사용해야할까?
2. CHAR와 VARCHAR 중 어느 것을 사용해야 할까?
CHAR와 VARCHAR의 혼용은 내부적 형 변환 문제를 초래한다. 따라서 둘 중 하나의 값으로 통일하는 편이 좋다.
CHAR는 고정 길이 타입이라 데이터베이스가 각 레코드의 위치를 더 쉽게 찾을 수 있고, VARCHAR의 경우 더 작은 데이터 크기로 인해 디스크 I/O가 더 적다. 따라서 이 둘 사이의 성능의 차이는 미미하고(유동오, 핵심 데이터 모델링, 디비안, 2020) 조금 더 유연성을 확보할 수 있는 VARCHAR로 통일하여 데이터베이스를 구성한다.
3. 일자는 DATE형으로 해야 할까 VARCHAR(8)로 해야 할까?
VARCHAR(8)에는 날짜가 아닌 데이터가 유입될 수 있고, 데이터 품질을 우선적으로 고려한다면 DATE형을 쓰는 편이 좋다(유동오, 핵심 데이터 모델링, 디비안, 2020). 이 때 DATETIME이 Y2K38 문제에서 자유롭기 때문에 TIMESTAMP가 아닌 DATETIME을 사용한다.
user_profile 테이블 설계
1. 이름은 성과 이름으로 나누어야 할까?
다국적 서비스를 염두에 두고 있기 때문에 사용자의 이름이 반드시 first name과 last name으로 이루어질 것이라는 보장이 없다. 또한 그 둘을 나누는 것에 특별한 이익이 없다. 따라서 하나의 user_name에 넣는다.
2. 국적은 별도의 테이블로 분리 해야 할까?
유저가 다중 국적자일 경우 하나의 column에 복수의 정보가 삽입되어 원자성이 깨어진다. 제 1 정규형을 지키기 위해 국적은 별도의 테이블로 분리한다.
3. 현재 위치는 어떻게 표현할까?
실제 x, y 좌표를 매번 요구하는 것은 웹 서비스로 기획 되어 있는 현재 상황과는 맞지 않는다 따라서 city의 상위 엔티티로 country 엔티티를 만들고 접속 ip 정보를 통해 해당 국가, 도시에 맞는 피드를 내보내는 방식으로 해결한다. 칼럼명도 조금 더 구체적인 current_location으로 변경한다.
4. user_location에 많은 I/O가 예상되는데 이를 미리 분리해야 할까?
실제로 많은 I/O가 발생할지는 알 수 없다. 또한 확장성을 고려하여 미리 작업한다면 소프트웨어 설계 원칙인 KISS, YAGNI 등을 어기게 된다. 서비스 이용의 실태를 확인한 뒤 분리해도 늦지 않는다.
follow 테이블 설계
1. 유저의 팔로워, 팔로잉 count를 user_profile 테이블에 넣어 곧바로 표시해야 할까?
count는 indexing이 되어도 느리다(Hussein Nasser, Fundamentals of Database Engineering, Udemy). 하지만 데이터베이스를 설계할 때는 무결성, 유연성, 확장성이 우선이고 성능은 가장 마지막에 고려해야 할 사항이다 (마이클 J. 헤르난데즈, 파워 오브 데이터베이스, 송현호, 황규용, 비제이퍼블릭, 2019) 따라서 ‘무결성’을 해칠 수 있는 결정을 성급하게 하지 말고 문제가 발생할 때 즈음 캐시를 사용하는 것을 우선적으로 고려해본다.
city 테이블 설계
1. city에 속한 테이블들이 많은데 별도로 분리해야 할까?
- can_travel은 두 country 사이의 관계이다. 따라서 city에서 제거하고 country 사이의 N:M 관계를 해소하기 위해 별개의 테이블을 만든다. 이 때 여행 불가능한 국가의 숫자가 훨씬 적기 때문에 cannot_travel로 테이블명을 바꾼다.
- city의 여러가지 평가 요소를 city_score로 빼서 각각의 유저들이 평가할 수 있도록 하고 이를 기반으로 점수를 보여주게 만든다. 이때 exchange_rate의 경우 rate로 명명되어 있지만 실제로는 평가의 요소가 없기 때문에 city에 남겨둔다.
- 추천 / 비추천 여부는 하나의 BOOLEAN값으로 바꿀 수 있다 is_recommendable로 변경하여 city_score에 넣는다.
- 종합 평점 (total_score)는 칼럼에 들어갈 값으로 피해야 하는 계산을 통해 도출된 값이다(이행적 함수 종속관계가 생긴다). 삭제 해준다.
2. 채팅방, 공유 오피스 정보를 분리해야 할까?
채팅방과 공유 오피스에 대한 정보는 NoSQL로 작성 할 것이라고 예상된다. 분리를 고려하되 개발의 우선순위가 낮기 때문에 미리 테이블에 넣지 않고 때가 되면 city 혹은 별개의 entitiy에 넣는다.
user_post의 설계
1. 좋아요를 별개의 테이블로 분리 해야 할까?
제 1 정규형을 지키기 위해 post_like를 별개의 테이블로 분리한다.
2. 포스트의 이미지, 동영상을 별개의 테이블로 분리 해야 할까?
마찬가지로 제 1 정규형을 지키기 위해 post_media를 별개의 테이블로 분리한다.
3. hash_tag를 별개의 테이블로 분리 해야 할까?
데이터 베이스 설계 도중 hash tag를 통해 post를 검색할 수 있도록 해야 한다는 것을 알게 되었다. 이것 또한 다중값을 가질 수 있기 때문에 별개의 테이블로 분리한다.
post_comment의 설계
post_comment는 상당 부분 user_post와 유사하지만 media와 hash tag가 없다. 따라서 좋아요만 별개의 테이블로 분리해서 추가 해준다.
테이블의 물리적 구현
위의 내용 대로 1차 테이블을 구현했다.
'Project > nomadia' 카테고리의 다른 글
Nest.js logger middleware 테스트 (TDD) (2) | 2024.03.17 |
---|---|
Nest.js - winston logger 적용하기 (0) | 2023.08.27 |
Nest.js - config 설정 (0) | 2023.08.20 |
TypeScript - const enum에서 as const로 변경 (0) | 2023.08.05 |
Next.js - atomic pattern 구조 잡기 (0) | 2023.08.02 |