[JAVA] Lombok의 @UtilityClass 어노테이션 정리

2025. 2. 13. 16:26·BackEnd/JAVA
목차
  1. 1. @UtilityClass란?
  2. 1.1 주요 기능
  3. 2. @UtilityClass 사용법
  4. 3. Lombok이 @UtilityClass를 컴파일하면?
  5. 3.1 컴파일 후 변환된 코드
  6. 3.2 자동으로 추가된 기능
  7. 1) final 키워드 추가
  8. 2) 모든 멤버를 static으로 변환
  9. 3) private 생성자 자동 추가
  10. 4. 유틸리티 클래스 설계 시 고려해야 할 점
  11. 4.1 유틸리티 클래스 장점
  12. 4.2 유틸리티 클래스의 단점
  13. 5. 결론
  14. 6. 참고

자바를 개발하다 보면 Math, Collections 같은 유틸리티 클래스를 만들 일이 많습니다. 일반적으로 유틸리티 클래스는 정적(static) 메서드만 포함하며, 객체로 생성할 필요가 없습니다.

Lombok에서는 이러한 유틸리티 클래스를 간편하게 정의할 수 있도록 @UtilityClass 어노테이션을 제공하며, 이를 통해 자동으로 인스턴스 생성을 막고 모든 멤버를 static으로 변환할 수 있습니다.
이번 포스팅에서는 @UtilityClass의 개념과 사용법, 컴파일 후 코드 변환 과정, 그리고 유틸리티 클래스 설계 시 고려해야 할 점들을 정리해보겠습니다.

1. @UtilityClass란?

@UtilityClass는 Lombok v1.16.2에서 도입된 어노테이션으로, 객체 생성이 불필요한 유틸리티 클래스를 쉽게 정의할 수 있도록 도와줍니다.

유틸리티 클래스는 상태(State)가 없고, 행위(Behavior)만을 가지는 클래스를 의미합니다. 대표적으로 Math 클래스처럼 모든 메서드가 static으로 정의되어 있으며, 인스턴스를 생성할 필요가 없습니다.

1.1 주요 기능

  • 클래스를 자동으로 final로 변환 → 상속 방지
  • 모든 필드와 메서드를 static으로 변환 → 객체 없이 사용 가능
  • private 생성자 자동 생성 → 객체 생성 불가능하도록 제한
  • 명시적인 생성자 작성 방지 → 생성자를 수동으로 만들 수 없음
  • 내부 클래스도 자동 static 처리 → 유틸리티 성격 유지

2. @UtilityClass 사용법

Lombok의 @UtilityClass를 사용하여 유틸리티 클래스를 작성하면, 클래스 내부의 모든 필드와 메서드가 자동으로 static이 됩니다.

import lombok.experimental.UtilityClass;

@UtilityClass
public class UtilityClassExample {
    private final int CONSTANT = 5; // static으로 자동 변환됨

    public int addSomething(int in) {
        return in + CONSTANT;
    }
}
  • CONSTANT 필드는 자동으로 static final로 변환됩니다.
  • addSomething(int in) 메서드도 자동으로 static이 됩니다.
  • 해당 클래스를 생성하려고 하면 컴파일 에러 발생 → 객체 생성을 원천적으로 차단

@UtilityClass를 사용하면 객체를 생성할 필요 없이 클래스명.메서드명() 형식으로 접근 가능합니다.

int result = UtilityClassExample.addSomething(10); // 객체 없이 사용 가능

3. Lombok이 @UtilityClass를 컴파일하면?

@UtilityClass 어노테이션을 사용하면, Lombok이 컴파일 과정에서 자동으로 필요한 코드들을 추가해줍니다.

3.1 컴파일 후 변환된 코드

아래는 위의 Lombok 코드를 컴파일했을 때 생성되는 순수 자바 코드입니다.

public final class UtilityClassExample { // final 키워드 추가 (상속 방지)
    private static final int CONSTANT = 5; // 모든 멤버 자동 static 적용

    private UtilityClassExample() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }

    public static int addSomething(int in) {
        return in + CONSTANT;
    }
}
  • 클래스에 final 키워드 추가 → 상속 불가
  • 모든 필드와 메서드를 static으로 자동 변환
  • private 생성자 추가 → 강제로 예외 발생 (UnsupportedOperationException)
  • 인스턴스화 방지 → 객체 생성이 불가능

3.2 자동으로 추가된 기능

1) final 키워드 추가

  • 유틸리티 클래스는 상속할 필요가 없으므로 final로 자동 변환됩니다.
  • 하위 클래스를 생성할 수 없도록 제한됩니다.

2) 모든 멤버를 static으로 변환

  • 필드(CONSTANT)와 메서드(addSomething())가 자동으로 static으로 설정됩니다.
  • 객체를 생성하지 않고도 클래스명.메서드명() 형태로 호출 가능합니다.

3) private 생성자 자동 추가

  • 유틸리티 클래스는 객체를 생성할 필요가 없으므로, 인스턴스화를 방지해야 합니다.
  • Lombok은 자동으로 private 생성자를 추가하고,객체가 생성될 경우 UnsupportedOperationException을 던지도록 구현합니다.
