약식 에러 핸들링(1) - 도면

정세연·2023년 10월 6일
5

약식 에러 핸들링

목록 보기
1/2

프로젝트를 진행하며 전반적인 에러 핸들링을 맡게 되었고, 이 과정 속 고민했던 것들을 기록한 글입니다.

시작과 함께 막연함이 몰려왔습니다. 그래서 에러 핸들링이 무엇인지 생각해 보았습니다.
에러를 핸들링한다는 것은 서비스가 발생한 에러의 성격에 따라 적절하게 대처한다는 뜻입니다.

'성격', 그리고 '적절하게'.

성격에 따라 대처한다는 것은 에러의 종류가 다양하다는 의미고, 적절하게 대처한다는 것은 대처에 대한 명확한 기준이 필요다는 의미라고 생각했습니다. 이것을 출발점으로 삼았습니다.

에러의 종류


에러의 종류를 생각하다 보니 다시 막막해졌습니다.
통신 에러, 네트워크 에러, 런타임 에러, 사용자의 고의적인 에러, 보안 공격...
통신 에러도 다시, 요청이 실패한 경우, 통신은 성공했지만 400번대와 500번대의 클라이언트, 서버 오류가 발생한 경우 등 잠깐 생각해 보아도 너무 많은 경우의 수가 존재했습니다.

무슨 에러가 발생할지 모르는데 대처를 어떻게 하나 고민하던 중 JBEE님의 글을 읽고 갈피를 잡았습니다.

글을 다회독 한 후 결과적으로 에러를 바라보는 관점을 에러의 유형이 아닌, 서비스 수복 가능 여부로 바라보기로 결정했습니다.
에러를 핸들링하는 가장 큰 이유 중 하나가 에러가 발생했을 때 사용자에게 더 나은 경험을 제공하기 위해서라는 점을 생각해보면 근거 있는 관점이라고 판단했습니다.

수복 가능 여부


수복이 가능한지 파악하려면 우선 해당 에러가 예상 범위 내의 에러인지 파악해야 합니다.

제가 결정한 예상 가능 범위는 다음과 같습니다.

  1. 런타임에 직접 발생시킨 에러
  2. 통신이 성공한 API 에러

이 외에는 발생한 에러가 어떤 종류의 에러인지 모르니 수복 방법을 제공할 수 없다고 판단했습니다.

이 같은 기준으로 서비스 전반에서 사용할 에러 객체를 구체화하였습니다.

class ZipgoError<Code extends ErrorCode = 'UNEXPECTED_ERROR'> extends Error {
	...
}

class RuntimeError<Code extends RuntimeErrorCode> extends ZipgoError<Code> {
	...
}

class UnexpectedError extends ZipgoError<'UNEXPECTED_ERROR'> {
	...
}

class APIError<T = unknown, D = unknown> extends ZipgoError<APIErrorCode> {
	...
}

적절한 대처


적절한 대처라 함은 사용자에게 현재 상황을 전달하고 다음 행동을 제시해 주어야 할 것입니다.

저희 프로젝트의 에러 대처 형태는 두 가지로 설정하였습니다.

  1. 에러 페이지
  2. 에러 토스트
  3. 리다이렉션

각 형태가 갖는 성격이 다르기 때문에 제공하고자 하는 사용자 경험에 따라 구분하여 사용했습니다.

에러 페이지

에러 페이지와 토스트 사용을 구분 짓게 한 가장 큰 차이점은 시각적 차이와 사용자 경험 강제 여부입니다.

에러 페이지는 상대적으로 토스트보다 큰 UI를 갖고 있습니다. 따라서 더 많은 세부 내용을 표시할 수 있습니다.

또한, 에러 페이지는 사용자가 현재 작업을 중단하고 오류 메시지를 확인하도록 유도할 수 있습니다. 즉, 심각한 오류가 반복되지 않도록 강제함과 동시에 사용자에게 해당 페이지 사용이 불가능하다는 메시지를 좀 더 명확히 전달할 수 있습니다.

이런 특성을 고려하였을 때 에러 페이지는 서비스의 핵심 기능이 동작하지 않는 경우에 유용할 것이라고 판단했습니다.

에러 토스트

토스트는 사용자의 행동을 중단시키지 않습니다. 또한 상대적으로 에러 메시지가 간결하고 사용자의 주의를 분산시키지 않기 때문에 이전 행동을 재시도하도록 어렵지 않게 유도할 수 있습니다.

이런 간결함은 사용자에게 해당 기능을 제외한 다른 기능들은 정상적으로 동작하는 인상을 전달합니다.
따라서 서비스의 핵심 기능이 아닌 경우, 혹은 재시도가 용이한 경우 에러 토스트가 유용할 것이라고 판단했습니다.

리다이렉션

에러가 발생했을 때 사용자의 다음 대처가 명확한 경우 사용자의 편의를 위해 해당 페이지로 즉시 안내할 수 있습니다.

예를 들어 로그인 유효 기간이 만료된 경우 사용자를 즉시 로그인 페이지로 리다이렉트 시켜주어 서비스 이탈을 최소화할 수 있습니다.

맺으며


에러 핸들링에 할애한 시간 중 8할은 구상에 썼던 것 같습니다. 고작 이런 기준들로 수많은 위협들이 대처가 될 수 있는 것인지 끊임없는 의문이 들었고, 하나의 위험에 대처하면 또 다른 위험이 떠올라 쉽사리 펜을 놓지 못했습니다. 많은 사람들에게 조언을 구하며 갈무리한 결과 현재의 도면이 탄생했고 만족하는 마음으로 적용했습니다.

다음 글에서는 해당 기준들에 따라 에러를 대처하기 위해 코드적으로 고민한 것들과 결과물에 대해 이야기해 보도록 하겠습니다.

에러 핸들링에 대해 고민이 있었던 분들께 도움이 되길 바랍니다.

많은 피드백 바랍니다.

Reference

0개의 댓글