[내일배움캠프Spring-94일차] 클럽 가입 로직 재설계 책임 주체 명확화와 도메인 분리

2025. 7. 3. 20:47·백엔드 부트캠프/TIL

1. 구현한 기능

이번에 제가 맡아 구현한 기능은 유저의 클럽 가입 흐름 전반에 대한 도메인 구조 개선입니다. 주요 작업은 다음과 같습니다:

  • 유저가 가입 가능한 클럽(모임 및 스터디) 기능 구현
  • 클럽의 가입 방식 다양화 및 클럽장이 직접 설정 가능하도록 설계
  • 가입 양식과 가입 신청을 분리하여 독립적인 관리 구조 마련
  • 향후 가입 승인, 멤버 관리, 내부 기능 확장까지 고려한 유연한 구조 설계

2. 배경

초기 설계에서는 Club, JoinRequest, JoinForm이라는 세 개의 Entity를 사용했는데요.

  • 가입 양식은 가입신청서와 문제 제출용 양식을 한 테이블에 통합
  • 가입 방식(JoinType)은 유저가 제출하는 요청(JoinRequest)에서 관리

이러한 구조는 도메인 흐름상 비자연적이며, 확장성이나 유지보수 측면에서도 여러 문제점을 갖고 있었습니다.


3. 요구사항

우리 팀이 설정한 클럽 가입 관련 요구사항은 다음과 같습니다:

  1. 클럽 생성 시, 클럽장이 가입 방식을 설정할 수 있어야 한다
  2. 가입 방식은 아래 네 가지 중 하나를 선택
    • 즉시가입 / 일반가입 / 가입양식가입 / 문제양식가입
  3. 클럽장은 가입 양식 및 문제 양식을 직접 생성하고 관리
  4. 유저는 클럽이 정한 가입 방식에 따라 가입 신청서를 제출
  5. 구조는 향후 기능 확장에 유연하게 대응 가능해야 한다

4. 주요 로직

이를 바탕으로 구현한 핵심 로직은 다음과 같습니다:

  • Club이 직접 가입 방식을 설정하며 (JoinType 필드로)
  • 가입 방식에 따라 양식 제출 플로우를 자동 제어
  • 유저는 설정된 방식에 맞춰 SubmissionForm 또는 ProblemForm을 작성하여 신청
  • 클럽장은 신청서를 확인하고 승인/거절 처리 가능
  • 양식 관계는 다음과 같이 설정:
    • SubmissionForm: Club과 1:1
    • ProblemForm: Club과 1\:N (단, 하나만 활성화 가능)

5. 의사결정 및 리팩토링 전략

1) 문제 정의 (Why)

  • 책임 주체의 혼동
    • JoinType이 유저의 요청에서 관리되고 있었지만, 실제 가입 방식의 주체는 클럽입니다.
  • 도메인 분리 원칙 위반
    • JoinForm 하나로 가입 양식과 문제 양식을 모두 처리, 역할과 책임이 불분명
  • 잘못된 연관관계
    • Club과 JoinForm이 1:1이 아닌 Many-to-One으로 설계되어 불일치 발생
  • 확장에 비유연한 구조
    • 신규 가입 방식이나 조건 추가에 대한 대응이 어려운 설계

2) 문제 분석 (What)

  • 클럽이 가입 방식을 정하고, 유저는 그에 따라 요청해야 하는데 흐름이 반대로 구현
  • 가입 양식과 문제 양식은 목적, 주체, 사용 시점이 완전히 다름
  • 따라서 역할을 구분하고, 연관관계도 명확히 재설계할 필요가 있었습니다

3) 해결 방안 (How)

새롭게 설계한 ERD는 다음과 같습니다:

  • JoinType은 JoinRequest에서 제거 → Club Entity에서 직접 관리
  • 가입 양식(SubmissionForm)과 문제 양식(ProblemForm)을 명확히 분리
  • 연관관계 재설정:
    • Club ↔ SubmissionForm: 1:1 관계
    • Club ↔ ProblemForm: 1\:N 관계 (단, 하나만 활성화)
  • 확장성을 고려해 새로운 가입 방식 추가도 쉽게 대응 가능한 구조로 설계

6. 기대 효과

효과 설명

