구인구직 사이트를 만들면서, 구인자와 구직자간 프로필을 생성하는 기능을 구현중이다.
구직자는 자신의 프로필을 등록하여 해당 프로필로 지원을 하고, 구인자는 본인의 가게 정보를 업로드시켜야하는데,
구인자의 프로필이 곧 이력서가 될수있도록 항목들을 구현하는 과정에서 순환참조 문제가 발생하였다.
- User 화면
- 사장님 화면
알바를 지원하는 사용자가 여러 성격에 관한 태그나, 선호하는 시간대에 관한 태그 정보를 설정해두고,
사장님은 공고를 올릴때 원하는 태그를 설정할수있다.
해당 태그와 지원자, 사장님의 관계는 Many to Many to Many로
그냥 테이블의 하나의 컬럼에 콤마(,)를 주어 여러값들을 넣어줄수도있지만,
추후에 해당 태그들을 가지고 선호하는 시간, 성격에 맞는 최적의 공고나 지원자를 검색할수있는 기능을 구현하려면 성격을 나타내는 Personality 테이블과 선호하는 시간대 time 테이블을 따로 빼는것이 좋을것 같았다.
따라서 JPA의 Entity를 구현하기위해 중간에서 Many to one를 받아주는 중개테이블을 생성하여 각각의 값들을 받아준다.
Entity의 객체를 타임리프 스크립트에서 직렬화하여 Json객체로 받기
Entity에서 List<Personality>타입의 객체를 model에 싸서 타임리프로 보내는데,
해당 값을 <script>요소에서 받으려면 타임리프 문법을 통해 Javascript 객체로 변환하여 받아야한다.
해당 라이브러리는 Java8의 Date와 같은 라이브러리를 타임리프에서 받아서 사용하게 해주는 라이브러리인데,
그외에도 다양한 기능을 지원하기때문에 해당 라이브러리를 통해 엔티티내 컬렉션 객체도 받을수있다.
// 자기소개 출력
/*<![CDATA[*/
var personalities = /*[[${resume.personalitys}]]*/ [];
console.log(personalities);
/*]]>*/
personalities.forEach(function (item){
const addSpan = $('<span>').attr('id', 'intro').text(item.name);
$('#intro-box').append(addSpan);
});
그리고 스크립트 구문내에서 <![CDATA ]]> 문법을 통해 model을 통해 날아온 List<Personality> personalitys 컬렉션 타입의 객체를 받아주면 Javascript 배열로 받을수있다.
이후, 제이쿼리를 사용하여 해당 배열값들을 꺼내서 view에 출력해주려하는데,
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)
클라이언트에서 해당 에러가 발생하였다.
해당 해러는 스프링부트에서 jackson라이브러리를 통해 컬렉션 객체를 Json으로 직렬화/역직렬화 하는 과정에서,
JPA의 엔티티가 다대다 관계일 경우 엔티티간 순환 참조가 발생하여 무한루프를 돌아
StackOverflow가 발생한다는 것이다.
Entity를 다시한번 살펴보면
다음 두개의 Entity에서 resumes와 personality간에 순환참조가 발생하고있는게 문제였다.
Resume와 Personality를 중간에서 받는 Resume_Personality는 Entity로 구현되지않고 ManyToMany 어노테이션을 통해 매핑시켜, 해당 컬럼을 조인해서 각 Entity에 받아오기때문에 클라이언트로 직렬화를 하여 보내면서 순환 참조가 발생한다는 것이 주요 원인으로, JPA에서 다대다 관계 테이블을 직렬화 할경우 자주 발생하는 문제라고한다..
기능을 구현하면서 테이블 설계를 할때 다대다 관계의 표현문제때문에 고민을 많이했는데, 관계형 데이터베이스에서
다대다 관계의 표현을 일반적으로 잘 사용하지않고, MongDB처럼 키-값 형태의 NoSQL을 많이 사용한다고 하는데,
왜 그런지 확실히 알것같았다..
그래도 일단 억지로 구현해보려 하면서 문제가 생겨 해결하는데 시간이 오래걸렸지만 그래도 테이블 관계에 대해서 자세히 알게되었다.
아무튼 해당 문제를 해결해주기위해
@JsonIgnore
해당 어노테이션을 둘중 한군데에 붙여주면 직렬화할때 해당 컬럼을 무시하기때문에 순환참조가 발생하지않는다.
본질적인 해결책은 아니지만 resumes 컬럼은 자주 사용하지않기때문에 일단 해당 어노테이션을 ignore하였다.
'Category > Project' 카테고리의 다른 글
[개인프로젝트] 11일차 - 스프링시큐리티+OAuth2 소셜로그인 (0) | 2024.02.27 |
---|---|
[개인프로젝트] 10일차 - JPA 페이징처리,검색기능 (0) | 2024.02.27 |
[개인프로젝트] 5일차 - 카카오 주소 api를 사용해서 네이버 map api 표현하기 (0) | 2024.02.22 |
[개인프로젝트] 3일차 - 시큐리티 + JWT 토큰을 통한 인증 (0) | 2024.02.20 |
[개인프로젝트] 2일차 - 시큐리티 권한 세팅하기, 영속성 컨텍스트 (0) | 2024.02.19 |