리액트 프로젝트 시작하기

2023. 4. 10. 11:10React/실전 리엑트 프로그래밍

📘 리액트 프로젝트 시작하기

✅ 리액트란 무엇인가?

  • 페이스북에서 개발하고 관리하는 UI 라이브러리
  • 리액트는 UI 기능만 제공 ( 앵귤러가 웹앱 개발에 필요한 다수의 기능을 제공하는 것과는 달리)

따라서 전역상태관리, 라우팅, 빌드 시스템 등을 각 개발자가 직접 구축해야한다.

  • 전반전인 시스템을 직접 구축하기 때문에 자유롭다는 장점이 있지만, 개발 환경을 직접 구축해야하는 번거로움이 있다.
  • 리액트 팀에서 create-react-app이라는 툴을 제공해서 어느정도 이 단점을 보완해준다.
  • 프론트엔드 프레임워크를 사용하는 이유는?

자동으로 UI를 업데이트 해준다는 장점!
UI = render(state) 라고 함축적으로 표현할 수 있다.

  • render 함수는 순수함수로 작성하는 것이 좋다.
    - 순수함수입력값이 같으면 출력값이 같다는 특징
    - 혹은 render 함수 내부에서 외부 상태를 변경하게 되면 다른 render함수의 출력값에 영향을 줄 수 있다. (하지 않는게 좋다)
  • state불변 변수로 관리하는게 좋다.
  • 이렇게 코드에서 순수함수와 불변변수로 관리하게 되면 복잡도가 낮아지고 버그 발생 확률도 줄어든다.
  • 또한 리액트 내에서 이 조건을 따른다면 렌더링 성능을 크게 향상 시킬 수 있다.
  • 리액트의 또 다른 장점은 가상돔(virtual dom)을 이용해 빠르게 UI를 업데이트한다.
    - 가상돔은? 이전 UI 상태를 메모리에 유지해서 변경된 부분만 실제 DOM에 반영해주는 기술

✅ 리액트 개발 환경 직접 구축하기

function  LikeButton() {
const [liked,setLiked] = React.useState(false); // 기본값은 false
const text = liked ? '좋아요 취소' : '좋아요';

// createElement는 리액트 요소를 반환함
return  React.createElement(
	'button',
	{ onClick:()=>setLiked(!liked) },
	text,
)
// 문자열로 입력하면 html로 해당하는 태그가 만들어진다.
// likeButton 이라는 컴포넌트가 완성됨
}

// div안에 렌더링을 하기위한 작업
const domContainer1 = document.getElementById('root1');
// 렌더링 부분
ReactDOM.render(React.createElement(LikeButton),domContainer1) 
// 컴포넌트를 렌더링할때도 마찬가지로 리액트 요소로 만들어준다.
  • createElement()
React.createElement(
	'button',
	속성 값, 
	// 두번째요소는 속성값, 우리는 onclick이라는 이벤트 핸들러가 표현
	children,
	// 버튼의 children으로 텍스트를 출력
)
  • useState컴포넌트의 상태값을 추가할때 사용한다.
  • React는 react.development.js가 실행될때 전역변수로 노출됨
  • 리액트에서는 리액트를 표현하는 가장 작은 단위가 리액트 요소라고 보면 된다.
  • ReactDom도 마찬가지로 react-dom.development.js이 실행될때 전역변수로 노출이 된다.

createElement를 이용해 다음과 같은 구조의 엘리먼트를 생성하고 싶다면?

<div>
	<p>hello</p>
	<p>world</p>
</div>
const helloEl = React.createElement(
	'div',
	null,
	React.createElement('p',null,'hello'),
	React.createElement('p',null,'world'),
)
 
ReactDOM.render(helloEl,domContainer);

DOM 여러 요소에 렌더링해보기

html을 다음과 같이 마크업 하고

<h3>root1</h3>
<div id="root1"></div>

<h3>root2</h3>
<div id="root2"></div>

<h3>root3</h3>
<div id="root3"></div>
// 루트1
const domContainer1 = document.getElementById('root1');
ReactDOM.render(React.createElement(LikeButton),domContainer1);

// 루트2