도메인 흐름의 자연스러움 JoinType을 Club에서 관리함으로써 책임 주체가 명확해짐
유지보수성 향상 가입 양식과 문제 양식을 분리하여 각각 독립적으로 개선 가능
관계 명확화 1:1, 1\:N 관계를 명확히 설정해 JPA 매핑, DB 무결성, 가독성 향상
확장 용이성 확보 추후 가입 조건 커스터마이징, 관리자 기능 확장 등에 유리

7. 회고

1. 유저 시나리오를 설계에 더 강하게 반영했어야 했다

  • 클럽 → 가입 방식 → 유저의 요청이라는 자연스러운 흐름이 존재하는데, 초기에 요청 객체 중심의 비직관적 구조를 설계한 것이 리팩토링의 주요 원인이 됐습니다.

2. 단기 효율보다 ‘유지보수 가능한 설계’가 중요하다

  • 양식이 유사하다고 하나의 테이블로 통합한 결정은 초기에는 효율적이었지만, 결과적으로 확장성과 유지보수 비용 측면에서 더 큰 부담을 초래했습니다.

3. 설계 고민 없이 빠르게 구현하는 것이 오히려 더 느릴 수 있다

  • 초기 설계를 꼼꼼히 했더라면, 이번 리팩토링과 그에 따른 테스트, 코드 수정 비용을 크게 줄일 수 있었을 것입니다.

마무리

이번 기능은 단순한 기능 구현을 넘어서, 도메인 설계의 원칙과 책임 분리의 중요성을 다시금 체감하는 계기였습니다. 앞으로도 구조적 설계와 흐름 중심의 개발을 통해 변화에 강한 시스템을 만드는 데 집중하겠습니다.

'백엔드 부트캠프 > TIL' 카테고리의 다른 글

[내일배움캠프Spring-96일차] 문서작업 중 발견한 QueryDSL 오류 트러블슈팅 🚀🚀  (2) 2025.07.07
[내일배움캠프Spring-95일차] 동일 사용자의 빠른 중복 클릭으로 인한 중복 가입 요청 처리 실패  (0) 2025.07.04
[내일배움캠프Spring-93일차] Chunk 기반을 Tasklet 기반으로 리팩토링  (0) 2025.07.02
[내일배움캠프Spring-92일차] Spring Batch에서 Chunk는 왜 JdbcTemplate, Tasklet은 왜 JpaRepository를 많이 쓸까?  (0) 2025.07.01
[내일배움캠프Spring-91일차] Redis Redisson 기반 클럽 즉시가입 동시성 제어 구현  (0) 2025.06.30
'백엔드 부트캠프/TIL' 카테고리의 다른 글
  • [내일배움캠프Spring-96일차] 문서작업 중 발견한 QueryDSL 오류 트러블슈팅 🚀🚀
  • [내일배움캠프Spring-95일차] 동일 사용자의 빠른 중복 클릭으로 인한 중복 가입 요청 처리 실패
  • [내일배움캠프Spring-93일차] Chunk 기반을 Tasklet 기반으로 리팩토링
  • [내일배움캠프Spring-92일차] Spring Batch에서 Chunk는 왜 JdbcTemplate, Tasklet은 왜 JpaRepository를 많이 쓸까?
sintory-04
sintory-04
🚀🚀🚀
  • sintory-04
    Sintory Dev Blog
    sintory-04
    글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (290)
      • 백엔드 부트캠프 (111)
        • TIL (97)
        • WIL (0)
        • 문제풀이 (7)
        • 기타 (6)
      • 백엔드 부트캠프[사전캠프] (35)
        • TIL (16)
        • 문제풀이 (17)
        • 기타 (1)
      • Troubleshooting (11)
      • 코딩 공부 (118)
        • Java (28)
        • Baekjoon-Java (24)
        • Programmers-Java (40)
        • Spirngboot (11)
        • typescript (1)
        • JavaScript (6)
        • Spring 입문 (8)
      • 프로젝트 (1)
        • ToDoApp(FireBase) (3)
        • ToDoApp(Spring) (5)
      • 기타 (4)
  • 블로그 메뉴

    • 소개
    • Github
  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
sintory-04
[내일배움캠프Spring-94일차] 클럽 가입 로직 재설계 책임 주체 명확화와 도메인 분리
상단으로

티스토리툴바