프리코스 3주차 디버깅

Rookedsysc·2024년 11월 5일

발단

3주차 구현 요구사항 중에서 IllegalArgumentException을 필터링하고 User가 잘못 input한 경우에 대해서 다시 입력을 받으라는 요구사항이 있었다. 이전에 해봤던 방식대로 while문 안에 try-catch로 감싸고 Error만 발생시키고 다시 input을 받으러 가는 형식으로 구현을 했다.

그리고 TestCode를 돌렸을 때

에러가 무한히 반복되는 것을 볼 수 있다.

그래서 내가 뭔가 잘못이해하고 있는지 궁금해서 작년에 프리코스를 진행했던 분께 해당 내용에 대해서 물어봤다. 그런데 작년에 진행 했던 분은 while(true)를 반복하면서 try catch를 하는게 맞다고 하는 것이다.
그 사람의 코드를 찾아봤고 컨닝한거 양식 고백이 될지 모르겠지만 똑같이 적용해놓은 모습이 위와 같다. 그런데 그 사람의 코드는 되고 나는 안된다.

Stacktrace 비교

추측을 해봤을 때, IllegalArgumentException이 발생했을 때 Test의 특정 로직에서 해당 Exception을 감지하고 Application을 종료시켜주는 로직이 있을 것이라고 생각했다.

그래서 IllegalArgumentExceptioncatch하는 로직에 디버그 포인트를 걸어놓고 Exception을 비교해봤다.

호출하는 Depth가 조금 달라서 그렇지 별 다른 차이가 없어보인다.

Debugging

장장 5시간 가까이를 woowacourse-projects:mission-utils:1.2.0의 코드를 뒤져봤지만 이렇다할 해결책을 찾지 못했다.

해결

프로젝트 내에 있는 모든 catch(IllegalArgumentException) 코드를 제외한 catch block을 다 지우면 아래와 같은 코드가 무한루프를 돌지 않고 프로그램이 종료가 되게 된다.

원인 파악

    private <T> T read(final Supplier<T> supplier) {
        while (true) {
            try {
                return supplier.get();

            } catch (final IllegalArgumentException e) {
                consoleOutput.print(e.getMessage());
            } catch (final Exception e) {
                consoleOutput.print(e.getMessage());
                for(StackTraceElement st: e.getStackTrace()) {
                    consoleOutput.print(st.toString());
                }
                throw new RuntimeException(e);
            }
        }
    }

위와 같이 코드를 변경해보면 그 원인을 알 수 있는데 아래와 같은 에러 메시지가 출력된다.

구입금액을 입력해주세요.
[ERROR] 숫자로 파싱하는데 실패했습니다.
No line found
java.base/java.util.Scanner.nextLine(Scanner.java:1660)
camp.nextstep.edu.missionutils.Console.readLine(Console.java:12)
lotto.view.ConsoleInput.inputString(ConsoleInput.java:8)
lotto.LottoApp.lambdacreateLottoFactory$2(LottoApp.java:80) lotto.LottoApp.read(LottoApp.java:89) lotto.LottoApp.createLottoFactory(LottoApp.java:79) lotto.LottoApp.run(LottoApp.java:29) lotto.Application.main(Application.java:6) lotto.ApplicationTest.runMain(ApplicationTest.java:59) camp.nextstep.edu.missionutils.test.NsTest.run(NsTest.java:37) camp.nextstep.edu.missionutils.test.NsTest.runException(NsTest.java:45) lotto.ApplicationTest.lambda예외_테스트1(ApplicationTest.java:52)org.junit.jupiter.api.AssertTimeoutPreemptively.lambda1(ApplicationTest.java:52) org.junit.jupiter.api.AssertTimeoutPreemptively.lambdaassertTimeoutPreemptively0(AssertTimeoutPreemptively.java:48)org.junit.jupiter.api.AssertTimeoutPreemptively.lambda0(AssertTimeoutPreemptively.java:48) org.junit.jupiter.api.AssertTimeoutPreemptively.lambdasubmitTask3(AssertTimeoutPreemptively.java:95)java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)java.base/java.util.concurrent.ThreadPoolExecutor3(AssertTimeoutPreemptively.java:95) java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) java.base/java.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:642)
java.base/java.lang.Thread.run(Thread.java:1583)

원래 NoLineFound라는 메시지를 담고 있는 NoSuchElementException이 발생하면서 프로그램이 종료되야 하는건데 내가 해당 에러를 catch해서 무시해주고 있었으니 무한루프가 도는 것이었다.

Reference

프리코스 커뮤니티의 예찬님의 도움으로 알게되었습니다! 감사합니다.

0개의 댓글