런닝 코스 공유 서비스

[런닝 코스 공유 서비스] - 2. ERD 설계

sson-coding 2025. 12. 11. 00:13


ERD 설계

러닝 코스 공유와 커뮤니티 기능을 제공하는 Run -ing(가제) 의 요구사항을 분석한 뒤, 분석한 것을 기반으로 ERD를 설계했다.

어떻게 설계했는지 ERD에 대한 설명을 해보려고 한다.

공통

  1. PK : 주키 - BIGINT, 보조키 - UUID
    • 모든 테이블의 기본키를 auto increment 기반 BIGINT 로 통일했다.
    • 외부 API 및 URL 노출되는 식별자는 예측이 어렵기 때문에 보조키로 UUID 설계했다.
    • 테이블 간 관계는 조인,인덱싱 효율을 위해 BIGINT 로 연결했다.
  2. INT 대신 BIGINT 사용 이유
    • INT 타입은 최대 약 21 억 개의 식별자 생성 가능하다.
    • BIGINT 타입은 약 922 경으로 엄청 크다.
    • 데이터가 빠르게 증가하는 서비스(게시글, 댓글 등) 에서는 INT 가 한계에 도달할 수 있다.
    • INT 가 터질 경우를 대비해 BIGINT 설계해 리스크를 미리 제거했다.

회원 : User / Profile / Address

  • 회원 관련 테이블을 합치지 않고, 역할에 따라 분리했다.
  • User
    • 이메일, 비밀번호 등 인증·인가 중심의 정보를 담당한다.
  • Profile
    • 닉네임, 프로필 이미지 등 화면 표시용 정보를 관리한다.
    • 유저 1명당 프로필 1개라서 User(1):Profile(1) 로 설계했다.
  • Address
    • 지역 기반 검색이나 서비스 확장을 고려한 위치 정보를 담당한다.
    • 유저 1명당 여러개의 주소를 가질 수 있게 User(1):Address(N) 으로 설계했다.

게시판 : Board / Post / PostComment / PostLike

  • Board
    • 게시글을 코드로 구분하는 것 담당한다.
    • 하나의 카테고리에 여러 개의 게시글이 등록될 수 있기 때문에 Board(1) : Post(N) 로 설계했다.
  • Post
    • 게시글을 올릴 때 필요한 정보를 담당한다.
    • 좋아요 수, 조회 수는 +1 씩 업데이트 한다.
    • 유저 한 명이 여러 게시글을 작성할 수 있도록 User(1) : Post(N) 로 설계했다.
  • PostComment
    • 게시글에 달리는 1차 댓글을 담당한다.
    • 한 게시글에 여러 댓글이 달릴 수 있으므로 Post(1) : PostComment(N) 으로 설계했다.
    • 유저 한 명이 여러 댓글을 작성할 수 있도록 User(1) : PostComment(N) 로 설계했다.
    • 댓글과 대댓글의 관계는 재귀적인 관계를 사용했다.
      • 댓글이 다른 댓글의 부모가 되고, 자식이 될 수 있다.
  • PostLike
    • 게시글 좋아요를 담당한다.
    • 게시물별 회원별 한번씩만 좋아요가 가능해야 하기 때문에 별도 테이블로 분리했다.
    • User(1) : PostLike(N), Post(1) : PostLike(N) 관계를 가진다.

