티스토리 뷰
항상 개발해올 때,
JWT에 대한 참고 코드를 살펴보면 util 이라는 네이밍을 할 때가 많다.
그런데 다른 코드를 레퍼런스로 사용하다가 같은 기능을 제공하는데 이번에는 네이밍을 helper로했다..
조금 더 가독성 높은 네이밍을 가지려면 무엇이 더 알맞을까??
먼저 공식 Spring 사이트에 들어가보자.
https://www.baeldung.com/java-helper-vs-utility-classes
역시나
나만 고민한게 아니였음을 확인할 수 있다.
공식사이트에서 말하는 Utily 클레스랑 Helper 클레스의 특징을 살펴보고 차이점을 통해 네이밍을 택해보자 .
Helper 코드
class MyHelperClass {
public double discount;
public MyHelperClass(double discount) {
if (discount > 0 && discount < 1) {
this.discount = discount;
}
}
public double discountedPrice(double price) {
return price - (price * discount);
}
public static int getMaxNumber(int[] numbers) {
if (numbers.length == 0) {
throw new IllegalArgumentException("Ensure array is not empty");
}
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
return max;
}
public static int getMinNumber(int[] numbers) {
if (numbers.length == 0) {
throw new IllegalArgumentException("Ensure array is not empty");
}
int min = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] < min) {
min = numbers[i];
}
}
return min;
}
}
위 코드를 잘 살펴보면 해당 코드 내에서 작동하여 수정하고 결과를 만들어, 끝내고자하여 끝내는 것이 아닌,
다른 클레스에서 사용할 수 있는 기능들을 제공해준다.
다시금 말하자면!
HelperClass는 Java 프로그램의 전반적인 실행에 필요한 기능을 제공하는데,
응용 프로그램의 핵심 목적이 아닌 반복 작업을 수행하기 위해
다른 클래스에서 사용하는 메서드가 포함되어 있다는 것이다.
Utility 코드
public final class MyUtilityClass {
private MyUtilityClass(){}
public static String returnUpperCase(String stringInput) {
return stringInput.toUpperCase();
}
public static String returnLowerCase(String stringInput) {
return stringInput.toLowerCase();
}
public static String[] splitStringInput(String stringInput, String delimiter) {
return stringInput.split(delimiter);
}
}
위 코드를 잘 살펴보면,
방금 설명한 Helper 코드의 목적과 비슷하게 다른 클레스에서 사용할 수 있는 기능들을 제공해준다.
그럼 차이점은 어디서 있다는 것일까?
결론을 통해 생각을 정리해보자
결론
Java의 Helper 및 Utility 클래스는 일반적으로 동일한 목적을 갖고 있다.
그러나 Utility 클래스는 도우미 클래스보다 더 범용적으로 사용된다고한다.
이 둘은 매우 유사하지만 몇 가지 미묘한 차이점이 있는데, 아래와 같이 세개의 차이점이 있다고한다.
(다시 위에 코드를 잘 살펴보면, 인스턴스가 가능한지와 전용 생성자를 가졌는지에 대해 차이점을 볼 수 있다)
1. Helper 클래스는 인스턴스화할 수 있지만
유틸리티 클래스는 전용 생성자가 있기 때문에 인스턴스화할 수 없다.
2. Helper 클래스는 인스턴스 변수를 가질 수 있으며 인스턴스 및 정적 메서드도 모두 가질 수 있다.
그러나 유틸리티 클래스에는 정적 변수와 메서드만 있습니다.
3. 유틸리티 클래스는 종종 응용 프로그램 내에서 전역 범위를 갖는
반면 헬퍼 클래스에는 항상 패키지 범위가 제공된다.
그렇기 때문에 만약 아래와 같이 JWT 를 생성하는 및 검증하는 클레스가 Bean으로 주입되어야한다면,
네이밍 시에 Helper가 더 적합한 것 같다.
@Component
public class JwtTokenHelper implements TokenHelperIfs {
@Value("${token.secret.key}")
private String secretKey;
@Value("${token.access-token.plus-hour}")
private Long accessTokenPlusHour;
@Value("${token.refresh-token.plus-hour}")
private Long refreshTokenPlusHour;
@Override
public TokenDto issueAccessToken(Map<String, Object> data) {
var expiredLocalDateTime = LocalDateTime.now().plusHours(accessTokenPlusHour);
var expiredAt = Date.from(
expiredLocalDateTime.atZone(
ZoneId.systemDefault()
).toInstant()
);
var key = Keys.hmacShaKeyFor(secretKey.getBytes());
var jwtToken = Jwts.builder()
.signWith(key, SignatureAlgorithm.HS256)
.setClaims(data)
.setExpiration(expiredAt)
.compact();
return TokenDto.builder()
.token(jwtToken)
.expiredAt(expiredLocalDateTime)
.build();
}
@Override
public TokenDto issueRefreshToken(Map<String, Object> data) {
var expiredLocalDateTime = LocalDateTime.now().plusHours(refreshTokenPlusHour);
var expiredAt = Date.from(
expiredLocalDateTime.atZone(
ZoneId.systemDefault()
).toInstant()
);
var key = Keys.hmacShaKeyFor(secretKey.getBytes());
var jwtToken = Jwts.builder()
.signWith(key, SignatureAlgorithm.HS256)
.setClaims(data)
.setExpiration(expiredAt)
.compact();
return TokenDto.builder()
.token(jwtToken)
.expiredAt(expiredLocalDateTime)
.build();
}
@Override
public Map<String, Object> validationTokenWithThrow(String token) {
var key = Keys.hmacShaKeyFor(secretKey.getBytes());
var parser = Jwts.parserBuilder()
.setSigningKey(key)
.build();
try{
var result = parser.parseClaimsJws(token);
return new HashMap<String, Object>(result.getBody());
}catch (Exception e){
if(e instanceof SignatureException){
throw new ApiException(TokenErrorCode.INVALID_TOKEN, e);
}
else if(e instanceof ExpiredJwtException){
throw new ApiException(TokenErrorCode.EXPIRED_TOKEN, e);
}
else{
throw new ApiException(TokenErrorCode.TOKEN_EXCEPTION, e);
}
}
}
}
'Backend(개발)' 카테고리의 다른 글
Custom Validation 적용 (0) | 2024.06.01 |
---|---|
회원 정보를 보호합니다. (0) | 2024.06.01 |
FriendShip의 채팅은 어떻게 이루어지나요? (0) | 2024.06.01 |
테스트 코드를 왜 작성하는가? (with TDD) (0) | 2023.10.14 |
< git > 오류 fatal: 'origin/remote-branch-name' is not a commit and a branch 'local-branch-name' cannot be created from it (0) | 2023.07.19 |