Skip to content

Comments

[REFACTOR] Redisearch로 매칭 알고리즘 리팩토링#374

Merged
Yoonchulchung merged 4 commits intodevfrom
refactor/372-match-type
Feb 11, 2026
Merged

[REFACTOR] Redisearch로 매칭 알고리즘 리팩토링#374
Yoonchulchung merged 4 commits intodevfrom
refactor/372-match-type

Conversation

@Yoonchulchung
Copy link
Member

Summary

기존 Redis를 캐싱 형태로 사용하여, 모든 연산을 어플리케이션 서버에서 진행하던 것을 Redisearch를 이용해
Redis에서 연산을 수행하도록 로직을 수정했습니다.

Changes

  • 서버 기반 알고리즘 추론 방식에서 Redisearch로 매칭 알고리즘 수정
  • 유저 타입 알고리즘 추가

Type of Change

  • Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
  • New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
  • Breaking change (기존 기능에 영향을 주는 수정)
  • Refactoring (기능 변경 없는 코드 개선)
  • Documentation (문서 수정)
  • Chore (빌드, 설정 등 기타 변경)
  • Release (develop → main 배포)

Related Issues

#372

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Yoonchulchung, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 기존에 애플리케이션 서버에서 처리하던 매칭 로직을 Redisearch를 활용하여 Redis에서 직접 연산을 수행하도록 변경하는 대규모 리팩토링을 포함합니다. 이를 통해 매칭 프로세스의 효율성을 높이고, 사용자 유형을 더욱 정교하게 분류하는 새로운 알고리즘을 도입하여 개인화된 매칭 경험을 제공하는 데 기여합니다.

Highlights

  • Redisearch 기반 매칭 알고리즘 리팩토링: 기존 애플리케이션 서버에서 처리하던 매칭 로직을 Redisearch를 활용하여 Redis에서 직접 연산을 수행하도록 변경했습니다.
  • 사용자 유형 알고리즘 개선 및 확장: 사용자 유형을 결정하는 로직을 더욱 정교하게 개선하고, 새로운 사용자 유형 태그를 추가하여 개인화된 매칭 경험을 강화했습니다.
  • Redisearch TAG 필드 데이터 형식 통일: Redisearch의 TAG 필드가 문자열만 허용함에 따라, 정수 리스트를 문자열 리스트로 변환하는 유틸리티 메서드를 추가하고 관련 필드에 적용했습니다.
  • Redisearch 인덱스 스키마 확장: 브랜드 및 캠페인 문서의 Redisearch 인덱스 스키마에 체형, 사이즈, 콘텐츠 시청자 정보 등 다양한 태그 필드를 추가하여 검색 기능을 확장했습니다.
  • 매칭 서비스 Redisearch 통합: 매칭 서비스 로직에서 Redisearch를 활용하여 후보 브랜드 및 캠페인을 효율적으로 검색하도록 변경하여 성능을 향상시켰습니다.
