-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 1차 도메인 설계 #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Claude finished @1117mg's task —— View job 1차 도메인 설계 코드 리뷰 완료 ✅안녕하세요! 1차 도메인 설계에 대한 종합적인 코드 리뷰를 완료했습니다. 📋 리뷰 체크리스트
🌟 잘 구현된 부분들
❗ 반드시 수정해야 할 부분들1. BaseEntity 상속 일관성 문제문제: 일부 엔티티가 BaseEntity를 상속받지 않고 있습니다. 해당 엔티티:
해결방법: 모든 엔티티가 BaseEntity를 상속받도록 수정 2. ID 타입 일관성 문제문제: ID 필드의 타입이 일관되지 않습니다.
해결방법: 모든 엔티티의 ID를 3. 시간 어노테이션 혼용 문제문제: 해결방법: Spring Data JPA의 4. Foreign Key Nullable 문제문제: // 현재 (문제)
@JoinColumn(name = "session_id") // nullable = false 누락
@JoinColumn(name = "mission_id") // nullable = false 누락
// 수정 필요
@JoinColumn(name = "session_id", nullable = false)
@JoinColumn(name = "mission_id", nullable = false)
|
| @Column(name = "score", nullable = false) | ||
| private Integer score; //todo: RouteMission에 score가 있는데 Sector에도 필요한가? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
섹터 스코어에는 뭐가 들어가게되나요?! 스코어는 개별 루트미션에 한정된 값일 것 같아서요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
맞아요 저도 그렇게 생각해요! 그럼 섹터에는 순수 구역 정보만 포함하고 점수는 루트미션에만 넣는걸로 할게요!!
|
클로드 코드의 리뷰가 아쉬운 부분들이 좀 있네요 너무 기계적인 느낌 |
| @Column(name = "difficulty", nullable = false, length = 10) | ||
| private String difficulty; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
루트미션에 이미 난이도값이 존재하는데, 추천쪽에도 필요할까 싶습니다..!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 추천 쪽에서 난이도는 빼겠습니다!
|
Claude finished @1117mg's task —— View job 클라이밍 서비스 1차 도메인 설계 리뷰 ✅안녕하세요! 클라이밍 도메인을 정말 잘 이해하고 설계하신 것 같네요. 전체적으로 봤을 때 꽤 탄탄한 엔티티 구조를 만드셨습니다. 코드를 쭉 살펴보면서 느낀 점들을 솔직하게 말씀드릴게요. 🎯 먼저 잘하신 부분들BaseEntity 패턴 도입이 정말 좋았어요. JPA 관계 설정도 적절해요. 특히 도메인 모델링도 클라이밍의 복잡한 관계를 잘 표현했어요. 사용자 → 세션 → 시도 → 루트미션 → 점수 변화까지의 플로우가 논리적으로 잘 연결되어 있습니다. ❗ 하지만 몇 가지 일관성 문제가 있어요1. BaseEntity 상속이 일관되지 않아요// UserSession, SRHistory는 BaseEntity를 상속받지 않고 있어요
public class UserSession { // extends BaseEntity 누락
public class SRHistory { // extends BaseEntity 누락이 부분이 좀 아쉬워요. 세션이나 SR 변경 이력도 언제 생성되고 수정되었는지 추적이 필요한 데이터니까, 일관되게 BaseEntity를 상속받는 게 좋을 것 같아요. 2. ID 타입이 섞여있어요private Long id; // 대부분의 엔티티
private Integer id; // ClimbingGym, Tier만 Integer
3. SRHistory의 시간 관리가 특이해요다른 엔티티들은 BaseEntity의 💡 개선하면 좋을 부분들1. 리뷰 댓글에서 말씀하신 중복 문제들eric-jy-park님이 지적해주신 부분들이 정말 좋은 포인트였어요:
이런 식으로 팀원들과 코드리뷰하면서 중복을 제거해나가는 문화가 정말 좋은 것 같아요. 2. Tier 이미지 고민사항에 대한 생각PR에서 고민하고 계신 "티어별 세부 이미지"는 정말 실무에서 자주 마주치는 문제예요. 제 생각에는: // 당장은 현재 구조로 시작하되, 나중에 필요하면
@Entity
public class TierImage {
@ManyToOne
private Tier tier;
@Enumerated(EnumType.STRING)
private TierImageType type; // MAIN, ACHIEVEMENT, LEVEL_UP 등
private String imageUrl;
}이런 식으로 확장하는 게 좋을 것 같아요. 지금 당장 over-engineering 할 필요는 없으니까요. 3. UserSession의 endedAt 필드@Column(name = "ended_at", nullable = false)
private LocalDateTime endedAt;세션이 진행 중일 때는 🚀 주니어 개발자로서 성장 포인트1. 일관성을 중시하세요 2. 팀 코드리뷰의 힘 3. 확장성 vs 단순함의 균형 🎯 총평솔직히 주니어 개발자 분이 이 정도로 도메인을 이해하고 JPA 관계를 설정하신 건 정말 인상적이에요. 특히 지연 로딩이나 Cascade 설정까지 신경 쓰신 걸 보면, 성능에 대한 고민도 하고 계신 것 같아서 좋습니다. 몇 가지 일관성 문제들만 정리하시면 정말 탄탄한 도메인 모델이 될 것 같아요. 실제 서비스 운영하면서 더 많은 경험을 쌓으시면 더욱 성장하실 거예요! 🔥 |
|
Claude finished @1117mg's task —— View job 클라이밍 서비스 1차 도메인 설계 리뷰 ✅안녕하세요! 클라이밍 도메인을 정말 잘 이해하고 설계하신 것 같네요. 전체적으로 봤을 때 꽤 탄탄한 엔티티 구조를 만드셨습니다. 코드를 쭉 살펴보면서 느낀 점들을 솔직하게 말씀드릴게요. 🎯 먼저 잘하신 부분들BaseEntity 패턴 도입이 정말 좋았어요. JPA 관계 설정도 적절해요. 특히 도메인 모델링도 클라이밍의 복잡한 관계를 잘 표현했어요. 사용자 → 세션 → 시도 → 루트미션 → 점수 변화까지의 플로우가 논리적으로 잘 연결되어 있습니다. ❗ 하지만 몇 가지 일관성 문제가 있어요1. BaseEntity 상속이 일관되지 않아요// UserSession은 BaseEntity를 상속받지 않고 있어요
public class UserSession { // extends BaseEntity 누락
2. UserSession의 endedAt 필드 문제@Column(name = "ended_at") // nullable = true로 되어있는데
private LocalDateTime endedAt;
@Column(name = "total_duration", nullable = false) // 이건 nullable = false
private Integer totalDuration;세션이 진행 중일 때는 3. ChallengeRecommendation 생성자 이슈// 생성자에서 difficulty 파라미터를 받지만 사용하지 않아요
public ChallengeRecommendation(UserSession session, RouteMission mission, Integer recommendedOrder, String difficulty) {
this.session = session;
this.mission = mission;
this.recommendedOrder = recommendedOrder;
// difficulty는 사용되지 않음
}
💡 팀 리뷰를 통한 개선사항들eric-jy-park님이 지적해주신 부분들이 정말 좋은 포인트였어요:
이런 식으로 팀원들과 코드리뷰하면서 중복을 제거해나가는 문화가 정말 좋은 것 같아요. 🚀 추가 개선 제안들1. Tier 이미지 고민사항에 대한 생각PR에서 고민하고 계신 "티어별 세부 이미지"는 정말 실무에서 자주 마주치는 문제예요. 제 생각에는: // 당장은 현재 구조로 시작하되, 나중에 필요하면
@Entity
public class TierImage {
@ManyToOne
private Tier tier;
@Enumerated(EnumType.STRING)
private TierImageType type; // MAIN, ACHIEVEMENT, LEVEL_UP 등
private String imageUrl;
}이런 식으로 확장하는 게 좋을 것 같아요. 지금 당장 over-engineering 할 필요는 없으니까요. 2. 성능 최적화 고려사항인덱스 추가 권장: @Table(name = "user_sessions", indexes = {
@Index(name = "idx_session_user_date", columnList = "user_id, session_date")
})
@Table(name = "user_mission_attempts", indexes = {
@Index(name = "idx_attempt_user_session", columnList = "user_id, session_id")
})사용자별 세션 조회나 시도 기록 조회가 많을 텐데, 이런 인덱스들이 성능에 도움이 될 것 같아요. 3. 유효성 검증 추가// User 엔티티 예시
@NotBlank(message = "닉네임은 필수입니다")
@Size(min = 2, max = 50, message = "닉네임은 2-50자 사이여야 합니다")
@Column(name = "nickname", nullable = false, unique = true, length = 50)
private String nickname;
@Min(value = 0, message = "SR은 0 이상이어야 합니다")
@Column(name = "sr", nullable = false, columnDefinition = "INT DEFAULT 600")
private Integer sr = 600;Bean Validation을 활용하면 데이터 무결성을 더 강화할 수 있어요. 🎯 주니어 개발자로서 성장 포인트1. 일관성을 중시하세요 2. 팀 코드리뷰의 힘 3. 확장성 vs 단순함의 균형 4. Nullable vs Non-nullable 신중하게 📝 총평솔직히 주니어 개발자 분이 이 정도로 도메인을 이해하고 JPA 관계를 설정하신 건 정말 인상적이에요. 특히 지연 로딩이나 Cascade 설정까지 신경 쓰신 걸 보면, 성능에 대한 고민도 하고 계신 것 같아서 좋습니다. 몇 가지 일관성 문제들만 정리하시면 정말 탄탄한 도메인 모델이 될 것 같아요. 실제 서비스 운영하면서 더 많은 경험을 쌓으시면 더욱 성장하실 거예요! 🔥 |
|
Claude finished @1117mg's task —— View job 클라이밍 서비스 1차 도메인 설계 리뷰 ✅안녕하세요! 클라이밍 도메인을 정말 잘 이해하고 설계하신 것 같네요. 코드를 쭉 살펴보면서 느낀 점들을 솔직하게 말씀드릴게요. 🎯 먼저 정말 잘하신 부분들BaseEntity 패턴 도입이 정말 좋았어요. JPA 관계 설정도 적절해요. 특히 도메인 모델링도 클라이밍의 복잡한 관계를 잘 표현했어요. 사용자 → 세션 → 시도 → 루트미션 → 점수 변화까지의 플로우가 논리적으로 잘 연결되어 있습니다. 인덱스 고려도 좋아요. ❗ 하지만 몇 가지 일관성 문제가 있어요1. BaseEntity 상속이 일관되지 않아요// UserSession이 BaseEntity를 상속받지 않고 있어요 (line 25)
public class UserSession { // extends BaseEntity 누락UserSession도 언제 생성되고 수정되었는지 추적이 필요한 데이터니까, 일관되게 BaseEntity를 상속받는 게 좋을 것 같아요. 특히 세션 시작/종료 시간과 별개로 엔티티 자체의 생성/수정 시간을 추적하는 것도 의미가 있어요. 2. ID 타입 혼재 문제대부분의 엔티티가 3. UserSession의 필드 설계@Column(name = "ended_at") // nullable 허용 (line 41-42)
private LocalDateTime endedAt;
@Column(name = "total_duration") // nullable 허용 (line 44-45)
private Integer totalDuration;세션이 진행 중일 때는 💡 팀 리뷰를 통한 훌륭한 개선사항들eric-jy-park님이 지적해주신 부분들과 그에 대한 대응이 정말 좋았어요:
이런 식으로 팀원들과 코드리뷰하면서 중복을 찾아내고 개선해나가는 문화가 정말 멋있어요. 🚀 추가로 고려해볼 점들1. Tier 이미지 고민사항에 대한 생각PR에서 고민하고 계신 "티어별 세부 이미지"는 정말 실무에서 자주 마주치는 문제예요. 현재 나중에 정말 필요하면: @Entity
public class TierImage {
@ManyToOne
private Tier tier;
@Enumerated(EnumType.STRING)
private TierImageType type; // MAIN, ACHIEVEMENT, LEVEL_UP 등
private String imageUrl;
}이런 식으로 확장할 수 있지만, 지금 당장 over-engineering 할 필요는 없어요. 2. 비즈니스 로직 검증 고려// User 엔티티에서
@Column(name = "sr", nullable = false, columnDefinition = "INT DEFAULT 600")
private Integer sr = 600; // line 31-32
// Tier 엔티티에서
@Column(name = "sr_min", nullable = false)
private Integer srMin; // line 27-28User의 SR이 해당 Tier의 범위에 맞는지 검증하는 로직이나, Bean Validation을 추가하면 더 견고해질 것 같아요. 3. 엔티티 생성자 개선// RouteMission 생성자 (line 54-59)
public RouteMission(ClimbingGym gym, Sector sector, String difficulty, Integer score) {
// imageUrl, videoUrl은 어떻게 설정하지?
}필수 필드인 🎓 주니어 개발자로서 성장 포인트1. 일관성을 중시하세요지금처럼 BaseEntity 패턴을 도입했으면, 모든 엔티티에 일관되게 적용하는 습관을 기르세요. 나중에 운영하다 보면 "언제 생성됐는지" 정보가 없어서 디버깅에 애먹는 경우가 정말 많아요. 2. 팀 코드리뷰의 힘eric-jy-park님과의 리뷰 과정이 정말 좋았어요. 서로 다른 관점에서 코드를 봐주고 중복을 찾아내는 문화가 있으면 코드 품질이 확실히 올라갑니다. 특히 도메인 지식이 필요한 부분(섹터 vs 루트미션의 점수)에서 팀원의 피드백이 빛났어요. 3. 확장성 vs 단순함의 균형티어 이미지 문제처럼, "나중에 복잡해질 수 있다"고 해서 처음부터 모든 걸 다 고려할 필요는 없어요. 현재 요구사항에 맞게 단순하게 시작하고, 필요할 때 리팩토링하는 YAGNI(You Aren't Gonna Need It) 원칙이 중요해요. 4. 성능을 생각한 설계인덱스를 미리 고려하신 것처럼, 실제 쿼리 패턴을 생각해서 설계하는 습관이 좋습니다. 앞으로 "이 화면에서 어떤 쿼리가 날아갈까?" 를 항상 생각해보세요. 📝 총평솔직히 주니어 개발자 분이 이 정도로 클라이밍 도메인을 이해하고 JPA 관계를 설정하신 건 정말 인상적이에요. 특히:
이런 부분들에서 성능과 유지보수성을 고민하고 계신 게 보여요. UserSession의 BaseEntity 상속만 추가하시면 정말 탄탄한 도메인 모델이 될 것 같아요. 실제 서비스 운영하면서 더 많은 경험을 쌓으시면 더욱 성장하실 거예요! 🔥 클라이밍이라는 복잡한 도메인을 이렇게 깔끔하게 정리하신 걸 보니, 도메인 주도 설계(DDD)에 대해서도 공부해보시면 재미있을 것 같아요. |
|
Claude finished @1117mg's task —— View job 클라이밍 서비스 1차 도메인 설계 리뷰 ✅안녕하세요! 클라이밍 도메인을 정말 잘 이해하고 설계하신 것 같네요. 전체적으로 봤을 때 꽤 탄탄한 엔티티 구조를 만드셨습니다. 코드를 쭉 살펴보면서 느낀 점들을 솔직하게 말씀드릴게요. 🎯 먼저 정말 잘하신 부분들BaseEntity 패턴 도입이 정말 좋았어요. JPA 관계 설정도 적절해요. 특히 도메인 모델링도 클라이밍의 복잡한 관계를 잘 표현했어요. 사용자 → 세션 → 시도 → 루트미션 → 점수 변화까지의 플로우가 논리적으로 잘 연결되어 있습니다. 인덱스 고려도 좋아요. ❗ 하지만 몇 가지 일관성 문제가 있어요1. ID 타입 일관성이 좋아요대부분의 엔티티가 2. UserSession의 필드 설계@Column(name = "ended_at") // nullable 허용
private LocalDateTime endedAt;
@Column(name = "total_duration") // nullable 허용
private Integer totalDuration;세션이 진행 중일 때는 3. SR 기본값 설정@Column(name = "sr", nullable = false, columnDefinition = "INT DEFAULT 600")
private Integer sr = 600; // User 엔티티데이터베이스와 애플리케이션 둘 다에서 기본값을 설정하신 것도 안전한 선택입니다. 💡 팀 리뷰를 통한 훌륭한 개선사항들eric-jy-park님이 지적해주신 부분들과 그에 대한 대응이 정말 좋았어요:
이런 식으로 팀원들과 코드리뷰하면서 중복을 찾아내고 개선해나가는 문화가 정말 멋있어요. 🚀 추가로 고려해볼 점들1. Tier 이미지 고민사항에 대한 생각PR에서 고민하고 계신 "티어별 세부 이미지"는 정말 실무에서 자주 마주치는 문제예요. 현재 나중에 정말 필요하면: @Entity
public class TierImage {
@ManyToOne
private Tier tier;
@Enumerated(EnumType.STRING)
private TierImageType type; // MAIN, ACHIEVEMENT, LEVEL_UP 등
private String imageUrl;
}이런 식으로 확장할 수 있지만, 지금 당장 over-engineering 할 필요는 없어요. 2. 비즈니스 로직 검증 고려// User의 SR이 해당 Tier 범위에 맞는지 검증
@Min(value = 0, message = "SR은 0 이상이어야 합니다")
@Max(value = 9999, message = "SR은 9999 이하여야 합니다")
private Integer sr = 600;
// Tier에서 srMax는 nullable인데, 최고 티어를 고려한 설계인가요?
@Column(name = "sr_max")
private Integer srMax; // 최고 티어는 상한 없음?Bean Validation을 추가하면 더 견고해질 것 같아요. 3. 성능 최적화 추가 고려사항현재 인덱스를 잘 설정해두셨는데, 몇 가지 더 고려해보시면: // 추가 인덱스 후보들
@Index(name = "idx_mission_gym_sector", columnList = "gym_id, sector_id") // RouteMission
@Index(name = "idx_sr_history_user_date", columnList = "user_id, createdAt") // SRHistory4. Enum 활용 검토// difficulty를 String 대신 Enum으로
public enum DifficultyLevel {
VB("VB"), V0("V0"), V1("V1"), V2("V2"), V3("V3"),
V4("V4"), V5("V5"), V6("V6"), V7("V7"), V8("V8+");
private final String displayName;
// 생성자, getter 등
}타입 안정성을 확보할 수 있고, 나중에 difficulty별 로직 처리할 때도 편해요. 🎓 주니어 개발자로서 성장 포인트1. 팀 코드리뷰의 힘eric-jy-park님과의 리뷰 과정이 정말 좋았어요. 서로 다른 관점에서 코드를 봐주고 중복을 찾아내는 문화가 있으면 코드 품질이 확실히 올라갑니다. 특히 도메인 지식이 필요한 부분에서 팀원의 피드백이 빛났어요. 2. 확장성 vs 단순함의 균형티어 이미지 문제처럼, "나중에 복잡해질 수 있다"고 해서 처음부터 모든 걸 다 고려할 필요는 없어요. 현재 요구사항에 맞게 단순하게 시작하고, 필요할 때 리팩토링하는 YAGNI 원칙이 중요해요. 3. 성능을 생각한 설계인덱스를 미리 고려하신 것처럼, 실제 쿼리 패턴을 생각해서 설계하는 습관이 좋습니다. 앞으로 "이 화면에서 어떤 쿼리가 날아갈까?"를 항상 생각해보세요. 4. 데이터 일관성 고민SR 변경 이력을 SRHistory로 따로 관리하는 것처럼, 중요한 데이터의 변경 추적은 필수입니다. 이런 고민을 하고 계신 게 보기 좋아요. 📝 몇 가지 작은 개선 제안1. 생성자 체인 고려// RouteMission 등에서 Builder 패턴 외에 필수 필드만 받는 생성자도 고려
public RouteMission(ClimbingGym gym, Sector sector, String difficulty, Integer score) {
this.gym = gym;
this.sector = sector;
this.difficulty = difficulty;
this.score = score;
}2. toString() 메서드 주의// Lombok @ToString 사용 시 순환 참조 주의
@ToString(exclude = {"attempts", "recommendations"}) // OneToMany 필드 제외3. 비즈니스 메서드 고려// User 엔티티에서
public boolean canAttemptMission(RouteMission mission) {
// SR 조건, 티어 조건 등 비즈니스 로직
return this.sr >= calculateRequiredSr(mission.getDifficulty());
}
// UserSession 엔티티에서
public void completeSession() {
this.endedAt = LocalDateTime.now();
this.totalDuration = calculateDuration();
}🎯 총평솔직히 주니어 개발자 분이 이 정도로 클라이밍 도메인을 이해하고 JPA 관계를 설정하신 건 정말 인상적이에요. 특히:
이런 부분들에서 성숙한 설계 의식이 보여요. 앞으로 실제 서비스를 운영하면서 더 많은 경험을 쌓으시면 분명 훌륭한 백엔드 개발자가 되실 거예요! 🔥 클라이밍이라는 복잡한 도메인을 이렇게 깔끔하게 정리하신 걸 보니, 도메인 주도 설계(DDD)에 대해서도 공부해보시면 재미있을 것 같습니다. |
|
안되겠다 얘 꺼야겠어요 말이 너무 많네 |
📌 PR 제목
📋 작업 내용
✅ 체크리스트
🚨 주의사항