GeoIP 자동 업데이트 구성


GeoIP 데이터베이스 파일을 이용하면 접근한
IP 주소의 국가, 도시 등의 정보를 얻을 수 있다. 먼저 이 파일을 다운로드 해보자.
또한, 갱신되는 파일을 
주기적으로 업데이트해 줄 필요가 있으므로 자동으로 업데이트 가능하도록 해보자.

GeoIP update 설치
geoipupdate 다운로드 링크에서 geoipupdate-3.1.1.tar.gz  파일을 다운로드하여 해당 경로에서 아래 명령들을 순차적으로 수행한다.

$ tar -zxvf geoipupdate-3.1.1.tar.gz
$ cd geoipupdate-3.1.1
$ ./configure
$ make
$ make install

명령 실행중 curl 이나 zlib이 설치되어 있지 않으면 에러가 발생한다. 해당 경우, 설치 후 명령을 다시 수행하면 된다.
# curl 설치
$ yum install curl-devel

# zlib 설치
$ yum install zlib-devel 

GeoIP.conf 설정
GeoIP.conf 파일에 계정 정보와 필요한 에디션을 설정한다.
유료 이용자에게는 GeoIP2와 GeoIP Legacy DB를 지원하고, 무료 이용자에게는 GeoLite2 DB만 지원한다. (유료 이용 라이센스 발급)

/usr/local/etc/GeoIP.conf

# Paid
AccountID YOUR_ACCOUNT_ID_HERE
LicenseKey YOUR_LICENSE_KEY_HERE
EditionIDs YOUR_EDITION_IDS_HERE
# Free
AccountID 0
LicenseKey 000000000000
EditionIDs GeoLite2-City GeoLite2-Country 

GeoIP update 실행

$ /usr/local/bin/geoipupdate 

위 명령을 수행하면 /usr/local/share/GeoIP 경로에 설정한 Edition이 생성된다.
예를 들어, EditionIDs GeoIP2-City 이면 GeoIP2-City.mmdb 파일이 생성된다.
(단, 방화벽을 사용하는 경우에는 DNS와 443 포트를 열어줘야 한다.)

실행 스크립트를 crontab에 설정하여 주기적으로 동작시키고 결과 값을 메일로 전송할 수 있다.
# top of crontab
MAILTO=mirotic91@tistory.com
2 22 * * 4 /usr/local/bin/geoipupdate2
# end of crontab

GeoIP 자동 업데이트
자동으로 업데이트 받는 shell을 간단히 작성했다. 실행하면 최신 GeoIP2-City.mmdb 파일을 원하는 경로로 이동시킨다.
배포 스크립트에 아래 shell 실행문을 추가해주면 최신 GeoIP를 유지할 수 있다.
#!/bin/bash
/usr/local/bin/geoipupdate
DOWNLOAD_DIR=/usr/local/share/GeoIP
TARGET_DIR=/DATA/GeoIP

mv -f $DOWNLOAD_DIR/GeoIP2-City.mmdb $TARGET_DIR/
chown -R tomcat:tomcat $TARGET_DIR

참고 링크 - https://dev.maxmind.com/geoip/geoipupdate/

'Development > Etc' 카테고리의 다른 글

ssh 접속 불가 현상 해결  (0) 2018.07.22

SSHProtocolException 에러 해결

서버에서 다른 서버로 API 호출하던 중에 아래와 같은 에러가 발생했다.

Caused by: javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name 

수신 서버가 송신 서버의 name을 알지 못한다는 내용이다.

해당 에러를 해결하기 위해서는 두가지 방법이 있다.
- System 환경변수를 설정한다. System.setProperty("jsse.enableSNIExtension", false);
- JVM 옵션을  설정한다. -Djsse.enableSNIExtension=false

한가지 방법을 선택해 설정하면 정상적으로 API 호출되는 것을 확인 할 수 있다.

'Development > Java' 카테고리의 다른 글

UnsupportedClassVersionError 에러 해결  (0) 2018.07.16
Garbage Collection 방식  (0) 2018.05.12
Garbage Collection 과정  (0) 2018.04.28
Garbage Collection 용어 정리  (0) 2018.04.26
AES256 암호화 오류 해결  (4) 2017.10.06

JSR-303 Annotation Customizing

데이터를 저장하기 전에는 데이터에 대한 검증이 요구된다.
서비스에 정의한 값들이 매우 반복적이여서 검증하는 코드를 숨기고 명시적으로 보여줄 수 있는 것 같아서 JSR-303 어노테이션을 커스텀하는 방식을 사용해봤다.

우선 필드에서 검증할 어노테이션을 생성해준다. 이 때, message, groups, payload 메소드는 반드시 존재해야 한다.
그리고 values 라는 속성을 추가하여 주로 사용되는 값을 디폴트로 설정했다. 다른 값을 검증하려면 필드에 설정한 어노테이션에 values 속성을 설정해주면 된다.
@Constraint 어노테이션에는 직접 생성할 ConstraintValidator를 구현하는 Validator를 지정해줘야 한다.

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AllowedValueValidator.class)
public @interface AllowedValue {
  String[] values() default { “S”, “M”, “L" };
  String message() default “{com.validator.constraints.AllowedValue.message}";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}

Validator를 생성하여 ConstraintValidator 인터페이스를 상속 받고, 인터페이스에 선언된 메소드를 구현해줘야 한다.
initialize 메소드에서는 초기화할 데이터가 필요한 경우 설정해주면 된다. 앞서 만든 어노테이션을 인자로 하여 디폴트로 설정한 값으로 초기화했다.
isValid 메소드에서는 실제 검증할 내용을 작성해주면 된다. 검증할 필드에 요청된 값이 values에 정의된 값 중에 존재하는지 확인했다.

public class AllowedValueValidator implements ConstraintValidator<AllowedValue, String> {
  private String[] values;
  @Override
  public void initialize(AllowedValue constraintAnnotation) {
    this.values = constraintAnnotation.values();
  }
  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    return ArrayUtils.contains(values, value);
  }
}

검증할 필드에 커스텀한 어노테이션을 표기한다.
특정 필드에서는 기본 검증 값이 아닌 “red”, “blue” 값을 검증하도록 표기했다.

public class Clothing {

  private String id;

  private String name;

  @AllowedValue
  private String topSize;

  @AllowedValue
  private String bottomSize;

  @AllowedValue(values = { "red", "blue" })
  private String color;
}

컨트롤러에서는 기존 처럼 모델에 @Valid와 BindingResult만 표기해준다.
해당 요청이 들어오면 모델 필드에 표기한 커스텀 어노테이션의 Validator에 작성한 isValid 메소드로 검증하게 된다.
조건에 맞지 않는 경우에는 bindingResult의 해당 필드에 대한 에러 내용이 담긴다.

@PostMapping("/clothing/update")
public void update(@Valid Clothing clothing, BindingResult bindingResult) {
  if (bindingResult.hasErrors()) {
    FieldError fieldError = bindingResult.getFieldError();
    throw new RuntimeException(fieldError.getDefaultMessage());
  }
  ...
  clothingManager.update(clothing);
}

매우 반복적인 값들에 대한 검증으로 괜찮다고 생각한다.
하지만 모델 필드에 values 에 표기할 값들이 많아지는 경우는 오히려 코드가 복잡해 보일 수도 있다.
검증하는 방법은 다양하니 상황에 적절하게 잘 사용하면 좋을 것 같다.

+ Recent posts