Redis - Geospatial

2026. 5. 28. 15:38·Redis

Redis의 Geospatial 자료구조란?

위치데이터(위도, 경로)를 저장하고 검색하는데 최적화된 자료 구조

 

 

특정 위치를 기준으로 주어진 거리 내의 데이터를 찾을 때 주로 사용한다.

ex) 현재 사용자의 위치를 기반으로 반경 3km내의 음식점 조회하기

 

 

또한 Geospatial은 별도의 자료구조가 아니라 내부적으로 Sorted Set(ZSET)을 사용하여 데이터를 저장한다.


Geospatial 기본 명령어

 

데이터 삽입

 // GEOADD [KEY] [longitude] [latitude] [member]
 GEOADD cafe 127.0276 37.4979 a_cafe

 

이때 내부적으로 cafe라는 key의 Sorted Set에 a_cafe라는 member가 추가되고, 그 score 자리에는 경도·위도를 인코딩한 52비트 Geohash 정수가 들어간다.

출처: https://redis.io/docs/latest/commands/geoadd/

 

또한 표준 형식인 x,y로 인수를 받으므로 반드시 위도보다 경도를 먼저 지정해야 한다고 한다.

 

인덱싱 가능한 좌표에는 한계가 있는데, 극지방에 매우 가까운 영역은 인덱싱되지 않는다고 한다.

 

이 한계는 EPSG:900913 / EPSG:3785 / OSGEO:41001 좌표계 규격을 따르며, 구체적인 범위는 다음과 같다.

  • 경도(longitude): -180 ~ 180도
  • 위도(latitude): -85.05112878 ~ 85.05112878도

하지만 일상적인 위치 기반 서비스(가게 검색, 배달 반경, 주변 사용자 매칭 등)에서 다루는 지역은 모두 이 범위 안에 들어오기 때문에 실제로 이 제약이 문제가 되는 경우는 거의 없다고 한다.

 

키의 member 조회

데이터 저장을 위해 Sorted Set 자료구조를 사용하기 때문에 Sorted Set의 명령어로 member 조회 또한 가능하다

ZRANGE cafe 0 -1

1) "c_cafe"
2) "a_cafe"
3) "b_cafe"

 

 

특정 member의 위도, 경도 조회

// GEOPOS [KEY] [member..]
GEOPOS cafe a_cafe b_cafe c_cafe // 여러 개의 member 조회 가능

1) 1) "127.02759772539139"
   2) "37.4979006128309"
2) 1) "127.0294001698494"
   2) "37.498100855802484"
3) 1) "127.03299969434738"
   2) "37.49500089182462"

 

여러 member의 위도, 경도를 한번에 조회하는 것도 가능하다.

 

두 데이터 간 직선 거리 구하기

// GEODIST [KEY] [member1] [member2] [M | KM | FT | MI]
GEODIST cafe a_cafe b_cafe m

"160.6069"

 

구하는 거리의 단위는 M(미터), KM(킬로미터), FT(피트), MI(마일)의 4가지가 가능하다고 한다.

 

또한 두 멤버 중 하나 또는 둘 다 누락된 경우 NULL을 반환한다고 한다.

 

출처: https://redis.io/docs/latest/commands/geodist/

 

특정 위치에서 정해진 반경 이내의 데이터 조회

// GEOSEARCH [KEY] FROMLONLAT [longitude] [latitude] [BYRADIUS] [radius] [M | KM | FT | M] [ASC | DESC] [COUNT count [ANY]] [WITHCOORD] [WITHDIST] [WITHHASH]

GEOSEARCH cafe FROMLONLAT 127.0280 37.4975 BYRADIUS 1000 m ASC WITHDIST

1) 1) "a_cafe"
   2) "56.9703"
2) 1) "b_cafe"
   2) "140.4732"
3) 1) "c_cafe"
   2) "521.4656"

 

입력한 위도, 경도로 조회 기준이 될 위치를 지정하고, BYRADIUS를 써줌으로써 반경으로 계산하도록 하고, WITHDIST로 거리를 포함해서 출력하도록 한다.

 

추가로 여기에 더해 더 다양한 옵션으로 조회가 가능하다.

 

  • COUNT count [ANY] : 반환 결과 개수를 제한 (예: 가까운 5개만)
  • FROMMEMBER [member] : FROMLONLAT [longitude] [latitude] 대신 변경 시 좌표 대신 저장된 멤버를 중심으로 검색
  • BYBOX width height : BYRADIUS 대신 변경 시 원형이 아닌 사각형 영역으로 검색
  • WITHCOORD : 멤버의 좌표를 함께 조회
  • WITHHASH : 52비트 Geohash 값을 함께 반환

 

내 위치를 기준으로 반경 1km 이내 카페 찾기

 

테스트를 위해 다음과 같이 코드를 작성한다.

@Service
@RequiredArgsConstructor
public class CafeService {
    private final RedisTemplate<String, String> redisTemplate;
    private final String GEOSPATIAL_KEY = "cafe";

    public void addCafe(AddCafeRequestDto addCafeRequestDto) {
        // GEOADD [KEY] [longitude] [latitude] [member]
        redisTemplate.opsForGeo()
                .add(GEOSPATIAL_KEY,
                     new Point(addCafeRequestDto.getLongitude(), addCafeRequestDto.getLatitude()),
                     addCafeRequestDto.getName());
    }

    public List<Object> findCafesNearby(double longitude, double latitude, double distanceKm) {
        GeoSearchCommandArgs args = GeoSearchCommandArgs
                .newGeoSearchArgs()
                .includeDistance()
                .sortAscending();

        // GEOSEARCH [KEY] FROMLONLAT [longitude] [latitude] [BYRADIUS] [radius] [M | KM | FT | M] [ASC | DESC] [WITHDIST]
        return redisTemplate.opsForGeo().search(
                GEOSPATIAL_KEY,
                GeoReference.fromCoordinate(new Point(longitude, latitude)),
                new Distance(distanceKm, Metrics.KILOMETERS),
                args
        ).getContent().stream()
                .map(geoResult -> new CafeDistance(
                        geoResult.getContent().getName(),
                        geoResult.getDistance().getValue()
                ))
                .collect(Collectors.toList());
    }
}

 

GeoSearchCommandArgs로 GEOSEARCH 명령어에서 지정해줬던 검색 옵션들을 지정하여 검색한다.

(위 코드에서는 WITHDIST, ASC를 추가)

 

이후 postman으로 redis에 데이터를 저장하고, 

 

만들어놓은 코드대로 위도, 경도 기준 반경 1km이내의 카페를 조회하면

 

가까운 순으로 거리와 함께 데이터가 잘 조회됨을 확인 할 수 있다.

 

'Redis' 카테고리의 다른 글

Redis - Hash  (0) 2026.06.04
Redis - Set & BitMap  (0) 2026.05.28
Redis - Sorted Set (ZSET)  (0) 2026.05.20
'Redis' 카테고리의 다른 글
  • Redis - Hash
  • Redis - Set & BitMap
  • Redis - Sorted Set (ZSET)
kkyc
kkyc
  • kkyc
    개가 짖어도 기차는 달린다.
    kkyc
  • 전체
    오늘
    어제
    • 분류 전체보기 (7)
      • Spring (1)
      • Java (0)
      • Kotlin (0)
      • Redis (4)
      • Programming (0)
      • 성능테스트 (0)
      • 기타 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    zset
    Sorted Set
    redis
    Geospatial
    bitmap
    set
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
kkyc
Redis - Geospatial
상단으로

티스토리툴바