[Java] 표준 입출력 리다이렉션

조애옹·2025년 6월 2일

🔍 개념 정리

스트림 종류클래스기본 목적
입력System.in키보드 입력
출력System.out콘솔 출력
에러 출력System.err콘솔 에러 메시지

리다이렉션(Redirection) 이란, 이 스트림의 흐름을 다른 방향(예: 파일) 으로 바꾸는 것

  • System.setIn(InputStream) → 입력을 다른 곳(파일 등)으로
  • System.setOut(PrintStream) → 출력을 콘솔 대신 파일 등으로
  • System.setErr(PrintStream) → 에러 출력을 파일 등으로

💻 예제: 표준 입출력 리다이렉션으로 테스트하기

TestUtil.java

public class TestUtil {
    private static final PrintStream ORIGINAL_OUT = System.out;

    /**
     * 주어진 문자열을 기반으로 Scanner 객체를 생성하여 리턴
     * 테스트 중 입력값을 시뮬레이션할 때 사용
     *
     * @param input 테스트용 입력 문자열
     * @return 해당 입력을 읽을 수 있는 Scanner
     */
    public static Scanner genScanner(String input) {
        return new Scanner(input);
    }

    /**
     * System.out(표준 출력)을 ByteArrayOutputStream으로 리다이렉트
     * 이후 출력 내용을 문자열로 비교할 수 있음
     *
     * @return 리다이렉트된 ByteArrayOutputStream 객체
     */
    public static ByteArrayOutputStream setOutToByteArray() {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        System.setOut(new PrintStream(output, true));
        return output;
    }

    /**
     * 표준 출력 스트림을 원래대로 복구하고,
     * 테스트 중 사용된 ByteArrayOutputStream을 안전하게 닫음
     *
     * @param output 리다이렉트된 출력 스트림
     */
    public static void clearSetOutToByteArray(ByteArrayOutputStream output) {
        System.setOut(ORIGINAL_OUT);
        try {
            output.close();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

QuoteApp.java

public class QuoteApp {
    private static int nextId = 1;

    /**
     * 명언 등록 메서드
     * 사용자로부터 명언 내용과 작가 이름을 입력받아 지정된 형식으로 출력
     *
     * 출력 형식: [id] / [작가명] / [내용]
     *
     * @param scanner 사용자 입력을 처리할 Scanner 객체
     */
    public static void registerQuote(Scanner scanner) {
        String content = scanner.nextLine();
        String author = scanner.nextLine();
        
        System.out.printf("%d / %s / %s%n", nextId++, author, content);
    }
}

QuoteAppTest.java

public class QuoteAppTest {

    @Test
    @DisplayName("명언 등록시 올바르게 출력된다")
    void testRegisterQuote() {
        // given: 사용자 입력을 시뮬레이션한 Scanner 객체 생성
        Scanner scanner = TestUtil.genScanner("""
                죽음을 두려워 말라.
                유관순
                """.stripIndent().trim());

        // 표준 출력을 메모리 스트림으로 리다이렉트
        ByteArrayOutputStream out = TestUtil.setOutToByteArray();

        // when: 명언 등록 로직 실행
        QuoteApp.registerQuote(scanner);

        // then: 출력 결과를 문자열로 추출 후 검증
        String printed = out.toString().trim();
        TestUtil.clearSetOutToByteArray(out); // 리다이렉션 복구 및 스트림 정리

        // 예상된 형식과 실제 출력이 일치하는지 확인
        assertThat(printed).isEqualTo("1 / 유관순 / 죽음을 두려워 말라.");
    }
}
profile
아자잣

0개의 댓글