IT/Java

성능 저하 및 Full GC - e.printStackTrace()를 피해야 하는 이유

Dev. Sean 2024. 2. 28. 00:37
반응형

자바 개발 시, 예외 처리는 필수적이다.

그러나 많은 개발자들이 예외 처리를 위해 e.printStackTrace()를 사용하는 경향이 있다.

이 방식은 단순하고 직관적이지만, 성능 저하를 초래하고, 특히 가비지 컬렉션(GC)의 빈도와 깊은 관련이 있다.

 

 

 

 

e.printStackTrace()의 문제점

      • 예외 데이터의 과도한 생성
        e.printStackTrace()는 예외와 스택 추적 정보를 출력하기 위해 내부적으로 문자열 객체를 생성한다. 과도한 예외 발생 상황에서 이러한 문자열 객체들이 대량으로 생성될 수 있으며, 이는 메모리 사용량을 증가시킨다.
      • 로깅 관리의 어려움
        e.printStackTrace()는 예외 정보를 표준 에러 스트림에 직접 출력하기 때문에, 이 정보를 파일이나 데이터베이스로 리디렉션하는 것이 어렵다. 이는 효과적인 로깅 관리를 방해하며, 오류 모니터링과 분석을 복잡하게 만든다. 예외 정보가 적절한 로깅 시스템을 통해 관리되지 않고, 단순히 콘솔에 출력되기만 한다면, 중요한 예외 정보를 시스템적으로 분석하거나 모니터링하는 것이 어렵다. 이는 장기적으로 볼 때, 잠재적인 성능 문제나 버그를 조기에 발견하고 대응하는 데 있어서 장애가 될 수 있다.
      • Full GC
        e.printStackTrace() 사용은 메모리 사용량 증가로 이어질 수 있다. 과도한 예외 정보의 생성과 출력은 가비지 컬렉터에 의해 회수될 객체의 수를 증가시킨다. 특히, 대량의 예외 정보가 짧은 시간 내에 생성되면, 이는 가비지 컬렉션의 빈도를 높이고, 최악의 경우 Full GC를 유발할 수 있다. 이는 애플리케이션의 성능 저하로 이어지며, 사용자 경험에 부정적인 영향을 미칠 수 있다.

Full GC란?

Garbage Collection(GC)은 자바 가상 머신(JVM)이 프로그램에서 더 이상 사용되지 않는 메모리(가비지)를 자동으로 회수하는 과정이다.

Full GC는 JVM의 힙 영역 전체를 대상으로 불필요한 객체들을 청소하는 과정으로, 이 과정 중에는 애플리케이션의 실행이 일시적으로 멈출 수 있다.

Full GC는 메모리가 부족할 때나 System.gc() 메서드 호출과 같은 특정 조건에서 발생하며, 애플리케이션의 성능 저하를 일으킬 수 있다.

Full GC 가 일어나면 보통 수초에서 수십초의 시간을 소요하게 되며, 이때 JVM 은 Full GC 이외의 일은 하지 않는다.

즉,  WAS가 Full GC 가 일어나면 수초에서 수십초간 정지되는 상황에 놓이는 것이다. 

 

e.printStackTrace() 자체가 직접적인 메모리 누수를 일으키는 것은 아니지만, 이 메서드의 사용은 부적절한 예외 처리와 관련된 문제들로 이어질 수 있다.

 

e.printStackTrace() 사용 예제

public class Example {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
}

 

logger를 대신 사용하자

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BetterExample {
    private static final Logger logger = LoggerFactory.getLogger(BetterExample.class);

    public static void main(String[] args) {
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            logger.error("An error occurred: ", e);
        }
    }
}

 

e.printStackTrace()는 개발 단계에서 빠른 디버깅을 위해 유용할 수 있으나, 프로덕션 환경에서는 성능 저하, 로깅 관리의 어려움, 그리고 Full GC 발생 빈도 증가와 같은 다양한 문제를 초래할 수 있다.

따라서, SLF4J, Logback, Log4j와 같은 로깅 프레임워크를 사용하여 예외를 효과적으로 관리하는 것이 권장된다.

 

Log4j의 효율성 이유

Log4j는 자바 기반의 로깅 유틸리티로 Log4j의 효율성엔 다음과 같은 것들이 있다.

  • 비동기 로깅
    Log4j는 비동기 로깅 기능을 제공한다. 이는 로깅 작업이 애플리케이션의 성능에 미치는 영향을 최소화하여, 로그 메시지를 처리하는 동안 애플리케이션의 메인 스레드가 블록되지 않도록 한다.

  • 성능 최적화
    Log4j는 내부적으로 메시지 포맷팅과 I/O 작업을 최적화하여 로깅의 오버헤드를 최소화한다. 예를 들어, 로그 레벨이 비활성화된 경우, 관련 로그 메시지는 생성조차 되지 않아 성능에 미치는 영향이 거의 없다.
반응형