3.22일 기준 엔티티 연관관계가 미흡하면서 발생하는 문제는 아래와 같다.
casecade
, orphanRemoval
등의 연관관계 옵션을 사용하면 객체를 자동으로 관리할 수 있다. 엔티티 구조를 리팩토링하여 기존에 수동으로 처리하던 부분을 자동화하려고 한다.
Entity Diagram - 3.22일 기준
User(사용자): X
Student(학생)
Professor(교수)
Department(학과): X
Course(과목): X
CourseOffering(연도+학기 강의 단위, 과목이 실제 개설된 시점의 정보)
StudentCourse(수강 기록)
StudentAcademicRecord(학생의 누적 성적 요약 정보)
SemesterAcademicRecord(특정 학기 성적 요약 정보)
StudentGraduationProgress(학생 졸업 요건 충족 여부)
기존 코드
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "student_id", unique = true)
private Student student;
변경 코드
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "student_id")
private Student student;
GraduationRequirement(졸업 요건 기준 - 학과 + 입학년도 기준)
DepartmentAreaRequirement(졸업 요건 세부 기준)
LiberalArtsAreaCode(교양 분류 코드): X
User
다만, 이를 응용하려면 User-Student 양방향 연관관계가 설정되어야 하지만 현재 Student 생성을 크롤링 로직에서 담당하고 있다. 추후 Student 생성 로직을 백엔드 코드로 가져오기 전까지는 User 삭제 시 studentId를 사용해 직접 Student를 제거한다.
@Transactional public void deleteUserByEmail(String email){ UUID userId = getUserId(email); userRepository.deleteById(userId); // User - Student 연관관계를 엮어 자동 삭제 로직을 만들어야 하지만, Student 저장 로직이 별도로 존재하지 않아, 연관관계를 형성하지 못함. 수정하기 전까지 임의 삭제 방식으로 진행 studentRepository.deleteById(userId); }
User 탈퇴 시 같이 삭제되어야 하는 엔티티
Student
연관관계 설정
@OneToOne(mappedBy = "student", cascade = REMOVE, orphanRemoval = true)
private StudentAcademicRecord studentAcademicRecord;
@OneToOne(mappedBy = "student", cascade = REMOVE, orphanRemoval = true)
private StudentGraduationProgress graduationProgress;
@OneToMany(mappedBy = "student", cascade = REMOVE, orphanRemoval = true)
private List<SemesterAcademicRecord> semesterAcademicRecords = new ArrayList<>();
@OneToMany(mappedBy = "student", cascade = REMOVE, orphanRemoval = true)
private List<StudentCourse> studentCourses = new ArrayList<>();
Student 삭제 시 같이 삭제되어야 하는 정보이기 때문에 cascade REMOVE, orphanRemoval 설정으로 자동 삭제 활성화
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "graduation_requirement_id")
private GraduationRequirement graduationRequirement;
CourseOffering
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "area_code")
private LiberalArtsAreaCode areaCode;
GraduationRequirement, DepartmentAreaRequirement 테이블이 따로 존재할 필요가 있을까?
둘은 역할과 범위가 다르기 때문에 분리하는 것이 적절하다.
✅ 두 테이블의 핵심 차이점
왜 분리해야할까?
통합했을 때의 문제점
✅ 결론
두 테이블은 졸업 요건
이라는 공통 주제를 다루지만, 역할이 다르기 때문에 분리 설계가 필요하다.
지금처럼 분리된 두 테이블 구조는 도메인 설계 관점에서도, 데이터베이스 정규화 관점에서도 괜찮은 구조이다.