Skip to content

멀티 호스트 지원

wlgh1553 edited this page Dec 4, 2024 · 3 revisions

📄 멀티 호스트 지원 설계 과정

  • 시작: 세션에서 호스트 권한을 멀티플하게 부여하는 기능을 추가하고자 시도.
  • 문제 발생: 조인 테이블을 도입하려던 초기 설계가 복잡해지고, 실제 요구사항과 맞지 않는 구조를 만들 가능성이 생김.
  • 최종 설계: 호스트를 슈퍼호스트(Super Host)서브호스트(Sub Host)로 구분하여, createUserId 필드를 통해 슈퍼호스트를 관리하고, isHost 필드를 통해 서브호스트 권한을 부여.

🧩 배경 및 필요성

설계 초기 목표

  • 멀티 호스트 지원:
    • 세션에서 여러 사용자가 호스트 권한을 가지도록 설계.
    • 슈퍼호스트와 서브호스트의 역할과 권한을 명확히 구분.
    • 세션 내 권한 변경과 부여 과정이 효율적이어야 함.

🗺️ 문제 해결 과정

1. 조인 테이블 방식

설계 시도:

  • 기존 테이블

    model User {
      userId        Int      @id @default(autoincrement()) @map("user_id")
      email         String   @unique
      password      String
      nickname      String   @unique
      createdAt     DateTime @default(now()) @map("created_at")
    
      sessions          Session[]          @relation("UserSessions")
      userSessionTokens UserSessionToken[] @relation("UserTokens")
    }
    
    model Session {
      sessionId     String   @id @default(uuid()) @map("session_id")
      title         String
      expiredAt     DateTime @map("expired_at")
      createdAt     DateTime @default(now()) @map("created_at")
      createUserId  Int      @map("create_user_id")
    
      user              User               @relation("UserSessions", fields: [createUserId], references: [userId])
      userSessionTokens UserSessionToken[] @relation("SessionTokens")
      questions         Question[]         @relation("SessionQuestions")
      replies           Reply[]            @relation("SessionReplies")
      chattings         Chatting[]         @relation("SessionChattings")
    }
    
    model UserSessionToken {
      token          String @id @default(uuid())
      userId         Int?   @map("user_id")
      sessionId      String @map("session_id")
    
      user           User?          @relation("UserTokens", fields: [userId], references: [userId])
      session        Session        @relation("SessionTokens", fields: [sessionId], references: [sessionId])
      questions      Question[]     @relation("TokenQuestions")
      questionLikes  QuestionLike[] @relation("TokenQuestionLikes")
      replies        Reply[]        @relation("TokenReplies")
      replyLikes     ReplyLike[]    @relation("TokenReplyLikes")
      chattings      Chatting[]     @relation("TokenChattings")
    }
  • SessionHosts 조인 테이블 추가.

model SessionHosts {
  sessionId String
  userId    Int
  role      String // "SUPER_HOST" 또는 "SUB_HOST" 지정
  session   Session @relation(fields: [sessionId], references: [sessionId])
  user      User    @relation(fields: [userId], references: [userId])
  @@id([sessionId, userId])
}

⚙️ 트러블슈팅

문제 상황

  1. 조인 테이블 설계:
    • Session과 User 간 다대다(M:N) 관계를 조인 테이블로 관리하려 함.
    • 조인 테이블 설계로 인해 권한 계층 구조를 구현하는데 복잡성이 증가.
    • 토큰기반 식별이기 때문에 토큰조회 → userId → sessionId, userId를 가지고 SessionHosts 테이블 조회라는 복잡한 과정이 생김.
    • 실제 구현에서 슈퍼호스트는 단일 사용자로 제한되는데, 조인 테이블로 관리하는 것은 불필요한 복잡성 추가.
    • 쿼리 작성 시 성능 문제 발생 가능.
  2. 권한 계층 문제:
    • 조인 테이블만으로는 권한 계층과 역할에 대한 명확한 관리가 어려움.

해결 방안

설계 변경: 단순화된 권한 필드 사용

  • Session 모델의 createUserId 필드를 사용하여 슈퍼호스트 관리.
  • UserSessionToken 모델의 isHost 필드를 통해 서브호스트 관리. → 서브호스트의 권한만 있다면 충분한 일을 굳이 SUPER_HOST || SUB_HOST 연산을 이용하지 않아도 될 수 있게 됨.

최종 모델:

  • 슈퍼호스트: Session.createUserId 필드를 사용하여 단일 관리.
  • 서브호스트: UserSessionToken.isHost 필드를 사용하여 권한 관리.
model UserSessionToken {
  token          String @id @default(uuid())
  userId         Int?   @map("user_id")
  sessionId      String @map("session_id")
  isHost         Boolean @default(false) @map("is_host")

  user           User?          @relation("UserTokens", fields: [userId], references: [userId])
  session        Session        @relation("SessionTokens", fields: [sessionId], references: [sessionId])
  questions      Question[]     @relation("TokenQuestions")
  questionLikes  QuestionLike[] @relation("TokenQuestionLikes")
  replies        Reply[]        @relation("TokenReplies")
  replyLikes     ReplyLike[]    @relation("TokenReplyLikes")
  chattings      Chatting[]     @relation("TokenChattings")
}

최종적으로 다음과 같은 권한 정책이 생김.

특징 슈퍼 호스트(세션 생성자) 서브 호스트 기명 참가자 익명 참가자
로그인 필요 여부
세션 종료 권한
타인에게 호스트 권한 부여/해제 권한
타인의 질문 삭제 권한
타인의 답변 삭제 권한
답변에 ✔️ 뱃지 부여 및 상단으로 정렬
답변 고정 / 답변 완료 선택 권한
답변에 닉네임 명시

📈 결과 및 성과

1. 구조적 단순화

  • 조인 테이블 없이 권한을 단일 필드로 관리.
  • 데이터베이스 구조 단순화로 유지보수 용이.

2. 역할 명확화

  • 슈퍼호스트는 Session.createUserId로 관리.
  • 서브호스트는 UserSessionToken.isHost로 관리.
  • 권한 계층 및 역할 구분 명확.

3. 성능 최적화

  • 불필요한 조인 쿼리 제거로 데이터 접근 속도 향상.
  • 단일 테이블 조회로 권한 부여/해제 효율성 증가.

4. 권한 관리 로직 간소화

  • 슈퍼호스트는 세션 생성 시 자동 설정.
  • 서브호스트는 update 메서드로 권한 부여/해제.

Clone this wiki locally