Skip to content

[Feat] GPS 노이즈 필터링으로 불필요한 DB 저장 절감#250

Merged
howooyeon merged 2 commits into
developfrom
feat/#249-gps-noise-filter
Jul 1, 2026
Merged

[Feat] GPS 노이즈 필터링으로 불필요한 DB 저장 절감#250
howooyeon merged 2 commits into
developfrom
feat/#249-gps-noise-filter

Conversation

@howooyeon

@howooyeon howooyeon commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • GPS 트래킹 중 이동이 거의 없는 점(수평 10m 미만 + 고도 3m 미만)을 서버에서 필터링
  • TrackingSessionStatsServicegetLastPosition() 읽기 전용 메서드 추가
  • TrackingStreamConsumer.onMessage()에서 recordPoint() 호출 전 노이즈 필터 적용

변경 파일

  • TrackingSessionStatsService.javaLastPosition record + getLastPosition() 메서드 추가
  • TrackingStreamConsumer.javashouldAcceptPoint() 필터 + haversineMeters() 거리 계산 추가

기대 효과

  • 등산 평균 속도(시속 2~3km) 기준 약 90% 이상 DB 저장 절감
  • Redis Lua 스크립트 실행, 마일스톤 평가, 메모리 버퍼 사용량 동시 절감
  • k6 부하 테스트로 Before/After 정량 비교 예정

Test plan

  • k6 부하 테스트 Before(1,984건) vs After 비교
  • 필터 적용 후 경로 끊김 없이 정상 표시 확인
  • 정지 상태에서 불필요한 점 저장 안 되는지 확인

Closes #249

수평 거리 10m 미만 + 고도 변화 3m 미만인 GPS 점을 서버에서 drop하여
DB 쓰기, Redis 통계 연산, 메모리 버퍼 사용량을 절감한다.

- TrackingSessionStatsService에 getLastPosition() 읽기 전용 메서드 추가
- TrackingStreamConsumer에 shouldAcceptPoint() 필터 로직 추가
- Haversine 공식으로 수평 거리 계산

Closes #249
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bbd26cf7-94e7-4c86-95b4-04c01351a06d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#249-gps-noise-filter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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은 GPS 트래킹 데이터의 노이즈를 서버 측에서 필터링하여 불필요한 DB 쓰기 작업을 대폭 줄이는 것을 목적으로 합니다. 또한, 기존의 읽기-수정-쓰기 패턴을 Redis Lua 스크립트로 교체하여 동시성 안전성을 확보하고 시스템 효율성을 개선했습니다.

Highlights

  • GPS 노이즈 필터링 도입: 수평 이동 거리 10m 미만 및 고도 변화 3m 미만인 GPS 데이터를 필터링하여 불필요한 DB 저장을 방지합니다.
  • Redis Lua 스크립트 적용: TrackingSessionStatsService의 데이터 갱신 로직을 Lua 스크립트로 전환하여 원자적(atomic) 연산을 보장하고 동시성 문제를 해결했습니다.
  • 성능 최적화: 불필요한 데이터 저장을 줄임으로써 DB 부하를 약 90% 이상 절감하고 Redis 및 메모리 사용량을 최적화했습니다.
New Features

🧠 You can now enable Memory (public preview) 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.

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 the 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 counterproductive. 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.

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.

@howooyeon howooyeon self-assigned this Jul 1, 2026
@howooyeon howooyeon changed the title feat: GPS 노이즈 필터링으로 불필요한 DB 저장 절감 [Feat] GPS 노이즈 필터링으로 불필요한 DB 저장 절감 Jul 1, 2026

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

이번 PR은 Redis Lua 스크립트를 도입하여 위치 정보 누적 및 통계 업데이트 작업을 원자적(atomic)으로 처리하도록 개선하고, GPS 노이즈 필터링 로직을 추가하여 불필요한 데이터 입력을 방지합니다. 이에 대해 리뷰어는 매 GPS 수신마다 발생하는 Redis 조회 성능을 최적화하기 위해 인메모리 캐싱을 적용할 것과, getLastPosition 메서드에서 multiGet 결과에 대한 방어적인 null 및 크기 체크를 추가하여 안정성을 높일 것을 제안했습니다.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +99 to 108
public LastPosition getLastPosition(Long sessionId) {
HashOperations<String, String, String> hash = redisTemplate.opsForHash();
String key = statsKey(sessionId);
List<String> values = hash.multiGet(key, List.of("last_lat", "last_lng", "last_altitude"));
return new LastPosition(
parseNullableDouble(values.get(0)),
parseNullableDouble(values.get(1)),
parseNullableDouble(values.get(2))
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

[P3] getLastPosition에서 multiGet 결과에 대한 방어적 null 체크 추가

redisTemplate.opsForHash().multiGet은 Redis 연결 장애, 파이프라인/트랜잭션 환경 등 다양한 원인으로 인해 null을 반환할 가능성이 있습니다. 또한, 반환된 리스트의 크기가 예상보다 작을 경우 IndexOutOfBoundsException이 발생할 위험이 있습니다.

안전한 실행을 위해 valuesnull이거나 크기가 부족한 경우를 대비한 방어적 코드(Null-safe guard)를 추가하는 것을 권장합니다.

    public LastPosition getLastPosition(Long sessionId) {
        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        String key = statsKey(sessionId);
        List<String> values = hash.multiGet(key, List.of("last_lat", "last_lng", "last_altitude"));
        if (values == null || values.size() < 3) {
            return new LastPosition(null, null, null);
        }
        return new LastPosition(
                parseNullableDouble(values.get(0)),
                parseNullableDouble(values.get(1)),
                parseNullableDouble(values.get(2))
        );
    }

- shouldAcceptPoint에서 Redis HMGET 대신 ConcurrentHashMap 캐시 우선 조회
- recordPoint 성공 시 캐시 갱신, 세션 종료 시 캐시 제거
- getLastPosition의 multiGet 결과에 null/size 방어 코드 추가
@howooyeon
howooyeon merged commit 60a9eb6 into develop Jul 1, 2026
1 check passed
@howooyeon
howooyeon deleted the feat/#249-gps-noise-filter branch July 21, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] GPS 노이즈 필터링으로 불필요한 DB 저장 절감

1 participant