최근에 제 토이 프로젝트를 손 보면서, 바꾼 것이 몇 가지 있습니다. 이 중에서 UserService 단에서 예외 처리하는 부분을 추가하였습니다. 해당 부분은 여기서 볼 수 있어요. 현재 제 토이 프로젝트 레포에 있는 예외 처리 코드들이 살짝 비대한 경향이 있어서 추가적인 리팩토링을 할 예정입니다. 그 부분은 나중에 언급할 기회가 있을 듯 싶습니다.

 

 이 글에서 설명할 부분은 이 문서와 일맥 상통한 내용이니 간단하게 읽어보시면 도움이 될 듯 합니다.

 


 원래 regUser는 위와 같이 구현이 되어 있었습니다. 그리고 예외가 발생하면 Service 단에서도, Controller 단에서도 처리가 되지 않는 구조였습니다.

 

 

 제 도서관 api의 db에 저장되어 있는 user_name은 위와 같습니다. 'cho'가 있으니, user_name이 'cho'인 데이터를 하나 추가해서 register를 시도해 보겠습니다.

 

 

 뭔가 명령어가 복잡해 보이지만, swagger로 테스트 했기 때문에, try-it-out만 채워주면 됩니다. 'cho'가 중복되었으니, 중복된 경우에 처리를 따로 해야 할 겁니다.

 

 

 그런데 뜬금없이 500이 떨어집니다. 500이 떨어진 이유는 무엇이였을까요?

 

 

 이미 'cho'가 있었기 때문입니다. user_name은 unique 하다는 조건이 걸려 있으니, 'cho'를 등록한다고 하면 문제가 생길 겁니다. 그런데, 그렇다고 해서 500은 문제가 있어 보이긴 합니다. 왜냐하면, 중복된 케이스에 대해서 잘 걸러냈기 때문입니다. 클라 쪽에서 이미 있는 아이디를 다시 등록하려고 했기 때문에, 4xx대 에러를 떨구는 게 좋지 않을까요?

 


 regUser를 이렇게 바꿔 보았습니다. insert를 하는 도중에 Exception이 떨어지면, -1을 돌려줍니다.

 

 

 그리고 서비스 단에서 regUser를 한 결과가 0보다 작다면, id가 중복된다는 메세지와 409 코드를 떨굽니다. 원래는 403을 떨구게 했는데 리소스가 충돌되는 것이니, 409가 나은 선택일 듯 하더라고요.

 

 

 cho가 중복된다는 메세지가 나오니 잘 처리된 것 처럼 보입니다. 그런데, Exception e 이렇게 처리하는 것은 생각보다 좋지 못합니다. 광범위한 예외이기 때문입니다. 사실, insert를 하다가 떨어지는 Exception 은 매우 많습니다. 그 중 한 예를 들어보도록 하겠습니다.

 

 

 postgresql을 stop 시켜 보겠습니다. 저는 postgresql이 돌아가고 있는 서버에서 spring boot 서버를 돌리고 있으니, 저 서비스가 stop이 되면 데이터 베이스에 당연히 접근을 하지 못할 겁니다.

 

 

 이번에 POST /reg api에 유저 이름이 'dijkstra'인 데이터를 보내 봅시다.

 

 

 그랬더니, dijkstra가 중복된다는 에러 메세지가 뜨게 됩니다. 그런데, 실제로는 유저 이름이 'dijkstra'인 케이스는 없었습니다. 논리적으로 모순된 상황이 나타나 버린 겁니다. 그러면 어떤 예외가 잡혔길래, 'dijkstra'가 중복된다는 모순된 결과가 나타났는지 볼까요?

 

 

 Failed to validate connection. 즉 Connection과 관련된 Exception이 떴을 거라는 짐작을 할 수 있습니다. 데이터 베이스 서비스가 내려가서 발생한 건데, 이것이 Exception에 속했고, 이 Exception이 catch가 되었기 때문에, 'dijkstra'가 중복된다는 이상한 결과가 나온 셈입니다.

 

 


 user_name이 중복되어서 떨궈진 Exception은 DuplicateKeyException입니다. 이것이 걸렸을 때만 잡도록 하겠습니다.

 

 

 그러면, ConnectException이 떴을 때, 409가 떨어지지 않고, Internal Server Error를 떨어트리게 됩니다. 왜냐하면, 연결 예외가 키가 중복되는 예외가 아니기 때문에, catch되지 않기 때문입니다.

 

 

 아까와는 다르게 500이 떨어집니다. 데이터베이스가 내려갔고 서버 내에서 db와 통신을 할 수 없었기 때문입니다.