블랙 커피 프론트엔드 레벨 1 스터디 2주차 정리

이번에는 중간에 정보처리기사 시험이 껴있어서 2~3주차 정리를 못해서 😭 이제와서라도 한다.

최종 회고는 버퍼 기간이 모두 끝나면 작성하도록 하겠다.

결론적으로 매우 2~3주차 미션도 매우 재미있었고 많은 생각을 요했으며 꽤나 발전했다고 느꼈던 2주였다. 😃

2주차 미션 요구사항

  • 1주차에 만든 자바스크립트에 서버와의 비동기 통신을 추가한다.
  • 투두리스트에 관한 CRUD 연산을 서버와 통신하여 수행할 수 있다.
  • 여러명의 User를 생성 , 삭제 및 불러올 수 있다.

구현에 관한 고민

2주차 미션을 진행하면서 가장 신경썼던 부분은 아래와 같다.

  1. API 코드를 분리하여 재사용성 고려
  2. 적절한 에러 핸들링

구현 방법

1. API 코드 분리

  • request 함수 : 파라미터로 받은 url과 option을 통해 서버로 비동기 요청을 보내고 받아온다. 응답 결과를 파싱하여 리턴해준다.
const request = async (endPoint, option = {}) => {
  const response = await fetch(baseUrl + endPoint, option)
  const data = await response.json()
  if (!response.ok) {
    if (response.message === NO_USERLIST_MESSAGE) return []
    throw ERROR_TYPE_BY_MESSAGE[data.message] ?? ERROR_TYPE.SERVER_ERROR
  }
  return data
}
  • options 객체 : httpMethod에 따라서 원하는 option을 바로 리턴해주거나, 해당 option을 생성할 수 있는 함수를 담고있다. Post option을 쓰다보면 header나 body 부분을 계속 반복해서 연산하는게 비효율적이어서 만들었다.
const headers = { 'Content-Type': 'application/json' }

const options = {
  GET: { method: HttpMethod.GET },
  POST: (body = '') => {
    return {
      method: HttpMethod.POST,
      headers,
      body: body ? JSON.stringify(body) : '',
    }
  },
  PUT: (body = '') => {
    return {
      method: HttpMethod.PUT,
      headers,
      body: body ? JSON.stringify(body) : '',
    }
  },
  DELETE: {
    method: HttpMethod.DELETE,
  },
}
  • endPoints 객체 : 연산에 따른 endPoints를 담고있다. 이 역시 파라미터가 필요하지 않으면 문자열을 바로 리턴해주고, 그렇지 않으면 문자열을 생성할 수 있는 함수를 리턴해준다.
const endPoints = {
  getUserList: 'api/users',
  addUser: 'api/users',
  getUser: userId => `api/users/${userId}`,
  removeUser: userId => `api/users/${userId}`,
  getUserTodo: userId => `api/users/${userId}/items/`,
  addTodoItem: userId => `api/users/${userId}/items/`,
  removeAllTodo: userId => `api/users/${userId}/items/`,
  removeTodo: (userId, itemId) => `api/users/${userId}/items/${itemId}`,
  updateTodo: (userId, itemId) => `api/users/${userId}/items/${itemId}`,
  todoToggle: (userId, itemId) => `api/users/${userId}/items/${itemId}/toggle`,
  setPriority: (userId, itemId) =>
    `api/users/${userId}/items/${itemId}/priority`,
}


2. 에러 핸들링

에러핸들링은 처음에는 놓치고 있던 부분인데, 먼저 풀리퀘스트를 올려주신 분의 코드를 보고 인사이트를 얻어서 수정하였다 ㅎㅎ. 다중 사용자가 허용되는 어플리케이션이므로, 충분히 고려해야할 사항이었다.

에러는 response.ok 여부로 판단을 했고, 에러의 종류는 response.message에 들어오는 메시지에 따라서 달리 하였다. 아래는 util/errors 의 소스코드이며, 에러와 관련된 객체들이 저장되어 있다.

