순환 참조
TODO 리스트 토이 프로젝트를 해보다가 순환 참조 문제가 발생했다.
순환참조란, 참조하는 대상이 서로 물려 있어서 참조할 수 없게 되는 현상을 말한다.
TodoListInfo.java
@Entity
@Getter
@Builder
@NoArgsConstructor @AllArgsConstructor
public class TodoListInfo {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long code;
@OneToOne
private Member writer;
@OneToMany(mappedBy = "todoListInfo", cascade = CascadeType.ALL)
private List<Todo> todoList = new ArrayList<>();
}Todo.java
@Entity
@Getter
@Builder
@NoArgsConstructor @AllArgsConstructor
public class Todo {
@Column(name = "todo_id")
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "todo_list_info_code")
private TodoListInfo todoListInfo;
private String description;
private boolean isCompleted;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "Asia/Seoul")
private LocalDateTime startTime;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "Asia/Seoul")
private LocalDateTime endTime;
}위 두 객체를 보면 TodoListInfo 에서는 List<Todo> 를 통해, Todo 에서는 TodoListInfo 를 통해 서로 참조하고 있다.
만약 JSON 응답으로 이 관계를 그대로 보내게 되면 순환 참조 문제가 발생한다.
예를 들어, TodoListInfo 의 형식 그대로 응답으로 내보냈다고 해보자.
그러면 TodoListInfo 의 List<Todo> 에서 각각의 Todo 는 TodoListInfo 를 참조할 것이다. 이 방식이 계속 반복되게 된다.
이러한 순환 참조를 막기 위한 2가지 방법을 알아보자.
@JsonIgnore
Todo 클래스의 TodoListInfo 필드에 @JsonIgnore 애노테이션을 추가해준다.
이 애노테이션을 사용 시 조회할 경우 해당 필드를 조회하지 않는다.
DTO
해당 응답에 따른 DTO를 생성하여 필요한 데이터만 담아서 반환하면 순환 참조 문제를 방지할 수 있다.
ReadTodoListDto.java
TodoDto.java
TodoListInfo 를 조회할 때, DTO를 이용하여 필요한 정보만 담아줌으로써 순환 참조를 방지한다.
TodoDto 에는 TodoListInfo 에 대한 참조가 빠져있다.
Last updated