개발공부/SPRING

Lombok의 @RequiredArgsConstructor는 무엇이며 왜 사용할까?

Grogrammer 2026. 6. 28. 15:58

Spring Boot를 공부하면 거의 모든 Controller에서 아래와 같은 코드를 보게 된다.

@RestController
@RequiredArgsConstructor
public class ScheduleController {

    private final ScheduleService scheduleService;

}

처음에는 @RequiredArgsConstructor가 단순히 “생성자를 만들어주는 어노테이션” 정도로만 이해했다.

하지만 공부를 하다 보니 이 어노테이션은 Spring의 생성자 주입(Constructor Injection)과 밀접한 관계가 있다는 것을 알게 되었다.

이번 글에서는 @RequiredArgsConstructor가 무엇인지, 왜 사용하는지, 그리고 Spring 내부에서는 어떤 방식으로 동작하는지 정리해보려고 한다.


@RequiredArgsConstructor란 ?

@RequiredArgsConstructor는 Lombok에서 제공하는 어노테이션이다.

이 어노테이션은 필수(required) 필드만을 매개변수로 받는 생성자를 자동으로 생성해준다.

⭐️여기서 “필수 필드”란 다음 두 가지를 의미한다.

  • final 필드
  • @NonNull이 붙은 필드

Spring에서는 대부분 final 필드를 사용하기 때문에 사실상 final 필드를 위한 생성자를 자동 생성한다고 이해해도 된다.

예를 들어 다음과 같은 코드가 있다고 가정해보자.

@RestController
@RequiredArgsConstructor
public class ScheduleController {

    private final ScheduleService scheduleService;

}

겉으로 보기에는 생성자가 존재하지 않는다.

하지만 실제 컴파일이 되면 Lombok이 아래와 같은 생성자를 자동으로 만들어준다.

@RestController
public class ScheduleController {

    private final ScheduleService scheduleService;

    public ScheduleController(ScheduleService scheduleService) {
        this.scheduleService = scheduleService;
    }
}

즉,

@RequiredArgsConstructor

한 줄이 위 생성자를 대신 작성해주는 것이다.


왜 이름이 RequiredArgsConstructor일까?

어노테이션 이름을 그대로 해석하면 의미를 이해하기 쉽다.

Required       필요한
Args           Arguments(매개변수)
Constructor    생성자

즉,

필요한 값을 매개변수로 받는 생성자를 만들어준다.

라는 의미이다.


왜 final 필드는 생성자가 반드시 필요할까?

다음 코드를 보자.

public class ScheduleController {

    private final ScheduleService scheduleService;

}

이 코드는 컴파일조차 되지 않는다.

그 이유는 final 필드는 반드시 초기화되어야 하기 때문이다.

final이 붙은 변수는 한 번만 값을 저장할 수 있다.

따라서 객체가 생성되는 순간 반드시 값을 넣어주어야 한다.

그래서 원래는 아래와 같은 생성자를 직접 작성해야 한다.

public ScheduleController(ScheduleService scheduleService) {
    this.scheduleService = scheduleService;
}

하지만 이런 생성자는 대부분 동일한 형태가 반복된다.

Lombok은 이런 반복 코드를 대신 작성해주는 것이다.


Spring에서는 왜 많이 사용할까?

Controller는 혼자서 일을 하지 않는다.

예를 들어 일정을 생성하는 기능이 있다면 Controller는 Service에게 일을 맡긴다.

@PostMapping
public ScheduleResponse createSchedule(@RequestBody ScheduleCreateRequest request) {
    return scheduleService.createSchedule(request);
}

여기서 scheduleService가 존재하지 않으면 Controller는 아무 일도 할 수 없다.

즉, Controller에게 ScheduleService는 반드시 필요한 객체이다.

그래서 다음과 같이 선언한다.

private final ScheduleService scheduleService;

이 코드의 의미는 다음과 같다.

ScheduleController는 ScheduleService 없이는 정상적으로 동작할 수 없다.


그런데 new를 사용하지 않았다.

여기서 한 가지 의문이 생긴다.

우리는 어디에서도

new ScheduleController(...)

를 작성하지 않았다.

그런데 어떻게 ScheduleController 객체가 생성될까?

그 이유는 Spring이 대신 객체를 생성하기 때문이다.

@RestController가 붙은 클래스를 발견하면 Spring은 이 클래스를 Bean으로 등록한다.

그 다음 생성자를 확인한다.

public ScheduleController(ScheduleService scheduleService)

생성자를 확인한 Spring은 다음과 같이 판단한다.

ScheduleController를 만들려면
ScheduleService가 필요하구나.

그러면 Spring Container 안에서 ScheduleService Bean을 찾아 생성자에 넣어준다.

즉 내부적으로는 다음과 같은 과정이 일어난다.

1. Spring이 ScheduleService Bean을 생성한다.

        ↓

2. ScheduleController를 생성하려고 한다.

        ↓

3. 생성자를 확인한다.

        ↓

4. ScheduleService가 필요하다는 것을 확인한다.

        ↓

5. ScheduleService를 생성자에 전달하여
   ScheduleController를 생성한다.

실제로 내부에서는 아래 코드와 비슷한 동작이 수행된다.

ScheduleController controller =
        new ScheduleController(scheduleService);

우리가 직접 작성하지 않을 뿐, Spring이 대신 생성자를 호출해주는 것이다.


이것을 생성자 주입(Constructor Injection)이라고 한다.

객체를 생성할 때 필요한 객체를 생성자의 매개변수로 전달하는 방식을 생성자 주입(Constructor Injection)이라고 한다.

public ScheduleController(ScheduleService scheduleService) {
    this.scheduleService = scheduleService;
}

Spring에서는 여러 의존성 주입 방식이 존재하지만, 현재는 생성자 주입을 가장 권장한다.


생성자 주입을 권장하는 이유

예전에는 다음과 같은 필드 주입 방식을 많이 사용했다.

@Autowired
private ScheduleService scheduleService;

하지만 현재는 다음과 같은 방식이 가장 많이 사용된다.

private final ScheduleService scheduleService;

@RequiredArgsConstructor

그 이유는 다음과 같다.

  • final을 사용할 수 있다.
  • 객체 생성 시점에 반드시 의존성이 주입된다.
  • 생성 이후에는 다른 객체로 변경할 수 없다.
  • 테스트 코드 작성이 쉽다.
  • 순환 참조 문제를 비교적 빠르게 발견할 수 있다.

즉 객체가 생성되는 순간부터 완전한 상태를 보장할 수 있다는 것이 가장 큰 장점이다.


정리

@RequiredArgsConstructor는 Spring에서 제공하는 기능이 아니다.

Lombok이 제공하는 기능이다.

하지만 Spring에서 가장 권장하는 생성자 주입 방식과 매우 잘 어울리기 때문에 Controller와 Service에서 거의 필수적으로 사용된다.

결국 @RequiredArgsConstructor는 단순히 생성자를 자동으로 만들어주는 어노테이션이 아니라, Spring의 생성자 주입을 간결하고 안전하게 구현하기 위한 Lombok의 도구라고 이해하면 된다.