에러 처리 플로우를 정리하자면 아래와 같다

  1. API request 에서 response.ok 로 에러가 판별되면, 해당 Error 유형을 Throw 해준다. 이 때 Error Type이 정해져 있지 않다면 Server Error로 통일해준다.
  2. Throw 된 Error는 해당 API call을 호출한 함수에서 catch 하여 , catch 된 error type에 따라 Error handler 함수에서 처리해준다.
export const ERROR_TYPE = {
  NO_USER: 'NO_USER',
  NO_TODO: 'NO_TODO',
  SERVER_ERROR: 'SERVER_ERROR',
  NOT_VALIDATE_USERNAME: 'NOT_VALIDATE_USERNAME',
  NOT_VALIDATE_TODO: 'NOT_VALIDATE_TODO',
  NOT_VALIDATE_TODOLIST: 'NOT_VALIDATE_TODOLIST',
}

export const NO_USERLIST_MESSAGE = 'user가 없습니다'

export const ERROR_TYPE_BY_MESSAGE = {
  '해당 이름의 user가 없습니다.': ERROR_TYPE.NO_USER,
  '해당 이름의 유저가 없습니다.': ERROR_TYPE.NO_USER,
  '해당 유저가 존재하지 않습니다.': ERROR_TYPE.NO_USER,
  'Todo Item을 수정하는데 에러가 발생했습니다.': ERROR_TYPE.NO_TODO,
  'Todo Item의 priority를 수정하는데 에러가 발생했습니다.': ERROR_TYPE.NO_TODO,
}

export const ERROR_HANDLER = {
  NO_USER: () => {
    alert('존재하지 않는 유저입니다.')
    return location.reload()
  },
  NO_TODO: () => alert('존재하지 않는 항목입니다.'),
  SERVER_ERROR: () => {
    alert('잠시후 다시 시도해주세요')
    return location.reload()
  },
  NOT_VALIDATE_USERNAME: () => alert('이름은 2글자 이상이어야 합니다'),
  NOT_VALIDATE_TODO: () => alert('2글자 이상 입력해주세요'),
  NOT_VALIDATE_TODOLIST: () => alert('삭제할 항목이 없습니다'),
}

에러 핸들링의 두가지 경우는 아래와 같다.

  1. 투두 작성 도중 유저가 삭제된 경우

    • 먼저 해당 alert를 띄워줘서 사용자에게 페이지 내 에러가 있음을 알린다.
    • 유저 리스트는 초기에 가져오기 때문에, 특정 컴포넌트를 reload 하지 않고, 전체 페이지를 reload 해준다.
  2. 투두 수정 도중 해당 투두 아이템이 삭제된 경우

    • 먼저 해당 alert를 띄워줘서 사용자에게 페이지 내 에러가 있음을 알린다.
    • 투두 항목에 변경이 생긴 경우는, TodoList 컴포넌트만 reload 해주도록 한다.

코드 리뷰 받은 것

  • TodoList 컴포넌트가 너무 많은 기능을 한다

    • 해당 컴포넌트에 투두 작성을 제외한 투두와 관련된 모든 연산을 넣어놓았더니 너무 무거워진 것 같다
    • 투두 Item을 아예 다른 컴포넌트로 빼버릴 수 있지 않을까 생각한다.

2주차 짤막한 회고

2주차에는 정말 정말 고민을 많이 했었고, 많이 고치고 리팩토링했었다. 아무리도 비동기 통신을 하다보니 코드가 여기저기 더러워져버릴 위험이 많았기 때문에 많이 신경을 쓰게 되었다.

정말 스터디 참여하면서, 코드를 최대한 깔끔하고 가독성 좋고 효율적으로 쓰기 위해 많이 노력하게되는데, 이게 큰 성장으로 이어지는 것 같아서 매우 뿌듯하다 😄

3주차도 마저 마무리하고 금방 회고를 가져오겠다 …


This is@moonee
프론트엔드 개발 공부 블로그

GitHub