Java의 System 클래스는 자바 개발자들에게 필수적인 유틸리티 클래스입니다. 자바를 시작하면 가장 처음 만나는 코드가 System.out.println("Hello world"); 일 것입니다. 이처럼 우리에게 익숙한 System 클래스는 텍스트 출력 뿐만 아니라 환경 변수 접근, 시스템 속성 관리, 시간 측정, 메모리 관리 등 다양한 시스템 관련 작업을 수행할 수 있습니다. 이 글에서는 System 클래스의 주요 기능, 실제 사용 사례, 그리고 주의해야 할 점들을 상세히 살펴보겠습니다.
System 클래스는 java.lang 패키지에 속한 final 클래스로, 생성자가 없어 인스턴스화할 수 없습니다. 그리고 모든 멤버가 static으로 선언되어 있어서 클래스 이름을 통해 직접 접근할 수 있습니다. 주로 표준 입출력 스트림, 시스템 속성 및 환경 변수 관리, 시스템 유틸리티 메서드 등을 제공합니다.
System.out.println("Hello World");
System.err.println("오류 발생 지점");
Scanner scanner = new Scanner(System.in);
System.out.print("이름을 입력하세요: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
String javaVersion = System.getProperty("java.version"); // "java version" 시스템 속성 가져오기
System.out.println("User Home: " + userHome);
String userHome = System.getenv("HOME"); // "HOME" 환경변수 가져오기
System.out.println("Java Version: " + javaVersion);
System.setProperty("custom.property", "Custom Value"); // "custom.property" 시스템 속성 설정하기
String customProperty = System.getProperty("custom.property"); // "custom.property" 시스템 속성 가져오기
System.out.println("Custom Property: " + customProperty);
long currentTime = System.currentTimeMillis(); // 글 작성중인 현재 시간은 1719838804327 (Mon Jul 01 2024 22:00:04 GMT+0900 (한국 표준시))
System.out.println("현재 시간: " + currentTime + " ms");
long startNanoTime = System.nanoTime();
for (int i = 0; i < 1000000; i++) {
// 작업 수행
}
long endNanoTime = System.nanoTime();
System.out.println("소요된 시간: " + (endNanoTime - startNanoTime) + " ns");
int[] srcArray = {1, 2, 3, 4, 5};
int[] destArray = new int[5];
System.arraycopy(srcArray, 0, destArray, 0, srcArray.length); // srcArray의 첫 번째 요소부터 5개의 요소를 destArray의 첫 번째 위치에 복사
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.hashCode() == str2.hashCode()); // true
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(System.identityHashCode(str1) == System.identityHashCode(str2)); // false
// 명시적인 어플리케이션 종료. 사용하지 않는 것이 권장되고, 특히 웹서버의 경우 절대 사용해선 안됨
System.exit(0);
System.out.println 메서드는 간단한 디버깅이나 로깅에 자주 사용되지만, 성능 측면에서 문제를 가지고 있습니다. println은 PrintStream 클래스의 메서드로, 동기화 방식으로 구현돼 있습니다. 따라서 멀티스레드 환경에서 병목현상이 발생할 수 있으며 콘솔 출력으로 인한 I/O 락은 전반적인 수행 속도 저하를 일으킵니다. 그리고 여러 값을 입력할 때 문자열 연결 연산이 발생하여 추가적인 오버헤드가 발생할 수 있습니다.
// 동기화 방식으로 구현된 PrintStream 클래스의 println 메서드
public void println(String x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
이에 대한 대안으로 로깅 프레임워크를 사용하면 문제들을 개선할 수 있습니다. 예를 들어 Logger는 비동기로 동작하기 때문에 로그 메시지가 별도의 스레드에서 처리되어, 메인 어플리케이션의 성능에 미치는 영향을 최소화 합니다. 그리고 로그 레벨 분리, 로그 메시지를 버퍼에 모았다가 일정한 조건에 의해 한번에 기록하는 버퍼링 방식 지원, 콘솔 출력 외에도 파일, 데이터베이스에 로그를 기록할 수 있기 때문에 서비스 유지보수 측면에서도 효과적입니다.
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.debug("디버그 로그");
자바의 System 클래스는 개발자에게 시스템 수준의 기능을 제공하는 강력한 도구입니다. 그러나 강력한 기능을 제공하는 만큼 일부 메서드는 안정적인 서비스 운영에 치명적인 영향을 끼칠 수 있기 때문에 신중하게 사용해야 합니다. System 클래스의 기능을 잘 이해하고 적절히 활용한다면, 더 효율적이고 견고한 Java 애플리케이션을 개발할 수 있을 것입니다.