#1 에러 살펴보기 🔦 in FrontEnd

Sally·2023년 2월 2일
3

What-I-Learn

목록 보기
4/6
post-thumbnail

짧은 개발 경험이지만,프론트엔드 쪽 개발을 하면서 가장 까다로웠던 부분은 에러 처리였다.

유저의 행동에 따라서 에러가 발생할 수 있는 상황도 다양하고,
고려해야할 경우의 수도 많기 때문에 자칫하면 몇 가지에 대해서는 고려하지 못하고 지나갈 수 있기 때문이다.

그래서 오늘은 에러의 종류에 대해서 정리해보고 처리 방법에 대해서 고민한 부분들을 서술하고자 한다.

에러 경우의 수 맛보기 with 검색 🔍

모든 에러에 대해서 서술하기에는 너무 방대하니...
한 가지 케이스를 통해서 에러 처리에 대해서 서술 해보고자 한다.

만약 검색이라는 기능을 만들었을 때 어떤 에러 상황들을 마주 할 수 있을까?

*유저가 불편하게 느낄 수 있는 부분도 에러로 고려하여 작성하였습니다

1. 유저가 아무런 값을 입력하지 않고 검색 버튼을 눌렀을 때
2. 특수기호를 검색어 값으로 입력했을 때 
3. 비동기 통신 중 에러가 발생할 때 
	3-1. 유저의 네트워크 연결이 끊겼을 때 
    3-2. 네트워크가 느려 로딩이 지나치게 오래걸릴 때 
    3-3. 서버 자체에서 에러가 발생하여 프론트에 응답을 보내줄 수 없을 경우 
    3-4. 프론트에서 잘못된 요청을 보냈을 때 
    3-5. 검색 결과가 없을 때
    3-6. 응답은 정상적으로 왔지만 일부 필드가 비어있을 때 
    3-7. api의 accessToken과 같은 인증값의 유효시간이 지났을 때 
    3-8. api에 할당된 제한 횟수를 초과했을 때 
    3-9. CORS 관련 에러가 발생하였을 때 
5. 서버에서 받아온 응답값에 포함된 이미지 등의 요소들의 용량이 너무 컸을 때 
6. 서버에서 받아온 응답값의 리스트의 개수가 수만개씩으로 너무 많은 개수를 화면에 랜더링해야할 때  

... 등등등 의 경우의 수가 있다.
검색에 어떤 기능들을 더 추가하냐에 따라서 에러의 경우의 수가 더 추가 될 수도 빠질 수도 있습니다 :)

이제 본격적으로 해당 에러들을 어떻게 대응할지 하나 하나 살펴보자 🔍

1. 유저가 아무런 값을 입력하지 않고 검색 버튼을 눌렀을 때

프로젝트에서 검색어의 유효범위를 미리 정했다면,
프론트엔드측에서 유저가 입력한 검색어의 유효성을 확인하여 유효한 경우에만 검색버튼을 누를 수 있도록 처리할 수 있다 (검색 버튼이 활성화 된다든지의 효과로)

만약 프론트의 로직이 잘못되어 유효하지 않은 값이 서버에 요청이 된다면
3-4인 프론트에서 잘못된 요청을 보냈을 때로 처리 될 수 있다.

혹은 빈값을 에러로 처리하지 않고 새로운 기능으로 만들어 대응할 수 있다.
가령, 네이버의 경우 빈 값을 검색창에 입력한다면 아래의 그림과 같이 랜덤하게 값을 보여주는 것으로 처리할 수 있다.

2. 특수기호를 검색어 값으로 입력했을 때

해당 에러 케이스는 공식프로젝트의 QA 도중 발견하게 되었다.

공식에서는 검색어를 url의 parameter로 요청을 보냈다. 아래의 querydata부분에 유저가 입력한 검색어를 넣어서 보내주었다.

/api/articles/search/text?text={query data}

그런데 검색창에 특수 기호들을 입력하게 되면 해당 검색어를 string으로 처리하는 것이 아닌 자바스립트 문법으로 보아서 에러가 발생하게 되었다.

