포시코딩

1월13일 - throw & try/catch 예외처리(Exception Handling) 본문

TIL

1월13일 - throw & try/catch 예외처리(Exception Handling)

포시 2023. 1. 13. 16:31
728x90

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

남은건 위 문제들을 실제로 갖고 있는 이전 팀프로젝트에 적용하는 것이다.

 

 

 

 

참고한 곳

https://webclub.tistory.com/71

 

예외 처리 - throw 및 try/catch/finally

throw & try/catch/finally(Exception Handling) 이 글에서는 예외 처리 방식에 대해 알아봅니다. 프로그램이 실행되는 동안 문제가 발생하면 프로그램이 자동으로 중단됩니다. 이럴 경우에 프로그램이 대처

webclub.tistory.com

728x90

'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