😵💫 복잡해질 수도 있는 경로
프로젝트를 진행하다 보면 폴더의 구조가 복잡해질 가능성이 충분히 존재한다. 규모가 큰 프로젝트일수록 더욱 원하는 파일에 접근하기 위해 이리저리 움직여야 한다.
특히, 하위 폴더에 접근하는 것이 아니라 형제 폴더, 부모의 형제 폴더에 접근하는 것은 더욱 까다롭다. 다행히 vscode는 이런 복잡한 문제를 자동 import를 할 수 있는 기능을 제공해 주기 때문에 쉽게 해결 가능하다.
import 하고 싶은 모듈을 타이핑을 하다 보면 자동으로 import 하는 기능을 모두 다 사용해 봤을 것이다. 이를 활용하면 다음과 같이 vscode가 알아서 모듈의 위치를 찾아 import를 해준다.
import CreditCard from '../../components/CreditCard';
이만해도 충분히 개발을 하는데 큰 어려움 없이 원하는 모듈을 쉽고 편하게 불러올 수 있다.
하지만, 조금은 과장해서 deps가 10단계인 모듈에서 최상위 폴더의 모듈을 부르고 싶다면 ../ 는 아주 많이 반복될 것이다.
😇 편안해진 경로 - paths alias 사용하기
이때, typescrt의 complierOptions 중 paths를 추가하여 복잡해질 수 있는 경로를 간단하게 바꿀 수 있다.
tsconfig.json의 컴파일러 옵션에 paths를 추가하자
tsconfig.json의 내부 코드를 다음처럼 수정하자.
{
"compilerOptions": {
// ...
"baseUrl": "./src",
"paths": {
"@Components/*": ["./components/*"],
"@Constant/*": ["./constant/*"],
"@Hooks/*": ["./hooks/*"],
"@Pages/*": ["./pages/*"],
"@Utils/*": ["./utils/*"],
"@Types/*": ["./types/*"],
"@Domains/*": ["./domains/*"]
}
},
// ...
}
paths를 설정하기 전 먼저 baseUrl 설정이 필요하다. baseUrl를 기준으로 paths에서 작성하게 될 경로의 시작점이 달라지기 때문이다.
설정이 끝났으면 이제 절대 경로를 사용하여 모듈을 import 할 수 있다. 매우 간단한 설정이지만, import 하는 모듈을 깔끔히 불러온다는 점이 매력적이다.
자동 완성도 된다
위의 사진에서 보이는 것과 같이, @만 입력해도 import를 어떤 폴더로부터 시작할지 알 수 있다. 물론 필요한 모듈을 작성하면서도 자동완성이 가능하다.(아래 사진 참고)
깔끔해진 import
../ 를 반복하는 것보다 훨씬 깔끔하게 모듈을 import 할 수 있다. 또한 어떤 폴더에서부터 시작하는지 알 수 있어 해당 모듈이 어떤 모듈인지 짐작 가능하다. 예를 들어, 위의 사진에서 CreditCard는 @Components에서 import를 하고 있기 때문에 CreditCard가 컴포넌트라는 것을 짐작할 수 있다.
👍 paths alias의 장점
paths alias 즉, 절대 경로를 사용함으로써 얻을 수 있는 장점은 다음과 같다.
1. 어디에서 모듈을 import를 했는지 쉽게 파악할 수 있다.
2. import로 불러온 모듈이 어떤 역할을 하는지 추측하기 쉽다.
3. 가독성이 높아진다.
😱 오류 발견...
여기서부터는 저의 의견이 아주 많이 포함되어 있습니다. 잘못된 내용이 있으면 언제든지 찾아와 주세요.💦
paths alias 설정을 마치고 리액트를 시작하게 된다면 아마 다음과 같은 오류를 발견할 것이다.
분명.. vscode에선 경로를 잘 찾아가는데, 왜 resolve를 하지 못한다는 것일까? 이 문제를 해결하기 위해 정말 많은 검색을 하였고 여러 기술 블로그, 스택오버플로우를 참고하였다.
여러 번의 삽질 끝에 설정을 마무리할 수 있었다. 이러한 설정은 CRA로 시작한 프로젝트뿐 아니라 어떠한 프로젝트에서도 웹팩 설정이 필요하다. 왜냐! 절대경로를 알아야 하기 때문! 다른 상황에 대해선 정리를 하진 않고 CRA에 대해서만 다룬다.
🗝️ 그래서 어떤 문제였는데?
컴파일 단계와 런타임(컴파일이 끝난) 단계에서의 문제라고 난 생각한다.
tsconfig.json의 컴파일러 옵션에 절대 경로를 추가하였다. 하지만 중요한 것은 컴파일이 끝난 런타임 환경도 우리가 설정한 절대 경로를 알아야 한다는 것이다. 즉, 컴파일 단계에서만 절대 경로를 아는 것이고 실제 런타임 환경에서는 절대 경로를 모르는 상황이다. 이런 문제를 해결하기 위해 웹팩설정이 필요하다. 하지만.. CRA로 시작한 리액트 프로젝트에서는 웹팩 설정이 까다롭다. 때문에 다른 방법을 소개한다.
1️⃣ 필요한 라이브러리 설치
CRA에서 웹팩 파일을 꺼내서 설정하는 것이 번거로울 때 사용할 수 있는 라이브러리들이 있다. 그중 나는 다음의 라이브러리를 사용하였다.
1. react-app-alias(플러그인)
2. craco(라이브러리)
이를 먼저 설치하자.
$ yarn add --dev react-app-alias craco
또는
$ npm install --save-dev react-app-alias craco
2️⃣ jsconfig.paths.json 또는 tsconfig.paths.json 추가
jsconfig.paths.json 또는 tsconfig.paths.json 파일을 루트에 생성하고 내가 절대 경로로 할 부분을 작성해야 한다.
> tsconfig.paths.json
// tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@Components/*": ["./components/*"],
"@Constant/*": ["./constant/*"],
"@Hooks/*": ["./hooks/*"],
"@Pages/*": ["./pages/*"],
"@Utils/*": ["./utils/*"],
"@Types/*": ["./types/*"],
"@Domains/*": ["./domains/*"]
}
}
}
이후 tsconfig.json이 위에서 작성한 내용을 알 수 있도록 해줘야 한다. 다음과 같이 extends를 해주자. 기존에 tsconfig.json에 작성했던 paths는 삭제해도 된다.
> tsconfig.json
// tsconfig.json
{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
// ...
}
3️⃣ craco에 plugin 추가
craco는 Create React App Configuration Override 약자로 CRA에서 루트에 craco.config.js를 추가하여 웹팩 설정을 쉽게 도와주는 역할을 한다. 비슷한 기능을 하는 라이브러리에는 react-app-rewired가 있다.
아무튼..! 다음으로 해야 할 일은 craco.config.js를 작성하는 것이다. 다음과 같이 carco.config.js 파일을 루트에 만들고 작성하면 된다.
> craco.config.js
// craco.config.js
const { CracoAliasPlugin } = require('react-app-alias');
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {
source: 'tsconfig',
baseUrl: './src',
tsConfigPath: './tsconfig.paths.json', // 위에서 작성한 tsconfig.paths.json입니다.
},
},
],
};
이후 package.json의 scripts도 수정해야 한다. react-scripts 가 아니라 craco로 시작해야 하기 때문이다.
> package.json
// package.json
{
// ...
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject",
// ...
},
// ...
}
이후 yarn start 또는 npm start를 통해 프로젝트를 실행하면 오류가 사라진 편한 상태를 볼 수 있을 것이다.
📑 참고한 사이트
이번 문제를 해결하기 위해 참고한 블로그이다.
https://github.com/oklas/react-app-alias
https://tesseractjh.tistory.com/232
https://www.howdy-mj.me/boilerplate/craco-absolute-paths-setting
📚 스토리북에도 절대 경로 알려주기
paths alias을 적용하고 스토리북을 실행하게 되면 다음과 같은 에러를 볼 수 있다.
ModuleNotFoundError: Module not found: Error: Can't resolve '@Domains/creditCard' in '/Users/hd/Documents/react-payments/src/components/CreditCard'
이는 CreditCard 컴포넌트에서 @Domains~ 에 존재하는 모듈을 찾을 수 없다는 것이다. 이를 해결하기 위해선 스토리북에도 내가 설정한 절대 경로를 알려줘야 한다.
1️⃣ 필요한 라이브러리 설치
이때 필요한 라이브러리는 다음과 같다.
1. tsconfig-paths-webpack-plugin
먼저 설치부터 하자.
yarn add --dev tsconfig-paths-webpack-plugin
또는
npm install --save-dev tsconfig-paths-webpack-plugin
2️⃣ 스토리북 설정 추가
라이브러리를 설치하였으면 스토리북 설정 파일의 main.js에 다음과 같은 내용을 추가하면 된다.
> .storybook/main.js
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const path = require('path');
module.exports = {
// ...
webpackFinal: async (config) => {
config.resolve.plugins.push(
new TsconfigPathsPlugin({
configFile: path.resolve(__dirname, '../tsconfig.json'),
}),
);
return config;
},
};
이제 로컬에서 스토리북을 실행시키거나 스토리북을 배포할 때, 경로에 관한 오류는 없어진다.
📑 참고한 사이트
스토리북 절대 경로와 관한 오류를 해결하고자 참고한 블로그이다.
✏️ Jest에 절대 경로 알려주기
jest로 테스트 코드를 작성할 경우 외부 모듈에서 컴포넌트, 훅 등을 불러와야 한다. 이때 절대 경로를 사용할 경우, jest에게 절대 경로를 알려줘야 한다.
필요한 설정은 다음과 같다.
> craco.config.js
// craco.config.js
const { CracoAliasPlugin } = require('react-app-alias');
module.exports = {
plugins: [
{
plugin: CracoAliasPlugin,
options: {
source: 'tsconfig',
baseUrl: './src',
tsConfigPath: './tsconfig.paths.json',
},
},
],
// 아래는 기존 설정에서 jest를 위해 새롭게 추가된 부분이다.
jest: {
configure: {
moduleNameMapper: {
'^\\@Domains/(.*)$': '<rootDir>/src/domains/$1',
'^\\@Constants/(.*)$': '<rootDir>/src/constants/$1',
'^\\@Hooks/(.*)$': '<rootDir>/src/hooks/$1',
'^\\@Contexts/(.*)$': '<rootDir>/src/contexts/$1',
},
},
},
};
컴파일 문제로 인해 이미 craco.config.js가 있다면 위와 같이 jest에 내가 테스트에 필요한 모듈이 위치한 절대 경로를 알려주면 된다. 만약 craco.config.js가 없다면 🗝️ 그래서 어떤 문제였는데? 챕터를 참고하여 웹팩 설정을 마무리하면 된다.
📑 참고한 사이트
스토리북 절대 경로와 관한 오류를 해결하고자 참고한 블로그이다.
https://tesseractjh.tistory.com/223
'⚛️ 리액트' 카테고리의 다른 글
타이머를 구현하면서 마주한 문제와 해결 (1) | 2024.03.06 |
---|---|
State를 구조화하는 다섯 가지 원칙 (0) | 2023.06.05 |
React Router v6.4 이상에서 Router 다루기(RouterProvider, createBrowserRouter, Route) (0) | 2023.06.03 |