Q6-1
PDF 가이드에서 `tosslib`의 `http` 클라이언트와 `isHttpError`를 예시로 보여줬는데요, 이걸 어떻게 활용하셨나요?
핵심 포인트
- PDF는
http.get/post와isHttpError두 개를 명시적 예시로 보여줌 — "fetch를 직접 쓰지 말고 tosslib을 쓰라"는 시그널. - 4개 API(
/api/stations,/api/tickets,/api/reservationsPOST/GET) 모두http.get/post로 통일. isHttpError는 사용자 친화 토스트 노출 같은 본격적 에러 처리에 쓰는 타입 가드 — 6시간 안에서는 react-query 자동 에러 관리에 맡기고 직접 호출은 보류 → README to-do.- 솔직하게 인정: "isHttpError 활용은 미구현이고, 실제로 했다면 mutation onError에서 토스트 노출이 표준 흐름"이라고 답변에서 명시.
모범 답안먼저 답해보고 펼치기
토스 가이드 PDF에 http와 isHttpError 두 가지가 코드 스니펫으로 명시돼 있어서, 이 둘을 어떻게 다룰지를 의식적으로 설계했습니다.
http.get/post는 모든 API 호출에 그대로 적용했습니다. useStationsQuery.ts, useTicketsQuery.ts, useReservationMutation.ts, useReservationQuery.ts 네 군데 모두 http.get<ResponseType>('/api/...', { searchParams: ... }) 또는 http.post<ResponseType>('/api/...', { json: body }) 형태입니다. fetch나 axios를 직접 쓰면 토스가 깔아둔 default header·base URL·인증 처리 같은 것들을 다시 깔아야 하는데, 이건 토스 가이드의 "익숙한 방법" 원칙에도 어긋난다고 봤어요.
isHttpError는 사용을 보류했습니다. 이건 type guard라 try/catch의 e: unknown을 좁혀서 e.status나 e.message에 안전하게 접근하기 위한 도구예요. 본격적인 활용처는 mutation의 onError 콜백에서 4xx/5xx로 분기해 사용자 친화 토스트를 띄우는 자리입니다. 다만 이번 과제에서는 — react-query가 isError boolean과 error 객체로 에러 상태를 자동 관리하기 때문에 — UI 측에서는 isPending으로 버튼만 disabled 하는 정도로 마무리하고, 본격적인 토스트 분기는 README to-do로 미뤘습니다. 솔직히 말씀드리면 이 부분은 미구현이라 인정하고, 실제로 했다면 mutation.onError에서 isHttpError(error) ? toast(error.message) : toast('알 수 없는 오류') 흐름이 표준이라고 답변할 준비를 했습니다.
이 답변, 어땠나요?
꼬리 질문
-
Q6-1-a.
isHttpError를 안 쓴 게 마이너스 평가는 아닐까요? → 그래서 README에 명시적으로 to-do로 남겨두고 인터뷰에서도 회피하지 않고 답하기로 했어요. 토스 가이드의 "사용자 경험 개선 지점은 README 등에 문서화" 원칙과도 맞고, 6시간 안에 골격(편도/왕복, 다시 선택 영속화, 검증) 안정성에 우선 시간을 썼다는 우선순위 결정이 더 중요하다고 봤습니다. 못 했다고 회피보다 "왜 우선순위에서 뺐는지" 설명이 더 신뢰감 있다고 생각해요. -
Q6-1-b. mutation onError에서 isHttpError로 분기하면 구체적으로 어떤 코드가 되나요? → 대략 이런 형태입니다:
useMutation({ mutationFn: postReservationApi, onError: (error) => { if (isHttpError(error)) { if (error.status === 409) toast('이미 예약된 좌석입니다'); else if (error.status >= 500) toast('잠시 후 다시 시도해주세요'); else toast(error.message); } else { toast('네트워크 오류가 발생했어요'); } }, });type guard로 분기해야 status code 기반의 친절한 메시지가 가능해집니다.
-
Q6-1-c. http.get의
searchParams에 undefined를 그대로 넘기는 패턴은 안전한가요? →useStationsQuery에서searchParams: params?.keyword ? { keyword: params.keyword } : undefined로 처리한 부분 말씀이시죠. tosslib의 http는 ky 기반이라 searchParams가 undefined면 query string을 붙이지 않습니다. 빈 문자열을 넘기면?keyword=가 그대로 붙어서 서버가 빈 키워드로 검색하는 사고가 날 수 있어요. 그래서 keyword가 falsy일 때는 명시적으로 undefined를 넘겨 query string 자체를 빼는 패턴을 썼습니다.
CS · 이론
- Type Guard (
isHttpError):(error is HttpError)형태의 user-defined type predicate.try/catch의unknown을 좁히는 표준 패턴 — TypeScript 4.4+의useUnknownInCatchVariables옵션과 짝을 이룹니다. - HTTP Client 추상화의 가치: base URL·auth header·retry·logging 같은 cross-cutting concern을 한 곳에 둘 수 있게 합니다. 직접 fetch를 쓰면 같은 boilerplate가 흩어집니다.
- 에러 처리의 layer 구분: 네트워크 레이어(http) → 데이터 페칭 레이어(react-query의 isError/onError) → UI 레이어(toast). 각 레이어가 자기 역할만 책임지면 디버깅과 테스트가 쉬워집니다.