자바 애플리케이션에서 로그는 시스템 동작 추적과 문제 진단을 위한 필수 요소지만, 잘못 사용하면 심각한 성능 저하를 유발할 수 있습니다
효과적인 로깅은 필요한 정보를 빠짐없이 기록하면서도 시스템 부하를 최소화하는 방법을 찾는 것입니다
System.out.println()
의 남용:가장 손쉽게 사용하는 System.out.println()
은 심각한 성능 문제를 내포합니다
콘솔 출력은 비용이 매우 비싼 동기 작업으로, 출력이 완료될 때까지 다른 작업을 대기시켜 애플리케이션의 전체 처리량을 떨어뜨립니다
로그 출력은 본질적으로 I/O 연산이므로 CPU 연산보다 훨씬 느립니다
특히 콘솔 출력은 파일 출력보다 50배 이상 느릴 수 있으며, 운영 환경에서는 파일로 로그를 남기는 것이 일반적입니다
로그 양이 디스크 쓰기 속도를 초과하면 애플리케이션 지연이나 로그 유실이 발생할 수 있습니다
로그 메시지를 만드는 문자열 연결 과정에서 임시 객체들이 생성됩니다
로그 레벨이 비활성화되어 실제 출력이 이뤄지지 않더라도, 메시지 생성 연산은 실행되어 불필요한 객체를 만들고 가비지 컬렉션(GC)의 부담을 높입니다
e.printStackTrace()
의 위험성:예외 발생 시 e.printStackTrace()
를 사용하는 것은 막대한 성능 비용을 유발합니다
이 메소드는 예외의 호출 스택 전체를 문자열로 변환하여 콘솔에 출력하는데, 이 과정의 90% 이상이 CPU를 사용합니다
또한 다중 스레드 환경에서는 로그가 뒤섞여 내용을 파악하기 어렵게 만듭니다.
System.out.println()
대신 Log4j2, Logback과 같은 전문 로깅 프레임워크를 사용해야 합니다
이러한 프레임워크는 로그 레벨(DEBUG, INFO, ERROR 등)에 따라 출력을 제어하고,
파일 롤링, 비동기 출력 등 다양한 기능을 제공하여 성능 영향을 줄여줍니다
불필요한 문자열 연산을 피하기 위해 로그 메시지 생성을 조건부로 실행해야 합니다.
if (logger.isDebugEnabled())
와 같이 로그 레벨을 먼저 확인하거나,
SLF4J의 플레이스홀더({}
) 문법을 사용하는 것이 좋습니다
플레이스홀더를 사용하면 로그 레벨이 비활성화되어 있을 때 메시지 생성을 위한
toString()
호출이나 문자열 결합이 발생하지 않아 성능을 지킬 수 있습니다.
e.printStackTrace()
대신 logger.error("에러 메시지", e);
와 같이 로거를 통해 예외를 기록해야 합니다
이를 통해 로그가 파일 등 지정된 위치에 일관된 형식으로 기록되며,
콘솔 출력으로 인한 성능 저하와 로그 뒤섞임 문제를 피할 수 있습니다