Search

“사용자 접속 정보” 최신화 하기

Created time
2022/08/29 11:29
Last edited time
2022/11/14 13:03
Tags
geo location
data

문제 배경

사용자가 서비스에 접속하면, “접속 정보"를 가져오고, DB에 영속화되어 관리되어집니다.
관리되어지는 가장 큰 이유는 비정상적인 또는 Fraud 여지가 있는 사용자들을 구분하기 위해서 입니다.
하지만,
IP와 Geo Location 정보는 시점에 따라서 달라질 수 있습니다.
그래서 사용자의 Geo Location 정보를 최신화하여, DB에서 관리되어지는게 중요합니다.
현재 사용자 접속 정보가 최신 정보가 아니라서 CX팀에서 최신화된 정보를 요구하고 있습니다.

문제 정의

“최신화되지 않은 Geo Location 정보가 영속화되어 변경된 정보와 매칭되지 않습니다”

문제 해결

1. Upgrade “Application Dependency Version” for ‘com.maxmind.geoip2’

AS-IS with 2.12.0
dependencies { implementation 'com.maxmind.geoip2:geoip2:2.12.0' }
JavaScript
복사
TO-BE with 2.16.1
dependencies { implementation 'com.maxmind.geoip2:geoip2:2.16.1'// todo: JDK 1.8 이후부터 상위 버전 변경가능 }
JavaScript
복사

2. Upgrade “Geo Location DB File” for ‘com.maxmind.geoip2’

Maxmind 로그인 (계정이 없으면, 가입해야합니다.)
“Download GZIP” 으로 “Geo Location DB File”을 다운로드 받습니다.
Application 에서 활용할 다운로드 받은 파일을 업데이트 합니다.
“Geo Location DB File” 파일은 다음 로직에서 활용됩니다.
public final class GeoIpClient { private static final Logger log = LoggerFactory.getLogger(GeoIpUtil.class); private static final DatabaseReader dbReader; private GeoIpUtil() { } static { try { dbReader = new DatabaseReader .Builder(GeoIpUtil.class.getClassLoader().getResourceAsStream("GeoLite2-City.mmdb")) .build(); } catch (IOException e) { throw new IllegalStateException("Geo IP data initialize failed", e); } } public static GeoIp getLocation(String ip) { try { InetAddress ipAddress = InetAddress.getByName(ip); CityResponse response = dbReader.city(ipAddress); String country = response.getCountry().getIsoCode(); String subdivision = englishSubdivision(response.getSubdivisions()); String cityName = response.getCity().getName(); String postal = response.getPostal().getCode(); String timezone = response.getLocation().getTimeZone(); String latitude = response.getLocation().getLatitude().toString(); String longitude = response.getLocation().getLongitude().toString(); return new GeoIp(ip, country, subdivision, cityName, postal, timezone, latitude, longitude); } catch (IOException e) { log.error("Unknown Host", e); } catch (GeoIp2Exception e) { log.error("Failed to get GeoIP", e); } return GeoIp.EMPTY; } }
Java
복사

3. Test application code

@ParameterizedTest @ValueSource(strings = {"143.55.59.173", "223.39.201.233"}) voidgetGeoIpByIpTest(String ip) { GeoIp geoIp = GeoIpClient.getLocation(ip); assertThat(geoIp).isInstanceOf(GeoIp.class); }
Java
복사
AS-IS GeoIp[ip='143.55.59.173', country='US', city='New York', postal='10001', timezone='America/New_York', latitude='40.7503', longitude='-74.0014']
TO-BE GeoIp[ip='143.55.59.173', country='US', city='Weatherford', postal='76088', timezone='America/Chicago', latitude='32.8476', longitude='-97.857']

비교해볼 사이트

문제 회고

IP가 주기적으로 다른 사용자들에게 양도 될 수 있다는 점은 기본인데, 고려하지 못했던 부분입니다.
휴먼 인터페이스에 의존하면 서비스의 품질이 저하될 수 있는 부분입니다.
주기적으로 파일을 업데이트하기 위해서 파일의 Updated 시간을 이용하여, Application의 Cron을 이용하여 오래된 파일은 교체를 요구하는 슬랙 알림을 추가 작업으로 진행합니다.