회고

TIL_210524

코동이 2021. 5. 25. 10:18

1. Facts(사실, 객관)

- JPA 프록시, 즉시로딩 / 지연로딩, 고아객체 강의

- JPA 값타입, 임베디드타입, 불변객체 강의

- javascript 실행 컨텍스트, this, 콜백함수 강의

- 블랙커피 1단계 9기 세션 시작 참여

- var, let, const 차이점 블로그 정리

 

2. Feelings(느낌, 주관)

- 오늘은 웬지 모르게 강의를 많이 듣고 싶은 날이었습니다. 아직 JPA의 기본내용밖에 모르기 때문에 이후에 진행할 프로젝트를 대비하기 위해서 계속 강의를 이어나갔습니다. 이전에 @MappedSuperclass에 이어서 여러 전략들을 확인했습니다.

 

- javascript에 대해 좀 더 공부하고 싶은 욕구가 최근에 있었습니다. 따라서 약 1달과정의 블랙커피 1단계를 신청하였고, todo list 과제에 돌입하였습니다. ES6 버전 이전과 이후로 javascript에는 큰 변화가 있었던 것 같습니다. 그 중에 먼저 var, let, const의 차이에 대해 알아보았습니다. 이전에 var만 사용한 저에게 굉장히 신선한 내용이었습니다.

 

- 이전에 인프런에서 구매해둔 js flow라는 강의에서 실행 컨텍스트, this, 콜백함수 강의를 들었습니다. ES6 이전 기반으로 생각되는데, 많으 부분을 자바와 비교해보면서 듣는 재미가 있었습니다. 저는 주로 자바 기반의 내용을 알다보니 차이점과 공통점이 더 잘 보였고, 이후 다른 언어를 공부할때도 비교하면서 공부하면 습득이 빠를 것으로 기대합니다.

3. Findings (배운 점)

*JPA에서 프록시 작동

1. client에서 메서드 호출을 요청한다(getName())

(Proxy 객체는 필드로 해당 엔티티를 가지고 있는데, 할당되었는지 null인지를 확인한다.)

2. 초기화를 요청한다

3. 영속성 컨텍스트를 거쳐 DB에서 조회한다

4. 조회 결과로 실제 엔티티를 생성한다

5. Proxy 객체의 필드에 엔티티가 할당되며, 필드의 엔티티를 통해서 실제 엔티티 값에 접근한다

 

*지연로딩 / 즉시로딩

member와 team이 N:1로 연관되어있다고 가정한다.

 

member기준으로

지연로딩은 member를 조회할 때, team을 신경쓰지 않고 member만 가져온다. member와 연관인 team을 조회할 때 비로소 team을 알기위한 쿼리를 날린다. 처음 쿼리를 날릴 때 프록시가 초기화되어야 하므로 쿼리가 발생한다. 즉, member, team을 모두 조회하기 위해서 총 2번의 쿼리가 필요하다. 프록시를 한번 초기화한 이후에는 쿼리가 발생하지 않는다. (FetchType.LAZY)

 

즉시로딩은 member를 조회할 때, 그 즉시 연관인 team의 내용까지 한번에 쿼리를 날린다. 즉시로딩은 모든 것을 한번에 조회하기 때문에 프록시가 필요하지 않다. (FetchType.EAGER)

 

실무에서는 지연로딩을 사용해야 한다. 즉시로딩은 JPQL에서 N+1 문제를 발생시킨다. JPQL은 입력받은 query string 그대로 SQL을 실행한다. member를 조회하기 위해 SQL을 날린다.

@Query("select m from Member m")

 

단지 SQL만 날리기 때문에 어떠한 연관정보에 대해서도 처음에는 알지 못한다. SQL을 날렸더니 EAGER이 사용된 것을 발견했고 추가적으로 team을 조회하기 위해서 위해 일일이 다시 쿼리를 날리게된다. 

 

@OneToMany, @OneToOne 의 경우 기본이 즉시로딩(EAGER)이다. 따라서 모두 LAZY로 명시해야 한다.

 

*영속성 전이

CASCADE를 통해 부모 생성시, 자식 생성, 부모소멸 시, 자식 소멸을 같이 작동시킬 수 있다.

@OneToMany(mappedBy="team", cascade=CascadeType.ALL)
private List<Child> children = new ArrayList<>();

 

*고아객체

자식 입장에서 부모와 연관관계가 끊어졌을 때, 같이 삭제된다.

@OneToMany(mappedBy="parent", cascade=CascadeType.ALL, orphanRemoval=true)
private List<Child> children = new ArrayList<>();

 

영속성 전이와 고아객체 사용시 주의점은 꼭 특정 엔티티가 개인에 의해서 소유가 될 때만 사용하는 것이다. 다른 엔티티에서 참조하거나 연관이 되어있을 때 관리가 복잡해지므로 잘 확인해야 한다.

 

*임베디드 타입

정의하는 곳 : @Embeddable

사용하는 곳 : @Embedded

 

- 임베디드 타입은 사용되고 있는 엔티티가 생성될 때 같이 생성되고, 삭제되면 같이 삭제된다

- 소유한 엔티티에 생명주기를 의존한다

- 임베디드 타입은 객체타입이기 때문에 참조값 대입을 막을 수 없다(공유참조를 피할 수 없다)

- 생성자로만 값을 설정하고 이후에는 값을 변경하지 못하도록 불변객체로 만들어야 한다.

- 수정이 필요하다면, 그때마다 새로운 객체를 만들어서 다시 설정한다

- 대표적인 불변객체는 Integer, String이 있다.

4. Affirmation (자기 선언)

- 나는, 심화되는 개념을 계속 탐구하고 범위를 차근히 넓혀서 학습하는 사람이다

5. Future Action ("구체적" 행동 계획)

반응형