티스토리 뷰
복구 가능성
소프트웨어에 대해 생각할 때, 특정 오류가 발생한 경우, 복구할 수 있는 현실적인 방법이 있는지 생각해야 하는 경우가 많다. 복구할 수 있는 오류와 복구할 수 없는 오류를 상황에 따라 어떻게 달라지는지 살펴보자. 즉, 오류가 발생했을 때 무엇을 할 것인지 결정하기 위해서는 자신의 코드가 어떻게 사용될지 신증하게 생각해야 한다.
복구 가능한 오류
많은 소프트웨어 오류는 치명적이지 않으며, 오류가 발생하더라도 사용자는 알아채지 못하도록 적절하게 처리한다면 작동을 계속할 수 있는 합리적인 방법이 있다.
- 네트워크 오류: 자신의 코드가 의존하는 서비스에 연결할 수 없는 경우, 몇 초 동안 기다렸다가 다시 시도하거나, 그 코드가 사용자의 장치에서 실행되는 경우라면 사용자에게 네트워크 연결을 확인하도록 요청하는 것이 최상이다.
- 중요하지 않은 작업 오류: 예를 들어 서비스 사용에 대한 어떤 통계를 기록하는 부분에서 오류가 발생한다면 실행을 계속해도 무방할 것이다.
일반적으로 시스템 외부의 무언가에 의해 야기되는 오류에 대해서는 대부분 시스템 전체가 표나지 않고 적절하게 처리하기 위해 노력해야 한다. 왜냐하면 이런 오류는 일어날 것이라고 적극적으로 예상해야 하는 오류이기 때문인데, 예를 들어 외부 시스템과 네트워크가 다운되고 파일이 손상되는 경우다.
복구할 수 없는 오류
오류가 발생하고 시스템이 오류를 복구할 수 있는 합리적인 방법이 없을 때다. 이러한 현상은 프로그래밍 오류 때문에 발생할 때가 많은데 이 경우는 개발자가 코드의 어느 부분에서 뭔가를 망쳐놓은 것이다.
예를 들면 아래와 같다.
- 코드와 함께 추가되어야 하는 리소스가 없다.
- 잘못된 입력 인수로 호출
- 일부 필요한 상태를 사전에 초기화하지 않음
오류를 복구할 수 있는 방법이 없다면, 유일하게 코드가 할 수 있는 합리적인 방법은 피해를 최소화하고 개발자가 문제를 발견하고 해결한 가능성을 최대화하는 것이다.
견고성 VS 실패
오류가 발생하면 다음 중 하나를 선택해야 한다.
- 더 높은 코드 계층이 오류를 처리하게 하거나, 전체 프로그램의 작동을 멈추게 한다.
- 오류를 처리하고 계속 진행한다.
신속하게 실패하라
신속하게 실패하기는 가능한 한 문제의 실제 발생 지점으로부터 가까운 곳에서 오류를 나타내는 것이다. 복구할 수 있는 오류의 경우 호출하는 쪽에서 오류로부터 안전하게 복구할 수 있는 기회를 최대한으로 제공하고, 복구할 수 없는 오류의 경우 개발자가 문제를 신속하게 파악하고 해결할 수 있는 기회를 최대한 제공한다. 두 경우 모두 소프트웨어가 의도치 않게 잠재적으로 위험한 상태가 되는 것을 방지한다.
만약 오류가 발생했을 때 바로 실패나 오류를 보여주지 않으면 문제가 발생할 때, 디버그하기 어려울 뿐만 아니라 코드가 제대로 작동하지 않거나 잠재적으로 문제를 일으킬 수 있다.
요란하게 실패하라
요란한 실패를 간단하게 표현하자면 오류가 발생하는데도 불구하고 아무도 모르는 상황을 막고자 하는 것이다. 이를 위한 가장 명백한 방법은 예외를 발생해 프로그램이 중단되게 하는 것이다. 코드가 실패할 때 신속하고, 요란하게 오류를 나타내면 개발 도중이나 테스트하는 동안에 버그가 발견될 가능성이 크다. 그렇지 않더라도 배포된 후에 오류 보고를 보기 시작할 것이고 보고 내용으로부터 버그가 발생한 위치를 정확하게 알 수 있는 이점이 있다.
오류를 숨기지 않음
전체 소프트웨어의 동작을 멈추지 않도록 하기 위해 코드의 독립적이거나 중요하지 않은 부분을 분리하면 견고한 시스템을 구축할 수 있다. 독립적이지 않거나, 중요하거나, 낮은 계층에서 오류가 발생함에도 불구하고 계속 진행하면 소프트웨어가 의도한 대로 작동하지 않는 경우가 많다. 오류가 적절히 기록되거나 보고되지 않으면 개발팀이 문제를 인식하지 못할 수 있다.
기본값 반환
코드에 기본값을 두는 것이 유용할 경우가 있을 수 있지만, 오류를 처리할 때는 대부분의 경우 적합하지 않다. 잘못된 데이터로 시스템이 제대로 작동하지 못하게 만들고 오류가 나중에 이상한 방식으로 나타날 수 있기 때문에 신속한 실패와 요란한 실패의 원리를 위반하는 것이다.
아무것도 하지 않음
오류가 발생해도 아무것도 하지 않는 경우, 호출하는 쪽에서는 코드에서 작업이 의도한대로 완료되었다고 가정하기 때문에 바람직하지 않다. 이것은 코드가 하는 일에 대해 개발자가 가지고 있는 정신 모델과 코드가 실제로 수행하는 것 사이의 불일치를 일으킬 가능성이 매우 높다. 이로 인해 소프트웨어에서 예상과 벗어나는 동작과 버그가 발생할 수 있다.
오류 전달 방법
오류가 발생하면 일반적으로 더 높은 계층으로 오류를 알려야 한다.
- 명시적 방법: 코드를 직접 호출한 쪽에서 오류가 발생할 수 있음을 인지할 수 밖에 없도록 한다. 그것을 처리하든, 이전 호출자에게 전달하든, 아니면 그냥 무시하든 간에 어떻게 처리할지는 호출하는 쪽의 선택이다.
- 암시적 방법: 코드를 호출하는 쪽에 오류를 알리지만, 호출하는 쪽에서 그 오류를 신경쓰지 않아도 된다.
예외
예외는 일반적으로 충분한 기능을 가진 클래스로 구현된다. 보통 프로그래밍 언어는 즉시 사용할 수 있는 예외에 대한 클래스를 제공하지만 개발자들은 자신이 요구 사항에 따른 맞춤형 예외 처리를 위해 오류에 대한 정보를 자유롭게 정의하고 캡슐화할 수 있다.
자바는 검사 예외(checked exception)와 비검사 예외(unchecked exception)의 개념을 모두 가지고 있다. 예외를 지원하는 대부분의 주요 언어는 비검사 예외만 가지고 있으므로 자바 이외의 거의 모든 언어에서 예외라는 용어는 일반적으로 비검사 예외를 의미한다.
명시적 방법: 검사 예외(checked exception)
컴파일러는 검사 예외에 대해 호출하는 쪽에서 예외를 인지하도록 강제적으로 조치하는데, 호출하는 쪽에서는 예외 처리를 위한 코드를 작성하거나 자신의 함수 시그니처에 해당 예외 발생을 선언해야 한다. 따라서 검사 예외를 사용하는 것은 오류를 전달하기 위한 명시적인 방법이다.
암시적 방법: 비검사 예외(unchecked exception)
비검사 예외를 사용하면 다른 개발자들은 코드가 이 예외를 발생시킬 수 있다는 사실을 전혀 모를 수 있다. 따라서 비검사 예외는 오류가 발생할 수 있다는 것을 호출하는 쪽에서 인지하리라는 보장이 없기 때문에 오류를 암시적으로 알리는 방법이다.
컴파일러 경고를 무시하지 말라
컴파일러 경고는 어떤 식으로든 코드가 의심스러우면 표시를 하는데, 이것은 버그에 대한 조기 경고일 수 있다. 이러한 경고에 주의를 기울이면 코드베이스에 병합되기 훨씬 전에 코드로부터 프로그래밍 오류를 발견하고 제거할 수 있다.
요약
- 오류에는 크게 "시스템이 복구할 수 있는 오류"와 "시스템이 복구할 수 없는 오류" 두 가지 종류가 있다.
- 생성된 오류로부터 복구할 수 있는지 여부는 해당 코드를 호출하는 쪽에서만 알 수 있는 경우가 많다.
- 에러가 발생하면 신속하게 실패하는 것이 좋고, 에러를 복구할 수 없는 경우에는 요란하게 실패하는 것이 바람직하다.
- 오류를 숨기는 것은 바람직하지 않을 때가 많으며, 오류가 발생했다는 신호를 보내는 것이 바람직하다.
- 오류 전달 기법은 두 가지 범주로 나눌 수 있다.
- 명시적 방법: 코드 계약의 명확한 부분, 호출하는 쪽에서는 오류가 발생할 수 있음을 인지한다.
- 암시적 방법: 코드 계약의 세부 조항을 통해 오류에 대한 설명이 제공되거나 전혀 설명이 없을 수도 있다. 오류가 발생할 수 있다는 것을 호출하는 쪽에서 반드시 인지하는 것은 아니다.
Reference
톰 롱. 『좋은 코드, 나쁜 코드』. 제이펍, 2022.
'Book > 좋은 코드, 나쁜 코드' 카테고리의 다른 글
[좋은 코드, 나쁜 코드] 코드를 오용하기 어렵게 만들라 (0) | 2023.01.26 |
---|---|
[좋은 코드, 나쁜 코드] 가독성 높은 코드를 작성하라 (2) | 2022.12.30 |
[좋은 코드, 나쁜 코드] 다른 개발자와 코드 계약 (2) | 2022.12.21 |
[좋은 코드, 나쁜 코드] 추상화 계층 (0) | 2022.12.19 |
[좋은 코드, 나쁜 코드] 코드 품질 (0) | 2022.12.18 |
- Total
- Today
- Yesterday
- webflux
- mysql 8.0
- 인프런
- 자료구조
- MySQL
- Algorithm
- 스프링부트
- 파이썬
- 노마드
- 문자열
- spring boot
- kotlin
- 스프링 부트
- 데이터베이스
- 노마드코더
- 리팩토링
- 코테
- 구현
- 김영한
- leetcode
- 알고리즘
- 스프링
- 정렬
- 그리디
- 북클럽
- 릿코드
- 백준
- 코틀린
- Real MySQL
- Spring
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |