본문 바로가기
왜?

[왜] 로그 찍을 때 System.out.println을 사용하면 안 좋을까?

by KKambi 2020. 4. 18.

System.out.println 이란?

java.lang.System

  • Among the facilities provided by the System class are standard input, standard output, and error output streams; access to externally defined properties and environment variables; a means of loading files and libraries; and a utility method for quickly copying a portion of an array.
  • (해석) System class에 의해 제공되는 기능에는 표준입력, 표준출력, 에러출력스트림, 외부 프로퍼티와 환경변수에 대한 접근, 파일과 라이브러리 로딩 수단, 배열의 일부분을 복사하는 유틸리티 메소드가 있다.
  • java.Object 상속 클래스
  • public final class = 인스턴스 생성불가 = 모두 static field / method

java.lang.System.out

  • System class의 public static final field
  • PrintStream 타입 참조 변수
  • PrintStream의 인스턴스가 할당됨
  • 이와 유사하게 System.err 또한 PrintStream 객체

public static final PrintStream out = null

  • System class의 out은 null로 할당되어있음

  • 언제 PrintStream의 인스턴스가 할당되는가?

  • 어떻게 final인데 인스턴스가 할당되는가?

  • 참고링크3을 보면, 자바 네이티브 인터페이스(JNI)에 의해 정의된 SetOut0()에 의해 할당

    정확히 이해불가. 결국 out은 PrintStream 인스턴스를 가리킨다고 생각하자.

PrintStream class

  • java.lang.Object - java.io.OutputStream - java.io.FilterOutputStream을 상속
  • 개행(println()) / 패턴출력(format()) 등과 같이 출력의 편리함을 위한 wrapper class
  • Decortaor pattern과 연관

왜 System.out.println을 사용하면 안 좋을까?

PrintStream의 println() 메소드

  • 파라미터와 \n을 출력하는 메소드
  • 파라미터 출력 메소드는 print() -> print()는 write() 호출
  • 개행 출력 메소드는 newLine()
  • 다양한 타입(char, char[], boolean, double, Object, String, ..)에 맞게 오버로딩되어있음

println()은 synchronized block

1
2
3
4
5
6
7
8
public class PrintStream extends FilterOutputStream implements Appendable, Closeable{
    public void println(boolean x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
}
cs
  1. synchronized = 오버헤드 증가 = 성능 저하

  2. log level 없음 = 로그 저장 공간 초과

    System.currentTimeMillis()로 측정해보면 오래 걸림!

해결책

  1. slf4j(Logging Facade)Logback(Logger)사용
  2. StringBuilder class를 통해 log를 모은 뒤, 한 번에 출력하기

참고링크1-OKKY
참고링크2-Oracle Docs
참고링크3-hashcode

댓글