예를 들어, &와 같은 경우 url에서 하나의 파라미터가 끝나고 다음 파라미터가 온다는 의미로 쓰이는 문법이기 때문에 검색어에 &가 들어간다면 예상치 못한 에러가 발생할 수 있다.

공식에서는 QA당시 & 검색어를 입력했을 때 무한서버요청이 가는 참사가 벌어졌다
*응답값이 제대로 오지 않으면 계속해서 응답을 요청을 보내는 방식으로 에러 핸들링이 되어 있어 발생한 일이였다. 이후에 1번만 재요청 하는 것으로 수정하였다.

이 케이스의 경우 encodeURL을 사용하면 쉽게 에러를 처리할 수 있다.
문자들을 UTF-8에 따라 치환해줘서 &가 들어가도 컴퓨터가 이를 올바르게 인식할 수 있도록 해준다

참고 1 생활 코딩
참고 2 MDN

3. 비동기 통신 중 에러가 발생했을 때

웹이 살아있게 만들기 위해서는 백엔드, 즉 서버와의 통신이 필수적이다.
그렇지만 안타깝게도 백엔드와의 연결에서 발생할 수 있는 에러의 경우의 수는 많은 편이다
위에서 살펴봤듯이 9가지의 경우의 수가 있을 수 있고 어떤 기능을 추가하냐에 따라서 에러의 경우의 수가 더 많이 증가할 수 있다.

예를 들어, 어떠한 기능을 구현하기 위해서는 3개의 api 호출이 필요한데 3중 하나만 성공한다든지와 같은 상황들이 있을 수 있다.

그래도 유저의 사용성을 위해서는 할 수 있을 만큼 경우의 수를 생각하는 것이 필요하다.

3-1. 유저의 네트워크 연결이 끊겼을 때

최근 와이파이가 아예 안되는 상황을 몇번 겪은 적이 있다.
앱이나 웹을 사용하던 도중 아무런 안내도 없이 그저 무한 로딩화면만 보여준다면 유저의 입장에서는 난감할 것이다. 이 서비스만 고장난건지, 나의 네트워크 상태가 이상한것인지 당장 알기 어려우니 말이다.

그래서 프론트엔드에서는 이에 대응하여 아래의 그림과 같이 유저에게 안내 화면을 보여주는 것이 좋다.
(*유튜브에서 네트워크 연결을 끊었을 때 보여지는 화면)

window.addEventlistener를 활용해서 네트워크가 offline인지 감지할 수 있다.
참고문헌 1 MDN

참고로, 자바스크립트 파일을 받아와서 실행을 시켜야 대응을 할 수 있기 때문에 유저가 홈페이지를 최초로 방문할 때에 해당 자바스크립트 파일을 받아오도록 하는 것이 좋다

3-2. 유저의 네트워크 연결이 느릴 때

우리 모두가 빠른 인터넷 속도를 사용할 수 있는 것이 아니기 때문에 개발을 진행하면서 여러 디바이스환경에 대한 고려가 필요하다 어떤 디바이스와 네트워크 연결에서는 너무 많은 작업과 큰 용량은 앱과 서비스를 버벅이게 만들 수 있다.

네트워크 연결이 느린 곳에서 최대한 빨리 유저에게 화면을 보여주기 위해서는 성능 최적화를 진행해야 한다.
성능최적화의 방법은 대략적으로 아래와 같은 것들이 있다.

  1. 코드 스플리팅
    • 현재 페이지에서 필요한 데이터만 받아와 보여줌으로써 네트워크 통신 횟수와 용량을 줄일 수 있다
  2. 스프라이트 이미지
    • 회사의 로고나 아이콘등에 사용되는 이미지를 각각 받아오는 것이 아닌 하나의 이미지에 합쳐서 관리할 수 있다.
  3. 캐싱 하기
    • 서버에서 받아오는 데이터들을 캐시처리하여 유저의 브라우저에 저장해두고 유저가 서비스를 재방문시 캐싱된 것을 사용한다
  4. 이미지 최적화
    • 고화질의 이미지일 수록 용량을 많이 차지하기 때문에 이미지의 형식을 webp로 바꾼다던가, 서비스에 맞게 이미지의 크기를 줄인다던가 하는 방식으로 이미지 용량을 줄일 수 있다.

