태그와 메타 설정 이미지 태그에 alt, head에 메타데이터, title은 페이지마다 달라야 하며 link에 alt도 붙여야한다. apple.com은 SEO를 위해 다음과 같이 meta tag를 설정해 놓았다 - apple home(www.apple.com) - apple watch(www.apple.com/watch)
페이지 속도 개선 PageSpeedInsights에서 웹페이지 속도 개선에 대해 리포팅을 받아볼 수 있다.
17에 비해 코드상으로 수정해야할 부분이 많지는 않다는 것이 다행이다. React18은 React 17에서 어떤점이 바꼈는지 알아보자
html과 js를 연결해주는 main.js안에서 사용하는 함수가 바꼈다.
import ReactDOM from 'react-dom'
import App from './App'
//17
//ReactDOM.render(<App />, document.getElementById('root'));
//18
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
Concurrent Rendering 동시에 일어난 다수의 상태 업데이트 처리하는 기법으로 urgent한 update는 오래 걸리거나 급박하지않은 update보다 우선되어진다. 만약 엄청나게 많은 component가 동시에 변해야하는 상황이라면 React 17에서는 동시에 state 변화가 일어난다고 해도 먼저 일어난 것 순서대로 순차적으로 처리되는 반면 React 18에서는 동시에 state 변화가 일어나야할 시 우선도를 보고 urgent한 update가 우선되어지고 urgent하지 않거나 오래걸리는 update는 background에서 수행된다.
우선도 구분은 다음 API를 사용하여 우선도가 높은 상태변화와 낮은 상태변화를 구분한다. - useTransition( ) - startTransition( ) - useDeferredValue( )
useTransition
startTransition
useDefferedValue
React에게 lower priority의 state update를 알려준다
- React에게 갱신된 값이 준비될때까지 이전값을 UI상 display 해야한다는 것을 알려준다 - 2개의 value 중 하나는 업데이트가 빠르고 나머지 하나는 업데이트가 느린경우 느린 업데이트의 value에 대해서는 update전 값을 보여준다.
함수형 컴포넌트에서 사용한다
hook이 사용될 수 없는 환경에서 사용한다
[isPending, startTransition] 반환 //isPending은 현재 background에서 state가 변화하고 있음을 알려준다
startTransition(()=>setUser(user));
const deferredVal=useDeferredValue(value);
import { useTransition } from 'react';
const [isPending, startTransition] = useTransition();
// Urgent
setInputValue(input);
// Mark any state updates inside as transitions
startTransition(() => {
// Transition
setSearchQuery(input);
})
{isPending && <Spinner />}
State Batching 개선 State Batching: 다수의 state 업데이트가 함께 실행된다. 그러므로 컴포넌트가 한번만 업데이트된다.
function increaseCouterHandler() {
//Two state update calls batched together
// +3 씩 이뤄진다
setCounter((curCounter)=>curCounter+1);
setCounter((curCounter)=>curCounter+2);
}
function increaseCouterAsyncHandler() {
setTimeout(()=>{
//Two state update calls not batched when using react 17
//+3 씩 이뤄지는데 오직 asynchronous 환경에서만 이뤄졌다
setCounter((curCounter)=>curCounter+1);
setCounter((curCounter)=>curCounter+2);
})
}
Suspense 개선 Suspense: Code(or data) fetching과 관련된 UI updates를 도와주는 component. 주로 lazy loading할때 사용한다. React 18에서는 Server side rendering 환경에서도 Suspense를 사용할 수 있다.
이 stylesheet를 해당 font를 사용할 js또는 css 에 import하면 Plus Jakarta Sans local로 import한 font를 사용할 수 있다. (위의 상황에서는 overloading으로 마지막에 import한 font가 Plus Jakarta Sans로 적용된다.)
기본적인 React Application 을 실행시키기 위해서는 다음과 같은 프로세스를 실행한다.
nodejs설치 -> npm install -> npm run build -> server 실행
이러한 일련의 과정을 Docker 는 이미지로 생성해 순서대로 처리할 수 있다.
그리고 이런 이미지 설정파일을 Dockerfile에서 정의한다.
Dockerfile의 생김새는 다음과 같다.
# parent image
FROM node:17-alpine as build-stage
# Run Command (ex. COPY, npm install, ...)이 작업되는 directory 선언
WORKDIR /app
# all source code copy , COPY <src> <dest>
COPY . .
# dependencies
RUN npm install
# container가 어떤 포트를 사용할지 선언한다. app.js에서 4000포트 사용중이므로 4000포트를 expose 한다.
EXPOSE 4000
# 다음 명령어가 안되는 이유: image는 container의 blueprint이지 application을 실행하는 곳이 아니다. container는 image의 running instance이다.
#RUN node app.js
# container가 RUN을 시작한 후 서버가 작동하게 하기 위해서 다음과 같이 CMD 명령어를 쓴다.
CMD ["node", "app.js"]
# 빌드하는 명령어 myapp: image 이름, . : dockerfile build하는 장소로부터의 상대 경로
#docker build -t myapp .
parent image 설정 -> work directory 설정 -> work directory에 source code 복사 -> package dependency 설치 -> 포트 설정 -> 서버 실행
의 순서대로 설정된다.
여기서 주의해야할 것이 2가지가 있다.
WORKDIR
작업이 이뤄지는 경로로서 WORKDIR이 선언된 이후 모든 작업은 선언된 directory에서만 이뤄진다.
두 명령어 모두 Command를 실행시켜주는 명령어이다. 하지만 RUN은 image를 구성하는데 사용하는 명령어로 image는 container의 blueprint이지 application을 실행하는 역할이 아니다. 왜냐하면 container는 image의 running instance이기 때문이다. CMD는 모든 image구성이 끝난 후 실행할 Command를 실행시켜주기 위해 사용한다.
Storybook은 Story를 모아놓은 집합체가 되고, 각각의 Story는 저마다의 Vision State를 가지고 있는 Component를 의미한다. ex) primary button, secondary button, large button, small button , ...
모든 storybook에 일괄적인 decorator을 적용하고 싶다면 global decorator을 사용한다. preview.js에서 설정할 수 있다.
import React from 'react';
import {addDecorator} from '@storybook/react';
import Center from '../src/components/Center/Center'
addDecorator(story=><Center>{story()}</Center>)