-
Notifications
You must be signed in to change notification settings - Fork 1
[Init] swagger-typescript-api 및 axios 초기 세팅 #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- api 자동 생성을 위한 swagger-typescript-api 실행을 위해 package.json script에 gen:swagger-ts-api 구문을 추가하였습니다. - swagger-typescript-api script옵션 중 swagger url은 .env에 명시한 후 불러와 사용하기 위해 dotenv 명령과 mac, window 환경 변수 문법 차이를 통일해주는 cross-var명령을 추가하였습니다.
- swagger-typescript-api는 기존의 템플릿을 기반으로 타입과 API요청 함수들이 자동 생성됩니다. - 하지만 기존 템플릿을 그대로 사용하면, .env에 존재하는 환경 변수가 그대로 노출되는 형태로 파일이 자동생성된다는 보안 상의 문제가 존재하여, 기존 템플릿의 형식을 유지하되 변경이 필요한 템플릿(api, http-client.ejs)만을 추출하여 일부 코드를 수정, 제거하였습니다.
- swagger-typescript-api가 수정된 템플릿을 기반으로 자동생성할 수 있도록 script를 -t (template path)옵션을 적용하도록 수정하였습니다.
|
API 스펙 변경 → 타입/요청 함수 갱신 흐름을 자동화하면서, 추후 확장(토큰 재발급, 전역 에러 처리, React Query 연동)까지 고려하면서 작업하시느라 수고 정말 많으셨습니다 😽 고려하면서 작업하신 내용들에 대한 설명을 꼼꼼히 적어주셔서 이해하기에 수월했습니다 :) 현재는 axios 인스턴스와 생성된 |
src/shared/api/error-handler.ts
Outdated
| export const isAxiosErrorWithCustomCode = ( | ||
| error: unknown | ||
| ): error is RequiredWith<AxiosError<ApiErrorResponse>, "response"> => { | ||
| return ( | ||
| isAxiosError(error) && | ||
| !!error.response && | ||
| !!error.response.data && | ||
| typeof error.response.data.code === "string" && | ||
| error.response.data.code in ERROR_MESSAGE | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RequiredWith<..., "response">로 response 존재를 보장한 뒤 타입가드로 좁혀가는 접근이 좋은 것 같습니다!! 덕분에 아래 분기 로직에서 optional chaining을 줄이고 타입 안정성을 확보할 수 있어서, 팀원들이 공통 에러 처리 코드를 쓰기 쉬워질 것 같습니다 :)
한 가지 확인하고 싶은 점이 있는데, 현재 “서버 정의 에러” 판단 기준이 code in ERROR_MESSAGE까지 포함되어 있어서, 서버가 새로운 에러 코드를 추가했는데 프론트 매핑이 아직 없으면 서버 정의 에러가 일반 axios 에러로 분류될 수도 있을 것 같아요. 이게 의도한 처리인지, 아니면 code가 string이면 서버 정의 에러로 보고 메시지는 fallback을 두는 쪽이 나은지 팀 컨벤션을 정리해보면 좋을 것 같습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
우선 제가 생각한 에러 처리 흐름에 대해 말씀드려보자면,
[1. 서버 정의 에러] 와 [2. 그 외 에러(ErrorBoundary 처리)] 로 크게 나누고, [1. 서버 정의 에러] 안에서 다시 POST(toast 노출)와 GET(Fallback UI 노출)을 분리(이건 아직 고민중...)하는 흐름으로 우선은 생각해두었습니다.
말씀하신 대로 판단 기준이 프론트 단에서 매핑해둔 ERROR_MESSAGE에 code가 존재하는지와 같은 엄격한 기준을 설정하다보면, 신규 에러 코드가 발생했을 때 [1. 서버 정의 에러] 로 분류되지 못하고 [2. 그 외 에러] 로 인식해서, toast메시지가 떠야하는데 에러 페이지가 뜰 가능성도 있을 것 같아요!
아직 서버에서 명확한 에러코드가 정의된 상태는 아니기 때문에, 우선 초반에는 안정적인 개발을 위해서는 유진님이 말씀해주신 code가 string으로 존재하면 서버 에러로 간주하고 방식으로 수정하는 게 적합할 것 같네요🥰
해당 내용 반영하도록 하겠습니다!
| private format?: ResponseType; | ||
|
|
||
| constructor({ securityWorker, secure, format, ...axiosConfig }: ApiConfig<SecurityDataType> = {}) { | ||
| this.instance = axios.create({ ...axiosConfig, baseURL: axiosConfig.baseURL || import.meta.env.VITE_API_URL }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생성 코드에 .env가 그대로 노출되는 문제 신경써서 해결하신 점 굳굳입니다 👍
src/shared/api/axios-instance.ts
Outdated
| api.interceptors.request.use( | ||
| async (config) => { | ||
| // TODO: 액세스 토큰 가져오는 로직은 utils/token로 대체 예정 | ||
| const accessToken = localStorage.getItem("access_token") || "temp"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
토큰을 interceptor에서 주입하는 흐름 너무 좋은 것 같습니다 👍 다만 이전까지 합의되었던 내용은 토큰을 shared/lib/auth/token.ts(storage 유틸)에서만 다루는 방향인걸로 기억해서, 추후 실제 적용 단계에서는 여기의 localStorage.getItem을 tokenStorage 조회로 통일하면 팀 컨벤션과 더 잘 맞을 것 같습니다
추후 컨벤션이 완전히 확정되면 더 적절한 방식으로 통일해보면 좋을 것 같아요 :)
추가로 지금은 임시 코드라 "temp"가 들어간 것 같은데 이렇게 되면 기본값 때문에 토큰이 없어도 Bearer temp가 붙어서 401을 유발할 수도 있을 것 같아서 실제 서비스 구현 시점에는 기본값을 제거하여 null/undefined로 “토큰 없음 케이스”를 확실하게 처리하면 좋을 것 같습니다 :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헉.. 제가 임시로 설정하고 올리기 전에 다른 값으로 대체한다는게 그대로 올려버렸네요.. 감사합니다ㅠ
스토리지 토큰에 접근하는 로직은 zustand PR이 머지되지 않았기도 했고 아직 axios instance를 사용하는 구현단계는 아니라 로그인 이슈 처리하면서 함께 shared/lib/auth/token.ts의 token 조회 유틸함수로 대체하도록 하겠습니다!
src/shared/api/axios-instance.ts
Outdated
| // TODO: 액세스 토큰 가져오는 로직은 utils/token로 대체 예정 | ||
| const accessToken = localStorage.getItem("access_token") || "temp"; | ||
| if (accessToken) { | ||
| config.headers["authorization"] = `Bearer ${accessToken}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
header 키값의 경우 보통 "Authorization"와 같이 첫글자로 대문자로 사용하는 게 조금 더 통용적인 방법이라고 해서 수정해도 좋을 거 같아요 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
새롭게 배워갑니다(^///^) header 키 값은 대문자로 사용... 메모...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
새롭게 도입해보는 시스템이라 어려움이 많았을 것 같은데, 그럼에도 불구하고 충분히 잘 도입해주셔서 API 관련 작업을 효율적이고 빠르게 진행할 수 있을 것 같습니다 ㅎㅎ 감사합니다!
제네레이터 도입뿐만 아니라 axios 초기 세팅 과정에서 axiosInstance 구성과 에러 핸들링까지 깔끔하게 처리해주셔서, 전반적인 안정성과 유지보수성 측면에서도 매우 좋다고 느꼈습니다.
특히 추후 발생할 수 있는 이슈들을 미리 고려하고, 이에 대한 대응 방향과 예방법까지 함께 제시해주신 부분에서 수빈님의 꼼꼼함이 잘 느껴졌어요 최고 .. 👍
To reviewer 섹션에 적어주신 부분들에 대해 이야기해보면 generate 관련 파일의 경우 수빈님에 해주신 방식(shared/api/generate 경로에 두는 것) 충분히 적절하다고 생각합니다.
또한 폴더 구조의 경우 이미 shared 레이어 자체가 segment로구성되어 있어서 api 폴더 내부에서 types,lib,confg 등으로 세분화하게 되면 오히려 뎁스가 너무 길어지고 자칫 너무 과한 폴더 세분화가 될 수도 있다고 생각해요!
generate 폴더는 그대로 두고 그 외에 api 관련 코드는 그냥 shared/api 위치에 모두 두고, 응답 타입 관련 파일인 response.ts 파일은 /shared/types/api 와 같은 위치에 두는 것은 어떨까요? 다만 응집도 측면에서는 수빈님이 제안해주신 방식이 더 적절해 보이기도 해서, 이 부분은 팀 내부에서 한 번 더 이야기해보면 좋을 것 같습니다😊
아 마지막으로!! 머지 전에 충돌해결 꼭 해주시고 해당 작업과 관련해서 서버 파트에 요청드려야하는 사항들이 있다면 미리 미리 전달드립시다 !! 👊 (이해하는 데 시간이 좀 걸려서 코드 리뷰가 늦어졌어요 ㅠ ㅠ.. 미안합니다 🙏)
qowjdals23
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
swagger-typescript-api 에 axios까지.. 세팅하시느라 수고 많으셨어요
도입 이유, 구조, 명령어 흐름까지 PR이랑 아티클에 너무너무 꼼꼼하게 정리해주셔서 이해하기 수월했습니다…..
generate 경로로 생성물 모아둔 것도 동선 명확해서 너무 좋고 ! axiosInstance / error-handler까지 같이 잡아두셔서 이후 API 붙이기 훨씬 편해질 것 같네요 !
유진님 채영님 말씀하신 것처럼 나중에 실 적용 들어갈 때 axios-instance 쪽 localStorage / temp 기본값 처리랑 Authorization 헤더 키 컨벤션 같은 포인트만 팀 컨벤션으로 한 번 정리하면 더 완벽해질 것 같습니당
전체적으로 구조랑 방향이 너무 깔끔했습니다!! 수고하셨습니다!! ❤️🔥
- 개발 단계에서는 서버에서 새로운 에러가 만들어져도 프론트 단에서 매핑을 하지 않으면, 서버정의에러 임에도 일반 axios로 처리될 수 있기 떄문에 이전보다 유연한 검사를 위해 error.response.data.code in ERROR_MESSAGE 조건 검사를 제거하였습니다.
🚀 빌드 결과✅ 린트 검사 완료 |
채영님이 말씀해주신 내용과 현재 구조에 대해 고민이 아직 많아,, 웹 회의 진행하면서(아티클 발표) 논의해보면 좋을 것 같아요. p.s. swagger-typescript-api를 사용하는데 있어 서버에 요청할 사항들은 정리해서 개발자 톡방에 전달하겠습니다! |
- 서버정의 에러를 판별하는 isAxiosErrorCustomError 함수명이 의미를 명확히 나타내지 못한다는 의견이 있어 isValidCustomError 네이밍으로 변경하였습니다.
- query-client 전역 설정 추가 (throwOnError 옵션 조정) - query(GET)와 mutation(POST 등)의 에러 처리 로직 분리 - query: ErrorBoundary로 에러 전파 (Suspense 위함) - mutation: 토스트 메시지 등 UI 피드백을 위해 에러 전파 방지 - 단, useSuspeseQuery는 handleApiError를 거치지 않고 바로 errorboundary가 잡게 됨.
|
웹 회의를 통해 기존 PR 내용에서 수정, 결정된 내용은 다음과 같습니다! 폴더 구조 유지
swagger-ts-api script 수정
에러 핸들링 로직 수정 (
|
hummingbbird
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고하셨습니다! 오늘 했던 회의와 수빈님의 no대본발표쇼 정말 인상 깊었고 오래 기억될 거 같아요 .. 🥺 코멘트 남긴 부분 한 번만 확인해주세요 최고 최고 ~~ 😍
src/app/providers/index.tsx
Outdated
|
|
||
| import type { PropsWithChildren } from "react"; | ||
|
|
||
| export default function AppProviders({ children }: PropsWithChildren) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
팀에서 정한 컨벤션에 따라 해당 프로바이더 화살표 함수로 수정해주실 수 있을까요~?? (수빈님 작업과 관련이 있는 내용은 아니긴 한데 이전 pr에서 미처 수정하지 못한 것 같은데 따로 이슈를 파서 해결하기엔 작은 부분이라 조심스럽게 요청드립니다 🙇♀️)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아 네네! 같이 수정해주세요~👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기도 화살표 함수로 변경 부탁드립니다 !! 🙇♀️
| * @param error 발생한 에러 객체 | ||
| * @param type 요청 종류 ('query': 조회 -> 에러페이지 / 'mutation': 수정 -> 토스트) | ||
| */ | ||
| export const handleApiError = (error: unknown, type: ErrorType) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type 파라미터를 query/mutation으로 설정해주셨는데, mutation을 사용하는 post/put/delete를 모두 아우를 수 있어 기존 회의에서 말씀주셨던 get/post보다 좋은 선택인 것 같습니다! 😙
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재 코드에서 type=="query"일 때에 대한 처리가 별도로 되어 있지 않은데, 혹시 이 부분에 대한 설명이 comment로 남겨주신
useQuery와 useMutation 요청에 대해 분기 처리하여 query(조회)는 에러 페이지(Suspense)로 이동하고, mutation(수정)은 토스트만 띄우도록 로직을 분리했습니다. (임시 처리로 추후 에러 처리에 대해서는 변경될 수 있습니다.) 단, useSuspenseQuery는 자체적으로 에러를 ErrorBoundary로 넘기게 됩니다. 결과적으로 useQuery 에러 처리 과정은 다르지만 에러 처리 결과는 동일합니다. 서버 정의 에러를 판별하는 isAxiosErrorCustomError 함수명이 의미가 좀 더 명확했으면 좋겠다는 의견이 있어 isValidCustomError로 네이밍을 변경하였습니다.
이 부분일까요? 여러 번 읽어보았는데 "query"일 때 에러 페이지로 이동하는 흐름이 어떤 식으로 이루어지는지 잘 이해가 되지 않아서 호옥시 조금 더 자세히 설명해주실 수 있을지 여쭤봅니다. !! 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handleApiError에서는 query, mutation에 대한 에러가 분기되어 처리된다는 것을 명시적으로 알려주기 위해
query 동작 시 에러가 발생하였을 때도, handleApiError에 "query" 인자를 넘겨주고 있긴 하지만,
defaultOptions에서 throwOnError 옵션을 이미 true로 설정하여 query에서 에러가 발생하였을 땐,
query 자체 동작으로 ErrorBoundary로 에러를 던져 처리할 수 있는 흐름이 됩니다!
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
// 생략 //
throwOnError: true, // throwOnError 옵션을 true 설정
},
mutations: {
throwOnError: false,
},
},
queryCache: new QueryCache({
onError: (error: unknown) => {
handleApiError(error, "query");
},
}),There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아하~ 정확히 이해했습니다! mutation error의 경우는 사용자 경험 개선을 위해 alert 메시지로 처리해주기로 하였기 때문에,throwOnError 옵션을 false로 설정하고 handleApiError에서 처리를 해주는 방식인 거군요! 친절한 설명 감사합니다 👼👼
hummingbbird
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반영 잘 된 거 확인 완 ~ 수고 많았어요 👍👍👍👍👍
|
웹 회의에서 논의된 내용들 PR에 잘 반영된 것 확인했습니다 🙌 |
| /** | ||
| * 서버 정의 에러(Business Error) 타입 가드 | ||
| * - HTTP 상태 코드는 정상이지만, 비즈니스 로직상 실패한 경우를 식별합니다. | ||
| * - 응답 본문(data)에 'prefix' 필드가 있는지 확인합니다. (추후 TODO) | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
주석에 “HTTP 상태 코드는 정상이지만 비즈니스 로직상 실패한 경우”라고 적혀 있는데, 현재 구현은 status와 무관하게 prefix가 있으면 커스텀 에러로 분류되는 구조라서 설명과 실제 동작이 살짝 다른 것 같아서요!
지금 당장 기능에는 영향 없지만, 나중에 다른 사람이 호옥시 코드를 읽을 때 “200 OK인데 body로 내려오는 에러만 처리하나?”라고 오해할 수 있어서 주석을 “서버가 정의한 error payload 식별” 쪽으로 수정하거나 실제로 status 조건을 추가하면 더 좋을 것 같습니다 😽
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
호오 그렇네요!!!!!! 세심막내의 코리다..d=(^o^)=b
이미 받아온 error객체에 대해서 판별하고 있는 구조이기 때문에 status 조건은 추가하기보다, 말씀해주신 코멘트대로 주석 수정해서 반영해두었습니다 .ᐟ

✏️ Summary
📑 Tasks
API Generator를 도입하게 된 이유
프론트엔드 개발을 하다 보면 서버 API 스펙이 변경될 때마다 타입을 수정하고, API 요청 함수를 다시 작성해야 하는 반복 작업에 시간을 쏟게 됩니다. 이 과정에서 잘못된 API주소를 작성하여 이상한 엔드포인트로 요청을 보내거나 서버와 타입이 어긋나 예상치 못한 버그가 발생되기도 합니다. 이러한 휴먼 에러들이 쌓이면서 작업해야 할 디버깅 비용이 증가하는 것이죠.
그래서 Comfit은 개발자가 반복 작업과 휴먼 에러를 줄여 개발 생산성과 코드 안정성을 높일 수 있도록 API 타입과 요청 함수 생성을 자동화하는 API Generator인
swagger-typescript-api를 도입하게 되었습니다.🗂️ Architecture
shared/api폴더 내에 API 관련 로직을 응집시켰습니다. (To Reviewer 섹션 확인부탁드립니다!)API 코드 자동 생성 (
swagger-typescript-api)swagger-typescript-api를 도입하여 API 명세 변경 시 명령어로 cmd창에 입력하면, API 타입과 API요청 함수를 최신화할 수 있습니다../src/shared/api/generate폴더 아래http-client.ts파일이 생성되며, 파일 내부에는 API 타입과 API요청 함수가 자동으로 생성됩니다.--extract-request-body,--extract-response-body,그리고 일관성 있는 타입 명이 생성되도록 접미사 DTO가 붙여지는--type-suffix DTO옵션을 추가했습니다.-t옵션으로 템플릿 경로(templates)를 명시적으로 지정했습니다.💟 swagger-typescript-api 템플릿 커스텀
swagger-typescript-api는 제공되는 기본 템플릿을 기반으로 API 타입과 API요청 함수들이 자동 생성됩니다.하지만 기존 템플릿을 그대로 사용하면, .env에 존재하는 환경 변수가 그대로 노출되는 형태로 파일이 자동 생성된다는 보안 상의 문제가 존재하여, 템플릿의 기존 형식은 최대한 유지하되 변경이 필요한 템플릿(
api.ejs,http-client.ejs)만을 추출하여 일부 코드를 수정하였습니다.실제 생성된 파일(
http-client)의 내부 코드가 하는 역할은 아래와 같아요.axios인스턴스의 초기화 및request메서드를 통해 실제 HTTP 요청을 실행합니다더 자세한 내용은 노션을 참조해주세요.
axiosInstance.ts공통적인 요청/응답 처리를 위해 axios.interceptor를 설정했어요.
API 요청 전, 공통적으로 accessToken을 header에 주입시킬 수 있도록 공통 요청 로직(
request)을 구현했습니다.API 요청 이후에 대한 응답은
response를 반환하며axiosInstance 로직은 서버 파트와 이야기하면서 달라질 부분이 많을 것 같아, 우선은 간략한 슈도코드 형태로 구현해 놓은 상태입니다. 흐름이 이렇게 흘러가는구나 정도로만 봐주시면 좋을 것 같아요!
공통 에러 핸들링 (
error-handler.ts)서비스를 개발하다 보면, 여러 에러 유형을 마주치게 됩니다. 보통 서버에서 정의된 에러와 서버/네트워크 에러, 그리고 그 어떤 유형에도 속하지 않는 예상치 못한 에러로 구분되어지죠.
서버 정의 에러는 단순히 토스트 메시지를 보여주거나, 특정 에러 문구를 보여줌으로써 에러가 발생했음을 유저에게 알려줄 수 있지만, 그 외의 에러(서버/네트워크 에러, 예상치 못한 에러)는 서버 정의 에러와는 다른 별도의 처리가 필요할 수 있겠다는 생각을 했어요.
그래서 에러 유형마다 구분이 필요하겠다는 생각을 하게 되었고, 타입 안전성을 보장하며 에러를 처리하기 위한 중앙 에러 핸들링 로직을 구현했습니다.
에러 타입 및 메시지 정의 (
./src/shared/api/type/response.ts)해당 파일은 서버에서 내려주는 에러 응답 타입(
ApiErrorResponse)을 정의하고, 에러 코드에 매핑되는 에러 메시지를 관리해요.타입 가드를 통한 안정성 확보 (
./src/shared/api/error-handler.ts)unknown타입인 에러 객체를 안전하게 다루기 위해, 서버에서 정의한 에러 타입인가를 판단하는 타입 가드(isAxiosErrorWithCustomCode)를 구현했어요.❓
RequiredWith타입이 왜 필요한가요?AxiosError타입에서response속성은 Optional(?.) 이에요. 네트워크 에러인 경우 응답(response) 자체가 없기 때문이죠. 따라서error.response.data.code에 접근하려고 하면 타입스크립트는response가 없을 수도 있다고 경고를 보냅니다.이를 해결하기 위해
RequiredWith타입을 사용하여 타입 가드를 통과한 에러는response객체를 반드시 가지고 있음을 보장해줍니다. 즉, 서버가 정의한 에러인 지를 나타내는 타입인 것이죠.위에서 만든 타입 가드를 활용해 공통 에러 핸들링 함수인
handleApiError에서 안전하게 분기 처리할 수 있습니다.또한 해당 로직을 적용하게 되면, 이미 error에 response가 들어있음을 보장하기 때문에, 아래와 같이 error에 response가 있는지 물음표 연산자로 확인할 필요가 없어집니다.
실제 사용할 때는 어떻게 사용하느냐?
tanstack-query와 함께 사용 시, 데이터를 바로 반환하므로 불필요한 래퍼 함수 없이 사용할 수 있습니다.
공통 에러 핸들링 함수는 tanstack-query(queryclient)에서 전역 공통 핸들러로 설정하면 중복 코드 없이 에러를 처리할 수 있을 것 같다는 생각입니다. (이건 개인 의견!!이라 api 연결할 때 한 번 고려해봐요🙌🏻)
👀 To Reviewer
./src/shared/api/generate경로에 위치시킬 예정입니다. 현재는 swagger 문서가 아직 만들어지지 않았기 때문에,http-client.ts역시 만들어지지 않았습니다.http-client.ts에는 타입과 API 함수가 존재하지만 별도 분리가 어렵다고 생각이 들어 template과 같은 경로인./src/shared/api/generate에 위치시켜 swagger-typescript-api와 연관이 있는 파일임을 명시하도록 했습니다.shared/api에 위치시켜 놓았지만, 각각shared/type과shared/utils로 이동시키는 것이 나을 지 고민 중..이에요.😭pnpm gen:swagger-ts-api명령으로 주기적으로 API 스펙을 업데이트할 수 있는데 업데이트를 남발하다보면 아무래도 내부에 생성된 타입을 사용하고 있는 다른 컴포넌트에 영향을 줄 수 있는 부분이다 보니,업데이트할 시점이나변경된 타입으로 인한 영향을 최소화할 수 있는 차선책(이것도 노션 아티클 한번 확인해주세요)을 생각해보면 좋을 것 같습니당.📸 Screenshot
🔔 ETC