이 글은 골든래빗 《Tucker의 Go 언어 프로그래밍》의 23장 써머리입니다.
23장은 error와 관련된 내용들을 소개하고 있다. 어떤 프로그래밍언어든 error처리는 중요하니 책에 나온 내용과 간단한 예제를 추가해 리뷰할 예정이다.
- 23 에러 핸들링
- 23.1 에러 반환
- 23.2 에러 타입
- 23.3 패닉
23.1 에러 반환
책에서는 두 가지 형태의 예제로 에러 처리에 대해 설명하고 있는데 첫 번째는 file 관련된 내장 라이브러리들의 함수를 호출하면서 발생하는 에러를 처리하는 방식이고 두 번째는 개발자의 코드에서 목적에 맞게 에러처리하는 예제로 설명한다.
에러를 반환한다는 뜻은 크게 세 가지의 이점이 있는데
1. 프로그래머가 예상하지 못해 발생한 에러나 외부 라이브러리를 사용 시 발생한 에러를 로깅해 추후에 빠르게 보안할 수 있음
2. 버그 발생 시 프로그램이 종료되지 않고 계속 실행함 (선택적으로 죽이기도 함)
3. 프로그래머끼리 협업할 때 단위테스트가 없는 경우 에러가 발생해도 반환된 에러로 추적하기 쉬움
사실 1번과 3번은 프로그램을 개발한 개발자가 에러 메시지를 잘 만들어서 반환해야 의미가 있다.
본인은 그나마 실무에서 사용할만한 예제를 공유하고 싶어 redis라는 in-memory db를 외부 라이브러리를 사용해 connection pool을 만들고 에러처리하는 예제를 만들어 보겠다.
외부 라이브러리는 redigo를 사용할 것이고 공유한 링크를 클릭하면 설치 방법도 다 나와있어 좋다.
KISS 원칙을 따라 쉽고 간결하게 만들어보도록 하자!
막상 코딩하고 보니 너무 양이 많아서... 에러처리하는 곳만 살펴보겠다. ㅠㅠ;;
위 이미지는 예제 코드 폴더 구조이며, redis 폴더의 package는 module_cache다.
앞서 설명한 첫 번째 방법처럼 함수를 호출한 후 error type의 결과를 받아 처리하는 예제로 main 파일부터 살펴보면
redisPoolInit 함수의 반환형은 error type인 것을 볼 수 있고 main 함수에서 redisPoolInit 함수를 호출하는 부분을 어떻게 하냐인데 이런 것을 error handling이라 한다.
두 번째 방법으로 프로그래머가 생각한 에러 상황에 에러를 만들어 error handling 하는 방법이다.
위 코드를 설명하면 redis connection pool를 만들어 pool에서 conn을 하나씩 꺼내면서 추후에 close 하기 위해 connList에 push 한 후 ping 테스트를 한다. ping을 날린 후 결과가 error인 경우 에러 메시지를 개발자가 더 알기 쉽게 만들고 반복문을 멈춘다. initClean함수를 통해 생성한 conn 객체를 close 한다.
initClean함수에서도 conn 객체를 close 할 때 발생한 에러를 개발자가 알기 쉽도록 에러 메시지를 변경한다.
책에서는 내장 라이브러리인 errors package를 사용해 error를 다루는 다른 방식을 알려주지만 본인은 fmt.Errorf나 github.com/pkg/errors package의 errors를 사용하는 게 편한 것 같다. 보통은 함수를 호출한 후 발생한 에러에 내용을 추가하는 식으로 많이 하지만 에러가 발생하지 않을 상황에서도 개발자가 에러를 발생시킬 경우도 있고 에러가 발생한 callstack도 같이 보고 싶을 때가 있기 때문이다. callstack를 볼 때 많은 도움을 주는 pkg/errors package 사용하면 좋다.
23.2 에러 타입
본인은 이것을 사용해 본 경험이 거의 없다. 앞서 설명한 redis에 저장한 내용이 없어 nil이 나올 경우 redis.ErrNil로 타입을 확인할 수 있지만 이것 조차 사용하지 않기 때문에 필요성을 잘 모르겠어 pass...
우리에겐 만능 %#+v 포맷이 있기 때문!!!
23.3 패닉
본인처럼 JAVA나 JS를 좋아하는 개발자들은 Golang을 하면서 error handling이 너무 짜증 나고 귀찮은 경험을 했을 것 같다. 이럴 때 Golang에서 try catch 같은 것이 있는지 찾을 때 자주 나오는 게 panic과 recover다. 하지만 try catch처럼 panic과 recover를 쓰는 것은 그다지 좋지 않은 방법인 것 같다. 책에서는 panic을 이렇게 설명하는데
프로그램을 정상 진행하기 어려운 상황을 만났을 때
라고 한다. 간단한 예제를 통해 이해해 보자.
앞서 사용했던 예제에서 main 함수만 수정한 코드이다. panic을 성명하기 앞서 간단한 전제를 두면 웹 서버를 코딩한다 생각해 보자. 사용자들의 정보를 저장하기 위해 필요한 db를 초기화하지 못한 상태에서 웹 서버를 띄우면 어떻게 될까?
당연히 웹 서버를 띄운 의미가 없을 것이다. 이렇듯 프로그램을 정상 진행하기 어려울 때 panic을 사용하는 것이다.
recover는 panic이 발생했을 때 catch 해주는 역할을 하고 panic 함수 호출 시 파라미터로 넣은 내용을 반환한다. 꼭 필요하진 않지만 panic이 발생한 경우는 큰 문제임으로 recover가 있는 defer에 다른 사람들과 공유할 수 있는 메신저를 통해 알리는 로직을 개발하는 것이 좋다.
23장은 이것으로 마치겠다.
'Golang > Tucker' 카테고리의 다른 글
[묘공단] 5주차 (3) (0) | 2023.10.29 |
---|---|
[묘공단] 5주차 (2) (0) | 2023.10.29 |
[묘공단] 4주차 (2) | 2023.10.22 |
[묘공단] 3주차 (2) (1) | 2023.10.16 |
[묘공단] 3주차 (1) (2) | 2023.10.15 |