Repository navigation
feat(team): 팀·팀원 엔티티와 멤버십 조회 기반 추가 - #64
Conversation
Pull Request 요약AuthorizationBeanConfig에 Authorization 관련 Bean을 신규 등록하여 인증 설정을 강화했습니다. TeamPersistenceTest의 @SpringBootTest 어노테이션에서 properties 배열 문법 오류가 발견되어 수정이 필요합니다. 팀·팀원 엔티티와 V3 마이그레이션, 팀원 ID 생성기, 로컬 시드 데이터, 그리고 TeamService에 권한 조회 메서드를 추가하여 팀 관리 기능을 확장했습니다. 복수 모델 · 입력 25,467 · 출력 2,910 · 합계 28,377 토큰 |
| fun changeRole(role: TeamRole) { | ||
| this.role = role | ||
| } |
There was a problem hiding this comment.
중요 TeamMember.changeRole이 팀장 유일성을 보장하지 않는다
TeamMember.changeRole이 팀장 유일성 제약을 확인하지 않고 역할을 변경합니다. 팀에 이미 팀장이 있으면 두 번째 팀장이 생길 수 있습니다. 서비스 계층에서 중복 팀장을 방지하지 않으면 DB 부분 고유 인덱스가 위반되어 운영 장애로 이어집니다.
제안:
fun changeRole(role: TeamRole) {
this.role = role
}
복수 모델
|
|
||
| @Transactional(readOnly = true) | ||
| override fun findMemberships(userId: String): Map<String, TeamRole> = | ||
| teamMemberRepository.findAllByUserId(userId).associate { it.teamId to it.role } |
There was a problem hiding this comment.
중요 findMemberships가 중복 팀 역할을 덮어쓴다
TeamService.findMemberships가 associate로 팀 id를 키로 삼아 중복 팀이 있으면 마지막 역할만 남깁니다. 사용자가 한 팀에 여러 멤버십을 가지는 것은 UNIQUE 제약으로 막히지 않으므로 데이터 무결성 문제가 될 수 있습니다. 팀당 하나의 역할만 반환하는 계약 의도가 아니라면 중복을 처리하거나 예외를 던져야 합니다.
제안:
teamMemberRepository.findAllByUserId(userId).associate { it.teamId to it.role }
복수 모델
| fun approve() { | ||
| check(status == TeamStatus.PENDING) { "승인 대기 중인 팀만 승인할 수 있습니다." } | ||
| status = TeamStatus.APPROVED | ||
| rejectionReason = null | ||
| } | ||
|
|
||
| fun reject(reason: String) { | ||
| check(status == TeamStatus.PENDING) { "승인 대기 중인 팀만 거절할 수 있습니다." } | ||
| require(reason.isNotBlank()) { "거절 사유는 비어 있을 수 없습니다." } | ||
| status = TeamStatus.REJECTED | ||
| rejectionReason = reason | ||
| } |
There was a problem hiding this comment.
경미 Team 상태 전이가 비멱등이다
Team.approve와 reject가 PENDING 상태가 아니면 check로 실패합니다. 이미 승인되거나 거절된 팀을 다시 처리하려 하면 예외가 발생하며, 이는 의도된 상태 전이 보호로 보입니다. 재실행 시 멱등성을 기대하는 호출자에는 영향을 줄 수 있습니다.
제안:
fun approve() {
check(status == TeamStatus.PENDING) { "승인 대기 중인 팀만 승인할 수 있습니다." }
status = TeamStatus.APPROVED
rejectionReason = null
}
fun reject(reason: String) {
check(status == TeamStatus.PENDING) { "승인 대기 중인 팀만 거절할 수 있습니다." }
require(reason.isNotBlank()) { "거절 사유는 비어 있을 수 없습니다." }
status = TeamStatus.REJECTED
rejectionReason = reason
}
복수 모델
| --- | ||
| spring: | ||
| config: | ||
| activate: | ||
| on-profile: local | ||
| flyway: | ||
| locations: classpath:db/migration,classpath:db/dev |
There was a problem hiding this comment.
경미 local 프로필에만 db/dev 시드가 적용된다
application.yml에 local 프로필 전용 flyway locations이 추가되었습니다. db/dev 디렉터리의 시드 파일이 local 프로필에서만 실행되며, 다른 프로필에는 적용되지 않습니다. 이는 의도된 로컬 전용 시드로 보이나 배포 환경과 스키마 불일치 가능성을 인지해야 합니다.
제안:
---
spring:
config:
activate:
on-profile: local
flyway:
locations: classpath:db/migration,classpath:db/dev
복수 모델
Pull Request 요약AuthorizationBeanConfig에 신규 Bean을 등록하여 인증 설정을 보강했습니다. 팀과 팀원 엔티티를 도입하고 DB 제약으로 팀장·멤버 중복을 방지하며, 해당 서비스·리포지토리에서 멤버십 조회를 제공하고 로컬 테스트용 시드 데이터를 추가했습니다. 복수 모델 · 입력 44,466 · 출력 7,661 · 합계 52,127 토큰 |
| val teamId: String, | ||
| @Column(name = "user_id", length = 17, nullable = false) | ||
| val userId: String, | ||
| role: TeamRole, |
There was a problem hiding this comment.
중요 엔티티 필드 중복 정의로 인한 런타임 오류 가능성
Team 엔티티와 마찬가지로 생성자 파라미터와 클래스 몸체에서 role 필드를 중복 정의하고 있습니다. 이는 JPA 엔티티 매핑 시 예상치 못한 동작을 유발할 수 있습니다.
같은 원인의 다른 위치: src/main/kotlin/com/gsmsv/api/team/domain/Team.kt:19-23
제안:
class TeamMember(
@Id
@Column(length = 16, nullable = false)
val id: String,
@Column(name = "team_id", length = 17, nullable = false)
val teamId: String,
@Column(name = "user_id", length = 17, nullable = false)
val userId: String,
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 16)
var role: TeamRole,
) {
복수 모델
There was a problem hiding this comment.
중요: TeamMember 엔티티의 role 필드 중복 정의가 해결되었습니다.
생성자 파라미터를 initialRole로 변경하고, 실제 엔티티 필드는 @Enumerated와 @Column 어노테이션이 적용된 role 프로퍼티로 선언했습니다.
이 구조는 JPA 매핑 시 하나의 컬럼만 사용되므로 런타임 오류 위험이 사라집니다.
추가로 role을 private set으로 제한하고 changeRole 메서드에서만 수정하도록 하여 캡슐화가 강화되었습니다.
다른 파일(Team.kt)에서도 동일 패턴을 적용해 동일 문제가 없도록 확인이 필요합니다.
GPT-OSS 120B · 입력 1,852 · 출력 179 · 합계 2,031 토큰
Summary
Team·TeamMember엔티티와 V3 마이그레이션을 추가하고, 중복 멤버십과 복수 팀장을 DB에서 막음TeamService가TeamReader·TeamMembershipReader를 구현하고, 멤버십을 요청마다 DB에서 조회하도록 연결mbr-id 생성기와 local 프로필 전용 테스트 사용자·팀 시드 추가Test plan
./gradlew compileKotlin compileTestKotlin ktlintCheck./gradlew test --tests 'com.gsmsv.api.team.service.TeamServiceTest' --tests 'com.gsmsv.api.team.domain.TeamTest' --tests 'com.gsmsv.api.global.grn.IdGeneratorTest' --tests 'com.gsmsv.api.global.authorization.*'./gradlew test --tests 'com.gsmsv.api.team.TeamPersistenceTest'(Docker 데몬이 없어 PostgreSQL 통합 테스트 실행 불가)관련 이슈
Closes #58
확인