JPA 즉시로딩과 지연로딩 / CS 스터디 / (항해일지 34일차)

김형준·2022년 6월 12일
0

TIL&WIL

목록 보기
34/45

1. 개발 및 학습일지


1) 미니 프로젝트 개발 현황

  • AWS S3 버켓에 이미지 업로드 테스트 성공
  • 프론트 분들과 협의하에 프론트에서 이미지를 따로 관리하는 방식으로 변경
  • API 명세 imgPath -> img 변경
  • 스프링 시큐리티 회원가입 / 로그인 기능과 통합
  • 현재 회원가입 / 로그인 / 게시글 CRUD 까지 통합
  • 🔗 미니프로젝트 코드 GitHub
  • 댓글 CRUD 중에 병합충돌 발생 -> 복구
  • 게시글 등록 시 로그인한 member 정보 같이 저장하기
  • 양방향 매핑으로 member의 postList에도 해당 post 저장하기
    -> LazyInitializationException 발생!

2) JPA 즉시 로딩과 지연로딩

  • LazyInitializationException은 왜 발생했을까?

  • 상황은 아래와 같다.

    • Post와 Member는 양방향으로 매핑되어있다.
    • Post는 Member에 @ManyToOne 으로
    • Member는 Post에 @OneToMany로
    • Post를 등록할 경우 requestDto로 받아온 정보와 @AuthenticationPrincipal로 받아온 로그인한 member의 정보를 같이 저장한다.
    • 이 때 Post 객체의 생성자 바디에서 파라미터로 받아온 member 객체의 postList에도 해당 Post 객체를 add 해줬다.
    • ❗❗❗ 이 때 LazyInitializationException이 발생했다
  • 구글링 결과 JPA 지연로딩과 관련된 예외가 발생한 것이었다.

    • 먼저 @~ToMany는 JPA가 디폴트로 fetch = FetchType.LAZY 를 전략으로 설정한다고 한다.
    • 즉, 지연로딩으로 설정되는 것인데, @~ToMany를 가지고있는 객체가 조회될 경우, @~ToMany가 붙어있는 객체를 불러오지 않고 프록시를 대신해서 가져오는 방식이다. (추가적인 쿼리를 날리지 않는다.)
    • 이 후 실제로 @~ToMany 객체가 사용될 때 쿼리를 날리게 된다.
  • 나의 상황에 적용해보면

    • Post를 등록할 때 member 정보를 같이 등록하고 나아가 member의 postList에도 이를 add 해주려고 했다.
    • 이때 member의 postList는 @OneToMany이기 때문에 지연 로딩으로 가져와서 그런줄 알았는데 아니다❗❗❗❗
  • 애초에 Controller에서 받아왔던 @AuthenticationPrincipal UserDetialsImpl이 준영속화 되어있는 상태여서, proxy 객체로 움직이는 것이었다.

    • 즉, postService에서 받은 userDetails는 이미 준영속화 된 상태이고, 여기에 연관된 값을 변경하려고 하여 LazyInitializationException이 발생한 것이다.
  • 해결 방법

    • 가장 간단한 해결 방법은 Member Entity 클래스의 postList 멤버변수에 @OneToMany(fetch = FETCH.EAGER)를 붙여주며 postList가 즉시 로딩되도록 바꿔주는 것이다.
    • 하지만 위와 같은 방식은 나중에 postList에 담긴 객체들이 많아졌을 경우 상당히 비효율적인 쿼리를 실행하게 된다고 한다.
    • service에서 userDetails.getUser().getId()를 통해 member를 findById(id) 해서 DB에서 영속성 컨텍스트를 불러오고, 이 컨텍스트의 postList에 add() 해주는 방법도 있다.
    • 아직 익숙치 않은 개념들이라 제대로 정리가 안되었지만, 시큐리티를 담당하셨던 분께서 @AuthenticationPrincipal UserDetialsImpl이 영속성 컨텍스트를 받아올 수 있도록 연구해보신다고 하셔서, 같이 취합하면서 다시 글을 수정해야 겠다.

3) CS 스터디

72. 월드 와이드 웹은 무료다

