Skip to content

[FEATURE]: 사용자 위치 기반으로 인기TOP 가맹점 위치 반환 - #34

Merged
Answl merged 7 commits into
developfrom
feature/#31
Mar 11, 2026
Merged

[FEATURE]: 사용자 위치 기반으로 인기TOP 가맹점 위치 반환#34
Answl merged 7 commits into
developfrom
feature/#31

Conversation

@Answl

@Answl Answl commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

📌 개요

사용자의 위치(위도, 경도, 반경)를 기반으로 DB에 저장된 가맹점 지점 중 Top10 가맹점에 해당하는 지점을
서버 Haversine 계산으로 필터링하여 최대 10개를 반환하는 지도 API를 구현합니다.

🔧 작업 내용

  • MerchantLocation 엔티티 추가 — 가맹점(FK), 지점명, 위도, 경도 저장 테이블 신규 생성
  • MerchantLocationRepository 추가 — Top10 가맹점명 목록으로 지점 일괄 조회 쿼리
  • GET /api/v1/map/nearby-top10 API 구현
    • 요청: latitude, longitude, radiusKm (쿼리 파라미터)
    • 서버에서 Haversine 공식으로 두 좌표 간 거리(km) 계산, 반경 초과 지점 제외
    • Top10 우선순위 순 → 같은 가맹점 내 거리 오름차순으로 최대 10개 반환
    • DB에 없는 Top10 가맹점은 결과에서 제외
  • SecurityConfig — GET /api/v1/map/** 인증 없이 허용

✅ 체크리스트

{
    "data": [
        {
            "merchantRank": 1,
            "merchantName": "스타벅스",
            "placeName": "스타벅스00001점",
            "latitude": 37.5508103363035,
            "longitude": 127.12685944831,
            "distanceKm": 0.005365323624173253
        },
        {
            "merchantRank": 1,
            "merchantName": "스타벅스",
            "placeName": "스타벅스20989점",
            "latitude": 37.5512876939133,
            "longitude": 127.127018691186,
            "distanceKm": 0.05755411418274506
        },
        {
            "merchantRank": 1,
            "merchantName": "스타벅스",
            "placeName": "스타벅스01144점",
            "latitude": 37.5505124105179,
            "longitude": 127.1274134559,
            "distanceKm": 0.0628276692126367
        },
        {
            "merchantRank": 4,
            "merchantName": "올리브영",
            "placeName": "올리브영64046점",
            "latitude": 37.550566957873,
            "longitude": 127.126960885128,
            "distanceKm": 0.029540656753608393
        },
        {
            "merchantRank": 4,
            "merchantName": "올리브영",
            "placeName": "올리브영71201점",
            "latitude": 37.5512604691138,
            "longitude": 127.127199712113,
            "distanceKm": 0.06215537196390446
        },
        {
            "merchantRank": 4,
            "merchantName": "올리브영",
            "placeName": "올리브영89273점",
            "latitude": 37.5503863809105,
            "longitude": 127.127311392293,
            "distanceKm": 0.06440309211413094
        },
        {
            "merchantRank": 5,
            "merchantName": "다이소",
            "placeName": "다이소30252점",
            "latitude": 37.5511616274855,
            "longitude": 127.126950577162,
            "distanceKm": 0.0423455409563499
        },
        {
            "merchantRank": 5,
            "merchantName": "다이소",
            "placeName": "다이소17940점",
            "latitude": 37.5510168339572,
            "longitude": 127.127538797826,
            "distanceKm": 0.06944958752888943
        },
        {
            "merchantRank": 9,
            "merchantName": "파리바게뜨",
            "placeName": "파리바게뜨69935점",
            "latitude": 37.55104451016,
            "longitude": 127.126939061853,
            "distanceKm": 0.029824349010004032
        },
        {
            "merchantRank": 9,
            "merchantName": "파리바게뜨",
            "placeName": "파리바게뜨08285점",
            "latitude": 37.5504504354081,
            "longitude": 127.126394858823,
            "distanceKm": 0.05278728581169389
        }
    ],
    "error": null,
    "status": 200
}

📝 기타 참고 사항

  • Top10 가맹점 목록(TOP10_MERCHANTS)은 NearbyMerchantService에 상수로 하드코딩되어 있음. 목록 변경
    시 해당 필드 수정 필요
  • MerchantLocation 데이터는 별도 적재 필요 (노션에 공유할 예정)
  • 반경 단위는 km (radiusKm 파라미터)

📎 관련 이슈

Close #31

@Answl Answl self-assigned this Feb 25, 2026
@Answl Answl added the ✨ Feature 새로운 기능을 추가합니다. label Feb 25, 2026
@Answl Answl linked an issue Feb 25, 2026 that may be closed by this pull request
1 task
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @Answl, 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은 사용자의 현재 위치를 기반으로 주변의 인기 TOP 10 가맹점 지점을 검색하는 새로운 지도 기능을 도입합니다. 이를 위해 가맹점 지점 정보를 저장하는 새로운 데이터 모델이 추가되었고, 지리적 거리 계산을 위한 하버사인 공식이 적용된 서비스 로직이 구현되었습니다. 또한, 해당 기능을 외부에 노출하기 위한 REST API 엔드포인트가 개발되었으며, 이 엔드포인트는 인증 없이 접근 가능하도록 보안 설정이 업데이트되었습니다. 이 변경 사항은 사용자에게 주변 상점 정보를 제공하는 데 중요한 역할을 할 것입니다.

Highlights

  • 새로운 지도 API 엔드포인트 추가: 사용자의 위치(위도, 경도, 반경)를 기반으로 인기 TOP 10 가맹점 지점을 반환하는 GET /api/v1/map/nearby-top10 API가 구현되었습니다.
  • 가맹점 위치 엔티티 및 리포지토리 도입: 가맹점 지점의 이름, 위도, 경도를 저장하는 MerchantLocation 엔티티와 이를 조회하는 MerchantLocationRepository가 새로 추가되었습니다.
  • 하버사인(Haversine) 공식 기반 거리 계산: NearbyMerchantService에서 두 좌표 간의 거리를 하버사인 공식으로 계산하여, 지정된 반경 내의 지점만 필터링하고 거리순으로 정렬합니다.
  • 보안 설정 업데이트: 새로 추가된 /api/v1/map/** 경로에 대한 인증 없이 접근을 허용하도록 SecurityConfig가 수정되었습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/main/java/com/payper/server/map/controller/MapController.java
    • 새로운 지도 관련 REST 컨트롤러가 추가되었습니다.
  • src/main/java/com/payper/server/map/dto/NearbySearchRequest.java
    • 주변 검색 API의 요청 파라미터를 위한 레코드가 정의되었습니다.
  • src/main/java/com/payper/server/map/dto/NearbySearchResponse.java
    • 주변 검색 API의 응답 항목을 위한 레코드가 정의되었습니다.
  • src/main/java/com/payper/server/map/service/NearbyMerchantService.java
    • 주변 TOP 10 가맹점을 검색하는 비즈니스 로직(하버사인 거리 계산 포함)이 구현된 서비스가 추가되었습니다.
  • src/main/java/com/payper/server/merchant/entity/MerchantLocation.java
    • 가맹점 지점 위치를 나타내는 새로운 JPA 엔티티가 생성되었습니다.
  • src/main/java/com/payper/server/merchant/repository/MerchantLocationRepository.java
    • MerchantLocation 엔티티를 위한 새로운 JPA 리포지토리가 사용자 정의 쿼리와 함께 추가되었습니다.
  • src/main/java/com/payper/server/security/SecurityConfig.java
    • 새로운 지도 API 엔드포인트에 대한 인증되지 않은 접근을 허용하도록 보안 구성이 업데이트되었습니다.
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.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

이 PR은 사용자의 위치를 기반으로 인기 TOP 10 가맹점의 위치를 반환하는 새로운 API를 구현합니다. 전반적으로 기능 구현은 잘 되었지만, 데이터베이스 조회 성능과 메모리 사용량 측면에서 개선할 수 있는 부분이 있습니다. NearbyMerchantService에서 모든 가맹점 위치를 가져와 메모리에서 필터링하는 현재 방식은 데이터가 많아질 경우 심각한 성능 저하를 유발할 수 있습니다. 또한, 스트림 처리 로직을 최적화하여 불필요한 객체 생성을 줄일 수 있습니다. 자세한 내용은 각 파일에 남긴 주석을 참고해주세요.

데이터베이스 수준에서 1차적인 필터링 진행 (Bounding Box)
@Answl

Answl commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

안녕하세요. 사용자 위치 기반으로 인기 가맹점 위치를 반환하는 API 구현 PR 잘 보았습니다.
전반적으로 새로운 기능의 요구사항이 잘 반영되었고, 코드 구조도 명확하게 잘 분리되어 있습니다.

몇 가지 코드 가독성 및 유지보수성 향상을 위한 제안을 드립니다.

  • NearbyMerchantService에서 for 루프와 가변 리스트를 사용하는 대신, Stream API를 활용하여 더 선언적이고 간결한 코드로 개선할 수 있습니다.
  • 또한, 유지보수 편의성을 위해 하드코딩된 Top 10 가맹점 목록을 외부 설정으로 분리하는 방안을 고려해보시면 좋을 것 같습니다.

자세한 내용은 각 파일의 주석을 참고해주세요.

Comment thread src/main/java/com/payper/server/map/service/NearbyMerchantService.java Outdated
seoyeon2001
seoyeon2001 previously approved these changes Feb 25, 2026

@seoyeon2001 seoyeon2001 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

고생하셨습니다~~

@Answl
Answl merged commit a2732d7 into develop Mar 11, 2026
4 checks passed
@Answl
Answl deleted the feature/#31 branch March 11, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능을 추가합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: 사용자 위치 기반으로 인기TOP 가맹점 위치 반환

3 participants