- Go의
if err!= nil 반복은 수년간 사용자 설문에서 큰 불만으로 남아 있었지만, Go 팀은 오류 처리 문법 변경을 당분간 추진하지 않기로 함
- 2018년
check/handle, 2019년 try, 2024년 ? 제안은 모두 충분한 합의를 얻지 못했고, 특히 try는 숨겨진 제어 흐름 때문에 강한 반발을 받음
- Go 제안 절차상 일반적 합의가 없으면 제안은 보통 거절되며, Google의 Go 팀 고참 구성원들 사이에서도 현재 최선의 방향에 대한 만장일치가 없음
- 현상 유지 쪽은 Go가 이미 작동하는 오류 처리 방식을 갖고 있고, 새 문법이 코드 스타일·디버깅·문서·도구·기존 코드에 큰 비용을 만든다고 봄
- Go 팀은 오류 처리 구문을 주된 대상으로 하는 열린 제안과 신규 제안을 추가 조사 없이 닫고, 더 명확한 문제 인식이 생기기 전까지 다른 개선 기회에 집중함
if err != nil이 만든 오래된 불만
- Go에서 가장 오래 지속된 불만 중 하나는 오류 처리 코드의 장황함임
- 대표 패턴은 다음 형태임
x, err := call()
if err != nil {
// handle err
}
- API 호출이 많고 오류를 단순히 반환하는 프로그램에서는
if err != nil이 코드의 나머지 부분을 압도할 수 있음
- 예시 함수
printSum에서는 함수 본문 10줄 중 실제 작업처럼 보이는 줄이 호출·출력·반환을 포함해 4줄이고, 나머지 6줄은 잡음처럼 보임
- Go 연례 사용자 설문에서 오류 처리는 수년간 최상위 불만이었고, 한동안 제네릭 부재가 이를 앞섰지만 Go가 제네릭을 지원한 뒤 다시 오류 처리가 최상위 불만으로 돌아옴
세 차례의 주요 문법 제안
- Go 팀의 첫 명시적 시도는 2018년 Go 2 노력의 일부로 Russ Cox가 문제를 공식 정리하면서 시작됨
- Marcel van Lohuizen의 초안 설계는
check와 handle 메커니즘을 기반으로 했고, 다른 언어 접근과 대안 분석도 포함함
func printSum(a, b string) error {
handle err { return err }
x := check strconv.Atoi(a)
y := check strconv.Atoi(b)
fmt.Println("result:", x + y)
return nil
}
check/handle 접근은 너무 복잡하다고 판단됐고, 2019년에는 더 단순한 try 제안이 나옴
check 유사 키워드는 try 내장 함수가 됨
handle 부분은 빠짐
- 기존 오류 처리 코드를
try 방식으로 바꾸는 도구 tryhard가 만들어짐
- 관련 GitHub 이슈는 900개에 가까운 댓글로 격렬하게 논의됨
func printSum(a, b string) error {
// use a defer statement to augment errors before returning
x := try(strconv.Atoi(a))
y := try(strconv.Atoi(b))
fmt.Println("result:", x + y)
return nil
}
try는 오류가 나면 둘러싼 함수에서 반환하는 방식으로 제어 흐름에 영향을 줬고, 깊게 중첩된 표현식 안에서도 반환이 일어날 수 있어 많은 사용자에게 받아들이기 어려웠음
- 당시에는 새 키워드를 도입하는 편이 나았을 수 있으며, 현재는
go.mod 파일과 파일별 지시어로 언어 버전을 세밀하게 제어할 수 있음
- Jimmy Frasche의 최근 제안은 원래
check/handle 설계로 돌아가면서 일부 단점을 다루는 방향을 따름
try 이후의 절차 반성과 ? 제안
func printSum(a, b string) error {
x := strconv.Atoi(a) ?
y := strconv.Atoi(b) ?
fmt.Println("result:", x + y)
return nil
}
- 이 제안도 빠르게 많은 댓글과 선호 기반의 세부 수정 제안으로 넘쳐났고, Ian은 제안을 닫은 뒤 내용을 discussion으로 옮김
- 약간 수정된 버전은 조금 더 긍정적인 반응을 얻었지만 폭넓은 지지는 얻지 못함
왜 지금은 멈추려 하는가
- Go 팀은 예측 가능한 미래에는 오류 처리의 구문 문제를 해결하려는 시도를 멈춰야 한다고 판단함
- 제안 절차는 이 결정을 뒷받침함
- 제안 절차의 목표는 적시에 결과에 대한 일반적 합의에 도달하는 것임
- 이슈 트래커 논의에서 일반적 합의를 찾지 못하면 보통 제안은 거절됨
- 합의도 다음 단계도 찾지 못하면 Go architects가 논의를 검토하고 내부 합의를 시도함
- 어떤 오류 처리 제안도 합의에 가까운 지지를 얻지 못했고, 모두 거절됨
- Google의 Go 팀 고참 구성원들조차 현재 최선의 진행 방향에 대해 만장일치가 아니며, 강한 합의 없이는 합리적으로 진행할 수 없음
현상 유지와 변화의 논거
- 현상 유지 쪽에는 Go의 성숙도와 생태계 비용이라는 현실적인 이유가 있음
- Go가 초기에 오류 처리 전용 문법 설탕을 도입했다면 지금은 논쟁이 적었겠지만, Go는 15년이 지났고 이미 작동하는 오류 처리 방식을 갖고 있음
- 지금 완벽한 해결책을 찾더라도 변화 지지자 대신 현상 유지 선호자가 불만을 갖는 상황으로 바뀔 수 있음
- 제네릭은 사용자가 반드시 직접 쓰지 않아도 되지만, 오류 처리 새 문법은 쓰지 않으면 코드가 비관용적으로 보일 수 있어 사실상 대부분이 사용해야 함
- 같은 일을 하는 여러 방법을 제공하지 않는다는 Go 설계 규칙과도 새 문법 추가는 충돌할 수 있음
:= 짧은 변수 선언의 재선언 기능은 오류 처리 때문에 생긴 문제를 해결하기 위해 도입됐음
- 재선언이 없었다면 연속 오류 검사마다 서로 다른
err 이름이나 별도 변수 선언이 필요했음
- 당시 오류 처리에 더 나은 문법 지원이 있었다면 재선언 규칙과 관련 복잡성도 필요 없었을 수 있음
- 오류를 제대로 보강해 처리하면 단순 반복의 비중은 줄어듦
- 사용자 설문에는 오류에 스택 추적이 없다는 반복 의견이 있음
- 보조 함수로 보강된 오류를 만들어 반환하는 방식이 가능함
fmt.Errorf("invalid integer: %q", a)처럼 입력값 정보를 붙이면 보일러플레이트의 상대적 비중이 작아짐
- 표준 라이브러리 기능도 오류 처리 보일러플레이트를 줄일 수 있음
- 쓰기, 읽기, 디버깅은 서로 다른 활동임
- 반복 오류 검사를 작성하는 일은 지루하지만, IDE와 LLM 보조 코드 완성이 기본 오류 검사를 쉽게 생성할 수 있음
- 읽을 때 장황함이 더 두드러지며, IDE가 오류 처리 코드를 숨기는 토글을 제공할 수 있음
- 디버깅할 때는 이미 별도
if 문이 있으면 println 추가나 중단점 설정이 쉬움
check, try, ? 뒤에 오류 처리가 숨으면 보통 if 문으로 되돌려야 할 수 있고, 이 과정이 디버깅을 복잡하게 하거나 미묘한 버그를 만들 수 있음
- 언어 변경에는 설계·구현뿐 아니라 기존 코드 변경, 문서 업데이트, 도구 조정 비용이 뒤따름
- Go 팀은 상대적으로 작고, 처리해야 할 다른 우선순위도 많음
- 우선순위와 팀 규모는 바뀔 수 있음
- Google Cloud Next 2025에서 Go 팀이 만난 일부 Go 사용자들은 더 나은 오류 처리를 위해 언어를 바꾸지 말아야 한다고 강하게 말함
- 이들은 다른 언어에서 막 넘어올 때 Go의 전용 오류 처리 문법 부재가 가장 눈에 띄지만, 더 관용적인 Go 코드를 쓰게 되면 덜 중요해진다고 말함
- 이 표본은 대표성을 갖기에는 충분히 크지 않지만, GitHub에서 보는 사람들과 다른 집단일 수 있음
- 변화 지지 논거도 여전히 유효함
- 더 나은 오류 처리 지원의 부재는 사용자 설문의 최상위 불만으로 남아 있음
- 문자 수를 줄이는 데만 집중하는 접근은 잘못된 방향일 수 있음
- 기본 오류 처리를 키워드로 눈에 잘 띄게 만들면서
err != nil 보일러플레이트를 제거하면 코드 리뷰에서 오류 처리 여부를 더 쉽게 확인할 수 있음
- 문제의 핵심이 단순 문법 장황함인지, API와 개발자·최종 사용자에게 의미 있는 오류를 구성하는 좋은 오류 처리의 장황함인지는 아직 충분히 알지 못함
Go 팀의 결정
- 지금까지 오류 처리를 다루려는 어떤 시도도 충분한 추진력을 얻지 못함
- Go 팀은 공유된 문제 이해가 부족하고, 애초에 문제가 있는지에 대해서도 모두가 동의하지 않는다고 판단함
- 예측 가능한 미래에는 오류 처리를 위한 문법적 언어 변경을 추진하지 않음
- 오류 처리 문법을 주된 대상으로 하는 열린 제안과 앞으로 들어오는 제안은 추가 조사 없이 닫을 예정임
- 커뮤니티의 탐색과 토론은 오류 처리 문법 변경으로 이어지지는 않았지만, Go 언어와 절차의 여러 개선으로 이어졌음