openlang

원인을 잃지 않고 예외 감싸기

임포트 도구가 하위 수준 실패를 잡아 다른 예외로 바꾸고 나면 진단 로그에 남는 것은 new ImportFailure("Import failed") 하나뿐입니다. 호출자가 로컬 파일 정보를 볼 이유는 없습니다. 하지만 실패를 조사하는 사람에게는 실제로 무엇이 잘못됐는지가 필요합니다.

도메인 예외는 그대로 두고, 그 생성자에서 원래 실패를 Throwable의 원인으로 넘기면 됩니다. 자바는 공개 예외의 분류를 하위 수준 분류로 바꾸지 않고도 이 인과 관계를 이어 줍니다.

공개 응답은 도메인 분류와 일부러 고른 메시지를 씁니다. 문구를 getCause().getMessage()에서 가져와서는 안 됩니다. 원인에는 바로 우리가 감추려던 로컬 정보가 들어 있을 수 있기 때문입니다. 내부 진단에도 다루는 방침이 있어야 합니다. 예외 값을 전부 출력하라는 지시는 방침이라고 하기 어렵습니다.

진단 정보가 풍부해지면 접근 권한과 마스킹 규칙이 따라옵니다. 그 부담은 분명히 있습니다. 원인을 버리면 그 부담은 피하지만 두 단어짜리 로그로 조사해야 합니다. 저라면 마스킹 쪽을 감수하겠습니다.

이어지는 대화 3

서로의 근거를 따라
  1. 고유 링크

    확인은 두 번, 순서대로 해요. 먼저 래퍼에서 getCause()를 호출하면 원래 실패가 돌아오는지 봐요. 그게 확인되면 원인 메시지는 아예 읽지 않고 도메인 분류만으로 공개 응답을 만들어요.

    다음으로 원래 메시지에 /example/private/input.csv를 넣고, 응답에 그 경로가 빠져 있는지 확인해요. 여기까지가 응답 쪽이에요. 로그 항목은 필드를 따로 가진 다른 목적지라서, 이 테스트로는 그중 어떤 필드를 보여 줘도 되는지 알 수 없어요. 로깅 경로는 그 경로대로 다시 살펴봐야 해요.

  2. 고유 링크

    실패 하나에 대해 래퍼를 만드는 부분이랑 로깅 호출만 올려 줄래요? 원인을 붙인다고 로그에 저절로 뭔가 남지는 않아요. 그러니 로깅 줄부터 볼게요. 경로는 가짜로 넣고, 로그 항목과 공개 응답을 하나씩 확인해 봐요. 이 정도로 줄이면 정보가 어디서 사라지는지 보여요.

  3. 고유 링크

    Cocoa는 오래전에 NSUnderlyingErrorKey로 이 문제를 정리했습니다. 돌려주는 도메인 수준의 NSError는 그 키 아래 userInfo에 하위 오류를 담고, localizedDescription은 경고창을 읽는 사람을 위해 쓰며, 하위 오류는 의도적으로 기록하려는 쪽에서 계속 꺼내 볼 수 있습니다.

    다만 같은 주의가 필요합니다. userInfo 사전을 통째로 기록하는 것은 모든 예외 값을 출력하는 일의 Objective-C판이고, 숨기려던 파일 경로도 기꺼이 함께 찍어 줍니다.