아웃소싱(배달 주문 어플리케이션) - 트러블 슈팅

J_log·2024년 12월 3일
0

@RequestParam 이용해 특정 키워드로 가게 검색하기

@RequestParm을 이용해 가게 이름에 특정 키워드가 포함되어 있다면 모두 가져오는 로직을 만들었다. JPQL을 이용해 직접 쿼리를 작성했고 특정 키워드를 포함시키기 때문에 LIKE를 사용했다.

  • Repostory

  • Service

  • Controller

postman을 이용해 가게 생성 API로 미리 몇 여러 가게들을 만들어 놓고 가게 조회 API를 테스트해봤다.

  • DB
  • postman

DB에는 정상적으로 여러 가게들이 생성된 모습을 볼 수 있다. 하지만 조회된 결과가 없어서 빈 배열을 반환하고있다.

원인 추론

JPQL이 잘 못 작성되었거나, 파라미터 값을 잘 못 넣고 있는건 아닌지 추론할 수 있었다.

해결 방안

먼저 Repository를 살펴보았다. LIKE 연산자는 기본적으로 포함하려는 문자열 앞 뒤로 '%'가 필요하다. 그러나 :name 파라미터 값에 %가 포함되지 않으면 문자열 매칭이 정확히 일치해야 하므로 결과가 반환되지 않을 수도 있다는 자료를 찾을 수 있었다.

@Query("select s from Store s where s.name like concat('%', :name, '%')")
List<Store> findAllByStoreName(@Param("name") String name);

concat을 이용해 쿼리를 수정해서 다시 시도 -> 실패

다음은 파라미터 자체를 잘 못 입력하고 있는건 아닌지 postman으로 돌아와봤다.

""를 없애고 바로 문자를 입력 -> 성공..
postman에서 요청을 보낼 때 ""를 포함하면, 쿼리 파라미터 값이 그대로 "키워드"로 처리된다. 이로 인해 문자열 비교에서 "키워드"와 키워드가 서로 다른 값으로 간주되어 매칭이 되지 않았던 것이다.

하지만 의문점이 생겼다. 쿼리에서 LIKE로 비교해서 찾으면 ""이 들어가도 어쨌든 안에 키워드가 포함되어 있는데 찾을 수 있어야되는게 아닐까? 이 부분에 대해서 알아보았다.

논리적으로는 LIKE 쿼리를 사용할 때, 파라미터 값에 "(따옴표)가 포함되더라도 SQL 자체는 문자열로 처리하기 때문에 문제가 없어야한다. 그러나 실제로는 따옴표가 포함된 값이 데이터베이스에 저장된 값과 매칭되지 않아서 결과가 나오지 않을 수 있다. 이를 이해하려면 몇 가지 세부 사항을 살펴보아야 한다.

  1. SQL에서 LIKE와 따옴표의 처리
    SQL 쿼리에서 LIKE는 문자열 비교를 수행한다. 만약 파라미터에 "가 포함되면, 이는 데이터베이스가 그 값을 정확히 포함하는 문자열을 찾게 만든다.
SELECT * FROM store WHERE name LIKE '%"메가커피"%';

이 쿼리는 name 컬럼에 메가커피가 아닌 정확히 "메가커피"라는 값을 가진 레코드를 찾는다. 따라서 name 컬럼에 실제 데이터가 "메가커피"로 저장되지 않았다면 결과가 반환되지 않는다.

  1. 문제의 원인
    Postman에서 "메가커피"를 요청하면, HTTP 요청 파라미터로 따옴표가 포함된 값이 전달된다. Spring에서는 이 값을 그대로 받으므로, 아래와 같이 JPQL 또는 Native Query에서 비교가 수행된다.
WHERE s.name LIKE '%"메가커피"%'

결국 따옴표가 매칭되지 않기 때문에 기대하는 값이 나오지 않는다.

따옴표를 허용하도록 처리하는 방법도 있다.

만약 입력 값에 따옴표가 포함되더라도 문제가 없도록 만들고 싶다면, 파라미터를 사전 처리하여 따옴표를 제거하거나 변환해줄 수 있다.

  • 파라미터 클리닝
    컨트롤러에서 따옴표 제거 :
@GetMapping("/store")
public List<StoreResponseDto> getStores(@RequestParam String name) {
    name = name.replace("\"", ""); // 따옴표 제거
    return storeService.findAll(name);
}
  • JPQL에서 공백 및 특수문자 제거
    SQL 함수로 직접 파라미터를 정리:
@Query("select s from Store s where replace(s.name, '\"', '') like concat('%', replace(:name, '\"', ''), '%')")
List<Store> findAllByStoreName(@Param("name") String name);

결과 확인

결론적으로는 ""를 없애고 바로 문자를 입력해서 이슈는 해결되었다.

  • 요약
    LIKE는 따옴표가 포함된 문자열도 찾을 수 있지만, 따옴표를 포함한 값이 데이터와 정확히 매칭되어야 한다.

  • 해결책

    • 따옴표를 자동을 제거하는 로직 추가
    • Native Query나 SQL 함수를 사용해 파라미터를 정리

Postman이나 클라이언트 측 입력값이 항상 일관적이지 않을 수 있으니, 서버 쪽에서 사전처리를 통해 유연하게 대응하는 것이 좋겠다.

0개의 댓글