일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 비동기
- 이종호
- 리액트 예제
- hokidoki
- hokeys
- jest
- TDD
- HTML
- 자료구조
- 자바스크립트
- 리액트
- Svelte
- IOS
- Hitit
- data structure
- 스벨트
- 계명대
- 힛잇
- SWIFT
- 호키도키
- 호키스
- 자바스크립트 자료구조
- 자스민
- 개발자
- 스위프트
- javascript
- 계명대 이종호
- queue
- 개발
- react
- Today
- Total
Dog foot print
React resolve + css/sass + typescript 적용하기 본문
기본 폴더 구조 및 파일 구조
Note : /src/Components/Header.jsx
, /src/Utils/Math.ts
, /src/style/main.css
, /src/Utils/index.ts
, /src/UI/Button.tsx
를 제외한 파일들은 이전 포스팅에서 내용을 확인해주세요
Note : 이 포스팅은 webpack-dev-server
사용 할 수 있도록 webpack.config.js
와 의존성이 일부 설치되어 있습니다. 이전 포스팅에서 내용을 확인해주세요.
폴더 구조
.
├── babel.config.js
├── dist
│ ├── bundle.js
│ └── index.html
├── package.json
├── public
│ └── index.html
├── src
│ ├── App.jsx
│ ├── UI
│ │ └── Button.tsx
│ ├── Utils
│ │ ├── Math.ts
│ │ └── index.ts
│ ├── Components
│ │ └── Header.jsx
│ ├── constants
│ ├── index.js
│ └── style
│ └── main.css
├── webpack.config.js
└── yarn.lock
src/Utils/Math.ts
export function add(a: number, b: number) {
return a + b
}
src/Utils/index.ts
export * from "./Math"
src/UI/Button.tsx
import React from 'react'
export default function Button() {
return (
<button>Hello world</button>
)
}
src/style/main.css
div{
color : blue
}
src/Components/Header.jsx
import React from 'react'
export default function Header() {
return (
<div>Header</div>
)
}
Resolve
Webpack의 Resolve 옵션은 모듈을 불러 올 때, 어디서 어떻게 찾는가? 에 대한 옵션이다. 예를 들어 우리는 모듈을 불러 올 때, 상대경로로 파일을 작성한다. 그러나, 프로젝트 규모가 커지고 폴더들이 분산되어 버린다면, 모듈을 찾기위해 ../../../
이렇게 작성한다면, 매우 폭력적인 코드가 될것이다. 이를 위해, Resolve
옵션은 alias
와 같은 기능을 통해 특정 문자열을 특정경로로 해석 해주는 기능을 제공한다.
alias
우리는 현재 위치를 기준해서, 특정 파일 혹은 폴더까지 경로를 상대경로 라고 한다. 그리고 컴퓨터 루트 폴더에서 특정 파일 혹은 폴더까지 경로를 절대경로라고 한다.
상대경로를 사용하는 경우, 바로 같은 폴더내에 위치하는 파일을 찾거나 하위 폴더에 위치한 파일을 찾는 것은 크게 불편하지 않다. 그러나, 찾는 파일이나 폴더가 현재 위치보다 상위 폴더에 위치하고 있을 때, 상위 폴더로 이동하기 위해서 ../
를 사용해야 한다.
문제는 상위 폴더로 이동이 많아 질수록 ../
를 많이 사용해야 하며, 현재 파일의 위치가 변경되면 이 경로 또한 변경되어야 한다.
alias
옵션은 특정 문자열을 특정 경로로 변경해 줄 수 있다. 이말인 즉 특정 문자열을 절대경로로 변경이 가능하다는 것이다.
현재 ‘src’ 폴더내에 폴더는 components, style, ui, utils가 존재하니 이를 alias를 이용해서 경로를 지정해보자.
const path = require("path");
...
module.export = {
...
resolve: {
alias: {
"@Components": path.resolve(__dirname, 'src/Components/'),
"@UI": path.resolve(__dirname, 'src/UI/'),
"@Utils": path.resolve(__dirname, 'src/Utils/'),
"@style": path.resolve(__dirname, 'src/style/')
}
},
...
}
alias옵션을 설정하는 것은 매우 간단하다. resolve 옵션을 생성하고 alias객체를 생성 한 뒤, 경로를 지칭할 key와 경로를 설정해주면 된다. alias 옵션으로 설정된 경로는 ‘at’의 의미를 담아 “@”를 접두사로 주로 사용한다. 이제 이를 이용하여, App.jsx 에서 /src/Components/Header.jsx를 불러보자.
/src/App.jsx
import React from 'react'
import Header from "@Components/Header.jsx"
export default function App() {
return (
<div>
<Header></Header>
</div>
)
}
성공적으로 App.jsx 에서 Header.jsx를 사용 할 수 있다.
Extensions
Css와 같은 파일들은 자주 임포트하지 않으니, 확장자를 사용하는 것은 감수 할 수 있다. 그러나 스크립트 파일은 자주 사용해야 하다보니, js,jsx,ts,tsx
를 사용하는 것은 매우 귀찮은 일이 될 수 있다.
extensions
옵션은 확장자를 가지지 않은 경우, 내가 지정한 순서에 따라, 해당 폴더내에서 확장자를 부여하며 같은이름의 파일을 찾을 수 있다
webpack.config.js
module.exports = {
resolve: {
extensions : [".js",".jsx",".ts",".tsx"],
alias: {...}
},
}
src/App.jsx
import React from 'react'
import Header from "@Components/Header"
export default function App() {
return (
<div>
<Header></Header>
</div>
)
}
이제 확장자 없이 경로를 지정하여도, 파일을 찾을 수 있다.
css 사용해보기
Src/index.js
import "@style/main.css"
css를 import 하기 위해서는 css-loader
가 필요하다.
$: yarn add -D css-loader
webpack.config.js
module.export = {
...
module: {
rules: [
...
{
test: /\.css$/i,
use: ["css-loader"],
},
],
},
...
}
여기까지 진행 했지만 파일이 생성되거나, 어떤 변화도 존재하지 않는다. 그 이유인 즉css-loader
는 ‘.js’ 파일에서 css파일을 가져오는 역할만 하기 때문이다. Import 되어 있는 css를 사용하기 위해서는 style-loader
혹은 MiniCssExtractPlugin
이 필요하다.
$: yarn add style-loader mini-css-extract-plugin -D
먼저 style-loader는 임포트되어 있는 css를 렌더링 되는 html에서 style태그를 만들어, 스타일을 사용 할 수 있게한다. 사용 방법은 use
배열에 style-loader
입력하면 된다.
webpack.config.js
module.export = {
...
module: {
rules: [
...
{
test: /\.css$/i,
use: ["style-loader","css-loader"],
},
],
},
...
}
이렇게 작성하고, $: yarn dev
명령어로 확인해보면 다음과 같이 임포트 된 css가 스타일 태그로 변경된 결과를 볼 수 있다.
이번에는 스타일 태그가 아닌 css 파일로 제공 해줄 수 있도록 mini-css-extract-plugin
을 사용해보자.
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
...
module.export = {
...
module: {
rules: [
...
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader,"css-loader"],
},
],
},
plugins: [
...
new MiniCssExtractPlugin()
],
...
}
위와 같이 작성하고, 다시 $: yarn dev
명령어를 실행해보면 아래와 같이 html파일에 main.css가 링크되고, dist폴더에는 ‘main.css’라는 파일이 생성된다.
sass 사용해보기
$: yarn add sass-loader sass
sass-loader : sass를 css로 변환해주는 모듈
sass : sass를 해석하기 위한 모듈
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
...
module.export = {
...
module: {
rules: [
...
{
test: /\.s[ac]ss$/i,
use: [
// css file gen
MiniCssExtractPlugin.loader,
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
],
},
...
}
src/components/Header.jsx
import React from 'react'
export default function Header() {
return (
<div>
<h1 className='title'>WOW</h1>
<h2 className='sub-title'>H2</h2>
</div>
)
}
src/style/main.css -> /src/style/main.scss
포맷 변경
div{
.title{
color: red;
}
.sub-title{
color : blue
}
}
Header.jsx와 main.scss를 변경하면 다음과 같은 렌더링 결과와 scss의 결과물을 볼 수 있다.
typescript 적용하기
$ : yarn add typescript ts-loader @types/react @types/react-dom -D
ts-loader : 웹팩에서 typescript를 사용 할 수 있게 해주는 모듈
typescript : typescript를 javascript로 변환시켜주는 모듈
@types/react : react type
@types/react-dom : react-dom type
ts파일을 웹팩으로 번들링 하기위해서, 아래와 같이 로더를 적용 시켜주고 js파일을 ts로 변환하기 위해서, entry를 index.js를 index.tsx로 변환합니다.
/webpack.config.js
...
const javascriptRegex = /\.(jsx|js)$/;
const typescriptRegex = /\.(ts|tsx)$/;
...
module.export = {
...
entry: "./src/index.tsx", // main
module : {
rules : [
...
{
test: javascriptRegex,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: typescriptRegex,
exclude: /node_modules/,
use: ["ts-loader"]
},
...
]
}
}
typescript를 처리 할 수 있도록 간단하게 tsconfig.json파일을 생성해줍니다.
/tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"moduleResolution": "node"
}
}
이제 index.js를 index.tsx로 변환하고 jsx파일들을 tsx파일들로 포맷을 변환시켜 줍니다.
Index.js -> index.tsx
Header.jsx -> Header.tsx
App.jsx -> App.tsx
Tip : index.js를 .ts포맷이 아닌 tsx포맷으로 변경하는 이유는 현재 index.js에서 jsx문법을 사용했기 떄문입니다. typescript를 설치한 지금 typescript의 규칙을 따라야합니다.
여기까지 하고 실행을 시작하면 아래와 같이 분명 번들링은 되었음에도, 에러메세지가 등장 할 것이다. 또한 에디터에서 @Components/Header가 무엇이냐고 비명을 지를 것이다.
이 문제는 typescript를 적용하면서, typescript에게 alias
된 경로를 알려주지 않았기 때문이다. 이는 typescript가 사용될 수 있는 javascript로 변환 되는 과정만을 행하고 import
되어 있는 모듈을 연결하는 일은 번들러가 담당하기 때문에 발생하는 것이다.
그렇기에 tsconfig.json 에서 alias된 값들을 명시하고 baseUrl위치 기준에서 작성해야 한다.
tsconfig.json
{
"compilerOptions": {
...
"paths" : {
"@Components/*" : ["src/Components/*"],
"@Utils/*" : ["src/Utils/*"],
"@UI/*" : ["src/UI/*"],
"@style/*" : ["src/style/*"]
}
},
...
}
이제 App.tsx에서 Header를 사용하는데, 문제가 없을 것이다. 추가로 Button.tsx도 변경하여, 사용해보자.
src/App.tsx
import React from 'react'
import Header from "@Components/Header"
import Button from '@UI/Button'
export default function App() {
const buttonAttributes = {
onClick : () => alert("???")
}
return (
<div>
<Header></Header>
<Button attribute={buttonAttributes}>
hi
</Button>
</div>
)
}
src/UI/Button.tsx
import React, { ReactNode} from 'react'
type JSX_ElementKey = keyof JSX.IntrinsicElements
interface ElementProps<T extends JSX_ElementKey> {
attribute? : JSX.IntrinsicElements[T],
children :ReactNode,
}
export default function Button(props? : ElementProps<"button">) {
const {attribute = {},children} = props
return (
<button {...attribute} >
{children}
</button>
)
}
폴더 index 탐색
onClick을 이전에 만들어놓았던 add함수를 이용을 해보자. 폴더 구조만 명시 했을 경우에는 자동으로 index
라는 파일을 찾게 된다.
src/App.tsx
import React from 'react'
import Header from "@Components/Header"
import Button from '@UI/Button'
import { add } from "@Utils"
export default function App() {
const buttonAttributes = {
onClick : () => alert(add(1,1))
}
return (
<div>
<Header></Header>
<Button attribute={buttonAttributes}>
hi
</Button>
</div>
)
}
이를 yarn dev
명령어를 이용해서, 실행하니 또 아래와 같이 에러를 발생시키지만, 코드는 작동한다.
이번에는 뭔가 느낌이 올 것이다. “아 … 이건 typescript에서 문제가 발생하는 구나 …” 그렇다.
tsconfig.json
{
"compilerOptions": {
...
"paths" : {
"@Components/*" : ["src/Components/*"],
"@Utils/*" : ["src/Utils/*"],
"@UI/*" : ["src/UI/*"],
"@style/*" : ["src/style/*"]
}
},
...
}
여기서 문제는 @Utils/*
는 @Utils
와 동일하지 않기 때문에 발생한 것이다. alias를 명시한 경로에서 index파일을 찾으려면 이를 명시해주어야 한다. 아래와 같이 @Utils 항목을 생성해주자.
tsconfig.json
{
"compilerOptions": {
...
"paths" : {
"@Components/*" : ["src/Components/*"],
"@Utils/*" : ["src/Utils/*"],
"@Utils" : ["src/Utils/index"],
"@UI/*" : ["src/UI/*"],
"@style/*" : ["src/style/*"],
}
},
...
}
이제 실행하였을 때 에러를 발생시키지 않는다.
'REACT' 카테고리의 다른 글
useEffect 조금 더 자세히 사용해보기 (0) | 2023.03.27 |
---|---|
useState 조금 더 자세히 사용해보기 (0) | 2023.03.23 |
React 시작 환경 구축하기 (0) | 2023.03.11 |
[React] Hook기본 다지기#3 context (0) | 2021.03.30 |
[React] Hook기본 다지기#2 custom hook. (0) | 2021.03.28 |