본문 바로가기
Spring/- [시리즈] Spring 프로젝트 되살리기

Spring 프로젝트 되살리기 7 - 코드 리팩토링 4 (record, 정적 팩토리 메서드 적용)

by 정구정구 2026. 7. 26.

이전 이야기

https://record47584.tistory.com/91

 

Spring 프로젝트 되살리기 6 - 유닛 테스트 코드 고치기

이전 이야기https://record47584.tistory.com/90 Spring 프로젝트 되살리기 5 - 리펙토링 3 (@EntityGraph 적용)이전 이야기https://record47584.tistory.com/89 Spring 프로젝트 되살리기 4 - 코드 리펙토링 2 (@Valid 적용)이전

record47584.tistory.com

 

 

시나리오 7

이제 프로젝트에 기능적으로 문제될 것은 없어보인다. 그럼 좀 더 유지보수가 편하도록 코드를 수정해보자.

 

 

리팩토링 1 - class를 record로 변경

record 자료형을 쓰면 더 간결하게 DTO를 작성할 수 있다.

 

record의 사용법과 장점은 아래의 링크에 정리해두었다.

( 참고 : https://record47584.tistory.com/7 )

 

record

record란?“데이터 저장 목적 객체를 간단하게 만들기 위한 Java 문법”(자바 16부터 정식 지원) record가 자동 생성하는 것생성자gettrt 비슷한 메서드 (기존 getter와 이름이 다르다. getId()가 아닌 id().

record47584.tistory.com

 

@Getter
public class TodoResponse {

    private final Long id;
    private final String title;
    private final String contents;
    private final String weather;
    private final UserResponse user;
    private final LocalDateTime createdAt;
    private final LocalDateTime modifiedAt;

    public TodoResponse(Long id, String title, String contents, String weather, UserResponse user, LocalDateTime createdAt, LocalDateTime modifiedAt) {
        this.id = id;
        this.title = title;
        this.contents = contents;
        this.weather = weather;
        this.user = user;
        this.createdAt = createdAt;
        this.modifiedAt = modifiedAt;
    }
}

 

위의 코드를 record로 바꾸면, 

public record TodoResponse(
        Long id,
        String title,
        String contents,
        String weather,
        UserResponse user,
        LocalDateTime createdAt,
        LocalDateTime modifiedAt
) {
}

 

위와 같이 짧고 간결해진다.

 

 

리팩토링 2 - 정적 팩토리 메서드 적용

정적 팩토리 메서드를 적용하면 유지보수에 유리한 코드 구조를 설계 할 수 있다.

 

정적 팩토리 메서드에 대해서는 아래의 링크에 적어두었다.

( 참조 : https://record47584.tistory.com/46 )

 

정적 팩토리 메서드

생성자 대신 정적 팩토리 메서드를 고려하라! 정적 팩토리 메서드란?객체의 생성을 담당하는 클래스 메서드 정적 팩토리 메서드의 특징1. 생성 목적에 대한 이름 표현 가능public final class Money { pr

record47584.tistory.com

 

public record TodoResponse(
        Long id,
        String title,
        String contents,
        String weather,
        UserResponse user,
        LocalDateTime createdAt,
        LocalDateTime modifiedAt
) {
    public static TodoResponse from(Todo todo) {
        return new TodoResponse(
                todo.getId(),
                todo.getTitle(),
                todo.getContents(),
                todo.getWeather(),
                // UserResponse에도 정적 팩토리 메서드 적용
                UserResponse.from(todo.getUser()), 
                todo.getCreatedAt(),
                todo.getModifiedAt()
        );
    }
}
public record UserResponse(
        Long id,
        String email
) {
    public static UserResponse from(User user) {
        return new UserResponse(
                user.getId(),
                user.getEmail());
    }
}

 

record 내부에 위와 같이 정적 팩토리 메서드를 구현하면,

    @Transactional(readOnly = true)
    public Page<TodoResponse> getTodos(int page, int size) {
        Pageable pageable = PageRequest.of(page - 1, size);

        Page<Todo> todos = todoRepository.findAllByOrderByModifiedAtDesc(pageable);

        return todos.map(todo -> new TodoResponse(
                todo.getId(),
                todo.getTitle(),
                todo.getContents(),
                todo.getWeather(),
                new UserResponse(todo.getUser().getId(), todo.getUser().getEmail()),
                todo.getCreatedAt(),
                todo.getModifiedAt()
        ));
    }

 

위의 service 코드를

    @Transactional(readOnly = true)
    public Page<TodoResponse> getTodos(int page, int size) {
        Pageable pageable = PageRequest.of(page - 1, size);

        Page<Todo> todos = todoRepository.findAllByOrderByModifiedAtDesc(pageable);

        return todos.map(TodoResponse::from);
    }

 

위와 같이 간결하게 표현할 수 있다.

 

코드가 간결해진 것 이외에도, TodoResponse의 객체 내부가 변경되었을 때,

TodoResponse이 생성되는 모든 곳을 수정할 필요 없이, 정적 팩토리 메서드 내부만 수정하면 된다는 장점이 생긴다.