월드 와이드 웹(W3)은 막대한 양의 문서에 범서계적으로 접근할 수 있는 시스템을 만드는 것을 목표로 하는 광역 하이퍼미디어 정보 검색 계획이다.

  • 웹(WWW):
    • 정보를 제공하는 컴퓨터(서버)와 정보를 요청하는 컴퓨터(클라이언트)를 연결한다.

    • **인터넷을 사용하여 연결을 맺고 정보를 전달하며 다른 인터넷 기반 서비스에 접근하기 위한 인터페이스를 제공한다.

      • 인터넷은 전 세계의 수많은 컴퓨터가 서로 쉽게 정보를 교환할 수 있도록 하는 통신 인프라 또는 하위 계층이다.
    • 어디에나 있고 효율적이며 개방적이고 기본적으로 무료인 하부 네트워크가 존재한다는 전제 하에 핵심은 4개

      • URL: 정보의 출처에 대한 이름을 지정한다.

      • HTTP(Hypertext Transfer Protocol): 인터넷 상에서 데이터를 주고 받기 위한 서버/클라이언트 모델을 따르는 프로토콜(통신규약)이다.

      • HTML(Hypertext Markup Language): 서버가 반환하는 정보 서식이나 표시 방식을 설명하기 위한 마크업 언어 ( != 프로그래밍 언어)

      • Browser: 컴퓨터에서 실행되는 크롬, 파이어폭스, 사파리, 엣지 같은 프로그램으로 URL과 HTTP를 사용하여 서버에 요청을 보내고 서버에서 보낸 HTML을 가져와 표시한다.

  • 최초의 웹은 1989년에 탄생했다.
  • 최초의 브라우저인 모자이크는 1993년에 출시되었고, 1년만에 최초의 상용 브라우저인 넷스케이프 내비게이터가 나왔다.
  • 넷스케이프 내비게이터는 초창기부터 성공을 거뒀는데, 이때까지 마이크로소프는 인터넷에 대한 관심이 급증할 줄 인식하지 못했다고 한다.
    • 그러나 곧 바로 인터넷 익스플로러를 신속히 출시했고 내일 모레 지원 종료된다.
  • 웹의 기술적 진화는 비영리 조직인 월드 와이드 웹 컨소시엄, 즉 W3C가 관리하거나 방향을 제시한다.
    • 최초의 웹을 탄생시킨 버너스리는 W3C의 설립자이자 현재 책임자다.
    • 버너스리는 모든 사람이 인터넷을 무료로 이용할 수 있길 원했다.

73. URL의 의미

  • 하이퍼 텍스트란 페이지를 연결하는 것을 말한다.

    • 브라우저 덕에 모든 사람들이 하이퍼 텍스트를 경험할 수 있게 됐다.
    • 링크
    • 링크를 클릭하면 브라우저가 도메인 w3.org의 80번 포트로 TCP/IP 연결을 열고, URL의 나머지 부분에서 제공하는 정보에 대해 HTTP 요청을 보낸다.
    • 서버에서 반환되는 텍스트는 거의 HTML 형식이다
      • @Controller에서 템플릿 엔진을 통해 View를 보내주는 방식
    • HTTP 프로토콜을 사용하면 브라우저가 클라이언트의 요청과 함께 몇 줄의 추가 정보를 보낼 수 있으며, 서버의 응답에는 일반적으로 데이터의 양과 종류에 대한 정보를 담은 여분의 행이 포함된다.
  • URL 자체는 정보를 인코딩한다.

    • 첫 번째 부분인 http는 사용할 특정 프로토콜을 알려주는 몇 가지 선택지 중 하나
    • :// 다음에는 도메인 네임 (뒤에 슬래시와 문자열이 올 수 있다.)
    • 도메인 네임만 보낸다면 서버는 index.html과 같은 기본 페이지를 반환한다. ( spring framework 도 static에 index.html을 만들어두면 이를 반환한다.)
    • 뒤에 작성되는 문자열을 쿼리스트링이라고 한다.
      • 단 이 문자열은 한정된 문자 집합으로 작성된다.
      • 공백을 비롯해 영문자와 숫자를 제외한 대부분의 문자가 허용되지 않으므로, 이러한 문자들은 인코딩 되어야 한다.
profile
BackEnd Developer

1개의 댓글

comment-user-thumbnail
2022년 6월 13일

감사합니다 👍

답글 달기