private UtilityClassExample() {
    throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

즉, 생성자가 private로 설정되면서 객체 생성이 원천적으로 차단됩니다.

아래와 같이 객체를 생성하려고 하면 컴파일 오류가 발생합니다.

UtilityClassExample util = new UtilityClassExample(); // 컴파일 오류 발생!

4. 유틸리티 클래스 설계 시 고려해야 할 점

유틸리티 클래스는 상태(State)가 없고, 행위(Behavior)만 존재하는 클래스입니다. 무분별하게 사용하면 객체지향적 설계에서 벗어날 가능성이 크며, 유지보수성이 떨어질 수 있습니다.

4.1 유틸리티 클래스 장점

  1. 객체 없이 호출 가능 → 불필요한 인스턴스 생성 방지
  2. 일관성 유지 → 특정 로직을 한 곳에서 관리 가능
  3. 재사용성 증가 → 여러 곳에서 동일한 메서드 활용 가능

4.2 유틸리티 클래스의 단점

  1. 객체지향 프로그래밍 원칙에서 벗어남
    • 모든 메서드가 static이므로 객체지향적이지 않음 (절차지향적 설계)
  2. 단위 테스트가 어렵다
    • static 메서드는 Mocking이 어렵고, 변경이 힘듦
    • 테스트 가능한 코드로 만들려면 의존성 주입(DI)을 고려해야 함
  3. 강결합 발생 가능성
    • static 메서드를 남용하면 다른 클래스들과 강한 의존성을 가짐
    • 유지보수 시 코드 변경이 어려워질 수 있음

따라서, 유틸리티 클래스 사용이 적절한 경우인지 신중하게 판단해야 합니다.

5. 결론

  • @UtilityClass는 Lombok을 활용하여 유틸리티 클래스를 간편하게 정의할 수 있도록 도와준다.
  • 자동으로 final 클래스, private 생성자, static 필드 및 메서드를 추가하여객체 생성이 불가능한 유틸리티 클래스를 만든다.
  • 유틸리티 클래스는 상태(State)가 없고, 행위(Behavior)만 존재해야 하므로필드에 상태값을 저장하는 것은 지양해야 한다.
  • 무분별한 사용은 객체지향적 설계에서 벗어나며, 유지보수성과 테스트성을 저하시킬 수 있다.
  • 꼭 필요한 경우에만 유틸리티 클래스를 사용하고,객체지향적인 설계를 우선 고려하는 것이 바람직하다.

6. 참고

  • Lombok 공식 홈페이지 - UtilityClass

'BackEnd > JAVA' 카테고리의 다른 글

[JAVA] equals()와 hashCode() 완벽 정리  (1) 2025.02.24
[JAVA] 익명 클래스 (Anonymous Class) 정리  (1) 2025.02.20
[JAVA] 얕은 복사 (Shallow Copy) VS 깊은 복사 (Deep Copy)  (2) 2025.02.06
[JAVA] 와일드카드 (Generic Wildcards) 정리  (3) 2025.02.05
[JAVA] 제네릭 (Generic) 정리  (2) 2025.01.26
  1. 1. @UtilityClass란?
  2. 1.1 주요 기능
  3. 2. @UtilityClass 사용법
  4. 3. Lombok이 @UtilityClass를 컴파일하면?
  5. 3.1 컴파일 후 변환된 코드
  6. 3.2 자동으로 추가된 기능
  7. 1) final 키워드 추가
  8. 2) 모든 멤버를 static으로 변환
  9. 3) private 생성자 자동 추가
  10. 4. 유틸리티 클래스 설계 시 고려해야 할 점
  11. 4.1 유틸리티 클래스 장점
  12. 4.2 유틸리티 클래스의 단점
  13. 5. 결론
  14. 6. 참고
'BackEnd/JAVA' 카테고리의 다른 글
  • [JAVA] equals()와 hashCode() 완벽 정리
  • [JAVA] 익명 클래스 (Anonymous Class) 정리
  • [JAVA] 얕은 복사 (Shallow Copy) VS 깊은 복사 (Deep Copy)
  • [JAVA] 와일드카드 (Generic Wildcards) 정리
개발자 동긔
개발자 동긔
배우고 느낀점들을 기록합니다. 열정 넘치는 백엔드 개발자로 남고싶습니다.
  • 개발자 동긔
    Donker Dev
    개발자 동긔
  • 전체
    오늘
    어제
    • Category (39)
      • BackEnd (23)
        • JAVA (15)
        • Spring & JPA (7)
      • Database (4)
      • Computer Science (2)
        • Network (0)
        • Security (0)
        • Web (1)
      • DevOps (6)
        • Docker (1)
        • Jenkins (0)
        • Monitoring (2)
        • CICD (1)
      • 트러블 슈팅 (3)
      • 성능 개선 (1)
      • Project (0)
  • 인기 글

  • 태그

    spring boot
    Database
    와일드카드
    master/slave db 이중화 처리
    mysql master/slave replication
    restful api 설계
    SSH
    restful api
    docker compose
    Jenkins
    nginx
    spring cloud msa
    interface
    java
    @RequestBody
    CICD
    docker
    인터페이스
    Spring
    JPA
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
개발자 동긔
[JAVA] Lombok의 @UtilityClass 어노테이션 정리
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.