일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 게임
- mongoose
- 자료구조
- class
- MongoDB
- OCR
- TypeScript
- Sequelize
- cookie
- Bull
- MySQL
- JavaScript
- Nest.js
- game
- nestjs
- GIT
- Express
- react
- 정렬
- dfs
- 공룡게임
- nodejs
- flask
- jest
- Dinosaur
- AWS
- Queue
- typeORM
- Python
- Today
- Total
포시코딩
1월13일 - throw & try/catch 예외처리(Exception Handling) 본문
throw & try/catch 예외처리(Exception Handling)
개요
지금까지 프로젝트를 진행하며 애매하면 무조건 try/catch로 감싸고 봤는데
그러다보니 정작 중요하게 예외처리를 해야되는 상황에서는 그러지 못하는 상황이 발생했다.
단적인 예로 살펴보면 다음과 같다.
controller
class OrdersController {
ordersService = new OrdersService();
test = async (req, res) => {
console.log('controller 진입');
try {
const result = this.ordersService.test();
console.log('service 결과: ', result);
if (result) {
res.json({ result: '성공' });
} else{
res.json({ result: '실패 - service fail' });
}
} catch (err) {
console.log('controller에서 catch 잡음');
console.log('err: ', err);
res.json({ result: '실패 - controller 예외상황' });
}
}
}
service
class OrdersService {
test = () => {
console.log('service 진입');
try {
const check = -1;
if (check == -1) {
throw new Error('check가 -1이 나옴');
}
return true;
} catch (err) {
console.log('service에서 에러 발생');
console.log('err: ', err);
return false;
}
}
}
결과
문제 파악
모든 곳에서 try/catch를 쓰고있다보니 service에서 발생한 error 상황에 대해
service에서 바로 잡아버려 catch 안에서 return 값을 또 설정해 넘기는 상황이 발생했다.
이 때문에 service의 catch에서 return한 결과를 받은 controller는
그 값에 대해 if문을 만드는 등 분기가 더러워지는 모습을 볼 수 있다.
이에 대해서 애초에 에러 상황을 어떻게 발생시키고 그 에러를 어디서 받을지, 또한 에러를 받아 어떻게 처리할지 등에 대한
플로우를 생각하지 않고 설계했기 때문에 생긴 문제로 파악하여
문제점을 확인했다.
일단, 좀 찾아보니 내가 몰랐던 부분이 있었다.
1. 예외가 발생하면 JavaScript 인터프리터는 정상적인 프로그램 실행을 즉시 중단하고 가장 가까운 예외 처리기로 넘어간다.
그렇다면 위 상황의 service에서는 굳이 try/catch를 쓰지 않아도 됐을 것이다.
2. new Error()로 생성하는 에러는 객체이며 throw로 넘겨줬을 시 catch(err)에서 받는 err는 해당 에러이다.
또한 객체이므로 프로퍼티를 갖고 있는데, name, message, stack이 그에 해당한다.
throw new Error('check가 -1이 나옴');
위 에러에 대해 name, message, stack을 출력한 결과이다.
보면 stack이 평소에 보던 err를 그대로 출력한 결과와 같다는 걸 알 수 있고
우리가 필요한 정보에 대해 전달하려면 err.message가 더 적합하다는 사실 또한 알 수 있게 되었다.
해결방안
controller
class OrdersController {
ordersService = new OrdersService();
test = async (req, res) => {
console.log('controller 진입');
try {
const result = this.ordersService.test();
console.log('service 결과: ', result);
res.json({ result: '성공' });
} catch (err) {
console.log('controller에서 catch 잡음');
res.json({ result: `실패 - ${err.message}` });
}
}
}
service
class OrdersService {
test = () => {
console.log('service 진입');
const check = -1;
if (check == -1) {
throw new Error('check가 -1이 나옴');
}
return true;
}
}
결과
결과적으로 service에서 따로 try/catch를 쓰지 않고 발생한 예외 상황에 대해 controller로 넘겨주었고
controller에서도 if문 사용을 하지 않고 catch문을 통해 해당 예외에 대한 err.message 까지 전달받아
json을 통해 잘 전달한 것을 볼 수 있다.
만약 service에서 repository로 depth를 늘린다면 또 달라질 수 있겠지만
응용한다면 쉽게 적용 가능할 것으로 보인다.
일단 중요한건
불안정했던 에러 처리건들에 대해 이 방식을 통해 더 안전하게 관리할 수 있을것을 보이며
코드의 가시성도 한층 좋아졌다는 결과도 얻을 수 있었다.
https://github.com/9hezo/save_my_keyboard/issues/39
남은건 위 문제들을 실제로 갖고 있는 이전 팀프로젝트에 적용하는 것이다.
참고한 곳
'TIL' 카테고리의 다른 글
1월15일 (0) | 2023.01.15 |
---|---|
1월14일 - 스터디 준비 (0) | 2023.01.14 |
1월12일 (0) | 2023.01.12 |
1월11일 - MySQL, CSS (0) | 2023.01.11 |
1월10일 (0) | 2023.01.10 |