3.4"Hashtag" System
해시태그 시스템 및 팔로우 시스템 추가하기
이번 포스팅에선 해시태그 기능을 추가해보자.
인스타그램에서 해시태그 기능(#태그명)은 캡션, 커멘트, 프로필 등에서 모두 쓰인다. 하지만, 정확히 그렇게 태그한 내용들은 다른 곳에서 어떻게 쓰일까?
찾아보면, 해시태그가 실제로 기능으로 쓰이는 곳은 검색 기능 뿐이다. 예를 들어, #happy를 검색하면 #happybirthday, #happy, #happyfriday 같은 결과들이 나오는데, 해당 결과들은 오직 해시태그가 쓰인 포스트 뿐이고, 댓글과 프로필은 검색 결과로 나오지 않는다.
따라서 hashtags_posts, hashtags_comments, hashtags_users와 같은 테이블들을 별도로 만들어 어떤 포스트/커멘트/프로필에 해시태그가 어디에 쓰였는지 모두 저장하고 관리할 필요는 없다. 물론 인스타그램에선 이렇게 별도로 테이블들을 만들어 관리하고 있을 수 있지만, 현재 구현된 기능들을 클론하는데는 모든 테이블들을 만들 필요가 없다. 즉, 우리가 현재 필요로 하는 테이블은 hashtags_posts 뿐이다.
Tables for Hashtags
첫번째 방법: hashtags 테이블을 만들어 post_id를 foreign key로 써서 포스트와 해시태그를 엮는다.
id | title | post_id |
---|---|---|
1 | birthday | 3 |
2 | summer | 5 |
3 | fun | 5 |
4 | fun | 4 |
두번째 방법: 성능 개선을 위해, 일반적으로는 hashtags 테이블을 만들고, posts 테이블과 연결시켜주는 hashtags_posts 테이블을 별도로 만들어 관리한다.
- 겹치는 hashtag 타이틀이 많고(위의 예에선 #fun), text를 저장하고 쿼리하는 것보단 number를 저장하는 것이 용량에도, 쿼리 성능에도 유리하므로 해시태그별로 아이디를 주고 같은 해시태그가 쓰이면 해당 아이디를 엮는 것이 낫다.
예: hashtags 테이블 (해시태그 아이디와 내용만 관리한다)
id | title |
---|---|
1 | birthday |
2 | summer |
3 | snow |
4 | fun |
예: hashtags_posts 테이블 (해시태그 아이디와 포스트 아이디를 엮어준다)
id | hashtag_id | post_id |
---|---|---|
1 | 3 | 3 |
2 | 1 | 1 |
3 | 4 | 4 |
4 | 3 | 2 |
우리의 dbdiagram.io에는 아래와 같이 추가한다. 실제 데이터베이스에 추가할 때는 hashtags 테이블의 title에 UNIQUE 제약을 건다.
sqlTable hashtags { id serial [pk, increment] created_at TIMESTAMP title VARCHAR(20) } Table hashtags_posts{ id serial [pk, increment] hashtag_id INTEGER [ref: > hashtags.id] post_id INTEGER [ref: > posts.id] }
유저 테이블 보완하기
유저 테이블에 몇가지 필요한 컬럼들을 추가하자.
현재 users 테이블은 아래와 같다.
sqlTable users { id SERIAL [pk, increment] created_at TIMESTAMP updated_at TIMESTAMP username VARCHAR(30) }
하지만, 인스타그램에 가입할 때는 전화번호 또는 이메일이 필요하고, 유저들은 각자의 소개(bio)와 사진(avatar)를 가지고 있다. 또, 어떤 유저가 온라인인지, 오프라인인지 등으 알려주는 status flag도 필요하다.
sqlTable users { id SERIAL [pk, increment] created_at TIMESTAMP updated_at TIMESTAMP username VARCHAR(30) bio VARCHAR(400) avatar VARCHAR(200) phone VARCHAR(25) email VARCHAR(40) password VARCHAR(50) status VARCHAR(15) -- 이후 Enum으로 대체할 예정! }
포스트 수, 팔로워 수, 팔로잉 수는?
이들은 모두 likes를 만들때와 비슷한 로직으로, 유저 id만 있으면 각각 posts 테이블 및 followers 테이블(추가 예정)에서 쿼리로 계산할 수 있는 데이터다. 이런 'derived data'는 아주 훌륭한 성능 개선이 있지 않거나 데이터를 얻기에 쿼리가 지나치게 복잡하지 않은 한 굳이 따로 저장하지 않는다.
그러면 followers 테이블을 만들어보자.
id | leader_id | follower_id |
---|---|---|
1 | 3 | 4 |
2 | 2 | 5 |
3 | 1 | 2 |
4 | 1 | 3 |
5 | 1 | 4 |
CHECK (leader_id <> follower_id)
와 UNIQUE (leader_id, follower_id)
로 본인 스스로를 팔로잉할 수 없게 제약하고, 팔로잉 관계는 유저-유저별로 딱 한번만 일어날 수 있게 중복을 막는다.
우리의 dbdiagram.io에는 아래와 같은 테이블이 추가된다.
sqlTable followers { id serial [pk, increment] created_at TIMESTAMP leader_id INTEGER [ref :> users.id] follower_id INTEGER [ref :> users.id] }
