일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 1차원 DP
- 2차원 dp
- 99클럽
- @BeforeAll
- @BeforeEach
- @Builder
- @Entity
- @GeneratedValue
- @GenericGenerator
- @NoargsConstructor
- @Query
- @Table
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- api gateway 설계
- api gateway 필터
- ApplicationEvent
- argocd
- assertThat
- async/await
- AVG
- AWS
- aws autoscaling
- aws eks
- aws iam role
- AWS KMS
- Today
- Total
기록
[Spring Boot Kafka] 실행되지만 바로 종료되는 Spring Boot 애플리케이션 본문
시작하면서
Kafka 기반의 오케스트레이터 마이크로서비스를 구성하는 과정에서, 애플리케이션이 정상적으로 빌드되고 실행되었음에도 불구하고 바로 종료되는 현상을 경험했다.
에러 메시지도 없고, 로그상으로는 성공적으로 기동된 것처럼 보이기 때문에 처음엔 의아할 수 있다. 해당 현상을 통해 Spring Boot 애플리케이션이 어떤 조건에서 프로세스를 유지하며, Kafka 기반 서비스에서는 어떤 요소들이 필수적인지를 정리해본다.
1. 문제 현상: 실행되지만 바로 종료되는 Spring Boot 애플리케이션
멀티모듈 기반 프로젝트에서 오케스트레이터 역할을 수행하는 모듈(service-membership-orchestrator)을 실행했더니 다음과 같은 로그만 출력되고 앱이 종료된다:
Started ServiceMembershipOrchestratorApplication in 4.3 seconds
BUILD SUCCESSFUL
Spring Boot 애플리케이션이 시작은 했지만, 곧바로 아무런 동작 없이 내려가버린다.
2. 원인 분석: Spring Boot는 아무것도 안 하면 내려간다
Spring Boot는 기본적으로 내부에 "계속 살아 있어야 할 이유"가 없으면 앱을 자동으로 종료한다.
이러한 조건에 해당하지 않으면 JVM이 유지될 이유가 없다고 판단한다:
✅ 앱이 살아 있는 조건
- 내장 웹 서버가 실행 중일 경우 (spring-boot-starter-web)
- Kafka 리스너가 등록되어 메시지를 대기 중일 경우 (@KafkaListener)
- 스케줄링 작업이 주기적으로 수행될 경우 (@Scheduled)
- 명시적으로 스레드를 유지할 경우 (Thread.currentThread().join() 등)
❌ 앱이 종료되는 조건
- 위 조건 중 아무것도 충족하지 않을 경우, Spring Boot는 컨텍스트 초기화 후 곧바로 종료된다.
이 문제의 경우, Kafka 설정은 되어 있었지만 @KafkaListener가 등록되지 않았기 때문에 Spring Boot는 "아무것도 할 일이 없네?"라고 판단하고 종료한 것이다.
3. 흔한 오해: "웹 서버가 없어서 종료된 거 아닐까?"
많은 개발자들이 spring-boot-starter-web이 빠져 있어서 앱이 종료된다고 오해하곤 한다.
하지만 실제로는, 웹 서버가 필수인 것이 아니라 무언가 지속적으로 수행할 작업이 필요할 뿐이다.
즉, 웹 API가 전혀 필요하지 않은 마이크로서비스도 Kafka 리스너만 제대로 설정되어 있다면,
아무 문제 없이 프로세스를 유지하면서 메시지를 처리할 수 있다.
4. 해결 방법
1) Kafka 리스너 추가
@Component
public class UserInfoSyncOrchestrator {
@KafkaListener(topics = "test-topic")
public void consume(String message) {
System.out.println("받은 메시지: " + message);
}
}
이처럼 @KafkaListener로 메시지 소비 로직을 정의하면, Spring Boot는 Kafka 메시지를 기다리기 때문에 애플리케이션을 종료하지 않는다.
필요하다면 @EnableKafka도 @SpringBootApplication에 함께 추가한다:
@EnableKafka
@SpringBootApplication
public class ServiceMembershipOrchestratorApplication { ... }
5. 정리
- Spring Boot 애플리케이션은 웹 서버가 없어도 Kafka 리스너가 등록되어 있으면 정상적으로 유지된다.
- Kafka 기반 오케스트레이터는 spring-boot-starter-web 없이도 충분히 동작한다.
- @KafkaListener는 단순한 메시지 소비 이상의 역할을 하며, 애플리케이션이 종료되지 않도록 유지하는 트리거 역할도 한다.
- 멀티모듈 프로젝트에서는 JVM 버전이 모듈 간에 일치하지 않으면 의존성 해석 중 오류가 발생할 수 있으므로 주의해야 한다.
✅ 핵심 요약
Spring Boot는 웹 서버가 없더라도 Kafka 리스너가 있으면 애플리케이션을 종료하지 않는다.
오케스트레이터처럼 비동기 이벤트만 처리하는 서비스는 이를 활용해 효율적으로 구성할 수 있다.
'코딩테스트 > Java' 카테고리의 다른 글
Spring Cloud Config Server에 AWS KMS 연동하기 – 커스텀 TextEncryptor로 안전한 암복호화 (0) | 2025.05.02 |
---|---|
백준_Java_22856_트리순회 (0) | 2025.01.13 |
백준_Java_20207_달력 (0) | 2025.01.10 |
백준_Java_14719_빗물 (0) | 2025.01.03 |
프로그래머스_Java_시소짝꿍 (0) | 2023.10.18 |