////
Search
9️⃣

9장. 버그와의 동거

이 장에서 다룰 내용

예외 처리 모범 사례
버그와의 동거
의도적 예외 처리
디버깅 방지
고무 오리 디버깅
소프트웨어 개발은 프로그램의 본질적인 예측 불가능성 때문에 굉장히 복잡하다.
이것이 튜링 기계의 본질이며 따라서 튜링 기계의 특성상 버그를 피할 수 없다.
따라서 버그가 없는 프로그램을 만들기란 불가능하며 소프트웨어 개발에 착수하기 전에 먼저 이 사실을 받아들이는 것이 여러분의 일을 더 쉽게 만들 것이다.

1. 버그를 수정하지 마라

어느정도 규모가 있는 개발팀이라면 어떤 버그를 수정할 것인지 결정하기 위한 트리아지 프로세스를 가지고 있어야 한다.
트리아지라는 용어는 1차대전 당시 의료진이 아직 생존 가능성이 높은 사람에게 제한된 자원을 할당했던 결정에서 유래되었다.
버그의 우선순위와 심각성을 판단하여 무엇부터 수정해야할 지 결정하라.
이 둘의 적절한 임계값을 설정하여 그 밑의 버그는 후순위로 미뤄두어야 한다.
우선순위
심각성
실제 의미
높음
높음
즉시 고쳐라
높음
낮음
사장이 수정을 원한다.
낮음
높음
인턴에게 수정하라고 지시하라.
낮음
낮음
고치지 않는다. 사무실에 다른 할 일이 없지 않는 이상 절대 고치지 마라. 할 일이 없더라도 인턴이 고치도록 둬라.

2. 오류에 대한 두려움

개발자는 본능적으로 모든 오류를 버그로 간주하고 지속적이고 끈질기게 제거하려 노력한다.
이런 식의 추론은 보통 알 수 없는 오류 상황으로 이어진다. 이는 무언가가 잘못되었을 때 개발자가 그것이 정말로 오류인지 아닌지 이해하는 것에 신경쓰지 않기 때문이다.
모든 오류를 동일한 방식으로 처리하려 하는 것을 해결하는 방법은 오류를 상태 중 하나로 생각하는 것이다.

1. 예외에 대한 진실

특정한 상태 중 하나이나 예상치 못했던 것이 뭘까? 바로 예외다.
예외는 정의되지 않는 상태 문제를 해결하는 방법 중 하나로 일반적인 흐름에서 제어되지 않는다.
예외가 발생하더라도 앱을 손상된 상태로 놔두어서는 안 된다.

2. 예외를 잡아내지 마라

예외를 무시하는 코드를 작성하는 경우가 많다.
예외를 두려워하지 마라. 예외가 있다는 것만으로 어딘가 충돌이 발생했음을 알 수 있다. 비어있는 catch 블록이 불러울 문제를 두려워하라.
예외 처리의 첫 번째 규칙은 예외를 처리하지 않는 것이다. 두 번째 규칙은 IndexOutOfRangeException이다.
이 예외가 잘못된 동작때문에 발생하는 것이라면 수정하라.
이미 알고 있는 이유 때문이라면 그것을 예외 처리 문에 작성하라.
코드의 어느 지점에서 예외가 발생할 가능성이 있을 때마다 스스로에게 이 예외를 위해 계획된 특정 수단이 있는가? 아니면 충돌을 피하기만 해도 될까?라고 질문하라.
후자의 경우라면 예외를 처리할 필요가 없을 수 있고 되려 독이 될 수 있다.
모든 예외를 잡아내기 위한 catch 블록은 로깅과 같은 일반적인 목적으로 세상에 존재하는 모든 예외를 정말로 잡아내야할 때 사용해야 한다.

3. 예외 복원성

코드에 충돌이 발생할 경우에도 예외 처리 없이 올바르게 동작해야 한다.
예외가 계속 발생하더라도 잘 작동하는 흐름을 설계해야 하며, 오염된 상태가 전이되지 않도록 만들어야 한다.
그 이유는 예외가 불가피하기 때문이다.

4. 트랜잭션이 없는 복원력

트랜잭션을 사용할 수 없는 경우, 데이터 정리 루틴을 추가하는 등의 행위를 통해 복원력을 만들 수 있다.

5. 예외와 오류

예외가 오류라고 주장할 수 있으며 이것이 사실일 수도 있다. 하지만 그렇다고 모든 오류가 예외는 아니다.

3. 디버깅하지 마라

디버깅은 항공학에서 항공기 결함을 식별하는 과정에서 사용되던 용어였다.
최근 디버깅은 대부분 디버거에서 프로그램을 실행하고 중단점을 두고 코드를 단계별로 추적하며 프로그램의 상태를 조사하는 것을 의미한다.
디버거는 매우 편리하지만 최고의 도구는 아닌데, 문제의 근본적인 원인을 파악하는데 더 시간이 걸릴 수 있기 때문이다.
항상 모든 상황에서 프로그램을 디버깅할 수 있는 것은 아니며 코드가 실행중인 환경에 접근하지 못할 수도 있기 때문이다.

1. printf() 디버깅

문제를 찾기 위해 프로그램 내부에 콘솔 출력 라인을 삽입하는 것은 오래된 관행이다.

2. 덤프 다이빙

단계별 디버깅을 위한 또 다른 방법은 크래시 덤프를 검사하는 것이다.
크래시 덤프는 프로그램의 메모리 공간의 스냅샷 내용을 담고 있는 파일을 말한다. 유닉스 시스템에선 코어 덤프라고 말하기도 한다.

3. 고무 오리 디버깅

이는 책상 위에 앉아있는 고무 오리에게 문제를 말해가며 해결하는 방법이다.
문제를 말로 표현하면서 문제를 더 확실하게 재구성하게 되고 마법처럼 문제에 대한 해결책을 찾을 수 있게될 것이다.

4. 요약

중요하지 않은 버그를 수정하기 위해 리소스를 낭비하지 않으려면 버그에 우선순위를 정해야 한다.
해당 사례에 대해 계획적이고 의도적인 대응 방안이 있는 경우에만 예외를 포착하라. 그렇지 않으면 잡지 마라.
충돌을 사후에 방지하는 대신 먼저 충돌을 견딜 수 있는 예외 복원 코드를 작성하라.
오류가 일반적이거나 예상되는 경우에는 예외 대신 결과 반환 코드나 enum을 사용하라.
투박한 단계별 디버깅보다 더 빠르게 문제를 확인하기 위해 프레임워크에서 제공하는 추적 기능을 사용하라.
사용 가능한 다른 방법이 없을 경우 프로덕션에서 실행 중인 코드의 문제를 분석하기 위해 크래쉬 덤프 분석을 사용하라.
웹 사이트의 임시 작성글을 고무 오리 디버깅 도구로 사용하고 그동안 무엇을 시도했는지 자문하라.