리액트 라이브러리는 SPA으로 url 이 바뀌어도 refresh 하지 않는 장점이 있습니다.
리액트는 CSR 방식으로 작동합니다. 그렇기 때문에 프로젝트가 복잡해지면 .js 가 커지는 단점이 있습니다.
또한 리액트는 Virtual ReactDOM 기반으로 뛰어난 퍼포먼스를 보여주고 개발 과정이 컴포넌트 기반으로 재사용성이 뛰어난 점이 있습니다. 그리고 해당 컴포넌트는 state와 props 를 가지게 됩니다.
Single Page Application 의 약자로,
하나의 안에서 추가적인 refresh 없이 서비스를 제공하는 개념이다.
Client Side Rendering 의 약자로,
Server 로부터 빈 index.html 과 *.js 을 받아와서 브라우저를 통해 사이트를 랜더링 한다는 개념이다.
서론에서 봤던 것 중,
우리가 먼저 알아야 할 핵심이론은 Virtual ReactDOM 과 State 입니다.
각각 어떤 의미를 가지고 있고 나아가 Props 와 State 에서 언급하고 넘어가겠습니다.
리액트 이전, 일반적인 웹사이트는 HTML, CSS, Vanilla JS 로 구성되었습니다.
따라서 서버는 클라이언트에게 이러한 파일들을 넘겨주게 됩니다.
그리고 클라이언트 측에서는 브라우저가 이러한 파일들을 랜더링하게 됩니다.
따라서 모든 파일을 받고 랜더링하게 됨에 따라 낮은 퍼포먼스를 보여주게 됩니다.
하지만, 리액트에서는 지침표가 될 index.html 과 하나의 bundle.js 파일만을 넘겨줍니다.
index.html 에는 id값을 가지고 있는 간단한 HTML Tags 만이 존재하고 실제 파일은 bundle.js 에 있습니다.
클라이언트의 요청에 따라 ReactDOM 은 내부 변화를 이루게 되고,
결과값만을 클라이언트에게 보내주어 실제 랜더링을 하게 됩니다.
따라서 높은 퍼포먼스를 가질 수 있게 됩니다.
state, 번역하면 상태 혹은 국가(또는 주)의 뜻을 가지고 있는 단어입니다.
props(properties), 속성이라는 뜻을 가지고 있는 단어입니다.
즉, properties 는 클래스라는 개념을 배운 분이라면 이미 접해본 단어일 것입니다.
클래스는 매개변수를 가지고 해당 매개변수를 "넘겨준다" 라는 관점에서 props 라느 단어를 사용하고 있습니다. args(arguments)라고도 하고 parameter라고도 합니다.
그렇다면 state는 이들과 무슨 차이점이 있을까요?
state 는 동적 상태의 변수 관리 개념입니다.
하나의 ReactDOM 안에는 state 가 존재하고 그 state 가 변수의 생성 및 사용을 담당하고 있는 하나의 "구역" 으로서 작동을 합니다. 나아가, 우리는 state 라는 기능을 사용하기 위해서 몇 가지 방법을 가지고 있습니다.
props 는 쉽게 말하면 함수에게 매개변수를 넘겨준다라는 관점이다.
받은 문자열을 출력해주는 함수 printMessage 를 아래에 만들었다.
function printMessage(hello){
console.log(hello);
}
당신이 printMessage("Hello") 라고 쓰면 콘솔창에 Hello 가 출력될 것이며,
printMessage("Oh! No!") 라고 쓰면 콘솔창에 Oh! No! 라고 출력될 것이다.
여기서 "..." 가 변수 hello가 될 것이며,
이것을 우리가 매개변수 이자 props라고 부른다.
그렇다면 state는 무엇일까?
state는 컴포넌트 내부에서 선언되고 사용되고 소멸되는 개념이다.
특히 React 에서는 Class Render 방식을 사용하게 되었을 때,
state 와 setState 가 명확하게 구분된다.
과거에는 이 state를 쓰려면 무조건 React.Components 를 상속한 class 의 방식을 사용해야 헀지만, 지금은 useState 를 통해서 사용할 수 있다.
파일구조는 지극히 개인적인 취향이며, 개인차가 있습니다.
기본적으로 다음의 구조를 따르도록 한다. (임포트 구문 생략하였음)
ReactDOM.render(<App />,document.getElementById("root"));
class App extends React.Component {
render(){
return (
<>
<Router />
<InitialStyles />
</>
)
}
};
import { createGlobalStyle } from "styled-components";
import reset from "styled-reset"
const InitialStyles=createGlobalStyle`
${reset};
*{
box-sizing: border-box;
}
// 구체적으로 적용할 요소들
`;
export default InitialStyles;
react-router-dom 에 있는 기능들을 이용해서 route 들과 연결합니다.
express 에서의 app.use("/link",linkRouter) 과 동일한 맥락입니다.
react-router-dom@6 삭제 및 대규모 업데이트가 있습니다.
이에 관한 주요 변동 사항은 최 하단에 기록되어 있습니다.
npm install react-router-dom@5 로 설치합시다.
import { BroswerRouter,Route,Redirect Switch } from "react-router-dom";
export default ()=>{
<Router>
<Switch>
<Route path="" exact component={Home} />
<Route path="/movie" exact component={Movie} />
<Redirect from="*" to="/" />
</Switch>
</Router>
};
express controllers 처럼 각 라우터에서 랜더링 할 코드들이 적혀있는 파일들이 있습니다.
리액트는 JS 파일 안의 render 안의 HTML 요소들을 사용자에게 보여줍니다.
이를 랜더링이라고 표현하고 그 방식에는 두 가지가 있습니다.
저는 여기서 Basic Render 과 Class Render 으로 분류하여 정리해보았습니다.
Basic Render 는 return 을 이용하여 랜더링한다는 의미입니다.
다음과 같이 작성된 Button 함수를 Router.js 에서 호출하면, Hello 가 나옵니다.
function Button(args){
return (<span> Hello </span>);
}
물론 해당 함수를 변수화 시켜서 사용할 수도 있습니다.
const Button=()=>{
return(<span> Button </span>);
}
ES6 의 Implicit Return, 암묵적 반환 을 이용하여 깔끔한 코드로 바꿔보았습니다.
const Button=()=><span> Button </span>;
익명함수에서 { } 를 쓰지않고 하나의 문장만 가리키고 있다면,
익명함수는 그 문장을 암묵적으로 반환합니다.
제가 Function Render 이 아닌 Basic Render 이라고 한 것이 이 이유입니다.
아래는 응용 사항에 대해서 적었으니, styled-components 를 사용하지 않으면 넘겨주세요.
styled-components 는 style sheets 를 JS 파일 안에 넣기 위해서 사용하는 module 입니다.
일반적으로 변수를 선언하고 그 변수 안에 모듈을 넣습니다.
stlyed.HTML_TAGS 혹은 styed(COMPONENTS) 의 방식으로 선언합니다.
import styled from "styled-components";
const Button=styled.Button``;
const Link=styled(Link)``;
그러나 styled-components 를 사용하여 Recyclablee Components 를 만들다 보면, 변수 이름과 관련하여 불편함이 있습니다.
export 할 Components 와 styled varbialse 의 이름이 겹쳐지기 때문입니다.
import styled from "styled-components";
const Button=styled.Button``;
export const Button=()=><Button>Hello</Button>;
이러한 경우에는 export default 를 이용해서 쉽게 해결할 수 있습니다.
하지만 이를 위해서 파일명을 Button.js 으로 정해줘야 합니다.(JS 내용)
import styled from "styled-components";
const Button=styled.Button``;
export default ()=><Button>Hello</Button>;
가장 바깥 영역에 익명함수를 선언하고 그 익명함수를 담을 변수 영역을 지정해주지 않고 export default 를 하면 해당 파일 이름으로 된 컴포넌트가 완성됩니다. 이를 통해 복수의 이름을 차지않고 하나의 컴포넌트를 내보낼 수 있습니다.
과거에는 state 를 쓰려면 무조건 React.Component 를 사용했어야 했다. 하지만 지금은 useState 나 useEffects 로 훨씬 functional 한 코딩이 가능하다.
class App extends React.Component {
// 내용들
}
여기서부터는 Class Render 안에서의 CRUD 와 관련된 내용이다
리액트 컴포넌트의 생성 시 아래의 메서드가 순차적으로 실행된다.
1. constructor(){ ... } // 어떻게 만들까요?
2. static getDerivedStateFromProps(){ ... }
3. render(){ ... } // 만들게요
4. componentDidMount(){ ... } // 만들었어요
리액트 컴포넌트의 수정 시 아래의 메서드가 순차적으로 실행된다.
1. static getDerivedStateFromProps(){ ... }
2. shouldComponentUpdate(){ ... } // 컴포넌트 업데이트 할까요?
3. render(){ ... } // 할게요
4. getSnapshotBeforeUpdate(){ ... }
5. componentDidUpdate(){ ... } // 다 했어요
리액트 컴포넌트의 제거 시 아래의 메서드가 실행된다.
1. componentWillUnmount
위의 Component 의 CRUD 모델 외에도 커스텀한 함수를 넣을 수 있다.
그 함수는 각 CRUD 모델 안에서 호출되어 작용하거나 Component 안의 다른 Component 안으로 props(args) 로 넘겨줄 수 있다.
앞에서 언급했듯이, state 기능을 사용하기 위해서는 React.Component 를 상속했어야 했다.
물론 state 를 사용하지 않고도 for 문을 통해서 비슷하게 만들 수는 있지만, state를 사용하기 위해서는 선택권이 없는 것이었다.
하지만,
이제는 useState 를 통해서 state를 사용할 수 있따.
그러므로 이제는 개인 취향에 의해서 사용하는 것이 맞는 것이 아닐까?
const { state이름, setState이름 }=React.useState(초기값);
const {count,setCount}=React.useState();
Router를 통해 각 url 마다 대응되는 상세 페이지에 관련된 파일입니다.
여기서 우리는 가장 많이 쓰이는 Container Presenter 기법을 사용할 것입니다.
이 패턴에서 사용될 파일들과 역할은 다음과같습니다.
0. routename/
1. routename/index.js : export default 를 통한 컴포넌트화
2. routename/routenameContainer.js : React.Component 를 통한 Presnter 랜더링
3. routename/routenamePresneter.js : HTML, CSS
자세한 코드는 다음을 참고하세요.
import [name]Container.js from "./[name]Container.js";
export default [name]Container;
import React from "react";
import [name]Presenter from "./[name]Presenter";
export default class extends React.component{
state={
// defualt state
}
//somethings more method
render(){
return <[name]Presenter/>
}
}
//implicit return
export default ()=><span>Questions</span>;
한 Route 에서 다른 Route 로 넘어갈 때 location 항목을 넘겨줌으로써, 사용자가 이전 페이지를 특정할 수 있다.
[✅] BroswerRouter
[✅] HashRouter
[ ] StaticRouter
[ ] MemoryRouter
[✅] WithRouter
[✅] Composition
[✅] Link
[✅] Route
Route 의 attributes 중 compont={} 가 element={} 로 바뀌었다.
component 를 계속 쓰고 싶으면 npm install react-router-dom@5 로 설치하자.
[✅] Switch
react-router-dom@6 에서 Switch 가 사라지고 Routes 가 생겼다.
Routes 가 아니라 Switch 를 쓰려면 npm install react-router-dom@5 로 설치하자.
[✅] Redirect
react-router-dom@6 에서 Redirect 가 사라졌다.
그렇다면 해당 기능은 어떻게 구현되고 있는 것일까?
리액트 Hooks 블로그 문서를 확인하세요.