[F-Lab 모각코 챌린지 51일차] Embedded 써보기, ERD

부추·2023년 7월 21일
0

F-Lab 모각코 챌린지

목록 보기
51/66

1. @Embedded

Person 엔티티를 다음과 같이 구성했다.

@Entity
@Getter
@Builder
@AllArgsConstructor
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Enumerated(EnumType.STRING)
    private Gender gender;

    // address
    private String shi;
    private String gu;
    private String ro;
    private String detail;
    private String zipCode;
}
  • DB에 저장될 PK값 id를 필드로 갖는다.
  • name은 사람의 이름이다.
  • gender은 enum 타입으로, FEMALE, MALE, UNSELECTED의 값을 갖는다.
  • shi~zipCode는 이 사람의 주소 정보를 나타낸다.

음~ 맘에 안든다. address는 "주소"라는 하나의 개념적 단위인데, 각각의 요소들이 저렇게 드러난게 좀 거슬린다. 더 심각한 문제는 repository에서 발생한다.

public interface PersonRepository {
    Optional<Person> findByName(String name);
    Optional<Person> findByShi(String shi);
    Optional<Person> findByGu(String gu);
    Optional<Person> findByRo(String ro);
    Optional<Person> findByZipCode(String zipCode);
    

    Person save(Person person);
}

특정 주소를 가진 사용자를 찾고 싶은데 repository를 이렇게 구성하면 변경에 매우매우 취약하고, 캡슐화가 똑바로 안된 코드가 되어버릴 것이다. 각각 요소를 개념적 단위로 묶어서 캡슐화 시켜 코드를 객체지향적으로 바꾸고 싶다.


그래서, DDD에서 말하는 "Value"로 address를 바꾸기로 한다. 밸류는 개념적으로 하나인 데이터를 묶고, 가독성이 좋게 표시하기 위한 수단이다. Person이 가진 address 정보를 하나의 Address 클래스로 묶어보자.

@Getter
@NoArgsConstructor
@Embeddable
public class Address {
    private String shi;
    private String gu;
    private String ro;
    private String detail;
    private String zipCode;
}
  • @Getter@NoArgsController는 Spring의 message converter가 @RequestBody로 들어온 JSON 값을 Address로 매핑하기 위해 필요한 값들이다. 간단히 말하면, 컨버터는 생성자로 객체를 만들고 getter 혹은 setter을 돌며 일치하는 필드명에 리플렉션으로 필드 값을 주입한다.
  • @Embeddable : Address가 하나의 개념적 단위인 "밸류"로서 엔티티에 존재하는 복합 필드로 존재할 수 있게 해준다.

그러면 Person의 코드는 어떻게 바뀌었을까?

@Entity
@Getter
@Builder
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Enumerated(EnumType.STRING)
    private Gender gender;
    
    @Embedded
    private Address address;
}

기존에 길게 늘어선 address 코드들이 사라졌다. 그리고 이 코드를 읽는 사람들은 Address의 클래스 이름을 보고 '이 필드 클래스는 주소 정보를 저장하고 있을 것'이라고 쉽게 예측 가능할 것이다.
ddl-auto: create 설정을 하고, h2-console에서 생성된 테이블 이름을 살펴보자. 이렇게 @Embeddable타입을 이용해도, JPA는 embedded 타입 내부의 필드를 알아서 꺼내 테이블 필드명으로 예쁘게 매칭해준다. 만약 루트 엔티티와 밸류의 property 이름이 겹치게 되면 hibernate 에러가 뜨는데, 그땐 @AttributeOverride같은걸 써서 임베디드 타입의 필드 이름을 특정 column명으로 override해야한다.


DTO는 이렇게 구성할 수 있다.

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PersonDto {
    private String name;
    private Gender gender;

    private Address address;

    public static PersonDto fromEntity(Person person) {
        return PersonDto.builder()
                .name(person.getName())
                .gender(person.getGender())
                .address(person.getAddress())
                .build();
    }

    public Person toEntity() {
        return Person.builder()
                .name(this.name)
                .gender(this.gender)
                .address(this.address)
                .build();
    }
}

@RequestBody의 JSON은 아래와 같이 구성한다. 메세지 컨버터가 밸류 객체(여기선 Address)를 예쁘게 바인딩해준다.

{
    "name":"부추",
    "gender":"FEMALE",
    "address": {
        "shi":"허리도",
        "gu":"가늘군",
        "ro":"만지면 부러지리",
        "detail": "빌라",
        "zipCode":"12345"
    }
}

해당 데이터를 요청메세지 본문에 담고 save 요청을 보내면?
굳ㅎㅎ



2. ERD!!!

대강의 프로젝트 ERD가 구성되었다. 각각의 엔티티들이 기본적으로 가질 수 있는 필드들에 대한 설명은 생략하고, application specific한 기능들은..

  1. 회원은 레시피를 작성하여 업로드할 수 있으며, 업로드된 레시피에 대해 댓글과 리뷰, 그리고 평점을 남길 수 있다.
  2. 레시피는 레시피 테이블 recipe와 해당 레시피의 단계들을 나타내는 step으로 구성된다. 일대다 관계를 가지며, 각각의
  3. 레시피 recipe는 여러 개의 재료 ingredient를 연관 관계로 가진다. 재료들은 재사용될 수 있고, 나중에 커머스 기능 등으로 확장될 수도 있다.
  4. recipe는 여러 개의 tag를 가진다. tag는 주요 재료, 음식의 종류, 음식 상황으로 나뉘며 여러 개를 가질 수 있다. 이는 추후 레시피를 검색하는데 활용된다.
  5. 회원은 레시피를 북마크할 수 있다.
  6. 레시피 북마크 수, 조회수에 기반하여 매일매일 user의 랭킹이 업데이트되고 이를 확인할 수 있는 페이지가 존재한다.
  7. 유저들은 서로를 팔로우할 수 있다. 유저가 새로운 레시피를 업로드했을 경우, 해당 유저를 팔로우한 유저들은 알림을 받을 수 있다.

... 정도를 ERD로 나타내면 아래 사진과 같다.


REFERENCE

https://sedangdang.tistory.com/307

profile
부추튀김인지 부추전일지 모를 정도로 빠싹한 부추전을 먹을래

0개의 댓글