해당 4가지 이외에도, gzip사용, 리플로우 피하기, CLS 피하기, 기본 글꼴 설정하기 등등의 방법들이 있다

3-3. 서버 자체에서 에러가 발생하여 프론트에 응답을 보내줄 수 없을 경우

공식 프로젝트를 개발하면서 경험했던 문제이다. 유저에게 무언가를 보여주기 위해을 Get 요청을 했지만 응답값이 오지 않으면 유저는 꽤나 오랜 시간 흰 화면을 봐야한다.

공식에서 경험했을 때에는 해당 경우, 서버에 응답값이 아예 오지 않았다
reponse값이 undefined인 것이다.

그래서, 공식에서 response가 undefined인 경우에는 프론트에서 에러를 던져 아래와 같은 500번 페이지를 보여주었다.

3-4. 프론트에서 잘못된 요청을 보냈을 때

흔하게는 유저가 url창에 아무 값이나 입력하면 볼 수 있는 에러 상황이다.

보통은 검색 기능을 구현할 때 검색어를 Url에 붙여서 보내기 때문에 해당 에러를 마주할 수 있다.
url을 통해서 유저가 검색어를 직접 입력을 하면 프론트에서 실시간으로 입력값에 대해 유효성 평가를 하기 어렵기 때문에 사전에 약속된 검색 값에 대한 유효성 범위에서 벗어난 값을 서버 측에 요청할 수 있게 된다.

이 때에는 프론트에서 잘못된 요청을 보내게 된 것이기 때문에 보통은 서버에서 404 status code를 반환하게 된다.
공식 프로젝트에서는 에러코드를 통해 사전에 0001 로 정의하여 404 에러를 처리하였다.

프론트에는 아래와 같이 404 화면을 보여주는 것을 대응할 수 있다
(*velog의 404 에러 화면)

3-5. 검색 결과가 없을 때

검색 결과가 없을 수 있다!
유저가 입력한 검색어와 일치하는 게시글이나 어떤 대상이 DB상에 존재하지 않을 수 있으니 말이다.

그렇지만 해당 경우에 대해서 따로 고려해주지 않는다면,
서버와의 통신에서 success하게 끝났음에도 유저는 빈화면을 보게 되어 당황할 수 있다

검색어가 존재하지 않는다는 문구를 보여주어 유저의 앱 사용 경험을 높여주어야 한다

3-6. 응답은 정상적으로 왔지만 일부 필드가 비어있을 때

사실 해당 케이스는 아직 마주한 적이 없다. 😅
서버와의 통신 중에 있을 수 있는 경우의 수를 생각하다 보니 나오게 된 경우의 수이다.

예를 들자면, 제목, 내용, 작성자 등의 내용이 담겨 와야 하는데
작성자 필드가 아예 없이 오거나 작성자 값이 빈 값일 수 있다.

해당 케이스에 대해서는 팀에서 정하기 나름이겠지만,
기본값을 넣어주거나 다시 서버에 재요청을 하거나 하는 방식이 있을 것이다.

하지만 유저에게 정확한 값을 보여주는 것이 중요하기 때문에 나라면 후자의 방법을 택할 것이다.

만약 해당 방법을 구현한다면, 응답값이 모두 올바르게 전달되었는지 확인 후
일부 필드값이 비어 있을 때에 react query의 queryClient 를 통해 refetch를 하는 방식으로 서버에 재요청하는 방식으로 처리할 것 같다.

3-7. api의 accessToken과 같은 인증값의 유효시간이 지났을 때

유저의 권한에 따라서 검색을 제한할 때 발생할 수 있는 에러일 것이다.

