개발자 노트

exception handling 여정 - Redirection 본문

이것저것

exception handling 여정 - Redirection

jurogrammer 2021. 7. 3. 11:58

상위 주제

exception handling 여정

 

참고

정의

redirection은 interprocess communication(IPC)의 한 형태입니다. 대부분 command line interpreter에서 가지는 함수이지요.

이전에 콘솔에 입력된 데이터가 어떻게 app으로 전달될까? 의 고민에서 나온 그 방법입니다.

Cat

사실 정의와 설명은 생활코딩님이 너무 잘 설명해주시니 링크로 대체하겠습니다.

https://opentutorials.org/course/2598/14199

java

제가 테스트하고 싶은 건 자바에서 어떻게 입출력을 다루는지 입니다. 언제 stdin, stdout, stderr를 사용하는지 알고 싶은 것이죠.

이를 알기 위해 테스트를 다음처럼 설계하였습니다.

기본적으로 exception을 던지는 메서드를 call 하도록 할 것입니다.

과정

  • exception을 던지는 method를 call하기 전 시작과 종료를 알리는 메세지를 System.out.println으로 출력합니다.
  • 그 다음으로 케이스를 2가지로 나눕니다.
    1. handling하지 않는 경우
    2. exception handling 하고 e.printStackTrace를 해본다.
  • 빌드 후 콘솔에서 jar파일을 실행할 때 stdout은 stdout.log, stderr은 stderr.log 파일로 각각 redirection 시켜줍니다.
  • std.log, err.log에 어떤 값이 출력됬는지 확인합니다.

CustomException

public class CustomException extends RuntimeException {

    public CustomException(String message) {
        super(message);
    }
}

다음처럼 구현된 custom exception을 던지도록 하겠습니다. main에서 throw가 있으면 보기 불편해서 runtime exception을 상속받도록 하겠습니다. (언제 exception을 상속받아야 하는지, 언제 runtime exception을 상속받아야 하는지는 추후 설명하도록 드리도록 하겠습니다.)

1. Handling을 하지 않는다.

public class Main {
    public static void main(String[] args) {
        System.out.println("exception throw method call 이전");
        throwException();
        System.out.println("exception throw method call 이후");
    }

    private static void throwException() {
        throw new CustomException("익셉션 테스트");
    }
}

jar 파일로 빌드한 뒤에 콘솔로 다음 명령어로 실행합니다.

java -jar javatest-1.0-SNAPSHOT.jar > stdout.log 2> stderr.log

결과

stdout.log

stderr.log

분석

  • 오~ System.out.println으로 찍힌 건 stdout하네용.
  • the runtime system에서 exception handler를 찾지 못하여 the runtime system이 종료되기 전에 stackTrace를 stderr로 출력하는구나!
  • the runtime system이 terminated되었으므로 mehtod call 이후의 stdout은 보이지 않네요.

라는 걸 알 수 있습니다.

다음으로, handling하고 stackTrace를 찍는 경우를 보겠습니다.

2. Handling 후 e.printStackTrace

handler 바깥에 System.out.println을 두도록 하겠습니다.

public class Main {
    public static void main(String[] args) {
        System.out.println("exception throw method call 이전");
        try {
            throwException();
        } catch (CustomException e) {
            e.printStackTrace();
        }
        System.out.println("exception throw method call 이후");

    }

    private static void throwException() {
        throw new CustomException("익셉션 테스트");
    }
}

결과

stdout.log

stderr.log

분석

  • 이번엔 System.out.println이 2개 모두 출력됬네요. 핸들러가 있었고, 핸들러가 처리했기 때문에 다음으로 넘어갔던 것이죠.
  • e.printStackTrace()를 했는데, stderr.log에 남네요...? stackTrace는 stderr에 출력하는 걸 알 수 있습니다!!

오잉... 메서드를 보니 이미 답이?

한 번 메서드의 구현을 살펴보았습니다...

System class

public final class System {

    private static native void registerNatives();

    static {
        registerNatives();
    }

    /** Don't let anyone instantiate this class */
    private System() {
    }

    public static final InputStream in = null;
    public static final PrintStream out = null;
    public static final PrintStream err = null;

ㅎㅎ;in,out,err가 정의되어 있는 것을 보니

in ⇒ stdin

out ⇒ stdout

err ⇒ stderr

같네요 ㅎㅎ; 여태껏 System.out에서 out의 의미가 표준 출력하겠다. 라는 뜻이였습니다. 허허;

printStackTrace

public class Throwable implements Serializable {
    public void printStackTrace() {
          printStackTrace(System.err);
      }
{

홀리씻~ System.err를 input으로 받네요. System.err가 PrintStream Type인 것 보니 DataStream이라 해석해도 될 것 같네요...?(유닉스의 표준 스트림)

충격입니다. ㅎㅎ; 그래서 stderr.log로 출력됬던 것이군요!

마지막으로...

어떻게 자바에서 stdout, stderr를 하는지 설계를 해보고 테스트를 진행해보았습니다. 이로써 java에서 어떻게 출력을 사용하는지 알 수 있었죠.

그 다음으로 위에서 본 출력 테스트 설계 방식을 다른 로깅 라이브러리를 사용할 때 적용해볼 수도 있을 것 같습니다. 때에 따라 stderr로 출력하고 싶을 때도 있을 테니까요.

참고로 스프링 부트에서 기본 설정으로 사용하는 logback 라이브러리는 log level이 error더라도 stdout을 합니다. 위 방식으로 테스트를 진행했죠 ㅎㅎ

이제 어떻게 출력되는지 명확하네요~~ ㅎㅎ

반응형
Comments