본문 바로가기
클라우드/쿠버네티스

[쿠버네티스] SpringBoot System.in 사용 시 터지는 문제 해결기

by 클레어몬트 2025. 4. 29.

최근에 Kubernetes 환경에서 Java 애플리케이션을 배포하는 과정에서 예상치 못한 문제가 발생했다. Local에서는 잘 돌아가던 코드가 Kubernetes Pod 안에서는 갑자기 죽어버리는 현상이 발생한 것이다. 문제의 원인은 생각보다 단순했다. 그리고 해결 방향은 ‘환경에 따라 동작 방식을 다르게’ 가져가는 것이었다. 이 글에서는 이 과정을 정리해보려 한다!

 

 

 

문제 상황

내가 작성한 Java 코드에서는 start() 메서드 안에서 Scanner(System.in)을 이용해 사용자 입력을 받고 있었다.

Scanner scanner = new Scanner(System.in);
System.out.println("명령어를 입력하세요:");
String input = scanner.nextLine();

 

 

Local에서는 이 방식이 아무 문제 없이 작동했다. 터미널에 입력하면 바로 입력을 받을 수 있었기 때문이다.

그런데 Kubernetes Pod에 이 애플리케이션을 띄우자마자 문제가 터졌다.

 

정확히는 Pod이 뜨자마자 CrashLoopBackOff 상태에 빠졌다.

로그를 확인해보니 java.util.NoSuchElementException: No line found 예외가 터지고 있었다.

 

처음에는 코드 문제를 의심했지만, 계속 파헤치며 자세한 원인을 살펴보니 "Kubernetes 환경에서는 기본적으로 System.in이 존재하지 않는다"는 사실을 알게 되었다. (엄밀히 말하면 stdin이 연결되어 있지 않다. Kubernetes는 사용자가 직접 입력하는 환경이 아니기 때문이다!)

 

 

 

 

해결 방향

  1. Local 개발 환경에서는 기존처럼 Scanner를 이용해 사용자 입력을 받을 수 있도록 유지
  2. 운영 Kubernetes 환경에서는 Scanner를 아예 사용하지 않고, 서버만 기동하도록 한다 (대신 당연히 서버는 API를 통해 외부에서 명령어나 데이터를 받을 수 있도록 구성한다)

 

정리하면, “환경에 따라 입력 방식이 달라져야 한다” 는 결론이었다

 

 

 

 

그래서 실제 코드 수정은?

환경 변수를 이용해서 Local과 Kubernetes 환경을 구분하기로 했다

public void start() {
    String environment = System.getenv("APP_ENV");

    if ("local".equalsIgnoreCase(environment)) {
        // Local 개발 환경: Scanner 사용
        Scanner scanner = new Scanner(System.in);
        System.out.println("명령어를 입력하세요:");
        while (scanner.hasNextLine()) {
            String input = scanner.nextLine();
            processCommand(input);
        }
    } else {
        // Kubernetes 운영 환경: 서버만 기동
        startServer();
    }
}

private void processCommand(String input) {
    // 명령어 처리 로직
}

private void startServer() {
    // API 서버 기동 로직
}

 

  • Local에서는 환경변수 APP_ENV=local로 설정하고 실행한다
  • Kubernetes에서는 APP_ENV=prod나 따로 설정 없이 운영되기 때문에 Scanner 코드가 실행되지 않는다

 

 

 

느낀 점

 

이번 문제를 통해 “Local에서 되는 게 Kubernetes에서도 당연히 될 거라고 믿으면 안 된다”는 교훈을 다시 한번 얻었다.

특히 System.in, System.out 같은 I/O 스트림은 컨테이너 환경에서는 다르게 동작할 수 있기 때문에 항상 주의가 필요하다.

 

또 하나 크게 느낀 점은, 환경에 따라 분기 처리를 깔끔하게 설계하는 것이 중요하다는 것이다.

처음에는 “Scanner가 안 되면 그냥 에러 캐치해서 넘어가자”는 식으로 땜질하려고 했지만, 결국 그렇게 하면 코드가 지저분해지고 유지보수성이 떨어진다.

 

애초에 ‘환경’을 기준으로 명확하게 동작 방식을 분리하는 것이 가장 깔끔한 해결책이었다..!

 

 

 

 

 

마지막 정리

  • Kubernetes Pod에서는 기본적으로 System.in이 제공되지 않는다
  • Local과 Kubernetes 환경을 구분해서 Scanner 사용 여부를 결정해야 한다
  • 환경 변수를 이용해 개발-운영 환경을 명확하게 분리하는 것이 좋다 :)

이 트러블슈팅 덕분에 Kubernetes 환경에 대한 이해도가 한층 더 깊어졌다!

앞으로도 “Local에서는 잘 되는데 서버에서는 왜 안 될까?” 싶은 문제가 생기면, 환경 차이부터 의심하는 습관을 가져야겠다