가장 먼저 미리 구현되어 있던 API 관련 파일들을 server 폴더 아래에 옮겼다. 이후 CRA를 사용하여 client 세팅을 해주었다.
이때 아래와 같은 에러가 나면서 CRA가 동작하지 않았다.
You are running `create-react-app` 4.0.3, which is behind the latest release (5.0.1).
We no longer support global installation of Create React App.
최근 버전의 create-react-app
에서는 패키지가 글로벌하게 설치되는 것을 막고 있나보다. 아래와 같이 입력하여 create-react-app
을 제거해준 뒤 다시 설치하니 제대로 동작하였다.
npm uninstall -g create-react-app
yarn global remove create-react-app
처음에 craco라는 라이브러리를 통해 설정하려 하였으나 CRA 4 버전까지만 지원하기 때문에 실패하였다. 그래서 다른 방법으로 시도해보았다. 참고링크
tsconfig.json
파일에 아래 내용을 추가// tsconfig.json
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"@/components/*": ["src/components/*"]
}
}
}
이제 IDE에서 절대경로를 사용할 수 있게 되었으나 브라우저에서 실행했을 때 파일을 찾을 수 없다는 에러가 나온다.
이는 typescript 컴파일 시에 tsconfig를 활용하여 경로 추적이 가능하지만, 실제 webpack 번들에서는 해당 경로가 고려되지 않은 채 빌드되기 때문이라고 한다. 번들 파일이 생성되고, 브라우저에서 스크립트 실행 시 해당 경로를 추적하지 못하여 모듈을 찾지 못하는 에러가 발생하는 것이다.
빌드 시 경로 설정을 해주려면 webpack.config
에서의 경로 설정이 필요한데 eject
를 해야한다는 단점이 있다. 그래서 사용하게 된 것이 react-app-rewired
이다. 이는 craco처럼 eject를 하지 않고 webpack 구성을 할 수 있게 도와주는 라이브러리이다.
npm install react-app-rewired customize-cra
2-1. package.json의 scripts 수정
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
2-2. config-overrides.js
파일 추가
const { override, addWebpackAlias } = require("customize-cra");
const path = require("path");
module.exports = override(
addWebpackAlias({
"@": path.resolve(__dirname, "src/"),
})
);
위와 같이 추가하여 webpack 설정을 오버라이드하고 커스터마이징할 수 있다.
다른 사람들이 어떻게 챌린지 작업을 했는지 보고 있는데 react-query
가 아닌 tanstack/react-query
를 사용하고 있는 걸 보았다. 무슨 차이인가 싶었는데 tanstack/react-query
는 react-query
가 리브랜딩된 버전이라고 한다. 버전 4부터는 tanstack/react-query
에서 업데이트 되기로 했다고 하니 나도 이걸로 선택하게 되었다.
retry 옵션은 API가 실패하면 설정한 값만큼 재시도 하는 옵션이다. 0으로 설정하면 재시도하지 않고 유저에게 빠른 응답을 보여줄 수 있다. 현재 나는 서버 이슈까지는 고려할 필요가 없으므로 0으로 설정하였다.
useErrorBoundary옵션은 리액트16 이상에서 제공하는 Fallback UI 설정에 대한 옵션이다. 에러 상황시 어떻게 되는지 테스트해보고 싶어 queries와 mutations에 true 값으로 설정하였다.
new QueryClient({
defaultOptions: {
queries: {
retry: 0,
useErrorBoundary: true,
},
mutations: {
useErrorBoundary: true,
},
},
});
회원가입 페이지를 만들면서 공식 문서에 나온대로 아래와 같이 useMutation을 작성해보았다.
const mutation = useMutation({
mutationFn: (variables) => {
return axios.post("http://localhost:8080/users/create", variables);
},
});
const onSubmit = (data: FormData) => {
mutation.mutate({
[EMAIL]: data[EMAIL],
[PASSWORD]: data[PASSWORD],
});
};
그런데 아래와 같이 type 에러가 떴다.
TS2345: Argument of type '{ email: string; password: string; }' is not assignable to parameter of type 'void'
useMutation을 (커맨드)클릭해서 어떻게 만들어져 있는지 보니 아래와 같이 되어있었다. 여기서 TVariables
부분이 void로 디폴트 설정이 되어있었던 것이다.
export function useMutation<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown,
>(
options: UseMutationOptions<TData, TError, TVariables, TContext>,
): UseMutationResult<TData, TError, TVariables, TContext>
아래와 같이 직접 타입을 지정해주었더니 에러가 사라졌다. 나머지 값들도 작업하면서 필요에 따라 넣어줘야겠다.
interface SignUpVariable {
email: string;
password: string;
}
const mutation = useMutation<unknown, unknown, SignUpVariable, unknown>({
mutationFn: (variables) => {
return axios.post("http://localhost:8080/users/create", variables);
},
});