Changelog
  • data/generators/redis_matching_generator.py
    • 정수 리스트를 문자열 리스트로 변환하는 _to_str_list 정적 메서드를 추가했습니다.
    • 브랜드 및 캠페인 문서 생성 시 다양한 태그 필드에 _to_str_list 메서드를 적용했습니다.
    • Redisearch 인덱스 스키마에 minCreatorHeight, maxCreatorHeight, preferredBodyTypeTags, preferredTopSizeTags, preferredBottomSizeTags, preferredContentsAverageViewsTags, preferredContentsAgeTags, preferredContentsGenderTags, preferredContentsLengthTags 필드를 추가했습니다.
  • src/main/java/com/example/RealMatch/match/application/service/MatchServiceImpl.java
    • 사용자 유형에 따른 태그를 정의하는 USER_TYPE_TAG_MAP 상수를 추가했습니다.
    • match 메서드에서 사용자 닉네임을 가져오도록 User::getNameUser::getNickname으로 변경했습니다.
    • MatchResponseDtouserTypeTag 필드를 추가하고, USER_TYPE_TAG_MAP을 사용하여 해당 값을 설정하도록 했습니다.
    • determineUserType 메서드의 로직을 대폭 개선하여 패션, 뷰티, 콘텐츠 태그의 비율, 체형/사이즈 디테일 입력 여부, SNS 시청자 정보 입력 여부 등을 기반으로 사용자 유형을 더 정교하게 분류하도록 했습니다.
    • 브랜드 및 캠페인 매칭 시 redisDocumentHelper.findAllBrandTagDocuments()redisDocumentHelper.findAllCampaignTagDocuments() 대신 redisDocumentHelper.findCandidateBrands(userDoc)redisDocumentHelper.findCandidateCampaigns(userDoc)를 호출하도록 변경하여 Redisearch를 통한 후보군 검색을 적용했습니다.
  • src/main/java/com/example/RealMatch/match/infrastructure/redis/RedisDocumentHelper.java
    • Redisearch 인덱스 이름 상수를 추가했습니다 (BRAND_INDEX, CAMPAIGN_INDEX).
    • findCandidateBrandsfindCandidateCampaigns 메서드를 추가하여 사용자 문서(UserTagDocument)를 기반으로 Redisearch 쿼리를 생성하고 후보군을 검색하도록 했습니다.
    • searchWithFallback 메서드를 구현하여 태그 기반 검색 결과가 부족할 경우 전체 검색으로 대체하는 로직을 추가했습니다.
    • extractDocId 유틸리티 메서드를 추가하여 문서에서 ID를 추출하도록 했습니다.
    • 기존 findAllBrandTagDocumentsfindAllCampaignTagDocuments 메서드를 @Deprecated 처리했습니다.
    • Redisearch 쿼리를 생성하는 buildTagOverlapQuerybuildTagClause 메서드를 추가했습니다.
    • Redisearch FT.SEARCH 명령을 실행하고 결과를 파싱하는 executeSearch, parseFtSearchResult, decodeBytes 메서드를 추가했습니다.
  • src/main/java/com/example/RealMatch/match/presentation/dto/response/MatchResponseDto.java
    • userTypeTag 필드를 추가했습니다.
Activity
  • 이 PR에는 현재까지 기록된 활동이 없습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@Yoonchulchung Yoonchulchung merged commit f9d9b70 into dev Feb 11, 2026
1 check passed
@Yoonchulchung Yoonchulchung deleted the refactor/372-match-type branch February 11, 2026 08:11
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR is a great refactoring that moves the matching logic from the application server to RediSearch to significantly improve performance, and it also introduces new user type determination logic. The RediSearch client implementation is robust, including a fallback mechanism, and its query construction appears safe from injection. However, a significant security issue was identified in MatchServiceImpl: the match method lacks authorization checks on the userId parameter, allowing for Insecure Direct Object Reference (IDOR). This could enable an attacker to access or modify matching data for other users, so it is highly recommended to add ownership verification for the userId before proceeding with the match operation. Additionally, an inconsistency in the test data generator was noted. Some refactoring suggestions for code maintainability have been identified but are noted as potential future tasks, aligning with the scope of this already complex refactoring.

I am having trouble creating individual review comments. Click here to see my feedback.

src/main/java/com/example/RealMatch/match/application/service/MatchServiceImpl.java (131-133)

security-high high

The match method uses the userId parameter to access and modify user-specific data without verifying that the userId belongs to the currently authenticated user. This is an Insecure Direct Object Reference (IDOR) vulnerability. An attacker could potentially call this method with an arbitrary userId to view another user's matching results (like their nickname) and, more critically, modify their matching details, SNS URL, and tags (via the replaceUserMatchingDetailAndTags call, which also uses the unvalidated userId).

To remediate this, implement an authorization check to ensure that the userId provided in the request matches the ID of the authenticated user. Alternatively, retrieve the user ID directly from the security context instead of accepting it as a parameter.

data/generators/redis_matching_generator.py (389)

high

인덱스 스키마에 preferredContentsAverageViewsTags 필드가 정의되어 있지만, generate_brand_documentsgenerate_campaign_documents 메서드에서 이 필드를 생성하는 로직이 누락되었습니다. 이로 인해 MatchScoreCalculator에서 매칭 점수가 의도와 다르게 계산될 수 있습니다.

데이터 생성 로직에 해당 필드를 추가하는 것을 권장합니다. 예를 들어, 다음과 같이 추가할 수 있습니다:

# in generate_brand_documents and generate_campaign_documents
... 
views_tags = self._get_random_tag_ids(['영상 조회수'], 1, 2)
doc = {
    ...
    'preferredContentsAverageViewsTags': self._to_str_list(views_tags),
    ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant