본문 바로가기
Projects/청하-청년을 위한 커뮤니티 서비스

[청하] TimeFormatter 클래스 리팩토링 (feat. @UtilityClass)

by Lpromotion 2025. 2. 2.

 

게시글 관련 기능에서 날짜를 "yyyy/MM/dd HH:mm:ss" 형식으로 반환하기 위해 TimeFormatter 클래스를 작성했었다.
하지만 코드 점검 과정에서 몇 가지 개선할 점을 발견하여 리팩토링을 진행했다.

 

기존 코드

TimeFormatter

package com.example.withpeace.util;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class TimeFormatter {

    public static String timeFormat(LocalDateTime time) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        return time.format(formatter);
    }
}

 

PostService

PostDetailResponseDto postDetailResponseDto =
        PostDetailResponseDto.builder()
                .postId(postId)
                .userId(post.getWriter().getId())
                .nickname(post.getWriter().getNickname())
                .profileImageUrl(post.getWriter().getProfileImage())
                .title(post.getTitle())
                .content(post.getContent())
                .type(post.getType())
                .createDate(TimeFormatter.timeFormat(post.getCreateDate())) // 날짜 포맷 적용
                .postImageUrls(postImageUrls)
                .comments(comments)
                .build();

 

문제점 분석

1. 불필요한 `@Component`가 사용되었다.

`@Component`는 스프링 빈으로 등록하기 위해 사용하는데, 이 클래스는 단순히 유틸리티 메서드만 제공하고 있기 때문에 빈으로 등록할 필요가 없다.

 

2. 매번 `DateTimeFormatter` 인스턴스 생성

`DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")`가 호출될 때마다 새로운 인스턴스가 생성된다.

→ 객체 생성 비용이 증가한다. (성능 저하)

`DateTimeFormatter`는 불변(immutable)하고 스레드-세이프(Thread-safe)하기 때문에 재사용이 가능하다.

 

리팩토링 방향

  • `@Component` 제거 → 불필요한 스프링 빈 등록 제거로 메모리 효율성 확보.
  • `DateTimeFormatter` 상수화 → `static final`로 선언하여 객체 생성 비용 절감.
  • `@UtilityClass` 적용 → Lombok의 `@UtilityClass`를 활용해 유틸리티 클래스임을 명시.

 

`@UtilityClass` 기능

  • 클래스에 `final` 키워드를 자동으로 추가한다. (상속 방지)
  • 모든 메서드와 필드를 `static`으로 자동 변환한다.
  • `private` 생성자를 자동으로 생성한다. (인스턴스화 방지)

 

리팩토링 적용 코드

TimeFormatter

package com.example.withpeace.util;

import lombok.experimental.UtilityClass;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@UtilityClass
public class TimeFormatter {

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");

    public String format(LocalDateTime time) {
        return time.format(FORMATTER);
    }
}

 

PostService

PostDetailResponseDto postDetailResponseDto =
        PostDetailResponseDto.builder()
                .postId(postId)
                .userId(post.getWriter().getId())
                .nickname(post.getWriter().getNickname())
                .profileImageUrl(post.getWriter().getProfileImage())
                .title(post.getTitle())
                .content(post.getContent())
                .type(post.getType())
                .createDate(TimeFormatter.format(post.getCreateDate())) // 변경된 부분
                .postImageUrls(postImageUrls)
                .comments(comments)
                .build();

 

성능 측정 (Prometheus 기준)

게시글 리스트 조회 API(/api/v1/posts)의 평균 응답 시간을 비교했다.

 

쿼리

rate(http_server_requests_seconds_sum{uri="/api/v1/posts", outcome="SUCCESS"}[5m]) 
/ 
rate(http_server_requests_seconds_count{uri="/api/v1/posts", outcome="SUCCESS"}[5m])

 

구분 평균 응답 시간
기존 0.0221초 (22.1ms)
리팩토링 후  

 

 

효과

  • 불필요한 빈 등록 제거 → 메모리 최적화
  • Formatter 재사용 → 객체 생성 비용 감소
  • 코드 간결성 향상
반응형

댓글