System.out.println을 실무에서 사용하면 안되는 이유

2024. 12. 5. 18:11·💻 Dev/Java & OOP

자바를 접하게 되면 제일 먼저 하는 것이 System.out.println("Hello, World!")일 것이다.
그만큼 기초이자, 아주 많이 사용하는 코드이다.
하지만 System.out.println은 실무에서 절대 사용하지 말라고들 한다.

 

왜일까?

성능 이슈로는 크게 2가지가 있다. 블로킹 I/O작업을 한다는 점과 멀티스레드에서 락이 발생한다는 점이다.

 

1. 블로킹 I/O 작업

먼저 System 클래스의 static 변수인 out은 PrintStream 타입의 인스턴스이다.

public static final PrintStream out = null;

그리고 PrintStream 클래스는 java의 io 패키지 내에 있다.

package java.io;

public class PrintStream extends FilterOutputStream  
    implements Appendable, Closeable

즉, println()은 I/O 작업이며 이는 프로그램이 데이터를 출력할 때 운영체제(OS)의 표준 출력 장치(콘솔 창, 터미널)로 데이터를 보내는 작업을 수행한다는 뜻이다.

 

이는 Blocking I/O 방식으로 동작하며 이는 데이터 출력 작업이 완료될 때까지 호출한 스레드가 블록(block)되어 다른 작업을 처리하지 못하는 방식을 의미한다.

 

2. synchronized 작업

표준 출력(System.out)은 공유 자원이기 때문에 여러 스레드에서 동시에 접근할 경우 출력 순서가 뒤섞이거나 충돌할 가능성이 있다.
이를 방지하기 위해 println 내부에선 snychronized 를 사용해 동기화 처리한다.
(String 뿐만 아니라 다른 매개변수도 비슷하다.)

public void println(String x) {  
    synchronized (this) {  
        print(x);  
        newLine();  
    }  
}

synchronized은 한 번에 하나의 스레드만 자원을 사용할 수 있도록 제한한다.
따라서 멀티스레드 환경에서 다수의 스레드가 동시에 로그를 출력하려고 하면 대기 시간이 증가하고 병목 현상이 발생한다.

 

즉, System.out.println()이 끝날 때까지 아무 일도 할 수 없고 대기해야 하기에 오버헤드가 발생해 성능이 저하되는 것이다.

 

+ 로그 레벨관리가 어려움

System.out.println은 로그의 중요도(DEBUG, INFO, WARN, ERROR 등)를 구분하지 못한다. 이는 프로덕션 환경에서 디버깅 메시지와 중요한 오류 로그가 섞이는 문제를 야기할 수 있다.

 

 

해결 방법은?

실무에서는 Log4j, SLF4J 같은 전문 로깅 프레임워크를 사용하는 것이 일반적이다.
디버깅 및 모니터링에 더 효과적이기 때문이다.


이 도구들은 로그를 별도의 스레드에서 처리해 병목 현상을 최소화하고, 로그의 중요도를 구분해 출력할 수 있다.

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

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

    public static void main(String[] args) {
        logger.info("This is an INFO message.");
        logger.debug("This is a DEBUG message.");
        logger.error("This is an ERROR message.");
    }
}

 

 

 

 

 

참고
System.out.println() 사용을 자제해야 하는 이유
System.out.println 메소드는 실무에서 절대 사용하지 마라.

저작자표시 비영리 (새창열림)

'💻 Dev > Java & OOP' 카테고리의 다른 글

자바는 왜 Lambda&Stream을 도입했을까? feat.함수형 프로그래밍  (0) 2024.12.26
리플렉션(Reflection)으로 DI 구현해보기 +단점  (0) 2024.12.22
Stack은 왜 상속의 실패 사례일까?  (0) 2024.12.12
가비지 컬렉터(GC)의 Roots  (0) 2024.12.04
Out-of-Memory(OOM)는 왜 발생하고, 어떻게 예방할까?  (0) 2024.11.30
instanceof 사용을 지양해야하는 3가지 이유  (0) 2024.11.29
'💻 Dev/Java & OOP' 카테고리의 다른 글
  • 리플렉션(Reflection)으로 DI 구현해보기 +단점
  • Stack은 왜 상속의 실패 사례일까?
  • 가비지 컬렉터(GC)의 Roots
  • Out-of-Memory(OOM)는 왜 발생하고, 어떻게 예방할까?
현주먹
현주먹
대구 불주먹 출신 현주먹의 개발.log
  • 현주먹
    현주먹의 개발로그
    현주먹
  • 전체
    오늘
    어제
    • 전체글 (179)
      • 👶🏻 CS (15)
        • Operating System (7)
        • DB (5)
        • Data Structure (2)
        • Software Engineering (1)
      • 💻 Dev (54)
        • Java & OOP (24)
        • Spring (4)
        • DB&JPA (6)
        • Test Code (1)
        • JSP & Servlet (13)
        • Etc (6)
      • 💡 Algorithm (25)
        • 인프런 (9)
        • 백준 (16)
      • 🛠 DevOps & Tool (11)
        • Linux (4)
        • AWS (1)
        • Git (2)
        • Etc (4)
      • 📝 끄적끄적 (74)
        • 후기 및 회고 (11)
        • TDD, 클린 코드 with Java 17기 (3)
        • F-Lab (23)
        • 🖥️ 자바의 정석 (11)
        • 📖 Clean Code (3)
        • 항해99 코테 스터디 (11)
        • 📖 가상 면접 사례로 배우는 대규모 시스템 설계 .. (11)
  • 블로그 메뉴

    • 🐈‍⬛ GitHub
    • TIL repository
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 태그

    객체지향
    에프랩
    개구리책
    TDD 클린 코드 with Java
    자바의신절판
    jsp
    개발자멘토링
    오라클
    항해99
    f-lab 후기
    개발자취업
    코테스터디
    F-Lab
    C
    티스토리챌린지
    인프런 특정문자뒤집기
    ==와 equals()
    백준
    데브클럽
    99클럽
    자바의정석
    jsp 2.3 웹 프로그래밍: 기초부터 중급까지
    코딩테스트준비
    로또 미션
    2025스프링캠프
    오블완
    til
    NextSTEP
    JPA
    에프랩 후기
  • hELLO· Designed By정상우.v4.10.2
현주먹
System.out.println을 실무에서 사용하면 안되는 이유
상단으로

티스토리툴바