const domContainer2 = document.getElementById('root2');
ReactDOM.render(React.createElement(LikeButton),domContainer2);

// 루트3
const domContainer3 = document.getElementById('root3');
ReactDOM.render(React.createElement(LikeButton),domContainer3);
  • 각각의 상태값을 갖고있는 컴포넌트가 렌더링된다.
  • 레거시 프로젝트를 리액트로 조금씩 포팅할때 이런 사용법 사용한다.(?)
  • but 이렇게 세개를 렌더링한다면 보통 리액트 안에서 해결하는 것이 좋다.

리액트 안에서 버튼 렌더링해보기

아까와는 모습이 조금 다르지만 얼마든지 리액트 안에서도 수정할 수 있다는 모습을 보여준다.

// 좋아요 버튼
function  LikeButton() {
const [liked,setLiked] = React.useState(false);
const text = liked ? '좋아요 취소' : '좋아요';

// createElement는 리액트 요소를 반환함
return  React.createElement(
	'button',
	{ onClick:()=> setLiked(!liked) },
	text,
)

// 브라우저에 렌더링
const domContainer = document.getElementById('root');

ReactDOM.render(
	React.createElement('div',
	null,
	React.createElement(LikeButton),
	React.createElement(LikeButton),
	React.createElement(LikeButton)
	),domContainer
)

✅ 바벨 사용해보기

  • 초기의 ES6 문법을 ES5 문법으로 변환해주는 용도로 사용
  • 최근에는 코드의 주석을 제거하거나, 코드를 압축하는 용도같은 다양한 용도로 사용
  • 리액트에서는 jsx의 문법을 createElement함수를 호출하는 코드로 변환하기 위해서 바벨을 사용한다.

createElement 문법을 jsx 문법으로 변환

function  LikeButton() {
	const [liked,setLiked] = React.useState(false);
	const text = liked ? '좋아요 취소' : '좋아요';
	
	return  <button  onClick={()  =>  setLiked(!liked)}>{text}</button> //  jsx 문법
}

function  Container() {
	const [count,setCount] = React.useState(0);
	//  jsx 문법
	return (
	<div>
		<LikeButton></LikeButton>
		<div>
			<span>현재 카운트:</span>
			<span  style={{ marginRight : 10 }}>{  count  }</span>
			<button  onClick={()=>  setCount(count+1)}>증가</button>
			<button  onClick={()=>  setCount(count-1)}>감소</button>
		</div>
	</div>
)

const domContainer = document.getElementById('root');
ReactDOM.render(React.createElement(Container),domContainer)

jsx 문법으로 변환했을때 다음과 같은 SyntaxError가 발생

Uncaught SyntaxError: Unexpected token '<'
  • jsx 문법은 자바스크립트 표준이 아니기 때문에 브라우저에서 실행하면 에러가 남
  • 에러가 나지 않도록 바벨을 이용해서 createElement 코드로 변환해줘야한다.

바벨 설치

npm으로 패키지를 관리할때는 package.json이 필요하다.

  • package.json 설치
$ npm init -y
  • 바벨 설치
$ npm install @babel/core @babel/cli @babel/preset-react
  • @babel/core 는 바벨의 핵심 기능을 가지고 있는 패키지
  • @babel/cli는 cli에서 사용할 바이너리가 들어있다.
  • @babel/preset-react는 리액트를 위한 플러그인 여러개를 모아놓은것
  • 바벨에는 프리셋과 플러그인이라는 개념이 있다.
    - 플러그인 : 하나의 변환하는 기능
    - 프리셋 : 여러개의 플러그인을 모아놓은 것이 프리셋, 특정 목적을 위해 하나의 프리셋으로 묶어주는 것

컴파일

컴파일을 통해 기존에 있던 위치에 simple.js 파일이 만들어지게 할것이다.

$ npx babel --watch src --out-dir . --presets @babel/preset-react
  • 한번만 컴파일을 해주는게 아니라 파일이 변경될때마다 자동으로 컴파일을 해준다.
  • src폴더에 있는 것을 현재 폴더로 출력해주고, 프리셋으로 이전에 설치했던 @babel/preset-react을 사용

컴파일이 완료된 것을 확인

function Container() {
	// ...생략
	<span  style={{ marginRight : 10  , color:'red'}}>{  count  }</span>
}

스타일에 color:red 속성을 추가해줬더니

컴파일이 실시간으로 완료된 것을 터미널로 확인되고

컴파일본에 스타일 속성이 추가된 것이 확인된다.

npx babel

  • ./node_moduls/.bin를 보면 babel이 보인다.
  • .bin폴더는 바이너리 파일만 모아놓은 폴더
    - 바벨을 설치했기때문에 바벨의 바이너리 파일이 있는것
$ npx babel
  • npx 명령어를 입력하면 .bin 폴더에 있는 바벨 바이너리를 실행시켜준다.
  • 만약 바벨을 설치하지 않았다면 npx명령어가 바벨패키지를 다운받아서 직접 실행시켜준다.

✅ 웹팩 사용해 보기

  • 파일 이름을 기반으로 파일이름에 해시값을 추가해준다.
    - 이것은 효율적으로 브라우저 캐싱을 이용할 수 있도록 도와준다.
  • 사용되지 않는 코드를 제거
  • 자바스크립트 파일 압축
  • 자바스크립트에서 css나 JSON, 텍스트 파일등을 자바스크립트 모듈처럼 불러올 수 있다.
    - 이렇게 자바스크립트 안에서 모든것을 처리할 수 있는 편리한 기능을 제공해준다.
  • 환경 변수 주입

가장 큰 이유는 모듈 시스템 사용

  • 모듈 시스템은 ESM  commonJS 가 있다.
    - ESM ES6에 추가
    - commonJS 노드에서 많이 사용하는 시스템
  • 모듈 시스템이란?
    - export와 import를 사용한 코드
    - ESM문법
  • 모듈 시스템 사용법
    - default는 괄호 없이 사용
    - 중괄호로 가져와서 as를 이용해 이름 변경
  • 기존 코드 사용시 문제점
- 자바스크립트가 동적으로 변하면서 자바스크립트 파일이 많아짐
- 글로벌 변수 충돌 가능성
- 외부 라이브러리 사용시

만약 웹팩을 사용한다면 변수 이름 충돌 같은 문제빌드 단계에서 잡아낼 수 있다.
외부라이브러리는 npm으로 관리할 수 있고, 그것들이 번들링 단계에서 하나의 파일로 합쳐지면서 앞서 말한 여러가지 문제들이 해결된다.

  • 요즘 브라우저에서 ESM을 지원
    - 웹팩 없이 ESM 사용해서 서비스
    - but 가능은 하지만, 오래된 브라우저도 지원을 해야한다는 문제가 있고, 많은 오픈소스가 commonJS로 작성됐다는 것
  • 요즘 브라우저는 commonJS는 처리를 못하기 때문에 웹팩을 사용해야 한다.

요즘 브라우저에서 ESM이 동작한다는 것

<script type="module" src="index.js">
  • type="module"로 줄 경우 ESM으로 동작
  • index.js로 연결된 a,b,c.js 코드들이 있고 이 파일들을 가지고 실습함.

serve 패키지 사용해서 연결 (직접 브라우저 연결시 에러 발생 가능성있기 때문)

$ npx serve
  • 로컬에 있는 파일을 정적파일로 서비스하는 동작, 브라우저로 경로로 접근할 수 있다.
  • 콘솔 네트워크 창에서 확인해봤을때 index, a, b, c 자바스크립트 파일이 연결된 것이 확인.
  • index 파일만 스크립트로 연결했는데 나머지 파일도 잘 받아온 것을 확인

웹팩 다뤄보기

index.js 이 코드를 웹팩을 이용해서 하나의 파일로 번들링 할 것임

$ npm install webpack webpack-cli react react-dom
  • 웹팩을 설치
    - webpack
    - webpack-cli
    - react,react-dom 리액트 패키지

다음은 웹팩을 실행

$ npx webpack
  • 웹팩을 실행하면 dist폴더가 생성되고 그안에 번들링된 파일이 생긴다.
  • 파일의 코드를 보면 굉장히 복잡하다. 이 안에 리액트 파일도 포함되어 있다.
  • 브라우저를 실행하면 렌더링이 잘 되는 것이 확인된다.
  • 이전에는 웹에서 리액트를 다운받아서 사용했다면,
  • 웹팩을 사용하게 되면서 즉 모듈시스템 을 사용할 수 있게 되면서 npm으로 인스톨해서 사용할 수 있게 된 것이다.
  • 그렇기때문에 index.js에서 가져다 쓰는 파일이 모두 하나의 파일로 압축되어 사용할 수 있다.

✅ create-react-app으로 시작하기

  • create-react-app은 리액트의 개발환경을 구축해주는 도구
  • 리액트의 개발환경을 직접 구축하려면 많은 지식이 필요
예를들어,
- 빌드시스템을 구축하기 위해서 웹팩이나 바벨을 사용해야함
- 테스트환경 - jest 테스트 프레임워크 사용
- 코딩 컨벤션을 정하고 자동으로 체크하기 위해서 eslint를 사용
- 오래된 브라우저 지원하기 위해 polyfill
- HMR 코드릉 수정하면 바로바로 화면에 적요이 되는 기능 -> 개발 생산성 높아짐
- css 후처리 , scss 를 사용하면 css 컴파일 과정이 필요
  • 페이스북에서 관리하는 툴

이러한 환경들을 create-react-app에서 자동으로 구축해서 제공해준다.

cra를 이용한 프로젝트 구축

  • next.js와 cra 차이
    - 서버사이드 렌더링 지원의 차이
    - cra 서버사이드 렌더링을 지원x
    - 서버사이드 렌더링 지원이 필요하다면 next.js
  • cra 단점은 빌드시스템이나 eslint 거의 변경할 수 없음
    - 설정 변경이 필요하다면 Next.js 바벨 웹팩 estlint 등의 설정을 변경할 수 있음
  • 백오피스를 개발할때는 cra로 개발하는게 좋음, 쉽고 빠르다는 장점

cra 설치

$ npx create-react-app cra-test
  • react-scripts
    - package.json 파일에서 react-scripts라는 명령어를 이용하고 있는데 create-react-app이 버전업이 될때는 대부분 react-scripts의 버전이 올라가는 것이다.
    - 때문에 나중에 새로운 버전이 추가됐을때 react-scripts 패키지의 버전만 올려주면 된다.
  • cra의 설정을 변경할 수 없다고 했는데, 굳이 변경하고 싶다면 react-scripts를 fork한 뒤 수정해서 사용하면 된다.
"browserslist": {
	"production": [
		">0.2%",
	],
  • browserslist 브라우저 지원범위에 관한 내용
    - polyfill이 어떻게 적용될지 여부를 나타냄
    - 0.2% 이상의 점유율을 가진 브라우저를 대상으로 하겠다는 뜻이다.

프로그램 실행

$ npm start
  • HMR 기능 덕분에 코드를 수정하면 바로바로 적용됨
    - Hot Module Replacement은 응용프로그램 실행 중에 추가 또는 제거된 모듈들을 페이지 리로드 없이 교체하는 기능
  • 이렇게 HMR이 동작하는 것은 npm start로 실행했을때 로컬에 서버를 띄워서 브라우저와 통신을 하기 때문에 가능한 것
  • npm start 배포시 x 개발모드만, 개발모드기때문에 성능 최적화가 안되어있음
  • 배포할 때는 반드시 빌드명령어
  • StrictMode
    - 개발환경에서 동작하는데 리액트에서 잘못사용한 것들에 대해서 빨리 잡아내기 위해 사용한다.
  • css나 이미지를 자바스크립트에서 import하는 방식으로 사용하는게 좋다.
    - 이미지 경로에 해시값이 들어가기 때문에 브라우저 캐싱을 효율적으로 사용할 수 있다.
  • 이미지뿐만아니라 데이터를 다룰때 json파일을 사용할 수 있다.
더보기

Hot Module Replacement

Hot Module Replacement(HMR)는 모듈 전체를 다시 로드하지 않고 애플리케이션이 실행되는 동안 교환, 추가 또는 제거합니다. 다음과 같은 몇 가지 방법으로 개발 속도를 크게 높일 수 있습니다.

  • 전체 다시 로드 중에 손실되는 애플리케이션의 상태를 유지합니다.
  • 변경된 사항만 갱신하여 귀중한 개발 시간을 절약하세요.
  • 소스 코드에서 CSS/JS를 수정하면 브라우저에서 즉시 업데이트합니다. 이는 브라우저의 개발자 도구에서 직접 스타일을 변경하는 것과 거의 비슷합니다.

출처 : https://webpack.kr/concepts/hot-module-replacement/

 

Hot Module Replacement | 웹팩

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

// data.json
{
	"name":"lee",
	"age":12
}
// app.js
import data from  './data.json'

function App() {
	console.log({data});
}
  • 데이터를 import 
  • 와서 사용시 장점은 데이터를 필요할때만 불러서 사용해야하는 동작에 유용하게 작용한다는 장점이 있다.

✅ create-react-app으로 시작하기2

개발할때 https로 실행하고 싶으면?

$ HTTPS=true npm start

window에서

$ (set HTTPS=true && npm start)

build

빌드명령어

$ npm run build
  • 빌드하면 정적파일 생성
    - 그리고 서버에서는 빌드 폴더 안에 내용들을 정적파일만 서비스하면 된다.
    - 서버사이드렌더링으로 동작할수 없다.
$ npx serve -s build
  • 로컬에서 정적파일을 서비스하기 위해서 서브패키지를 사용하고
    빌드폴더를 대상으로 정적파일을 서비스하는 명령어
  • 큰사이즈와 작은사이즈의 이미지를 로드한뒤 빌드했을때
    - 큰사이즈의 이미지는 미디어폴더밑에 생성
    - 작은사이즈의 이미지는 자바스크립트 파일에 내장된다
    - 이유는? http의 요청 횟수를 줄이기 위한 목적
    - but http 2.0 부터는 요청 횟수가 많아도 성능에 영향을 크게 받지 않기 때문에 큰 의미는 x
    - 좀더 빠르게 이미지를 보여주기 위한 목적

test

$ npm test
  • App.test.js를 App.spec.js로 바꾸더라도 test가 인식함
  • __tests__ 이름의 폴더를 만들면 폴더 아래의 파일은 모두 test파일이 된다.

eject

  • react-scripts를 사용하지 않고 모든 설정 파일을 추출하는 명령어
  • cra기반으로 개발환경을 직접 구축하고 싶을 때 사용
  • 추출을 하지 않으면 cra의 기능이 추가됐을때 단순히 react-scripts버전만 올리면 되는데 추출을하면 수동으로 설정파일을 수정해야함

polyfill

  • padStart()를 사용하고 싶을때 -> 오래된 브라우저는 지원x
    - canIuse페이지에서 브라우저별로 지원여부 확인 가능
    - IE는 지원되지 않음, IE에서 사용하고 싶다면 폴리필 추가해야한다.
  • 보통 core-js를 많이 사용한다.
    core-js(-pure)/es|stable|features/string/pad-start
    경로를 복사해서 index.js에 추가해준다
    import 'core-js/features/string/pad-start'이렇게 설치해서 코드에서 마음놓고 사용하면 된다.
  • 원래는 npm run core-js 설치해서 사용하지만
  • cra에서는 기본적으로 core-js가 내장되어 있기 때문에 필요한 부분만import해주면 된다.

환경변수

  • 개발, 테스트, 배포 환경별로 다른 값을 적용할때 유용하다.
  • 전달된 환경변수는 코드에서 process.env.{변수이름} 과 같이 사용한다.
  • cra에서는 기본적으로 process.env.NODE_ENV라는 환경변수를 갖고 있다.
  • process.env.NODE_ENV는
    - npm start -> development
    - npm test -> test
    - npm run build 로 실행하면 production 이라는 값을 가지고 있는다.
  • 환경변수를 커맨드라인에서도 실행할 수 있다.
  • REACT_APP_*으로 항상 시작
  • process.env.REACT_APP_API_URL
// 윈도우버전
$ set "REACT_APP_API_URL=api.myapp.com" && npm start
console.log('process.env.REACT_APP_API_URL',process.env.REACT_APP_API_URL);

콘솔로 출력해본 결과 변수의 값이 출력된다. (but 난 undefined가 찍힌다..?)

  • 환경변수가 많아지면 .env파일로 관리하는게 좋다.
  • 개발용, 배포용 따로 만들어서 콘솔로 찍어본다.
// 개발용
REACT_APP_API_URL=api.myapp.com
REACT_APP_TEMP1=temp_dev1
// 배포용
REACT_APP_API_URL=api-prod.myapp.com
REACT_APP_TEMP1=temp_prod1
console.log('process.env.REACT_APP_temp1',process.env.REACT_APP_API_TEMP1);

서버로 연결해서 확인시 배포했을때 배포용 정의가 출력되고 개발모드시에는 개발했을때의 결과가 출력된다. (이부분도 undefined 출력..)

  • 배포용 콘솔 결과창
1. process.env.NODE_ENV production
2. process.env.REACT_APP_API_URL api-prod.myapp.com
3. process.env.REACT_APP_temp1 undefined

✅ CSS 작성 방법 결정하기

일반적인 방법

  • 일반적인 css 파일로 작성할때는 이름이 충돌할 수 있다는 문제점이 있다.
  • 빌드해서 css파일을 확인해보면 이름 같아서 겹치는 것을 확인할 수 있음, 마지막 선언된 css 속성만 적용돼서 문제가 생겼음

css module

  • Box.module.css 처럼 css 파일의 모듈이름을 .module.css으로 작성해주고
  • import할떄는 import style from './Button.module.css 로 받아서
  • 객체 형식이기 떄문에 Style.big ,Style.small클래스명을 그 속성 이름으로 해주면 된다.
  • 콘솔에 출력해보면 객체 형태로 출력된다.
  • 객체 속성의 값을 보면 해시값이 붙어있다.
    - 이 해시값 덕분에 각 클래스명은 고유한 이름을 부여받을 수 있다.
    - 때문에 이름 충돌 문제가 없다.

클래스네임 입력하는게 다소 번거로울 경우 간편하게 하는 방법
classNames 패키지 이용

$ npm install classNames

사용법 classnames를 import

import cn from 'classnames'
<button className={cn(style.Button,style.big)}>큰 버튼</button>

css Sass

  • Sass문법에 있는 변수나 믹스인을 이용하면 스타일 코드 재사용할 수 있음
  • cra에서 Sass를 사용을 위한 패키지 설치 - node-sass
$ npm install node-sass
  • css 파일 확장명은 scss

css-in-js

  • css 코드를 자바스크립트 파일 안에서 작성하는 방식
  • css 코드도 얼마든지 재사용이 가능한 구조로 관리할 수 있음
  • 동적으로 css 코드를 작성하기도 쉽다.
  • styled-components 라이브러리 사용
$ npm install styled-components
import styled from 'styled-components';
const BoxCommon = styled.div`
	height : 50px;
	background-color:#ffff;
`;
const Big = styled(boxCommon) `
	width:200px;
`;
  • 값을 매개변수로 받아와서 실행하는 함수가 있다라고 이해하면 된다.
  • div로 이루어진 컴포넌트를 생성
  • 이를 확장해서 또 다른 컴포넌트를 만들 수 있다.
const BoxCommon = styled.button`
	width:${props => {props.isBig ? 100 : 50 }}px;
`;

위처럼 동적으로 코드를 작성할 수도 있다.

✅ 단일 페이지 애플리케이션(SPA) 만들기

  1. 전통적인 방식 (MPA)
  2. 단일 페이지 애플리케이션(SPA)
  • 클라이언트가 초기 요청을 보내고 서버가 html을 보내주는 방식은 전통적인 방식과 똑같다.
  • 그 이후에 페이지 전환 요청이 있으면 서버로 항상 요청하는 것이 아니라 필요할때만 데이터를 요청해서 받아오는 방식
  • 페이지 전환은 자체적으로 라우팅 처리를 할 수 있다.

SPA가 가능하기 위한 조건

  • 자바스크립트에서 브라우저로 페이지 전환 요청을 보낼 수 있어야 한다.
    - 이때 브라우저는 서버로 요청을 보내지 않아야 한다.
  • 브라우저에서 뒤로가기와 같은 사용자의 페이지 전환 요청을 자바스크립트에서 처리할 수 있어야한다.
    - 이때도 브라우저는 서버로 요청을 보내지 않아야 한다.

페이지 전환 이벤트

  • 페이지 전환 이벤트는 브라우저와 자바스크립트 양쪽에서 발생할 수가 있는데, 어떤 경우든 서버로 요청은 하지 않는다.
  • 사용자가 브라우저 UI를 통해서 페이지 전환 요청을 하면 브라우저는 자바스크립트한테 알려줘야하고 자바스크립트가 페이지 전환을 하고싶을때는 브라우저에게 알려줘야한다.

위 조건을 만족시켜주는 브라우저 API

  • pushState, replaceState함수
    - js가 페이지 전환을 하고싶을때 브라우저에게 페이지 전환 이벤트를 알려주는 방법으로 이 함수를 사용한다.
  • popState 이벤트
    - 반대로 사용자브라우저 UI를 통해서 페이지 전환하려고할때 브라우저는 js로 popState 이벤트를 통해 알려준다.

SPA 방식으로 페이지 만들어보기

import React, { useEffect } from  'react';
import ReactDOM from  'react-dom';

function  App() {

	useEffect(()=>{
		window.onpopstate  =  function  (event) {
			console.log(`location: ${document.location},state: ${event.state}`);
		}
	},[]);
  • 브라우저에서 페이지 전환 요청이 발생했을때는 자바스크립트가 알기 위해서 onpopstate 이벤트 핸들러를 등록하고 있다.
  • useEffect는 이벤트 핸들러를 등록하거나 api를 호출하는 등의 부수효과를 발생시킬때 사용하는 리액트 함수
  • pushState 함수는 브라우저에게 알려주는 것
return (
	<div>
		<button  onClick={()  => window.history.pushState('v1','','/page1')}>
			page1
		</button>
		<button  onClick={()  => window.history.pushState('v2','','/page2')}>
			page2
		</button>
	</div>
	)
}
  • pushState의 첫번째 매개변수 v1은 데이터를 의미
  • onpopstate에서 event.state가 있는데 onpopstate에서 넘겨주는 그 값이 첫번째 매개변수의 값이다.
  • 세번째 매개변수는 url 클릭하면 주소창에 설정한 값이 보인다.

react-router-dom을 이용해서 구현

  • react-router-dom은 여러가지 편의 기능을 제공해준다.
  • 컴포넌트를 다양한 조건으로 렌더링할때 라이브러리에서 제공해주는 기능을 활용하면 좋다.
  • 라이브러리에서는 현재 상태 정보 관리를 자동으로 해준다.
  • 코드스플리팅(분할)이라는 기능도 제공한다.
  • 쉽게 페이지 단위로 코드 분할이 가능하다.
import {Route, Link} from  'react-router-dom';
export  default  function  Rooms({match}) {
	return (
	<div>
		<h2>여기는 방을 소개하는 페이지입니다.</h2>
		<Link  to={`${match.url}/blueRoom`}>파란방입니다.</Link>
		// ...생략
	</div>
	)
}

function  Room({match}) {
	return  <h2>{`${match.params.roomId} 방을 선택하셨습니다.`}</h2>
}
  • match란?
    - 라우터 컴포넌트로 렌더링을 하면 해당 컴포넌트의 속성값으로 match라는 속성값을 넣어준다.
    - match에는 url이라는 속성이 있다. 의미는 Rooms컴포넌트가 렌더링 됐을 당시에 match됐던 그 url의 일부분
    - match.urlrooms로 되어있다고 생각하면 된다.

🔍 강의 출처
실전 리액트 프로그래밍

🧷 관련 링크

 

출처 : https://velog.io/@fromzoo/%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0

 

리액트 프로젝트 시작하기

페이스북에서 개발하고 관리하는 UI 라이브러리리액트는 UI 기능만 제공 ( 앵귤러가 웹앱 개발에 필요한 다수의 기능을 제공하는 것과는 달리)따라서 전역상태관리, 라우팅, 빌드 시스템 등을 각

velog.io