최근 매칭관련 매칭이 가능한 유저를 조회하는 로직에서 es를 사용하게 되었는데 이때 filter를 사용해서 충족되어야하는 조건, 그리고 조건에 포함되면안되는 조건, 선택 조건 등 검색시 조건을 추가하여 검색하는 로직을 만들었는데. 이를 정리하고자한다.
Elasticsearch 쿼리 조건 타입
ES에서 검색 조건을 설정할 때 주로 사용하는 세 가지 주요 쿼리 타입이 있다.
- must - 반드시 충족해야 하는 조건
- 이 조건에 맞지 않는 문서는 결과에서 완전히 제외됨
- 필수 조건으로 작동하며 AND 연산자와 유사함
- should - 충족하면 좋은 조건
- 이 조건을 만족하면 문서의 관련성 점수가 높아짐
- 가중치를 부여하는 방식으로 작동함
- 필수는 아니지만 만족할수록 검색 결과 상위에 노출됨
- must_not - 포함되면 안 되는 조건
- 이 조건에 맞는 문서는 결과에서 제외됨
- NOT 연산자와 유사하게 작동함
현재 구현 방식과 개선 방향
현재 방식: 백엔드 정렬 방식
현재는 다음과 같은 2단계 접근법을 사용하고 있음.
- ES filter를 사용한 1차 필터링
- 필수 조건(must)과 제외 조건(must_not)을 적용해 기본 후보군 추출
- 조건에 맞는 사용자들만 1차적으로 필터링
- 백엔드에서의 가중치 계산 및 정렬
- 필터링된 결과를 백엔드로 가져온 후
- 각 조건별 가중치를 직접 계산해서 점수 부여
- 최종 점수에 따라 정렬 후 클라이언트에 반환
이 방식은 구현이 직관적이고 백엔드에서 세밀한 제어가 가능하다는 장점이 있지만, 대량의 데이터를 백엔드로 가져와 처리해야 하는 부담이 있어.
개선 방향: script_score 활용
앞으로는 ES의 script_score 기능을 활용해 검색 단계에서 바로 가중치를 계산하는 방식으로 개선하려고 한다
//e.g
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{ "term": { "active": true } }
],
"must_not": [
{ "term": { "blocked": true } }
],
"should": [
{ "term": { "premium": true } }
]
}
},
"script_score": {
"script": {
"source": "params.weight * doc['rating'].value + (doc['premium'].value ? 10 : 0)",
"params": {
"weight": 2.0
}
}
}
}
}
}
이 방식의 장점은:
- 성능 향상 - ES 내부에서 스코어링과 정렬이 이루어져 백엔드 부하 감소
- 확장성 - 복잡한 스코어링 로직도 ES 내에서 처리 가능
- 효율성 - 이미 정렬된 상태로 결과를 받아 추가 처리 최소화
결론
현재는 필터링 후 백엔드에서 가중치 계산 및 정렬을 하는 방식을 사용하고 있지만, 곧 script_score를 활용한 방식으로 전환할 예정이야. 이렇게 하면 ES의 강력한 검색 및 스코어링 기능을 더 효과적으로 활용할 수 있고, 서비스 성능도 개선될 거라 기대중임.
'Project > TroubleShooting' 카테고리의 다른 글
포트포워딩 문제 (0) | 2025.04.01 |
---|---|
항상 마주하는 CORS 에러: 여기 고치면 저기 문제, 저기 고치면 여기 문제 (0) | 2025.01.15 |
U2Net 직접 사용 vs. rembg 활용: 어느 쪽이 더 나을까? (0) | 2024.11.19 |
AWS 과금 (1) | 2024.09.27 |
프로토콜 문제 (0) | 2024.09.11 |