[Springboot] jwt 구현 시 만난 에러

지영·2024년 7월 13일
1

백엔드개발자

목록 보기
10/11

많은 서비스에서 당연하게 제공 중인 회원가입과 로그인..그치만 Spring Security로 구현해보면서 공부하면 할 수록 알아봐야 할 게 많다는 것을 알게 되는 것 같습니다 ^^
역시 보안이 제일 중요하고 또 그만큼 공부할 거리가 많음을 깨닫게 되네요.

이번에는 기능 구현 절차는 나중에 자세히 포스팅하도록 하고,
제가 만난 에러와 해결방법, 원인까지 알아보겠습니다.

회원가입/로그인을 위한 회원(Member 엔티티)에서 회원이 가지는 권한(roles) 쪽에서 오류가 났습니다. 즉 회원가입API를 통해 파라미터로 ID, PASSWORD, ROLES를 전달했으나 아래의 오류를 만난 상황입니다.

우선 에러 메세지.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.example.플젝이름.persist.entity.MemberEntity.roles, could not initialize proxy

네...아무래도 엔티티의 roles를 가져올 때, lazy하게 가져오는 것 때문인 거 같습니다. 로그도 정말 친절하게 나와서 빠르게 해결할 수 있어습니다.

문제의 MemberEntity를 보면 이렇습니다.

제 경우에는 결론부터 보자면, 기본적으로 LAZY하게 가져오기 때문에 생긴 문제이기 때문에 fetch방식을 직접 EAGER라고 작성해서 해결해주었습니다. 이런 경우, 아래처럼 FetchType을 EAGER로 명시해주세요

그렇다면

org.hibernate.LazyInitializationException:은 어떤 에러를 뜻할까요?

우선 LazyInitializationException은 member까지는 잘 조회했으나, member.getRoles()를 호출할 때 영속성 컨텍스트가 끊어지면서 발생하는 오류입니다. 즉 지연로딩을 할 수 없는 상황에서 발생하는 에러입니다. 이미 아시다시피 지연로딩은 영속성 컨텍스트가 있어야 가능하니까요!

따라서 이 원인으로 보아서 해결방안은 2가지가 있을 것 같습니다.

1. 영속성 컨텍스트를 만들어주기

또는

2. 지연로딩하지 않기


✅ 해결방안

1. 영속성 컨텍스트 환경 만들어주기

간단합니다. @Transactional을 써주면 트랜잭션 내에서 member를 조회하든, 이 후 memeber.getRoles()를 하든 모두 지연로딩으로 해결이 가능합니다.

2. fetch타입을 EAGER로 만들기

**EAGER은 이미지와 같이 데이터 조회시 proxy객체 대신 실제 엔티티를 가지고 오는 fetch type입니다.**

제가 선택한 방식인데요, 저는 member, 즉 회원의 권한에 따라 Controller 접근 범위를 결정하므로 항상 member의 ROLES를 써야 하는 상황이었기 때문에 굳이 지연 방식을 사용할 필요가 없었기 때문이죠!

하지만 역시 개인프로젝트의 범주를 넘어선 실무에서는 즉시 로딩보다는 1번 방식이 더 현명하겠죠?
아무래도 연관관계에 있는 엔티티까지 한번에 다 가져오면 기대하지 않은 쿼리가 발생하기 때문입니다.

각자의 프로젝트 로직의 규모를 고려해서 위의 해결방식 중 하나를 택해주시면 될 것 같습니다.

profile
꾸준함의 힘을 아는 개발자📍

0개의 댓글