서비스마다 다르겠지만, 보안을 위해서 accessToken의 유효기간을 설정해두고 이를 계속해서 갱신해나가는 등의 방식을 취할 수 있다. 그래서 해당 케이스를 생각하여 에러를 처리해주어야 한다.

공식 프로젝트에서의 경우 accessToken이 무효화되어 로그인이 새로 필요할 때에는 아예 로그인 페이지로 유저를 이동시키는지 등의 대응을 하였다

더 자세한 내용은 공식의 refreshToken 포스팅에 있다.

3-8. api에 할당된 제한 횟수를 초과했을 때

아래는 github api를 활용하여 프로젝트를 구현했을 때 마주했던 에러이다.
api 요청을 너무 많이하게 되면 아래와 같은 에러가 발생하면서 응답값을 주지 않는다.

{ documentation_url: "https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting",
message : "API rate limit exceeded for - 
(But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)"

public api의 경우 하루 또는 몇 시간마다 보낼 수 있는 api 요청 수가 제한되어 있는 경우가 있다 😭

api에 이러한 제한사항이 있다면 꼭 처리를 해주자!

보통은 api를 제공해주는 측에서 docs로 에러에 대해서 보내주는 응답값을 사전에 안내하기 때문에 에러코드와 응답값으로 오는 메세지를 확인하여 유저에게 안내메세지를 보여주는 방식으로 처리 할 수 있다.

3-9. CORS에러가 발생했을 때

CORS란 Cross Origin Resource Sharing 의 줄임말로 교차 출처여도 통신이 가능하게 허용하는 것이다.

브라우저간의 통신은 기본적으로 동일 출처 정책을 채택하고 있다.
동일한 도메인 간의 요청이 아니면 안전하지 않은 요청으로 판단하여 응답값을 보내지 않고 에러를 뿜게 된다.

이럴 때에는 서버측에서 헤더에 Access-Control-Allow-Origin에 필요한 도메인을 추가하여 허용하면 해결된다.

참고 문헌 MDN

5. 서버에서 받아온 응답값에 포함된 이미지 등의 요소들의 용량이 너무 컸을 때

+ 6. 서버에서 받아온 응답값의 리스트의 개수가 수만개씩으로 너무 많은 개수를 화면에 랜더링해야할 때

응답 결과값으로 서버에서 받아온 이미지가 용량이 클 수 있다 (고화질이거나, 이미지의 크기가 크거나 할 때 용량이 크다)
거기에 더해 유저가 검색한 결과 값이 여러개 일 때 가령, 100개가 넘어가는 등일 때가 있을 수 있다.
이럴 때 100개의 응답값을 모두 렌더링하게 되면 처리해야할 경우가 많아져 화면이 버벅이거나 렌더링까지 오랜 시간이 걸릴 수 있다.

예를 들어 유저가 입력한 검색어와 일치한 결과물이 100개가 있다고 가정해보자.
유저가 보는 디바이스의 크기에 따라서 다르겠지만 보통은 유저가 보는 한 화면에 100개를 모두 밀어넣을 공간이 없다.
우리가 쉽게 스마트폰으로 이용하는 유튜브의 경우에도 한 화면에 2개 정도의 결과물을 보여주고 있다.

그렇기 때문에 이미지를 한 번에 모두 렌더링할 필요 없이 이미지에 lazy loading 처리를 해서 유저가 해당 게시물에 접근했을 때에 이미지를 불러오게 할 수 있다.

유튜브에서도 스크롤을 내렸을 때에 썸네일 이미지를 요청하여 받아오는 것을 볼 수 있다.

또한, 100개의 결과물을 한번에 서버에서 보여주는 것이 아니라 페이지네이션이나 무한스크롤등을 활용하여 한 번의 요청마다 받아오는 응답값의 개수를 분할하여 요청 받아올 수 있다.

이미지 처리와 관련하여 록바의 명강의가 있으니 한 번씩 보시길 추천드린다👍

0개의 댓글