런닝 코스 : Course / RunningRecord / RunningCourseComment / RunningCourseLike / RunningCourseBookmark

  • Course
    • 러닝 코스의 핵심 정보를 담당한다.
    • 공개 범위를 통해 코스 노출을 제어할 수 있다.
    • 좋아요 수, 조회 수, 북마크 수, 댓글 수는 조회 성능을 고려해 컬럼으로 관리한다.
    • 유저 한 명이 여러 코스를 등록할 수 있도록 User(1) : Course(N) 관계로 설계했다.
  • RunningRecord
    • 사용자의 실제 러닝 기록을 담당한다.
    • 하나의 코스에 여러 러닝 기록이 쌓일 수 있으므로 Course(1) : RunningRecord(N) 관계로 설계했다.
    • 유저 한 명이 여러 러닝 기록을 가질 수 있도록 User(1) : RunningRecord(N) 관계로 설계했다.
  • RunningCourseComment
    • 러닝 코스에 달리는 댓글을 담당한다.
    • 하나의 코스에 여러 댓글이 달릴 수 있으므로 Course(1) : RunningCourseComment(N) 관계로 설계했다.
    • 유저 한 명이 여러 댓글을 작성할 수 있도록 User(1) : RunningCourseComment(N) 관계로 설계했다.
  • RunningCourseLike
    • 러닝 코스 좋아요 정보를 담당한다.
    • 유저는 하나의 코스에 한 번만 좋아요를 누를 수 있도록 별도 테이블을 분리했다.
    • User(1) : RunningCourseLike(N), Course(1) : RunningCourseLike(N) 관계를 가진다.
  • RunningCourseBookmark
    • 러닝 코스 북마크 정보를 담당한다.
    • 자주 사용하는 코스를 저장해두기 위한 기능으로 별도 테이블로 분리했다.
    • 유저 한 명이 여러 코스를 북마크할 수 있도록 User(1) : RunningCourseBookmark(N), Course(1) : RunningCourseBookmark(N) 관계로 설계했다.

채팅 : ChatRoom / Chat / Message

  • ChatRoom
    • 채팅이 이루어지는 공간(방) 을 담당한다.
    • 1:1 채팅과 그룹 채팅을 구분할 수 있다.
    • 그룹 채팅의 경우 크루 단위로 묶일 수 있도록 crew_id 를 통해 확장 가능하게 설계했다.
  • Chat
    • 채팅방에 참여한 사용자 정보를 담당하는 중간 테이블이다.
    • User(1) : Chat(N), ChatRoom(1) : Chat(N) 구조로 설계했다.
  • Message
    • 채팅방에서 오가는 실제 메시지 데이터를 담당한다.
    • 하나의 채팅방에는 여러 메시지가 쌓이므로 ChatRoom(1) : Message(N) 관계로 설계했다.
    • 메시지 확인 여부(is_checked)를 통해 읽음 처리 기능을 구현할 수 있도록 했다.

크루 : Crew / CrewMember

  • Crew
    • 러닝 크루의 기본 정보를 담당한다.
    • 크루를 생성한 사용자를 명확히 하기 위해 crew_owner_id를 별도로 관리한다.
    • 하나의 크루에는 여러 명의 사용자가 소속될 수 있으므로 Crew(1) : CrewMember(N) 관계로 설계했다.
  • CrewMember
    • 크루에 소속된 사용자 정보를 담당하는 중간 테이블이다.
    • 유저와 크루는 N:M 관계이므로 별도 테이블로 분리했다.
    • 크루 내 역할을 구분하기 위해 role(MEMBER / LEADER / MANAGER) 컬럼을 사용했다.
    • 유저 한 명은 여러 크루에 가입할 수 있고, 하나의 크루에는 여러 유저가 참여할 수 있도록
    • User(1) : CrewMember(N), Crew(1) : CrewMember(N) 구조로 설계했다.

이번 ERD는 러닝 코스 공유와 커뮤니티 기능을 구현하기 위한 초기 설계안이다.
구현 과정에서 성능, 확장성, 유지보수를 고려해 테이블 구조와 관계는 충분히 변경될 수 있다.
변경 사항이 생길 경우 설계 의도와 함께 지속적으로 업데이트할 예정이다.


참고자료

https://kimseungjae.tistory.com/44

https://dataspace01.tistory.com/47

https://velog.io/@live_in_truth/ManyToOnefetch-FetchType.LAZY-JoinColumnname-parentid-private-Comment-parent

https://wans1027.tistory.com/20