[JAVA] IP 주소로 국가코드를 가져오기(w. IP Location API)
새로운 프로젝트를 진행하고 있는데, 접속자에 대한 국가코드 정보가 필요했다.
그래서 접속자의 IP 주소를 가지고 국가코드를 가져올 수 있는 방법을 알아봤다.
우선, IP 주소를 통해서 국가코드를 가져올 수 있는 방법은 크게 2가지인 것 같다.
- GeoIP 라이브러리
- 오픈 API
GeoIP 라이브러리에서도 데이터베이스를 사용하는 방법과 라이센스 키를 사용하는 방법이 있는 것 같다.
데이터베이스를 사용해 보려고 했지만 주기적으로 업데이트를 해줘야 하는 부담과 부정확한 데이터가 있는 것 같았다.
그리고 프로젝트의 마감 기간도 고려해야 해서 빠르게 처리할 수 있는 오픈 API를 사용하기로 했다.
오픈 API를 제공하는 곳도 다양했지만, 나는 IP Location API를 사용했다.
일단, 사용자의 IP 주소를 가져오자.
사용자 IP 주소 가져오기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static String getClientIp(HttpServletRequest request) {
if (request == null) {
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
request = attr.getRequest();
}
String[] headerNames = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED"
};
for (String headerName : headerNames) {
String ipAddress = request.getHeader(headerName);
if (ipAddress != null && !ipAddress.isEmpty() && !"unknown".equalsIgnoreCase(ipAddress)) {
return ipAddress;
}
}
return request.getRemoteAddr() != null && !request.getRemoteAddr().isEmpty() ? request.getRemoteAddr() : null;
}
IP 주소로 국가코드를 가져오기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public static String getCountryCodeByIp(String ipAddress) {
if (isLocalhost(ipAddress)) {
return null;
}
String countryCode;
try {
String response = getIpLocationApiResponse(ipAddress);
countryCode = getCountryCodeFromApi(response);
if (Objects.equals(countryCode, "-")) {
countryCode = null;
}
} catch (Exception e) {
countryCode = null;
}
if (StringUtils.isBlank(countryCode)) {
countryCode = getCountryCodeFromLocale();
}
return StringUtils.isNotBlank(countryCode) ? countryCode : "ETC"; // 국가코드 없으면 ETC로 저장
}
/**
* IP Location API에서 데이터 결과 가져오기
*/
private static String getIpLocationApiResponse(String ipAddress) {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject("https://api.iplocation.net/?ip=" + ipAddress, String.class);
}
/**
* IP Location API에서 반환 받은 데이터 중에 국가코드 가져오기
*/
private static String getCountryCodeFromApi(String response) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(response);
return jsonNode.get("country_code2").asText();
}
/**
* 국가코드를 반환 받지 못할 경우 Locale 값으로 가져오기
*/
private static String getCountryCodeFromLocale() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
Locale locale = request.getLocale();
return locale.getCountry();
}
아래 이미지와 같이 API에서 반환되는 데이터는 몇 개 있긴 한데, 내가 쓰고자 하는 건 country_code2
만 확인하면 된다. 이게 국가코드를 반환해 준다.
국가코드를 반환해 주지 못할 경우를 대비해서 Locale 값으로 가져오도록 했고, 이마저도 가져올 수 없으면 “ETC”로 처리를 했다.
HttpServletRequest의 Locale 값은 Request Header에
Accept-Language
값을 기반으로 가져온다.
Leave a comment