It's Ward

스프링부트 개발자 이건 고민 해야 돼 - 예외 처리와 오류 처리 본문

백엔드

스프링부트 개발자 이건 고민 해야 돼 - 예외 처리와 오류 처리

I'm ward 2022. 6. 29. 22:37

개발을 하다보면 예상하지 못했던 예외 처리와 오류 처리는 무엇을 고민해야할까?
예외(Exception)와 오류(Error)는 다르다.  오류(Error)는 시스템이 종료된다던지 서비스가 작동하지 않는 등 큰 악영향을 줄 수 있는 상황과 문제를 이야기하고, 예외(Exceoption)은 개발자의 로직 실수에서 나온다. 개발 당시 고민하지 못했던 부분에서 프로그램에 어느정도 잘못된 영향을 줄 수 있는 것이다.

고민 해야 하는 이유

오류 처리

오류를 해결 해야하는것은 고민할 필요도 없는 당연한 이야기이다. 프로그램 실행중에 오작동이 일어나거나 비정상적으로 종료가 된다고 생각하면 상상만해도 간담이 서늘해진다.

다행히도 내 개인 프로젝트였다면 문제가 되지 않겠지만, 기업은 <돈>을 벌기 위해 존재한다. 내가 부주의하게 만든 프로그램의 오류는 나만의 문제가 아니다. 잠깐의 서비스 종료로 인해 막대한 손실이 생길 수도 있고, 결국 오류를 처리하고 또다시 개발하는데에 필요한 자원(시간, 돈)이 엄청날 것이다. 

예외 처리

예외처리도 사실 마찬가지이다. 불행 중 다행히 큰 손실로 이루어 지지 않았겠지만, 그 과정에서 내 애플리케이션을 사용하는 누군가는 불편함을 겪을 수도 있는 것이고, 당장 필요한 일이라면 사용자에게 임시적인 가이드를 주고, 결국에는 해결해야할 것이다. 

당연하게도, 개발자가 원하는 방법대로 프로그램을 사용하세요 라고 하면 예외와 오류가 엄청나게 줄어들 것이다. 너 예외랑 오류처리 왜 해? 라고 물어본다면 가벼운 생각으로, 프로그램이 제대로 작동되어야 하니까 가 아니라 내가 소속된 회사의 유저 경험과, 매출까지도 이어질 수 있음을 명심하자.

의사 결정

예외 그리고 오류 처리 방지

오류와 예외처리를 방지할 수 있는 방법은 무엇이 있을까? 고민만 한다면 또는 요구사항이 많아질 수록 놓치는 부분이 분명 많을 것이다. 사전에 방지하려면 프로그램을 작성하기 전 어떻게 구성해야할까? 시간은 무한대가 아니라 한달 내에 서비스를 오픈해야 하는 상황이라고 가정하자.

어떤 방법들이 있을까? 아래에서 선택해보자.

1. 일단 내가 작성한 비지니스 로직대로 작성하고, 오류와 예외가 생길 때 마다 대응한다.

2. 생각나는 오류와 예외에 대해서 모두 작성한다.

3. 그동안 사용하면서 발생한 오류와 에러들 위주로 찾아본다.

4. 비슷한 서비스에서는 어떤 문제점이 있었는지 찾아본다.

 

한달 내에 서비스를 오픈해야 하는 상황이므로 나는, 비슷한 서비스에서는 어떤 문제점이 있었는지 찾아보며 ,  그동안 사용하면서 발생한 오류와 에러들 위주로 찾아보겠다.

일단 내가 작성한 비지니스 로직대로 작성하고, 오류와 예외가 생길 때 마다 대응하는 방법은 개발 속도를 굉장히 더디게 할 것이다. 최소한 어떤 오류가 발생할 것인지 예상하는 것과, 모르고 개발하는 것은 엄청난 차이가 있을거라고 생각한다. 물론 경험이 많아, 이런 오류가 발생하는 지 알고 있다면 어느정도 방어코드를 생각하며, 작성하겠지만 그렇지 않는 경우 개발하는 입장에서 많은 고민이 있을 것이며, 해당 오류가 발생하였을 때의 대응 방법도 좋지 않을거라 생각한다.

한 예시로, null이 들어오면 안되는 상황에서 아무런 방어를 하지 않고 기본적인 테스트 없이 동작 - 디버깅 - 동작 - 디버깅을 한다면 시간내에 끝내지 못할 가능성이크다. 

생각나는 오류와 예외에 대해서 모두 작성하는 방법 또한 효율적이지 못할 것이다. 물론, 생각나는 부분에 대해서는 어느정도 정리가 필요하다.  정리하지 말라는 것이 아니다.  필자는 두 경우를 모두 경험해 보았다.

