본격적으로 시작하기에 앞서 도메인 별로 모듈을 분리를 한다면 그에 따라 Entity도 각자 가지고 있을 것이고 만약 이 Entity들이 다른 도메인에서도 사용된다면(연관 관계 등에 의해서) 공통 모듈로 분리하는 것이 좋다고 생각이 되었다.
우선 로그인 기능을 붙이고 싶었다.
로그인, 회원 가입 등이 발생하는 Auth-API와 사용자들 관련 Member-API 두 가지를 만드려 하니 두 곳 모두 Member라는 Entity가 공통으로 사용될 것 같다고 생각이 되었다.
그래서 Entity를 분리하기로 했고 Member와 MemberInfo로 나누어서 관계 설정하여 모듈화 시켜보겠다.
Auth-API , Entity 모듈 생성
이전의 멀티 모듈 프로젝트 생성 과정에서 본 것과 같이 auth-api , entity 모듈을 생성해 준다.
기능은 회원 가입, 로그인 등의 기능만을 넣을 것이고 entity 모듈은 Entity만 관리할 것이다.
생성 후 위와 같은 구조를 이룰 것이다.
이전의 공통 응답 모듈에서는 단순 클래스만 있어 어떤 의존성도 추가해주지 않았지만 Entity의 경우 JPA의존성을 추가해 주어야 한다. 그래야 @Entity, @Id 등의 어노테이션을 사용할 수 있다.
build.gradle (common-entity 모듈)
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //JPA
}
Entity 모듈
Entity의 경우 이전에 API 테스트를 위해 만들었떤 Member와 이 사용자의 상세 정보를 담을 MemberInfo를 만들어보았다.
프로젝트 규모가 커질수록 여러 Entity가 생길 것이라 생각하여 같은 유형끼리 패키지로 묶었다.
member/Member (common-entity 모듈)
package com.seungh1024.member;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "member")
@Getter
@NoArgsConstructor
public class Member {
@Id
@Column(name = "member_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int memberId;
@Column(name = "member_email", unique = true)
private String memberEmail;
@Column(name = "member_password")
private String memberPassword;
@Column(name = "member_name")
private String memberName;
//상세 정보와 1:1 매핑
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "info_id")
private MemberInfo memberInfo;
@Builder
public Member(int memberId, String memberEmail, String memberPassword, String memberName){
this.memberId = memberId;
this.memberEmail = memberEmail;
this.memberPassword = memberPassword;
this.memberName = memberName;
}
public void updatePassword(String memberPassword){
this.memberPassword = memberPassword;
}
}
member/MemberInfo (common-entity 모듈)
package com.seungh1024.member;
import jakarta.persistence.*;
@Entity
public class MemberInfo {
@Id
@Column(name = "info_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int infoId;
@Column(name = "member_age")
private int memberAge;
}
Member Entity를 보면 연관 관계 설정이 된 것을 볼 수 있다.
MemberInfo와 1:1(One To One) 매핑했으며 테이블 생성 시에 FK로 info_id를 가질 것이다.
여기서 주의할 점이 fetch 옵션으로 LAZY를 주었는데 기본적으로 EAGER로 설정되어 있다.
EAGER는 즉시 로딩으로 연관 관계로 매핑된 데이터를 같이 조회하여 불필요한 조회가 발생한다.
LAZY 옵션을 사용하면 한 번에 즉시 조회하지 않고 연관 관계에 있는 객체에 접근할 때 쿼리문이 발생하고 데이터를 얻어온다. 즉, member.getMemberInfo() 이런식으로 접근해야지 쿼리가 발생하고 데이터를 가져온다.
auth-api 모듈
우선 Entity를 사용하기 위해 의존성을 추가한다
build.gradle (auth-api 모듈)
bootJar{
enabled = true
}
jar{
enabled = false
}
dependencies {
implementation project(':common-response')
implementation project(':common-entity')
runtimeOnly 'mysql:mysql-connector-java' //MySQL
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //JPA
implementation 'org.springframework.boot:spring-boot-starter-validation' //@Valid
}
공통 응답과 Entity를 추가하고 나머지 필요한 의존성을 추가해 주었다.
추가적으로 이전 member-api모듈을 다루며 설정했던 파일들을 가져온다.
env파일, application.yml 등 서비스 실행에 필요한 요소들을 가져오면 아래와 같은 형태일 것이다.
이대로 실행을 하면 Entity를 읽어서 테이블을 생성해 준다.
사실 다른 모듈에 있어서 Entity클래스를 읽어줄 추가 작업이 필요할 것이라고 생각했지만 손쉽게 해결되어 좋았다.
이전의 member테이블을 제거 후 프로그램을 실행하니
테이블 2개를 생성하고 관계 설정까지 전부 해준 것을 확인할 수 있었다.
직접 MySQL에 접속하여 확인 해보니 설계한대로 잘 생성된 것을 확인할 수 있었다.
'Java > Spring boot 프로젝트' 카테고리의 다른 글
Spring Security + JWT 적용하기(2) - 게시판 만들기(11) (0) | 2023.04.06 |
---|---|
Spring Security + JWT 적용하기(1) - 게시판 만들기(10) (0) | 2023.04.06 |
@Valid를 이용한 객체 유효성 검증 - 게시판 만들기(8) (0) | 2023.03.17 |
Spring Entity와 DTO 구분하기 -게시판 만들기(7) (0) | 2023.03.16 |
@ControllerAdvice를 사용한 예외 처리,에러 핸들링 - 게시판 만들기 (6) (0) | 2023.03.16 |