Skip to content

트러블 슈팅 [BE]

Soobeom edited this page Nov 28, 2021 · 4 revisions

🌟 트러블 슈팅

Wordi 프로젝트를 진행하면서 마주한 몇 가지 트러블 슈팅을 적어보았습니다.

Spring 내부 에러처리 관련

  • 문제 상황

  • 스프링 부트에서 일반적인 에러가 발생했을 경우, 에러 지점 부터 WAS까지 전달 후, 다시 request하여 에러 페이지를 요청하는 요청을 보내는 플로우를 탄다.

  • 여기서 문제가 되는게 WAS에서 error페이지 요청을 보내는 request 또한 Interceptor를 탄다는 문제가 있다.

  • interceptor에서 로그인 인가 처리를 구현했기 때문에 해당 request를 분리해주는 로직이 필요하다.

  • 해결 방법

  • 해결은 request를 분리하는 방법 보다는 Advice에서 Exception 예외를 잡아 등록하지 않은 모든 예외를 잡아서 처리해 버리도록 했다.

  • 만약, 별도의 View를 활용할 경우라면 /error 경로로 reqeust URI를 매핑하여 해당 에러 페이지 View가 출력되도록 하면 될 듯 하다.


List를 포함하는 DTO, Entity를 다룰 때 주의점
  • 문제 상황

  • 에러코드 : Problem deserializing 'setterless' property 'keywordList': get method returned null

  • Entity 내에서 컬렉션을 다룰 때 null이 반환되는 에러가 발생.

  • 해결 방법

  • Entity가 멤버변수로 컬렉션을 가지고 있을 때는 선언 시점 부터 빈 리스트로 항상 초기화시켜줘야 한다

  • 해결 방법: private List<String> KeywordList = new ArrayList<>(); 와 같이 빈 리스트 선언


MultipleBagFetchException 문제
  • 문제 상황

  • Mentor Entity를 Keyword와 Schedule을 함께 Fetch Join할 때 해당 에러 발생.

  • 원인은 Fetch Join을 사용할 수 있는 조건이 ManyToOne 관계는 여러 개 가능하지만, OneToMany 관계는 오직 1개만 fetch join에 포함시킬 수 있다.

  • OneToMany 관계를 여러 개 Fetch Join을 하게 되면 해당 예외가 터지게 된다.

  • 해결 방법

  • OneToMany 관계 객체를 1개만 Fetch Join하여 가져오고, 나머지는 지연 로딩 + batch size를 조절하여 묶음으로 가져오는 식으로 성능을 최적화한다.

  • batch size 설정은 어노테이션을 통해 단일 메서드에만 설정할 수 있으며, yml 설정 파일을 통해 글로벌 설정도 가능하다.

  • batch size의 경우, 기본적인 1 + N 이슈를 해결하기 위해 필요하다고 판단하여 구현은 yml 설정 파일을 통해 글로벌 설정을 해주었다.


LocalDateTime JSON으로 Request 시 변환 에러
  • 문제 상황

  • Request의 JSON에 LocalDateTime 형식에 맞추어 데이터를 요청 했음에도 불구하고 타입이 맞지 않다는 에러(직렬화 처리 에러)가 발생함

  • Request로 부터 어떻게 LocalDate와 LocalDateTime을 직렬화 해서 받을 수 있는지 고민

  • 해결 방법

  • 일반적으로 GET 요청 시 LocalDateTime 파라미터가 필요할 경우, 2018-12-15 10:00:00 보다는 2018-12-15T10:00:00을 선호한다.(띄어쓰기로 인해서 값이 잘못 넘어올수도 있기 때문에)

  • @JsonFormat으로 LocalDateTime 포맷을 지정할 수 있으나, 이 경우는 실패한다.

  • @DateTimeFormat을 활용하자. Spring에서 지원하는 어노테이션으로 날짜 관련 타입의 직렬화를 지원하는 어노테이션이다.

  • 해결: @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") 과 같은 형식으로 날짜 타입에 어노테이션을 명시해준다.


QueryDsl에서 멘토 키워드 조건 쿼리 구현
  • 문제 상황

  • 검색 필터링 API를 QueryDsl로 동적 쿼리를 구현하다 문제 발생

  • request로 부터 받아온 String keyword를 Mentor의 List의 단일 값인 MentorKeyword의 멤버 변수 중에 keyword와 비교하여 일치하는 Mentor만 조회하는 로직을 구현해야 하는 문제.

  • 해결 방법

  • 처음에 Join으로 테이블을 합친 후, MentorKeyword의 String keyword 값을 비교하는 식으로 구현하려 했으나, keyword와 Join을 하게 되어 Keyword 갯수만큼 데이터가 중복되어 출력되는 문제 발생

  • where 조건에 서브 쿼리를 구현하여, MentorKeywordList.contains() 메서드를 활용했다. contains안에 서브 쿼리로 request로 부터 받아온 String keyword와 일치하는 mentorkeyword를 조회하는 서브 쿼리를 작성함.