의존성 주입(dependency injection) : 어떤 함수나 클래스가 자신들이 내부적으로 사용할 기능을 자신들 내부에서(즉 스스로가) 만들어내지 않고, 외부에서 이 기능들을 만든 뒤 주입시키는 것.
예를 들어, app.jsx에서 유튜브 api를 호출하는 기능을 쓴다고 할 때 이 기능을 app.jsx 내에서 만들 수도 있겠지만, 외부에서 유튜브 api를 호출하는 기능을 만든 다음 app.jsx에게 주입(by props)하여 이를 쓰게 할 수도 있다. 이를 의존성 주입이라 한다. 찾아보니까 객체 지향 프로그래밍(OOP)에서 코드의 재사용성을 목적으로 잘 사용되는 패턴이라고 한다. (MVC패턴 등에서 view에 해당하는 애들이 비즈니스 로직도 처리할 수 있고 ~~도 할 수 있고~ 그러면 곤란..) 리액트에서는 컴포넌트들의 테스트를 하는 것에도 DI를 쓰는 게 좋다고 한다.
리액트에선 index.js에서 사용할 함수 등을 불러와 app.jsx에 집어넣고, 그 다음은 이를 쓰는 컴포넌트로 계속해서 전달전달하는 식으로 활용한다. 예를 들면 다음과 같다.
const authService = new AuthService();
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App authService={authService}/>
</React.StrictMode>
);
// authService객체는 login등의 메소드를 사용가능한 객체이다
그러면, App컴포넌트 안에 B컴포넌트 안에 C컴포넌트 안에 D컴포넌트 안에 E컴포넌트가 있다고 해보자. 또한 E컴포넌트는 login과 logout이라는 기능을 써야 한다. 이 때 방금 한 것처럼 index.js에서 login, logout메소드를 쓸 수 있는 객체(authService라고 가정)를 만들어 app.jsx에 넣어주고, app이 이를 계속 전달전달해주는 방식을 쓸 수 있다.
// index.js
const authService = new AuthService();
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App authService={authService}/>
</React.StrictMode>
);
// app.jsx
function App({authService}){
return <B authService={authService} />;
}
// B .jsx
function B({authService}){
return <C authService={authService} />;
}
// C.jsx
function C({authService}){
return <D authService={authService} />;
}
// D.jsx
function D({authService}){
return <E authService={authService} />;
}
// E.jsx
function E({authService}){
return(
<>
<button onClick={authService.login}>로그인</button>
<button onClick={authService.logout}>로그아웃</button>
</>
);
}
이 때 E에서 다른 기능들도 이용해야 한다면? 그래서 index.js에서 다른 객체를 만들어 E에 전달해야 한다면? app.jsx, B.jsx, C.jsx, D.jsx에 하나하나 직접 코딩을 해줘야 한다. 이 작업? 너무 귀찮다.
그래서 여기서 꼼수(?)가 하나 있다. index.js에서 애시당초에 필요한 의존성들을 집어넣은 E라는 컴포넌트를 만들어 이걸 전달하는 것이다. 다음과 같다.
const authService = new AuthService();
const youtube = new Youtube();
const Jofe = props => {
return(
<E {...props} authService={authService} youtube={Youtube}/>
);
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App Jofe={Jofe}/>
</React.StrictMode>
);
return <E authService={authService} youtube={youtube} /> 를 해도 되지만 확장성을 위해 저렇게 한 번 감싼 형태의 컴포넌트로 만들어서 전달할 수도 있다. 이렇게 하면 장점은, E에 새로 전달할 객체가 있어도 index.js에서 한 번만 수정하면 된다.
'WEB > REACT & NEXT' 카테고리의 다른 글
[짧][React.js] 렌더링이 2번 되는 현상 (0) | 2022.07.25 |
---|---|
[React.js] useEffect 정리 (0) | 2022.07.13 |
[React.js] setter함수의 비동기적 동작과 setter함수에 콜백사용(함수형 업데이트) (0) | 2022.07.04 |
[React.js] 리액트와 firebase로 구글로그인 연동하기 (0) | 2022.06.23 |
[React.js] 리액트에서 fontawesome 쓰는 법 (0) | 2022.05.11 |