[error] 스프링 순한참조

쭈·2023년 5월 7일
0

에러

목록 보기
7/9

오류 발생

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

java.lang.StackOverflowError: null

해당 오류에 대한 내용을 찾아보니 무한참조와 관련된 오류인 것 같았다.

오류원인

엔티티 구조가 다음과 같이 되어있다.

@Entity
@Table(name = "todo_task")
public class TodoTask {
    @JoinColumn(name = "todo_id")
    @ManyToOne()
    private Todo todo;

    @OneToOne
    @JoinColumn(name = "challenge_id")
    private Challenge challenge;
}
@Table(name = "challenge")
@Entity
public class Challenge {

	@Builder.Default
	@OneToMany(mappedBy = "challenge", fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
	private List<Challenger> challengers = new ArrayList<>();

	@OneToOne(mappedBy = "challenge")
	private TodoTask todoTask;
	}
}

오류가 난 서비스계층 flow를 보면
1. 요청이 들어온 날짜에 관한 user의 todo 객체가 있으면 객체를 가져온다.
2. 해당 todo객체와 연관된 todo task들을 가져온다.
3. 해당 todo task들을 리스트 형식으로 묶어서 dto에 저장한다.
4. dto를 반환한다.

디버깅했을 때 3번까지 데이터가 잘 들어오는 것을 확인했다. dto를 응답하는 과정에서 발생한 오류인 것 같아 해당 dto를 string값으로 확인한 결과 다음과 같다.

GetTodoResponseDto(date=2023-05-04, task=[TodoTaskDto(taskId=13, task=hi, complete=false, isFromChallenge=true, challenge=app.todoit.domain.challenge.entity.Challenge@53dd8da0), TodoTaskDto(taskId=20, task=foo, complete=false, isFromChallenge=true, challenge=app.todoit.domain.challenge.entity.Challenge@4f408cc5)])
@Data
@NoArgsConstructor
public class TodoTaskDto {
    private Long taskId;
    private String task;
    private Boolean complete;

    private Boolean isFromChallenge;

    private Challenge challenge;

    public TodoTaskDto toDto (TodoTask entity) {
        this.taskId=entity.getTaskId();
        this.task=entity.getTask();
        this.complete=entity.getComplete();
        this.isFromChallenge=entity.getIsFromChallenge();
        this.challenge = entity.getChallenge();
        return this;
    }

}

DTO를 확인해보니 challenge 객체를 그대로 담고있었다.
위의 엔티티에서 화긴할 수 있듯이 챌린지에서는 todotask와 매핑되어있기 때문에 이 부분에서 순환참조가 발생한 것 같다.

문제해결

우선 나는 challenge 정보가 클라이언트 입장에서 필요한 정보가 아니였기에 dto에 challenge 필드가 필요없다고 생각했기 때문에 팀원에게 제거요청 전달했다.
따라서 순환참조가 발생할 일이 없었기에 자동으로 문제가 해결됐지만 이러한 상황이 아닐경우 @JsonIgnore 어노테이션을 활용하면 된다.

profile
🌱

0개의 댓글