스프링부트/트러블 슈팅

LIKE 쿼리에서 "_" 검색이 안되는 이유

Choony 2025. 5. 26. 20:34

안녕하세요. CareerBee 서비스에서 백엔드 개발을 맡고있는 mumu입니다. 

 

해당 글은 기업 검색시 발생한 문제에 대해서 설명하고 어떻게 해결했는지를 서술하고 있습니다.


🔍 문제점

CareerBee에는 사용자가 입력한 키워드로 기업을 검색하는 기능이 있습니다.

 

문득, 이름에 _(언더바) 를 포함한 기업이 있는지 궁금해 "_"를 검색해봤습니다.

 

하지만 결과는 엉뚱했습니다. 언더바가 들어가지 않은 기업들이 검색되는 것이었습니다.


❓ 왜 이런 현상이 발생했을까?

결론부터 말하자면 LIKE 쿼리에서 특수문자 _를 escape 처리하지 않았기 때문입니다.

 

검색 결과를 가져오는 Repository 의 코드를 보면 다음과 같이 LIKE 구문이 사용됨을 볼 수 있습니다.

@Override
public CompanySearchResp fetchMatchingCompaniesByKeyword(String keyword) {
    List<CompanySearchInfo> result = queryFactory
        .select(
           Projections.constructor(
                CompanySearchInfo.class,
                company.id,
                company.name
            )
        )
        .from(company)
        .where(company.name.like("%" + keyword + "%"))
        .limit(8)
        .fetch();

    return new CompanySearchResp(result);
}

 

이 코드에서 사용자가 "_"를 입력하면 실제 쿼리는 다음과 같이 완성됩니다.

WHERE name LIKE '%_%'

 

 

이 쿼리의 뜻은 "한 글자를 포함하는 모든 문자열" 입니다. 따라서 위의 문제가 발생하게 된 것입니다.

 

SQL에서  _ , %, ! 는 모두 패턴 문자로 취급되며 이를 진짜 문자열로써 검색하기 위해선 추가 처리가 필요합니다.


✅ 해결방법

특수문자를 문자 그대로 검색하려면 다음과 같은 처리가 필요합니다.

  1. 해당 문자 앞에 escape 문자 삽입
  2. SQL 에서 ESCAPE 옵션 추가

이를 적용하기 위해서 Service 와 Repository Layer 에서 다음과 같이 처리를 할 수 있습니다.

// Service
@Override
public CompanySearchResp fetchMatchingCompaniesByKeyword(String keyword) {
    return companyRepository.fetchMatchingCompaniesByKeyword(escapeLike(keyword.strip()));
}
    
private String escapeLike(String keyword) {
    // !를 escape 문자로 사용하며 패턴 문자 앞에 삽입
    return keyword
        .replace("!", "!!")
        .replace("%", "!%")
        .replace("_", "!_");
}

 

// Repository
@Override
public CompanySearchResp fetchMatchingCompaniesByKeyword(String keyword) {
  ...
        // QueryDSL의 like() 함수에서 escape 명시
        .where(company.name.like("%" + keyword + "%", '!'))
  ...
}

📚 배운 점

LIKE 쿼리를 종종 사용했지만, escape 처리까지 신경 써 본 것은 이번이 처음이었습니다.

 

현재는 검색 결과가 최대 8개로 한정되어있어 성능상 큰 문제는 없지만,

제한이 없는 서비스였다면 _(언더바) 검색시 대량의 데이터를 반환해 성능 저하로 이어질 수 있겠다는 생각이 들었습니다.

 

이번 경험을 통해, 완성도 높은 검색 기능을 제공하기 위해선 Java, SQL 등 다양한 분야에 있어 고루 지식을 갖추는 것이 필요하다는 것을 배웠습니다.