[pre-project] 0224

박채은·2023년 2월 22일

Project

목록 보기
2/21

✔️ Todo

  • 연관관계 매핑
    • member, question, answer
  • 은선님이 요청하신 것
    • questions GET 메서드에서 최신 순으로 질문 가져오기
    • createdAt, modifiedAt 타입 수정 - 시분초까지

1. createdAt, modifiedAt 날짜 format 변경

@CreatedDate
@Column(name = "created_at", updatable = false, nullable = false)
private LocalDateTime createdAt;

LocalDateTime에서 기본으로 적용되는 날짜 포맷은 다음과 같다.

2023-02-24T16:23:47.960583

은선님이 yyyy-MM-dd HH:mm과 같이 깔끔하게 시간을 받고 싶다고 요청하셨다.

그래서 해당 기능을 할 수 있는 애너테이션이 있는지 찾아봤고 @DateTimeFormat을 찾았다.
하지만 @DateTimeFormat를 추가해도 변경되는 것은 없었다.

해당 블로그가 나와같은 상황인 것 같았고 @DateTimeFormat 대신 @JsonFormat을 사용했더니 수정되었다!

https://addio3305.tistory.com/101

🚨 주의할 점
나는 @JsonFormat 애너테이션을 Entity 클래스의 속성에다가 붙였는데 Entity가 아닌 ResponseDTO에 붙여야 한다!
왜냐하면 Entity에 붙여도 DB에 저장되는 타입은 Timestamp일테니까 DB에서 가져온 다음에 데이터를 변형시켜야 한다.

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy년 MM월 dd일 HH:mm", timezone = "Asia/Seoul")
LocalDateTime createdAt;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy년 MM월 dd일 HH:mm", timezone = "Asia/Seoul")
LocalDateTime modifiedAt;

[참고]
참고-1
참고-2


🚨 이슈 트래킹

1. 순환 참조

https://velog.io/@youns1121/JPA-java.lang.IllegalStateException-Cannot-call-sendError-after-the-response-has-been-committed

이전에 지은님이랑 이야기했었던 순환 참조 부분 에러가 터졌다!
순환 참조를 해결하는 것은 간단하게 애너테이션을 붙여서 해결했다.

순환 참조를 사전에 방지하기 위해서는 Entity를 리턴하는 일은 없도록 해야했다는 생각이 들었다.

바로 Entity를 리턴하면 순환 참조 문제가 발생할 수 있으므로 앞으로는 무조건 ResponseDTO를 리턴하자!


2. 같은 타입의 Bean이 여러 개인 경우

위 순환 참조 이슈로 인해서 QuestionResponseDTO를 재구성했다.
QuestionResponseDTO가 복잡해지면서 기본 Mapper 인터페이스로는 불충분해서 QuestionMapper 인터페이스를 구현한 CustomQuestionMapper 클래스를 생성하였다.

Controller에 QuestionMapper와 CustomQuestionMapper을 모두 DI 받아서 사용하려고 했다.
하지만 그때 이 required a single bean, but 2 were found 에러가 발생했다.

나는 두 Mapper를 모두 Bean에 등록해서 둘 다 각각 사용할 수 있는 줄 알았는데 두 Mapper가 같은 타입의 Bean이라서 같이 사용할 수 없는 것 같았다.

시도 1

에러에 뜬 대로 CustomQuestionMapper에 @Primary를 추가했다.
(CustomQuestionMapper가 QuestionMapper를 구현하고 있기 때문에 우선순위가 높음)

하지만 에러는 해결되지 않았다.
이때는 QuestionController에 QuestionMapper와 CustomQuestionMapper가 모두 선언된 상태었다.

@Primary를 작성해두면, QuestionMapper에는 QuestionMapper가, CustomQuestionMapper에는 같은 타입의 Bean인 CustomQuestionMapper과 QuestionMapper 중에 우선순위가 높은 CustomQuestionMapper가 들어갈 줄 알았는데 아니였다.

시도 2

혹시나 해서 QuestionController에서 QuestionMapper는 지우고 CustomQuestionMapper만 남겨봤다.
이렇게 했더니 해결되었다.

CustomQuestionMapper에는 CustomQuestionMapper가 DI가 되었고 에러는 해결되었다.

의문점 1

왜 QuestionMapper와 CustomQuestionMapper이 같은 타입의 Bean인가?

  • CustomQuestionMapper가 QuestionMapper 인터페이스를 구현하기 때문인지?
  • Mapper이기 때문인지?

구글링해보니 @Autowired는 Bean을 타입(Type)으로 조회한다고 한다.
CustomQuestionMapper가 QuestionMapper 인터페이스를 구현하기 때문에 같은 타입의 Bean으로 인식하게 된 것 같다.

참고한 블로그

의문점 2

왜 [시도 2]를 해야되는지? QuestionMapper와 QuestionController가 같은 타입으로 인식된 건 알겠는데 둘 다 작성해두면 안 되나요?
=> 아직 이유는 정확히 모르겠어서 나중에 알게 되면 작성해야겠다.

0개의 댓글