앱 서비스의 알파이자 오메가,
DB 스키마를 설계해보도록 하자
우선 필요한 테이블을 먼저 정리해보자면,
이렇게 큰 세개의 계층으로 나누어서 관련 테이블을 작성할 수 있겠다.
이 글에서는 users, products, lounge_posts 이렇게 세개만 소개하고
(어짜피 나머지는 이 세개와 연관되어있는 테이블들이니..)
작성하는 과정에서 새롭게 알게된 것들을 소개하도록 하겠다.
Table users {
id integer [primary key]
social_id text
social_type varchar
name varchar
email varchar
user_profile_url text [note: "S3에 저장된 이미지 URL"]
created_at timestamp
updated_at timestamp
}
가장 간단하다.
이름, 프로필 이미지,
소셜로그인(구글, 애플)을 통해 받아온 이메일과 id를 저장하도록 설계했다.
Table products {
id integer [primary key]
user_id integer [ref: > users.id]
title varchar [note: "글 제목"]
description text [note: '글 설명']
price decimal(10,2)
brand_id integer [ref: > brands.id]
club_type enum("Driver", "Wood", "Utility", "Iron", "Wedge", "Putter")
shaft_type enum("Steel", "Graphite", "Other")
flex_type enum("L", "A", "R", "SR", "S", "X", "TX")
year integer
location GEOGRAPHY(Point, 4326) [note: "ST_SetSRID 함수로 만들어서 저장"]
likes_count integer
reports_count integer
is_deleted bool
created_at timestamp
updated_at timestamp
}
가장 머리가 아팠던 곳이다.
product는 필터링을 하기 위해 필요한 클럽타입, 샤프트타입, 플렉스타입은 enum으로 했고, location(제품 거래 장소)는 postgre에서 제공하는 GEOGRAPHY타입으로 저장하기로 했다.
그리고 is_deleted 플래그로 물리적 삭제가 아닌 논리적 삭제를 구현하기로 했다.
GEOGRAPHY 타입에 대해 설명하자면..
geography 데이터 형식은 지리 공간 데이터를 효율적으로 저장하고 처리하기 위해 설계된 데이터베이서 데이터 형식이다. 특정 좌표계(일반적으로 WGS84 좌표계 - SRID 4326)을 많이 사용한다.
점, 선, 면, 다각형 등의 다양한 지리적 객체를 표현할 수 있다.
제일 중요 거리 계산 면적 계산, 포함 여부 판단 등의 지리 공간 연산을 지원하는 함수를 제공한다.
본 프로젝트에서 유저 주변의 특정 반경에 있는 제품을 볼 수 있도록 기획했기 때문에 효율적인 거리계산이 중요했다.
location GEOGRAPHY(Point, 4326) [note: "ST_SetSRID 함수로 만들어서 저장"]
CREATE EXTENSION postgis;
CREATE TABLE cities (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
location GEOGRAPHY(Point, 4326)
);
INSERT INTO cities (name, location)
VALUES ('서울', ST_SetSRID(ST_MakePoint(126.9780, 37.5665), 4326));
해당 기능은 postGIS의 기능으로, ST_DWithin의 함수를 통해 두 공간 사이의 거리를 계산할 수도있다고 한다. postGIS extension을 postgre에 설치하는 것은 다음에 다시 포스팅하도록 하겠다.
PostgreSQL로 위치 데이터 활용하기 (earthdistance, PostGIS, 공간 인덱싱) - Seyeon_CHOI
이 글에 아주 잘 정리되어 있다.
Table lounge_posts {
id integer [primary key]
user_id integer [ref: > users.id]
content text
likes_count integer
reports_count integer
is_deleted bool
created_at timestamp
updated_at timestamp
}
이 역시 논리적 삭제만 구현해 놓은 것 빼고는 특별할게 없다.
당연히 변동사항이 생기겠지만, 한방에 모든 걸 다 고려할 수 없기에 이제 server와 db를 구성하면서 수정해나가보려고 한다.
serverpod에 migration 기능이 잘 구성되어 있기 때문에 몇번이고 수정해도 괜찮을.. 것이다..
다음 진행은 serverpod 및 DB 세팅이다.