Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
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
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20240729 jwtUtil은 순수하다 본문

개발Article

[TIL]20240729 jwtUtil은 순수하다

최밤빵 2024. 7. 30. 00:51
기술매니저님께서 말씀하신 "JwtUtil 클래스는 순수해야 한다"는 말은 클래스가 특정 책임에 충실하고 외부 종속성이 없어야 함을 의미한다. 또한, POJO(Plain Old Java Object)의 개념을 이해하는 것이 이런 클래스를 설계할 때 중요하기 때문에 오늘 개발일지에서는 유틸리티 클래스의 순수성POJO의 의미를 정리하고, 조언에 따라 만든 예시코드로 이해를 위해 정리해봤다. 

 

🤓POJO와 순수한 유틸리티 클래스의 의미

Java 개발에서 POJO(Plain Old Java Object)와 순수한 유틸리티 클래스의 개념은 코드의 재사용성, 유지보수성, 테스트 용이성을 높이기 위해 매우 중요한 개념이다. 이 두 개념은 소프트웨어 설계의 기본 원칙 중 하나인 단일 책임 원칙(Single Responsibility Principle, SRP)을 잘 이해하고 적용하는 데 필수적이다.

 

▶ POJO란 ?

POJO(Plain Old Java Object)는 특정한 Java 객체를 의미하는 것이 아니라, 특정 프레임워크에 종속되지 않는 순수한 자바 객체를 말한다. POJO는 종속성 주입(Dependency Injection)과 ORM(Object Relational Mapping) 프레임워크의 사용이 일반화되면서 자주 언급되는 용어이다.

 

POJO의 특징은 다음과 같다.

  • 특정 라이브러리나 프레임워크에 의존하지 않는다.
  • getter/setter 메서드, 생성자, 일반적인 메서드 등으로만 구성된 단순한 클래스이다.
  • 비즈니스 로직을 캡슐화하여 테스트와 유지보수가 용이하다.
  • Spring, Hibernate와 같은 프레임워크에서 관리되지 않는 객체이다.
  • POJO를 사용하면 코드를 더 단순하고 명확하게 유지할 수 있으며, 특정 라이브러리나 프레임워크에 종속적이지 않아 코드의 재사용성과 독립성을 높일 수 있다.

▷ POJO의 예시

User라는 POJO 클래스의 예시이다. 이 클래스는 특정 프레임워크에 의존하지 않고, 순수한 자바 객체로 정의되어있다.

public class User {
    private Long id;
    private String username;
    private String email;

    // 기본 생성자
    public User() {

    }

    // 모든 필드를 초기화하는 생성자
    public User(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }

    // Getter와 Setter 메서드들
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{id=" + id + ", username='" + username + "', email='" + email + "'}";
    }
}

→ 예시 코드인 User 클래스는 간단한 POJO로, 특정 라이브러리나 프레임워크의 종속성이 없다. 생성자, getter/setter 메서드, toString() 메서드만을 가지며, 비즈니스 로직이 들어가 있지 않다. 이로 인해 독립적이며 재사용이 용이한 객체로 활용할 수 있다.

 

▶ 순수한 유틸리티 클래스의 의미

유틸리티 클래스는 일반적으로 반복적으로 사용되는 로직이나 기능을 한 곳에 모아놓은 클래스이다. 유틸리티 클래스는 인스턴스를 생성하지 않고, 모든 메서드를 static으로 선언하여 쉽게 사용할 수 있도록 설계한다.

 

순수한 유틸리티 클래스의 의미는 다음과 같다.

상태를 가지지 않는다:

유틸리티 클래스는 상태를 가지지 않으며, 오직 기능을 수행하는 메서드만 존재해야 한다.

외부 종속성이 없다:

유틸리티 클래스는 외부의 다른 클래스나 프레임워크에 의존하지 않고, 독립적으로 동작해야 한다.

인스턴스 생성이 불필요하다:

모든 메서드는 static으로 선언하여 인스턴스화 없이 사용할 수 있어야 한다.

단일 책임 원칙을 따른다:

하나의 클래스는 하나의 역할에 충실해야 하며, 그 역할에 맞는 기능만 제공해야 한다.

 

▷ 순수한 유틸리티 클래스의 예시

JwtUtil이라는 순수한 유틸리티 클래스의 예시이다. 이 클래스는 JWT 토큰 생성 및 검증 기능만을 제공하며, 외부 종속성이나 상태를 가지지 않는다. (매니저님이 말씀하신 그 순수 유틸!!) 

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import java.util.Date;
import io.jsonwebtoken.security.Keys;

public final class JwtUtil {

    // 비밀 키 생성 (HMAC SHA-256 알고리즘)
    private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    private static final long EXPIRATION_TIME = 86400000; // 1일 (밀리초 기준)

    // 인스턴스화를 방지하기 위해 private 생성자 선언
    private JwtUtil() { }

    // JWT 토큰 생성 메서드
    public static String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SECRET_KEY)
                .compact();
    }

    // JWT 토큰 검증 메서드
    public static boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(SECRET_KEY)
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false; // 검증 실패 시 false 반환
        }
    }

    // JWT 토큰에서 사용자 이름 추출 메서드
    public static String getUsernameFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }
}

 

→ JwtUtil 클래스는 순수한 유틸리티 클래스로, 인스턴스화를 방지하기 위해 private 생성자를 사용한다.

모든 메서드는 static으로 선언되어 있어, 클래스 인스턴스 없이 직접 사용할 수 있다.

클래스 내부에 상태를 가지지 않고, 외부 종속성도 없이 독립적으로 동작한다.

JWT 토큰 생성, 검증, 사용자 이름 추출과 같은 기능을 제공하며, 이외의 역할은 하지 않는다.

 

▶ POJO와 순수한 유틸리티 클래스의 차이점과 중요성

POJO와 순수한 유틸리티 클래스의 차이점은 각각의 역할과 책임에서 분명하게 드러난다.

 

→ POJO:

상태를 가지며, 객체로서의 의미를 가지고 특정 도메인 로직을 포함할 수 있다.

특정 프레임워크에 종속되지 않고, 독립적으로 관리된다.

엔티티(Entity), DTO(Data Transfer Object) 등으로 활용될 수 있다.

 

→ 순수한 유틸리티 클래스:

상태를 가지지 않고, 오직 메서드로서의 기능만을 수행한다.

외부 종속성이 없고, 인스턴스화가 불필요하다.

일반적인 로직이나 반복되는 기능을 모아서 제공하는 데 적합하다.

두 개념 모두 소프트웨어 설계에서 중요한 원칙을 준수하며, 코드의 재사용성, 유지보수성, 테스트 용이성을 높이는 데 기여한다. 특히, 유틸리티 클래스는 서비스나 도메인 로직과는 독립적으로 작성되므로, 언제든지 호출하여 사용할 수 있는 강력한 장점을 가지고 있다.

 

▶마무리 

오늘 공부한내용으로 POJO와 순수한 유틸리티 클래스의 개념과 중요성을 조금이나마 이해할 수 있었다. POJO는 특정 프레임워크에 의존하지 않고, 순수한 자바 객체로 유지되어 코드의 독립성과 재사용성을 보장한다. 반면, 순수한 유틸리티 클래스는 상태를 가지지 않으며, 모든 메서드를 static으로 선언하여 쉽게 사용할 수 있도록 설계된다. 이러한 개념들을 잘 이해하고 활용하여, 더 깨끗하고 유지보수하기 쉬운 코드를 작성해야 할 것 같다!