index.ts
라는 폴더에
export * from './something'
이렇게 작성된 코드들이 있었는데 대충 여기 해당된 모듈을 전부 Export 해주는구나 라고 알기는 했지만
이런 패턴을 뭐라고 명명하는지, 어떤 장점이 있는지 알아보고 싶어서 작성하게 됨
배럴(Barrel)이라는 이름은 마치 술통(barrel)처럼 여러 내용물을 하나의 통에 담아두는 것에서 유래
*
는 '모든 것'을 의미하는 와일드 카드 export 문법이다. export * from './Header
는
Header
파일에서 export 된 모든 것을 다시 export 한다는 의미
깔끔한 import 구문
모듈 구조 캡슐화
유지보수
export *
구문을 사용하면 번들러가 어떤 코드가 실제로 사용되는지 파악하기 어려울 수 있다.// components/index.ts
export { Button } from './Button';
export { Input } from './Input';
export { Modal } from './Modal';
export { Table } from './Table';
이렇게 명시적으로 export 하면 트리쉐이킹이 효과적으로 동작한다.
// components/index.ts
export * from './Button';
export * from './Modal';
// components/Button.ts
import { Modal } from './Modal';
export const Button = () => {
return <button onClick={() => Modal.show()}>Open Modal</button>;
};
// components/Modal.ts
import { Button } from './Button';
export const Modal = () => {
return <div><Button /></div>;
};
Button
이 Modal
을 참조하고, Modal
이 Button
을 참조하는 순환 구조
이런 구조는 예측할 수 없는 동작이나 런타임 에러를 발생
코드가 복잡해질 수록 디버깅 어려워 짐
// src/components/index.ts
export * from './Header'
export * from './Counter'
// src/components/Counter.tsx
import { useState } from 'react'
export const Counter = () => {
const [count, setCount] = useState(0)
return (
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
</div>
)
}
// src/components/Header.tsx
import { viteLogo, reactLogo } from '../assets'
export const Header = () => {
return (
<div>
<div>this is header</div>
</div>
)
}
컴포넌트들을 App.tsx
에 import 해보자
// src/App.tsx
import { Header, Counter } from './components'
import './App.css'
function App() {
return (
<>
<Header />
<h1>Vite + React</h1>
<Counter />
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
}
export default App
이렇게하면