@PostConstruct란?
@PostConstruct는 Spring에서 제공하는 생명주기 콜백 애노테이션으로,
객체 생성과 의존성 주입이 완료된 후 자동으로 실행되는 메서드에 사용된다.
@Component
public class SampleService {
@Resource
private DatabaseService databaseService;
@PostConstruct
public void init() {
// 의존성 주입 완료 후 실행되는 초기화 로직
databaseService.connect();
}
}
1. 왜 필요한가? (필드 주입 문제)
문제 상황: 필드 주입 방식
@Component
public class CacheService {
@Resource
private DataService dataService;
public CacheService() {
// ❌ 이 시점에는 dataService가 아직 null
// loadCacheData(); // NullPointerException 발생
}
}
실행 순서
- new CacheService() → 객체 생성
- Spring이 @Resource로 dataService 주입
- 생성자에서는 아직 의존성이 주입되지 않음 → null
해결책: @PostConstruct
@Component
public class CacheService {
@Resource
private DataService dataService;
@PostConstruct
public void init() {
// ✅ 의존성 주입 완료 후 실행
loadCacheData();
}
private void loadCacheData() {
dataService.getData(); // 안전하게 사용 가능
}
}
2. 생성자 주입에서는 불필요
현재 Spring 권장 방식은 생성자 주입이다.
생성자 주입은 의존성이 보장된 상태로 객체가 생성되므로 @PostConstruct가 필요 없다.
@Component
public class CacheService {
private final DataService dataService;
public CacheService(DataService dataService) {
this.dataService = dataService;
// ✅ 의존성이 이미 보장됨 → 바로 초기화 가능
loadCacheData();
}
private void loadCacheData() {
dataService.getData();
}
}
3. 의존성 주입 방식 비교
구분필드 주입 (@Resource, @Autowired)생성자 주입
| 문법 | 애노테이션으로 필드에 직접 주입 | 생성자 파라미터 |
| 불변성 | ❌ final 불가 | ✅ final 가능 |
| 초기화 시점 | @PostConstruct 필요 | 생성자에서 바로 가능 |
| 테스트 용이성 | Mock 주입 어려움 | Mock 주입 쉬움 |
| 순환 참조 발견 | 런타임에 발견 | 컴파일/시작 시점에 발견 |
4. Spring 권장사항의 변화
과거 (Spring 3.x 이전)
@Component
public class LegacyService {
@Autowired
private DependencyService dependency;
@PostConstruct // 필수
public void init() {
dependency.initialize();
}
}
현재 (Spring 4.3+)
@Component
@RequiredArgsConstructor // Lombok
public class ModernService {
private final DependencyService dependency;
// 생성자에서 바로 초기화 가능 → @PostConstruct 불필요
}
5. 여전히 @PostConstruct가 필요한 경우
- 레거시 코드 유지보수
- 외부 리소스 연결
- DB 커넥션, 파일 시스템 등
- 복잡한 초기화 로직이 필요한 경우
- 설정 프로퍼티(@Value) 기반 초기화
@Component
public class ExternalResourceService {
@Value("${external.api.url}")
private String apiUrl;
@PostConstruct
public void connectToExternalAPI() {
// @Value 주입 완료 후 안전하게 사용 가능
}
}
📌 정리
- 필드 주입 → @PostConstruct 필요
- 생성자 주입 (권장) → @PostConstruct 불필요
- 예외적으로 외부 리소스 연결, 설정 기반 초기화에서는 여전히 활용 가치 있음
👉 최신 Spring 프로젝트에서는 생성자 주입을 기본으로 하고, 특별한 경우에만 @PostConstruct 사용하는 것이 바람직하다.
'Java' 카테고리의 다른 글
| Logger를 static final로 선언하는 이유 (0) | 2025.10.02 |
|---|---|
| Java - Enum 클래스 사용 (0) | 2023.10.05 |
| Java - 람다 표현식(lamda Expression) (0) | 2023.10.02 |
| Java - 대용량 데이터 적재 로직 설계시 유념할 사항 (0) | 2022.11.04 |
| Java - properties 파일이란 무엇인가? (0) | 2022.06.17 |