일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- DesignPattern
- 스택
- 겨울카카오인턴
- Eclipse
- 로버트마틴
- 큐
- Pattern
- lambda calculus
- Spring
- exception
- Rails
- 파이썬
- 디자인패턴
- 자바
- Collection
- JavaScript
- Network
- JDBC
- tcp
- 함수형 프로그래밍
- Java
- functional programming
- Python
- javscript
- 람다 칼큘러스
- Collections
- solid
- 백준
- design-pattern
- 프로그래머스
- Today
- Total
개발자 노트
Exception handling - java의 Exception처리(이론) 본문
상위 주제
참고 자료
- clean code
- effective java
- oracle java docs
이번엔 exception이 무엇인지
exception을 어떻게 처리해야할 지를
말씀드려보겠습니다.
exception이란?
oracle에서 어떻게 정의하는지 보죠
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.
프로그램이 실행하는 중에 일반적인 흐름을 방해하는 이벤트를 의미합니다.
허허; 일반적인 흐름이 무엇일까요? 전 다음처럼 일반적인 흐름을 정의했습니다. 다음 상황을 가정해보죠
상황
divide함수를 정의했어요.
def divide(dividend, divisor):
return dividend/divisor
각자의 기대
caller 입장에선 divide에게 기대하는 것은 나누기 연산 값입니다.
divide 입장에서는 caller에게 기대하는 것은 나눗셈을 할 수 있도록 정상적인 값으 전달해주는 것이죠.
그래서 divide(1,10)
같은 연산은 제가 기대한대로 0.1을 반환해줍니다.
비정상 흐름
그런데 divide(1,0)을 호출했다면요? 이건 계산을 할 수가 없죠?
caller가 기대한대로 값을 전달해줄 수 없을 뿐더러, divide입장에서도 연산할 수 없는 값을 받았습니다.
다시 말해서 일반적인 흐름을 벗어났기 때문에 divide는 exception을 던질 수 밖에 없죠.
그래서 일반적인 흐름은 다음처럼 정의할 수 있을 것 같습니다. 기대한 결과를 전달받지 못하는 경우!
exception에 대해 어떤 조치를 취해야 할까?
그렇다면요, caller가 divide(1,0)을 호출해서 exception이 발생했다고 divide가 알려주어잖아요? caller 입장에선 어떤 조치를 취해야 할까요?
비유를 들어볼게요
편의점 아르바이트생
당신은 편의점 아르바이트생입니다. 손님이 담배를 달래용. 그런데 마침 담배가 다 떨어진겁니다 ㅠㅠ 이때 어떠한 조치를 취하시겠어요?
대응1. 옆 편의점에서 담배를 빌려온다.
옆 편의점에서는 그 담배가 남는다 하네용. 그래서 그 쪽으로부터 재고를 공급받아 손님에게 드렸습니다! 제가 맥도날드에서 일할 때 이런 일이 종종있긴 했어용
이건 최고의 대응이죠? 손님이 원하는 것을 드리고 돈을 벌었으니까요.
대응2. 점주에게 보고한다.
옆에 편의점도 담배가 없대요... 이 상황을 도저히 어떻게 대처할 지 모르겠습니다. 따라서 점주에게 이 상황을 잘 정리하여 전달해주는 것이죠. 그럼 뭐 점주가 잘 대응하리라 기대할 겁니다.
대응3. 아무것도 하지 않는다.
평소에 점주가 마음에 안든거에요. 손님에겐 없어요~ 만 말하고, 점주에게는 말을하지 않는거죠. 점주가 나중에 직접 확인하여 재고를 채우기 전까진 담배로 인한 수익이 발생하지 않겠죠 ㅠㅠ
컴퓨터에서도 동일합니다.
대응 1은 recovery를 한 것이고
대응 2는 다음 caller가 잘 처리할 수 있도록 exception translation 후 다시 throw한 것이며
대응 3은 exception을 catch하지 않는 것이라 볼 수 있죠.
작동과정
많이 사용해보셨을 테니까 문법은 넘어가고 작동과정만 설명드리겠습니다.
https://docs.oracle.com/javase/tutorial/essential/exceptions/definition.html
- method에서 error가 발생했을 때 Method는 exception object를 생성한 뒤에 runtime system에 넘깁니다.
- 이것을 throwing an exception 이라 표현하죠.
- runtime system은 exception object를 처리할 무엇가를 찾습니다. 바로 이 무언가는 methods의 정렬된 리스트라고 볼 수 있죠. 바로 call stack이요.
- call stack의 method에서 exception을 처리할 수 있는 code block을 찾습니다.
이 code block을 exception handler라고 부르죠. - method를 call 했던 순서의 역순으로 exception handler를 찾구요, 찾았다면 그 handler에게 에러 처리를 넘깁니다. 적절한 exception handler인 지는 exception type으로 찾죠.
exception handler가 선택된 것을 catch the exception이라고 부릅니다. - 만약에 runtime system이 call stack에서 적절한 exception handler를 찾지 못했다면 runtime system은 terminates됩니다.
자바에서 제공해주는 도구들
checked exception - unchecked exception
checked exception은 메서드를 호출하면 특정 타입의 exception을 던진다고 알려줘야하는 exception입니다. method signature중 하나죠. 그리고 이 method를 호출한 쪽은 해당 exception을 catch하든지, exception을 던지고 signature로 표시를 해주어야 합니다.
이에 반면 unchecked exception은 exception을 표기해주지 않아도 됩니다. 일반 exception이라 볼 수 있죠.
type
어떤 종류의 exception인지를 정의할 수 있습니다. exception hadler쪽에선 그 종류에 따라 다르게 에러를 catch하여 처리할 수 있도록 type을 catch하죠.
다음으로는 clean code, effective java에서 눈여겨 본 스킬을 언급해보겠습니다.
clean code
1.exception class는 caller의 요구사항에 맞추어 정의
현업에서는 exception class 1개만 정의하고 메세지만 바꾸는 형식을 사용했는데요, 어색하게 느껴지는 겁니당. 그래서 타입을 정의해야지~ 했는데, 도대체 어떤 기준으로 작성해야할 지 애매하더라구요. 그런데 클린코드의 이부분을 보고 확! 와닿았습니다.
결국 메서드를 call한 클라이언트가 exception 종류별로 handling하라고 class를 정의하는거니까요!
effective java
1.다시 던질 땐 catch후 error를 담아 던져라.
catch (CustomException e) {
throw new CustomException(message, e);
}
하하; 제가 이것을 하지 않아서 문제가 발생했었습니다. 단지 메세지만 던진다면 caused By가 사라지거든요. 다시 말해서 error stack trace가 잘립니다;;
2.다시 던질 땐 log를 찍을 필요없다.
catch (CustomException e) {
log.info("error 발생", e);
throw new CustomException(message, e);
}
이게 꽤 이상한 코드입니다.. 어차피 exception을 담아 던졌다면 맨 마지막의 error handling하는 곳의 stack trace에서 메세지를 확인할 수 있습니다.그 곳에서 log를 찍으면 되는 것이죠.
결국 두 번 출력하는거에요; stack trace속에 메세지가 있다면 흐름도 파악 알 수 있는데 이건 달랑 메세지 하나 출력되는 것이죠. 끔찍합니다.
이론 정리는 이정도로 마무리하구요, 다음엔 코드를 바탕으로 리팩토링하고 고민해보는 시간을 가지도록 하겠습니다.
'이것저것' 카테고리의 다른 글
Logging AOP 구현 - 1 (0) | 2021.09.19 |
---|---|
java - exception 처리 (코드) (0) | 2021.08.08 |
exception handling 여정 - Redirection (0) | 2021.07.03 |
키보드로 입력한 값이 콘솔로 출력될 때까지 (0) | 2021.07.03 |
Exception handling 여정 (0) | 2021.07.03 |