티스토리 뷰
잘 운영되고 있는 프론트엔드 코드 전체를 한번에 바꾸는것은 불가능하다. 천천히 하나씩 바꿔야한다.
왜 그렇게 해야하나?
많은 코드를 한번에 리팩토링하는것은 큰 위험부담이 따르기 때문이다. 다만, 리팩토링 기간이 길어질수록 두가지 application을 유지보수해야하는 기간도 늘어나며 이 리팩토링 기간에는 리액트의 완전한 장점을 누리지 못한다는 점을 감수해야한다.
현 상황 가정
당신은 서버사이드렌더링 방식으로 제공되는 HTML을 통해 고객들에게 서비스하고있다고 가정한다. 자바스크립트로 DOM을 조작하는 현재의 방식은 어플리케이션의 전체 상태를 관리하지 않는다. 그저 DOM에 직접 접근해서 하나하나를 수정할 뿐이다. 그래서 서버에서 받아온 데이터와 UI를 일치시키는 과정이 매우 까다로운 상태다. 그리고 가끔은 관련없는 컴포넌트가 같이 수정되기도 하는 애로사항이 있다.
이러한 불편함을 리액트는 바로잡아줄 수 있다. 리액트는 관련있는 코드(html, css, js)가 하나의 컴포넌트로 집약되기 때문에 관리하기 편하고 내가 변경하고 싶은 컴포넌트들만 일관되게 변경시킬 수 있으며 데이터와 UI를 일치시키는 문제도 아주 심플하게 해결해준다. 그저 데이터를 변경해주기만하면 리액트가 알아서 렌더링을 다시 해준다. 한마디로 리액트는 프로젝트의 유지보수성을 굉장히 높여주는 라이브러리이다.
Uyuni의 multi-page application To React 전환 과정
Uyuni는 15년 이상된 프로젝트이며 굉장히 많은 레거시를 갖고 있었다. 만약에 당신이 새로운 기술을 도입하면서 계속해서 유저들에게 새로운 기능을 제공하고 싶으면 반드시 반복적으로 리팩토링해야한다. 그렇지 않으면 굉장히 힘든 시간을 보내게 될 것이다.
당신이 특정 기술에 얽매이지 않도록 하는 두가지 조언이 있다.
- 새로운 라이브러리를 도입하는것은 당장의 몇일을 아낄 수는 있지만, 장기적으로는 오히려 도움이 안될 수도 있다.
- 당신의 비즈니스 로직이 특정 프레임워크에 종속되지 않고 언어의 native feature에만 종속되게 만들면 나중에 어떤 프레임워크로든 쉽게 이전할 수 있다.
Uyuni에서도 리액트 공식문서에서 추천하는 migration 방식인 ReactDOM.render(<App />, htmlContainer) 를 통한 점진적 리액트 도입 방식으로 전환을 했다고 한다.
위와 같이 컨테이너별로 독립적인 리액트 컴포넌트 트리를 구축하면 된다. 만약 리액트 컴포넌트끼리 서로 소통할 필요가 있다면 어떻게 해야할까? 어떻게 서버의 데이터를 리액트 컴포넌트로 주입해줄 수 있을까?
우리의 경우엔, 컴포넌트간 의사소통과 데이터 주입문제를 서버를 통해 해결했다. 애초에 서버에서 HTML을 내려줄때 데이터가 포함된 상태로 내려주기 때문에 각각의 컴포넌트는 그 정보중 자신이 필요한 정보를 가져와 사용하기만 하면 된다.
main.bundle.js
모든 컴포넌트를 쉽게 dynamic import 할 수 있도록 spaImportReactPage라는 global 함수를 export했다.
content-management/index.js
이 파일에선 컴포넌트 하나하나를 dynamic import하는 구문들이 들어있다.
spaImportReactPage('content-management/list-projects'); // Promise를 리턴함.
spaImportReactPage라는 글로벌 함수에 import하고 싶은 컴포넌트의 이름을 넘기면 다음 부분이 실행된다.
() => import('./list-projects/list-projects.renderer.js');
여기까지 실행되면 브라우저가 해당 페이지에서 사용되는 컴포넌트의 js파일을 동적으로 불러온 상태다.
init_data_projects 컨테이너에 #{contentProjects} 부분에는 jsp에서 만들어 내려준 데이터가 들어있을것이다.
거기에 있는 텍스트(리액트에서 필요한 state의 정적인 값) 를 리액트 컴포넌트 content-management-list-projects를 렌더링 하면서 같이 props로 주입해주고 있는 형태이다.
주의할것은 위에서 상당히 많은 ES6의 문법이 사용되고 있으며 전혀 트랜스파일링이 되지 않고 있다. IE나 안드로이드, ios 하위 버전을 대응하기 위해서는 polyfill을 추가해야한다.
빠른 개발 사이클
실 환경에서는 데이터를 서버에서 주입하고 있다. 그럼 개발할때는 데이터를 어디서 주입 받아야 하는가에 대한 또다른 문제에 부딪혔다. 이것은 생각보다 더 복잡한 문제였다. 그래서 우리는 이렇게 해결했다.
개발 환경 자체도 운영 환경에서 데이터를 서버에서 주입받는 환경과 똑같이 맞춘것이다. 중간에 프록시를 두고 로컬 백엔드 서버에서 똑같은 형태의 html을 내려받은 뒤 그곳에 주입된 데이터를 가지고 리액트 컴포넌트 트리를 구축하는 형태이다.
로컬에서 프론트 환경과 백엔드 환경을 모두 구축한뒤, 기존방식대로 프론트를 개발하고 프론트와 관련없는 것들은 모두 로컬 백엔드 서버에서 처리한다. 로컬 개발서버가 아니라 공유된 어떤 개발서버일수도있긴하다. 테스트를 하기 위해서 백엔드 환경을 구축할 필요가 없다.
출처
https://xebia.com/blog/migrating-to-react-step-by-step/
'React' 카테고리의 다른 글
JSX element type 'TabComponent' does not have any construct or call signatures. (0) | 2020.06.03 |
---|---|
JSX.Element vs ReactNode vs ReactElement의 차이 (1) | 2020.05.21 |
useRef vs document.getElementById 둘중 어느게 더 좋을까? (0) | 2020.05.07 |
emotion 사용시 jsx pragma 제거하기 (0) | 2020.04.17 |
useEffect 완벽가이드 - 3편 (0) | 2020.04.03 |
- Total
- Today
- Yesterday
- return type
- react hooks
- javascript
- server side rendering
- state
- atomic design
- type alias
- Action
- reducer
- design system
- reactdom
- reflow
- promise
- props
- Next.js
- await
- react
- hydrate
- Polyfill
- typescript
- mobx
- useRef
- async
- Babel
- rendering scope
- webpack
- computed
- storybook
- useEffect
- es6
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |