JAVA

[Java] GeoLite2 사용해 IP 위치 조회 기능 구현하기

그레이트현 2025. 2. 18. 22:01
반응형

1. 들어가며

방문자 통계 기능을 만들어야 하는데 국가별, 지역별 접속자 통계를 구현해 달라는 요청이 있었다.

무료인 것을 찾다 보니 GeoLite2라는 게 나오길래 한 번 테스트 삼아 이용해 봤다.

GeoLite2 Free APIDB파일을 다운 받아서 사용하는 2가지 방법을 발견했다.

api의 경우 하루 1000건의 제한이 있지만, DB파일은 무제한으로 이용이 가능하다고 해서 DB파일을 이용하는 방법을 사용해 봤다.

스프링 부트 환경에서 테스트를 진행했다.

 

2. MaxMind 접속 후 mmdb 파일 다운로드

귀찮지만 회원가입이 필요하다. 까다로운 것이 없으니 필요하다면 가입해야겠다.

가입 후 로그인하게 되면 위 스크린샷의 화면이 보이게 되는데 왼쪽메뉴의 GeoIP2 / GeoLite2 하단의 Download Files 메뉴를 클릭하자.

그러면 6종류의 파일이 있다.

파일형태는 두 종류로 mmdbCSV가 있다.

GeoIP2 라이브러리를 사용할 것이기 때문에 mmdb 파일을 다운로드할 것이다.


📍mmdb 파일이란?

`mmdb`MaxMind Database를 뜻한다. MaxMind사에서 개발한 바이너리 데이터 형식의 파일이라고 한다.

IP주소 범위와 해당 지역 정보를 저장한 데이터베이스 파일이다.

데이터베이스를 따로 운영할 필요가 없고, 연결할 필요도 없어 빠르고 편리하지만 정보를 최신화하기 위해서 파일을 다시 다운로드한 뒤에 교체를 해줘야 한다!


나는 국가 정보와 지역 정보가 필요했기 때문에 GeoLite2-City를 다운로드하였다.

Download GZIP을 클릭하여 다운로드하여주자.

다음은 파일별 특징이다. 필요한 파일을 사용하면 될 것이다.

파일명 내용
GeoLite2-Country 국가 정보만 (예: 대한민국, 미국 등)
GeoLite2-City 국가 + 도시 + 위도/경도 + 타임존
GeoLite2-ASN 네트워크 제공자(ASN), ISP 정보

 

압축을 풀면 다양한 텍스트 파일과 GeoLite2-City.mmdb 파일을 찾을 수 있다.

이 mmdb 파일을 프로젝트의 `resources`폴더 밑에 저장해 주자.

 

3. gradle

dependencies {
    implementation 'com.maxmind.geoip2:geoip2:2.15.0'
}

 

mmdb 파일을 사용하려면 maxmind에서 만든 geoip2 라이브러리가 필요하다.

 

4. GeoIpService

import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;

@Service
public class GeoIpService {
    private DatabaseReader databaseReader;

    public GeoIpService() throws IOException{
        ClassPathResource resource = new ClassPathResource("GeoLite2-City.mmdb");

        File database = resource.getFile();
        databaseReader = new DatabaseReader.Builder(database).build();
    }

    public String getGeoInfo(String ip) throws IOException, GeoIp2Exception{
        InetAddress ipAddress = InetAddress.getByName(ip);
        CityResponse response = databaseReader.city(ipAddress);

        String country = response.getCountry().getName();
        String city = response.getCity().getName();
        String subdivision = response.getMostSpecificSubdivision().getName();

        return String.format("국가: %s, 지역: %s, 도시: %s", country, subdivision, city);
    }
}

 

db파일에서 ip 정보를 조회할 서비스 로직이다.

resources 디렉터리에 파일을 저장했기 때문에 ClassPathResource를 사용해 파일을 불러온다.

나머지는 GeoIP2 라이브러리를 사용한다.

 

5. GeoIpController

import iirtech.com.test2025.geolite.service.GeoIpService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/geoip")
public class GeoIpController {
    private final GeoIpService geoIpService;

    public GeoIpController(GeoIpService geoIpService) {
        this.geoIpService = geoIpService;
    }

    @GetMapping("/search")
    public String getGeoIp(@RequestParam String ip){
        try{
            return geoIpService.getGeoInfo(ip);
        }catch (Exception e){
            return "실패: " + e.getMessage();
        }
    }
}

postman으로 간단한 테스트를 진행하기 위해 컨트롤러를 만들어줬다.

`@RequestParam`으로 쿼리스트링에 있는 ip값을 매핑해서 사용하겠다.

 

6. Postman 테스트 결과

테스트를 위해 임의의 IP 8.8.8.8을 넘긴 결과이다.

국가 정보는 잘 출력되었지만, 지역과 도시 정보는 넘어오지 못했다.

 

7. 결론

7-1 장점

무료이다.

건수 제한이 없다.

구현이 간단하다.

7-2 단점

db파일을 계속해서 관리해줘야 한다.

무료 버전은 한 달 간격으로 업데이트가 이뤄지기 때문에 정확도가 떨어진다.

지역 정보가 정확하게 파악되지 않는다.


무료이며 건수 제한이 없다는 것은 좋았지만 그 외의 단점이 크게 작용했다.

db파일을 자동으로 업데이트할 수 있는 기능을 구현할 수 있다면 어느 정도 단점을 커버할 수 있겠지만 그렇지 못하면 유지보수가 굉장히 힘들 것이다.

가장 중요한 점은 고객님께서 원하시는 지역별 통계를 제공할 수 없기 때문에 사용이 어려울 것 같다.

반응형