-
Notifications
You must be signed in to change notification settings - Fork 1
Redis GEO (유저 위치 저장 및 검색)
근처에 있는 사용자 조회 기능: Redis Geospatial가 적합한 선택일까?
Redis Geo는 Redis 3.2 버전부터 추가된 지리 공간 데이터를 처리하기 위한 특수 기능입니다. 이 기능을 사용하면 위도와 경도 좌표를 저장하고, 지리적 거리 계산, 반경 내 요소 검색 등의 작업을 매우 효율적으로 수행할 수 있습니다.
-
GEOADD: 지리 공간 데이터 저장
GEOADD key longitude latitude member [longitude latitude member ...]
예:
GEOADD locations 126.9780 37.5665 "seoul"
-
GEODIST: 두 위치 사이의 거리 계산
GEODIST key member1 member2 [unit]
예:
GEODIST locations seoul busan km
-
GEORADIUS: 특정 좌표 기준 반경 내 멤버 검색
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
예:
GEORADIUS locations 126.9780 37.5665 10 km
-
GEORADIUSBYMEMBER: 저장된 멤버 기준 반경 내 검색
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
예:
GEORADIUSBYMEMBER locations seoul 20 km
-
GEOHASH: 위치의 geohash 문자열 반환
GEOHASH key member [member ...]
예:
GEOHASH locations seoul
Redis Geo는 내부적으로 정렬 집합(sorted set) 자료구조를 사용하며, 위치 정보를 geohash로 변환하여 저장합니다.
Geohash는 위도와 경도를 결합한 문자열로, 비슷한 위치는 비슷한 해시 값을 가지는 특성이 있습니다. 이를 통해 Redis는 매우 빠른 지리 공간 검색을 제공할 수 있습니다.
// Spring Data Redis 사용 예시
@Service
public class LocationService {
private final RedisTemplate<String, String> redisTemplate;
public LocationService(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// 사용자 위치 저장
public void saveUserLocation(String userId, double longitude, double latitude) {
redisTemplate.opsForGeo().add("user:locations",
new Point(longitude, latitude), userId);
}
// 반경 내 사용자 검색
public List<GeoResult<RedisGeoCommands.GeoLocation<String>>> findNearbyUsers(
double longitude, double latitude, double radiusInKm) {
Distance distance = new Distance(radiusInKm, Metrics.KILOMETERS);
Circle circle = new Circle(new Point(longitude, latitude), distance);
RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs
.newGeoRadiusArgs()
.includeDistance()
.sortAscending();
GeoResults<RedisGeoCommands.GeoLocation<String>> results =
redisTemplate.opsForGeo().radius("user:locations", circle, args);
return results.getContent();
}
}
Redis Geo 기능은 위치 기반 서비스, 지리적 근접 검색, 위치 추적 등의 기능을 구현할 때 매우 유용합니다. 메모리 기반 데이터베이스인 Redis의 특성상 매우 빠른 응답 시간을 제공하며, 대규모 위치 데이터를 효율적으로 처리할 수 있습니다.
- 위치 업데이트 API:
POST /api/location/update
Request: {
latitude: float,
longitude: float,
accuracy: float (optional)
}
- 근처 사용자 조회 API:
GET /api/users/nearby
Parameters:
- radius: int (미터 단위, 기본값 500m)
- limit: int (최대 반환 수, 기본값 50)
-
위치 업데이트 시:
// 1. Redis에 위치 정보 저장 redisTemplate.opsForGeo().add( "user:locations", new Point(longitude, latitude), userId.toString() ); redisTemplate.expire("user:locations", 24, TimeUnit.HOURS); // 2. 일정 시간마다 또는 조건에 따라 PostgreSQL에도 저장 userLocationRepository.save(new UserLocation(userId, point, now()));
-
근처 사용자 조회 시:
// Redis에서 반경 내 사용자 검색 GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius( "user:locations", new Circle( new Point(longitude, latitude), new Distance(radius, Metrics.METERS) ) ); // 결과 필터링 및 사용자 정보 조회 List<String> nearbyUserIds = results.getContent().stream() .map(result -> result.getContent().getName()) .filter(id -> !id.equals(currentUserId)) .collect(Collectors.toList()); return userRepository.findAllByIdIn(nearbyUserIds);
-
Redis 캐싱 전략:
- 자주 접근하는 지역에 대한 결과를 추가로 캐싱
- 키 형식:
nearby:{geohash}:radius:{r}
-
위치 업데이트 최적화:
- 의미 있는 위치 변화가 있을 때만 업데이트 (예: 50m 이상 이동)
- 백그라운드 작업으로 DB 동기화
-
부하 분산:
- 지역별 샤딩 (geohash 기반)
- 읽기 전용 복제본으로 조회 부하 분산
- 백엔드 컨벤션
- TestContainer 적용 이유
- DB Read replica 구성 (AWS RDS)
- RDS 프라이빗 설정 후 로컬 터널링
- 공통 성공/에러 응답 정의
- 테스트 환경 통합 작업
- 소셜 로그인 설계(Spring Security 없이 OAuth2.0)
- 클라우드 환경변수 관리 AWS SSM Parameter Store
- 코드단 제안 사항 (카카오톡 내용 요약)
- Spring에서 JWT 인증/인가 위치 제안(Filter와 Interceptor)
- 알림 아키텍처 정리
- 외부 API Call 및 무거운 작업 Serverless Lambda 로 분리
- Redis GEO (유저 위치 저장 및 검색)
- 푸시알림 권한 받는 시점
- TestConfig 및 (이전) Fixture 활용 방법
- 테스트 코드 개선 제안: Mock과 Fixture 패턴
- 테스트 객체 자동 생성
- 푸시알림 설계
- Fixture 및 Factory 활용 방법
- 로그 모니터링 시스템 구축
- 성능테스트 케이스