글 작성자: 개발섭

문제 상황

JWT 토큰 발급시 이런 오류가 있었다. JWT_EXPIRED_TIME: 43200  (24시간 * 60분 * 30일) ⇒ 해서 나온값이 43200분이었고,  위와 같은 설정값을 통해서 아래의 설정으로 세팅으로 토큰을 발급 하려고 했었는데....

return Jwts.builder()
        .setClaims(claims)
        .setIssuedAt(Date())
        .setExpiration(Date(System.currentTimeMillis()+(JWT_EXPIRED_TIME.toInt()*60*1000)))
        .signWith(getSignKey(), SignatureAlgorithm.HS256)
        .compact()

…? 원래시간보다 오히려 줄었다? iat보다도 숫자가 꽤 작은걸 확인할 수 있는데, 단순하게 Date 객체만의 문제라고 생각했었는데 자세히 찾아보니까 그런 문제가 아니였다. 

Adding a large timestamp to the current time in Java

 

Adding a large timestamp to the current time in Java

I am working on an application that supports Google 2-step verification. This application also supports a feature to 'trust this device for 30 days'. I use a database to save all this information ...

stackoverflow.com

왜 줄었는지를 확인해보니까 단순하게 Integer overflow 떠서, 음수가 되어버렸고…. 그래서 일자가 줄었던것…

그래서 만약 위의 코드를 그대로 이용하면서 문제해결을 하기위해서는 다음처럼 수정만 하면된다. JWT_EXPIRED_TIME을 Long Type으로 받아놓은 다음에 더해버리면...? 

.setExpiration(Date(System.currentTimeMillis()+(JWT_EXPIRED_TIME.toLong()*60*1000)))

이러면 정상적으로 이후로 시간이 잘 저장됩니다!

하지만.. 더 좋은 방법!

근데 이건 직관적인 느낌은 없어서 즉, 내가 분을 계산을 해야하는 상황이다. 예를 들면, 30일을 계산하기 위해서 60*24*30을 해야하는 것 처럼.. 몇초를 더해야하는지 계산을 해야하며, 지금 위에서 발견한 것도 역시 integer overflow가 발생할거라고 생각하는 것도  못했던 것처럼 아예 시간계산에 대해서 신경을 쓰지 않도록 혹은 시간 계산에 집중된 클래스나 유틸 함수를 사용하는게 훨씬 좋다.

아래처럼 사용하면...?

val issuedAt: Instant = Instant.now().truncatedTo(ChronoUnit.SECONDS)
val expiration: Instant = issuedAt.plus(JWT_EXPIRED_TIME.toLong(), ChronoUnit.DAYS)
return Jwts.builder()
        .setClaims(claims)
        .setIssuedAt(Date.from(issuedAt))
        .setExpiration(Date.from(expiration))
        .signWith(getSignKey(), SignatureAlgorithm.HS256)
        .compact()

Instant 와… 그 값에 대한 plus를 ChronoUnit을 통해서 어떤 날짜 혹은 시간으로 더할지를 명확하게 판단해서 더하게 하거나 혹은 빼는 방법을 취해서 내가 얼만큼의 값을 더해야할지를 명확하게 코드로 보이게 하면. 아까보다 훨씬 더 명확하게 시간계산을 할 수 있을거라고 생각한다. 

Date.from을 활용하여, Date 객체를 삽입하는 방법을 이용하면 좋다.