April 24, 2026
좋은 오류 메시지가 시간을 절약하다
(이 글은 영어로 또 있어요.)
개발자는 자주 오류를 보고 오류의 메시지를 읽어야 해요. 그래서 나쁜 오류 메시지 시간 많이 필요할 수 있잖아요. 오류의 안내가 없으면 사람들 추측하기 시작해야 돼요.
나쁜 오류 예: - 프로세스는 비정상 종료 코드만 하하지마! 제발, 표준 에러에 오류를 설명해주세요! - 파일을 못 찾았다고요. 끝. 무슨 파일!, 무슨 파일 못 차았어요? - 등
근데 진짜 좋은 예도 있어요: Babashka HTTP client.
REPL에서:
(http/post "http://gamlor.info/nowhere"
{:headers {"Authorization" "Bearer open-sesame"}})
=> Execution error (ExceptionInfo) at babashka.http-client.interceptors/fn (interceptors.clj:251).
Exceptional status code: 404근데, 오류 정보를 더 잘 살펴보면 정보 많이 생기다:
REPL에서:
*e
=>
#error
{:cause "Exceptional status code: 404", ; 우류 매시지
:data {:status 404, ; HTTP 대답의 코드
:body "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\"> ; HTTP 대답의 본문
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
",
:version :http2, ; 어느 HTTP 버전
:headers {":status" "404", ; HTTP 대답의 헤더
"content-length" "315",
"content-type" "text/html; charset=iso-8859-1",
"date" "Mon, 20 Apr 2026 19:24:09 GMT",
"server" "Apache"},
:uri #object [java.net.URI 0x5a3fadf4 "https://gamlor.info/nowhere"], ; 어느 URI를 사용샜어요. HTTP 리디렉션이 URI를 바꿀 수 있어요.
:request {:headers {:accept "*/*", ; HTTP 요청의 헤더
:accept-encoding ["gzip" "deflate"],
:user-agent "babashka.http-client/0.4.23",
"Authorization" "Bearer open sesame"},
:uri #object [java.net.URI 0x5a3fadf4 "http://gamlor.info/nowhere"], ; 어느 URI 요청 시작했기. HTTP 리디렉션이 URI를 바꿀 수 있어요.
:method :get}}, ; 어느 HTTP 동사
:via [{:type clojure.lang.ExceptionInfo, ; 중첩된 Exception 정보. 이 예에 중첩 안 됬어요.
:message "Exceptional status code: 404",
:data {:status 404,
:body "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
",
:version :http2,
:headers {":status" "404",
"content-length" "315",
"content-type" "text/html; charset=iso-8859-1",
"date" "Mon, 20 Apr 2026 19:24:09 GMT",
"server" "Apache"},
:uri #object [java.net.URI 0x5a3fadf4 "https://gamlor.info/nowhere"],
:request {:headers {:accept "*/*",
:accept-encoding ["gzip" "deflate"],
:user-agent "babashka.http-client/0.4.23",
"Authorization" "Bearer open sesame"},
:uri #object [java.net.URI 0x5a3fadf4 "https://gamlor.info/nowhere"],
:method :get}},
:at [babashka.http_client.interceptors$fn__11817 invokeStatic "interceptors.clj" 251]}], ; 스택 트레이스
:trace [[babashka.http_client.interceptors$fn__11817 invokeStatic "interceptors.clj" 251]
[babashka.http_client.interceptors$fn__11817 invoke "interceptors.clj" 246]
[babashka.http_client.internal$then invokeStatic "internal.clj" 296]
[babashka.http_client.internal$then invoke "internal.clj" 290]
[babashka.http_client.internal$request$fn__11936 invoke "internal.clj" 329]
[clojure.lang.PersistentList reduce "PersistentList.java" 146]
[clojure.core$reduce invokeStatic "core.clj" 6964]
[clojure.core$reduce invoke "core.clj" 6947]
[babashka.http_client.internal$request invokeStatic "internal.clj" 327]
[babashka.http_client.internal$request invoke "internal.clj" 303]
[babashka.http_client$request invokeStatic "http_client.clj" 125]
[babashka.http_client$request invoke "http_client.clj" 100]
[babashka.http_client$get invokeStatic "http_client.clj" 132]
[babashka.http_client$get invoke "http_client.clj" 127]
[user$eval15344 invokeStatic "form-init8076736335536322939.clj" 1]
[user$eval15344 invoke "form-init8076736335536322939.clj" 1]
...이 오류는 개발자의 꿈 이예요. 정보가 다 있어요:
혹시 HTTP 대답의 본문나 헤더 오류가 있어요? 정보 있어요.
혹시 잘못된 HTTP 헤더 보냈어요? 정보 있어요.
혹시 HTTP 리디렉션이 URI를 바꿨어요? 정보 있어요.
어떻게 이 오류에 도착했어요? 정보 있어요.
그럼, 다음에는 우리가 오류를 쓰면 Babashka HTTP client 기억하고 정보를 충분히 추가하자!