모든 적당히가 좋은것이다.. 적당히라는 감을 분명하게 지키고, 내가 모르는 부분이 있으면 내가 소비할 수 있는 시간내에서, 주변 혹은 구글에서 정보를 습득하고 정리한 후 비지니스 로직을 작성하도록하자. 

당연하게, 모든 예외와 오류사항을 인지하고 있다면 굉장히 훌륭한 개발자겠지만  모든 것은 찾아 낼 수 없을 것이기 때문에 래퍼런스(비슷한 서비스의 기능들)에서 자주 발생하는 오류의 방어코드 정도를 인지하고, 그동안 사용한 오류와 에러들은 잘 정리해두도록 하자.

예외, Error 처리 방법

아무리 프로그램을 잘 작성하더라도 100% 완벽한 프로그램을 작성하긴 어렵다. 예외와 오류에도 여러가지 종류가 있다. 예기치 못한 상황에 예외가 발생한다면 개발자 답게 예외를 처리하는 방법은 무엇이 있을까?

1. Error Response는 객체(혹은 클래스)를 만들어 통일해서 사용한다.(예외도 동일하다)

동일한 로직으로 처리하기 위해 항상 동일하고, 명확하게 추론하기 쉽도록 구성해야한다.

Error – 오류에 대한 고유 식별자
Message – 개발자가 읽을 수 있는 간단한 메시지
Detail – 오류에 대한 자세한 설명

2. @ControlAdvice를 통해 모든 예외를 한곳에서 핸들링한다.

에러를 처리할 수 있는 공간을 각 컨트롤러마다 만들게 되는 경우, 유지보수하기 힘들다. 또한, CotrolAdvice를 사용하는 부분에서도 1번과 같이, 통일성 있게 처리하는 것을 목표로 해야한다.

3. Error Code를 정의하여 처리한다.

enum타입으로 한곳에서 관리하여, 메세지의 중복을 방지하고 도메인 별로 관리하는 것이 좋다.

4. 요구사항에 맞지 않는 경우에는 Business Exception을 만들어 따로 처리한다.

예외 처리의 경우, 로직의 책임이 증가하게 된다. 여러 경우에서 예외처리의 책임을 가지게 되는 순간 유지보수하기 어려운 코드가 되어, 코드의 가독성과 객체 본인의 책임을 모두 챙기도록 한다.

또한, Business Exception를 최상위로 만들고 상속받아 기능별로 구성하여 제작 하는 경우 통일성 있게 구성 할 수 있다.

5. 최대한 try ~ catch는 지양한다.

어쩔 수 없이 사용하는 경우 로그를 남기게 해야하며, 단순하게 Exception만 발동시키는 것이 아닌, 구체적인 Exception 이름을 이용하여 발생시키게 하는 것이 좋다. 

실천

나는 이전에는 1번의 방법대로 많이 진행해왔던 것 같다. 모든 예외나 오류가 발생할 수 있는 사항들을 생각하지 않고, 나의 개발에만 중점을 두고 개발한 것이 컸다. 

물론 지금도 모든 부분들을 생각하고 작성하지는 못한다. 개발을 하다보면 얼마든지 생길 수 있는 부분들이고, 완벽한 프로그램을 만드는 것은 사실 불가능에 가깝다고 생각한다.

그럼에도, 우리는 생각하여야만 한다. 내가 어떤 사항이 발생할지 알고 문제가 발생하는 것과, 아무런 정보도 없이 문제가 발생하는 것은 굉장히 큰 차이가 있을 것이다.

또, 팀끼지 진행하는 프로젝트에서는 해당 상황을 공유하고 앞으로의 진행 방법과 대비책을 미리 세울 수 있을 뿐더러 의외로 누군가의 경험으로 쉽게 해결할 수 있을것이다. 물론 이는 내가 발생할 수 있는 문제들을 최대한 많이 고민을 한다면 말이다. 공부를 처음 시작하면 가장 큰 문제는 무엇인지 모르기때문에 어떤걸 물어봐야 할지도 모른다는 것이다.

그리고 결국 모든 것은 내 관점에서 바라보는 것이 아닌 클라이언트 관점에서 바라보는게 너무나도 중요하다. 사용자는 불특정 다수가 (선량한 유저일 수도있고, 호기심 많은 이것저것 해보는 유저일 수도 있고, 해커일 수도 있겠다.)

내가 혹은 우리 팀이 개발한 애플리케이션을 클라이언트에게 어떻게 들어올 지 모르는 상황에서 가이드 하나를 주고, 이렇게 사용하세요. 이렇게 순서대로 사용안하면 오류납니다. 사용 못합니다. 라고 제한을 거는 것은 최악이라고 생각한다.

최대한 넓게 서비스를 이해하고 분석하고, 다른 서비스들을 경험하며 공부하고 고민하는 것이 중요할 것이다. 

 

Comments