em은 타이포그래피에서 현재의 지정된 포린트 사이즈를 나타내는 단위

즉 현재 폰트 사이즈를 나타내는 단위

em는 선택된 폰트에 상관없이 항상 고정된 폰트 사이즈를 가진다.

em 이라는 것은 부모의 폰트 사이즈에 상대적으로 크기가 계산이 된다.

 

rem 의 r은 root를 의미한다.

=> root에 지정된 폰트 사이즈에 의해 크기가 결정된다.

 

나누는 기준 1

부모 요소의 사이즈에 따라서 사이즈가 변경이 되야 된다면 %, em

부모와는 상관없이 브라우저의 사이즈에 대해서 반응해야된다면 vw, vh, rem

 

나누는 기준 2

요소의 너비와 높이에 따라서 사이즈가 변경되야 한다면 %, vw, vh

font 사이즈에 따라서 사이즈가 변경되야 된다면 em, rem

 

 

 

'web > React' 카테고리의 다른 글

visual studio Code 단축키/json  (0) 2020.12.31
create-react-app 정리  (0) 2020.12.30
React Hook  (0) 2020.09.15
fetch request 비동기통신  (0) 2020.09.01
React NodeJs express 연동  (0) 2020.09.01

** 본 정리는 실전 리액트 프로그래밍(저자 : 이재승) 으로 부터 작성하였습니다 **

 

리액트 훅은 기존에 리액트가 갖고 있던 여러 가지 문제를 해결해 준다.

함수형 컴포넌트는 리액트 팀에서도 적극적으로 기능 개발에 많은 시간을 투자하고 있기 때문에

당장 클래스 컴포넌트로 구현한 프로젝트가 아니라면 시작할 때 함수형 컴포넌트로 대체하는 것이 좋다.

 

리액트 훅?

훅이란 함수형 컴포넌트에서도 클래스형 컴포넌트의 기능을 사용할 수 있게 하는 기능이다.

훅을 통해서 함수형 컴포넌트에서도 컴포넌트의 상탯값을 관리할 수 있고, 생명주기 함수를 이용할 수 있다.

 

훅을 사용하면 재사용 가능한 로직을 쉽게 만들 수 있으며, 

클래스형 컴포넌트와는 다르게 중복된 코드가 서로 다른 메서드에 들어가지 않는다.

 

useState 훅

useState 훅은 컴포넌트의 상탯값을 관리하는데 사용된다.

import React, { useState } from 'react';

function component({props}){
	const [name, setName] = useState('jh0956');
    return(
    	<div>
        	<div>{`name is ${name}`}</div>
            <input type="text" value={name} onChange={e=>setName(e.target.value)} />
        </div>
    )
}

[name, setName] 으로 선언하는 방식은 1개의 상태값을 사용하는 단순 형태이다.

useState('jh0956') 은 name의 기본값을 'jh0956'으로 지정한다는 초기화이다.

여기서 name은 상탯값의 이름이 되고, setName은 name이라는 상탯값을 변경하기 위한 함수이다.

 

또한 위의 방법으로 여러개의 useState 훅을 사용할 수도 있다.

하지만 좀더 간단하게 useState 훅 1개로 여러개의 useState 훅을 사용할 수도 있다.

import React, { useState } from 'react';

function component({props}){
	const [state, setState] = useState({
	name : 'jh0965',
    age : 25
    });
    
    return(
    	<div>
        	<div>{`name is ${state.name}}</div>
			<div>{`age is ${state.age}}</div>
            <input
            	type="text"
                value={state.name}
                onChange={e => setState({...state, name : e.target.value})} />
            ...
        </div>
    )
}

배열 비구조화 방식에서 state라는 변수는 '객체'가 되고 setState는 state 객체의 각 상태값의 변경을 위한 함수가 된다.

 

위 코드에서 onChange에서 setState를 호출하게 되는데

useState의 방식은 현재 받는 매개인자를 원래 상태값에 덮어버리는

즉 원래 상태값은 전부 지워버리고 받은 매개인자를 추가하는 방식이다.

 

그래서 전개연산을 통해 ...state의 기존 상태값을 주고, 그 중 name의 상태값만 변경하도록 코드해야한다.

 

생명주기 함수 useEffect

클래스형 컴포넌트의 생명주기 메서드는 서로 연관성이 없는 여러 기능이 하나의 생명 주기 메서드에 섞이는 등의

여러가지 문제점이 있다. useEffect를 사용하면 비슷한 기능을 한곳으로 모을수 있어서 가독성이 좋아진다.

 

useEffect 사용법

import React, { useState, useEffect } from 'react';

function component({props}){
	const [count, setCnt] = useState(0);
    
    useEffect( () => {
    	document.title = `업데이트 횟수: ${count}`;
    });
    return <button onClick = { () => setCnt(count+1) }>increase</button>;
}

** useEffect 훅에 입력된 함수는 렌더링 결과가 실제 돔에 반영된 후 호출된다 **

따라서 document.title 을 변경하는 코드를 클래스형 컴포넌트의 componentDidMount와 componentDidUpdate 

양쪽 메서드에 추가하면 같은 기능을 하게 된다.

클래스형 컴포넌트에서는 서로 다른 로직이 하나의 생명주기 메서드에서 작성되었지만, useEffect 훅을 이용하면 하나의 로직을 위한 코드를 한 곳으로 모을 수 있다.

버튼을 클릭할 때마다 다시 렌더링되고, 렌더링이 끝나면 useEffect 훅에 입력된 함수가 호출된다.

 

API를 호출하는 기능: 함수형 컴포넌트로 작성하기

클래스형 컴포넌트의 생명 주기 메서드에는 API를 호출하는 코드가 자주 포함된다.

함수형 컴포넌트에서도 훅을 이용해서 다음과 같이 API를 호출할 수 있다.

import React, {useState,useEffect} from 'react';

function component({props}){
	const [user, setUser] = useState('');
    useEffect( () => {
    	getUserAPI(props).then(data => serUser(data));
    	}, [props] // here!
    );
    
    return(
    	<div>
        	{!user && <div> 사용자 정보를 가져오는 중... </div>}
            {user && (
            	<div>
                	<!-- name과 age는 API 통신의 결과로 받아온 데이터 -->
                	<p>{`name is ${user.name}`}</p>
                    <p>{`age is ${user.age}`}</p>
                </div>
        </div>
    )
}

useEffect 훅에서 API통신을 가정한 코드이며 useState로 받아온 데이터를 저장한다.

주석처리한 here 부분을 보자

 

useEffect 훅에 입력된 함수는 렌더링 될 때마다 호출되기 때문에 API 통신을 불필요하게 많이 하게 된다.

이를 방지하기 위해 useEffect 훅의 2번째 매개변수로 배열을 입력하면 배열의 값이 변경되는 경우에만 함수가 호출된다

그렇기 때문에 위의 코드는 배열 props가 변경되는 경우에만 API 통신을 하도록 설정한다.

 

만약 위 코드를 클래스형으로 작성했다면 componentDidMount와 componentDidUpdate 두 메서드에 모두 작성했을 것이다.  

 

useEffect 이벤트 처리 함수를 등록하고 해제하는 기능

클래스형 컴포넌트에서는 componentDidMount 에서 구독을 하고 componentWillUnMount에서 해제하는 방식이 일반적이다. 서로 다른 로직이 하나의 생명 주기 메서드에 추가되면서 코드는 복잡해지고 실수가 발생하기 쉽다.

useEffect 훅을 이용하면 이러한 등록과 해제 절차를 한 곳에서 관리할 수 있다.

 

import React, { useState, useEffect } from 'react';

function component(){
	const [width, setWidth] = useState(window.innerWidth);
    useEffect( () => {
    	const onResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', onResize);
        return () => { window.removeEventListener('resize', onResize};
    }, []); // here!!
    
    return <div> {`width is ${width}`} </div>
}

위 코드는 창 크기가 변경될 때마다 onResize 함수가 호출된다.

useEffect 훅의 첫 번째 매개변수에 등록된 함수가 또 다른 함수를 반환할 수 있다.

반환된 함수는 컴포넌트가 unMount 되거나 첫 번째 매개변수로 입력된 함수가 호출되기 직전에 호출된다.

따라서 첫 번째 매개변수로 입력된 함수가 반환한 함수는 프로그램이 비정상적으로 종료되지 않는다면 반드시 호출될 것이 보장된다.

 

주석 here을 보자

useEffect 훅의 2번째 매개변수에 빈 배열을 넣으면 컴포넌트가 Mount 될 때만 첫 번째 매개변수로 입력된 함수가 호출되고, 컴포넌트가 unMount 될때만 반환된 함수가 호출된다.

=> 즉 이 코드는 componentDidMount와 componentWillUnMount 메서드에서만 실행되는 것과 같은 맥락이다.

 

위에서 API 호출, 이벤트 리스너를 예로 들어 설명하였다.

그리고 다음처럼 코드별로 분리해서 useEffect를 작성할 수도 있다.

import React, { useState, useEffect } from 'react';

function component({props}){
	const [width, setWidth] = useState(window.innerWidth);
    const [user, setUser] = useState('');
    
    useEffect( () => {
    	getUserApi(props).then(data => setUSer(data));
    }, [props]);
    
    useEffect( () => {
    	const onResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', onResize);
        return () => { window.removeEventListener('resize', onResize};
    }, []);
    
    return ..
}

만약 클래스형 컴포넌트로 작성했다면, 서로 다른 여러 로직이 분리되어 있지 않아 가독성이 떨어짐을 알게 된다.

 

Custom Hook!

리액트가 제공하는 훅을 이용해서 custom 훅을 만들 수 있다.

그리고 커스텀 훅을 이용해서 또 다른 커스텀 훅을 만들 수도 있다.

훅을 직접 만들어서 사용하면 고차 컴포넌트와 렌더 속성값 패턴처럼 로직을 재사용할 수 있다.

* 커스텀 훅을 만들 때는 use로 시작하도록 변수명을 정하자.

 

위에서 창의 너비를 관리하는 이벤트 리스너 코드를 가지고 커스텀 훅을 만들어보자.

이름은 useWindowWidth

import React, { useState, useEffect } from 'react';

function useWindowWidth(){
	const [width, setWidth ] = useState(window.innerWidth);
    
    useEffect( () => {
		const onResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', onResize);
        return () => window.removeEventListener('resize', onResize);
	},[]);
    
    return width;
}

useWindowWidth 함수는 useState, useEffect로 만들어 졌으며

마지막에 width를 반환하는 커스텀 훅으로 코드되었다.

 

방금 만든 useWindowWidth 훅은 이렇게 사용할 수 있다.

import React, {useState} from 'react';
import { useWindowWidth } from './hooks';

function component(){
	const width = useWindowWidth();
    const [name, setName] = useState('');
    return(
    	<div>
        	<p>{`name is ${name}`}</p>
            <width < 600 && <br />}
            <input type='text' value={name} onChange={e => setName(e.target.value)}/>
        </div>
    )
}

 useWindowWidth를 사용하므로 창의 너비가 바뀔 때마다 새로운 창의 너비와 함께 재렌더링 된다.

 

 

 

 

 

 

'web > React' 카테고리의 다른 글

create-react-app 정리  (0) 2020.12.30
CSS 단위(responsive Units)  (0) 2020.09.16
fetch request 비동기통신  (0) 2020.09.01
React NodeJs express 연동  (0) 2020.09.01
바벨(babel)  (0) 2020.08.22

클라이언트와 서버를 연동했다면 서로 데이터를 보내거나 받을 수 있다.

그전에 클라이언트와 서버를 동시에 실행시키는 모듈을 소개하고자 한다.

 

npm-run-all                                                                       

npm-run-all 은 지정한 script를 차례대로 자동실행시켜주는 모듈이다.

사용하지 않는다면 프롬프트를 필요한만큼 켜서 실행시켜야 하는 불편함이 있기에 사용하면 편리하다.

 

설치가 끝났으면 script를 수정해준다.

 

-p는 병렬실행옵션

starts:**는 코드그대로 starts:로 시작하는 다음 스크립트를 2개 실행시킨다는 의미이다.

npm run start => 아래와 같이 client, server를 같이 실행시키게 된다.

 

 

 

비동기 통신                                                                             

클라이언트와 서버 사이의 데이터는 비동기통신인 fetch를 이용해서 통신할 수 있다.

클라이언트 단에서는 $.ajax, fetch같은 비동기통신 함수를 제공하고

nodejs 서버단에서는 request 같은 비동기통신 모듈을 제공한다

나는 보통 restAPI를 사용할때 fetch와 request를 사용한다

 

 

 

 

fetch                                                                                       

fetch를 이용하면 원하는 url로 비동기통신을 요청하고 정보를 받을 수 있다.

특히 restAPI처럼 특정 서버로부터 원하는 데이터를 얻고자할때 사용한다.

 

사용법은 다음과 같다

fetch( url, set ).then( ).catch( )

 

url은 말그대로 통신을 요청하는 위치가 되고

 

set에는 요청할 때 필요한 정보들을 담는 곳으로

method : 'GET', 'POST', 'PUT'

headers : 'Content-Type':'ex)application/json' , ...

form : POST같은 method를 사용할 때, 데이터들을 담아 보내는 공간으로 dataset이 된다.

 

 

 

 

request module                                                                         

NodeJS에서는 편리한 비동기통신을 위해 request 모듈을 제공한다.

다음과 같이 모듈을 require

 

request도 일반적인 비동기통신 함수들과 사용법이 거의 같다.

 

 

 

클라이언트와 서버간의 통신                                                        

 

클라이언트에서 서버로 데이터를 요청해보자

 

server/router/index.js

 

app.js

 

만들어진 버튼을 클릭하면

3001번 포트에서 가져온 데이터인 res, 타입, json을 통해 콘솔한 결과가 아래와 같이 나타난다.

정상적으로 잘 가져와진다.

 

 

 

 

 

 

 

 

 

'web > React' 카테고리의 다른 글

CSS 단위(responsive Units)  (0) 2020.09.16
React Hook  (0) 2020.09.15
React NodeJs express 연동  (0) 2020.09.01
바벨(babel)  (0) 2020.08.22
createElement 이해하기  (0) 2020.08.22

React와 Nodejs(express)를 연동

 

React                                                                                            

 

1. React => create-react-app 을 통해 환경을 편하게 구성 가능

2. create-react-app 작업할곳이름

3. 지정한 폴더로 이동하면 다음과 같이 환경구성이 끝났음을 알 수 있다.

4. npm start 를 통해 실행되는지 확인

 

 

 

 

Nodejs(express)                                                                            

express framework를 이용하여 backend 환경을 구성

React 내에서 연동하기 위해 폴더를 나누어 사용한다.

서버 사용을 위한 폴더내에 라우더 폴더/index.js 를 생성하고, 라우팅을 위한 server.js를 생성한다. 

 

기본 환경 구성

React는 기본적으로 3000번 포트를 사용하도록 설정되어 있기 때문에,

server단은 3001번 포트로 설정해주었다.

 

server.js

index.js

 

서버실행을 편하게 하기위해 script를 추가해준다.

 

서버가 작동하는지 확인

** script를 사용하는 명령어는 'run'을 꼭 사용해야한다.

다음과 같이 잘 작동하는 것을 확인할 수 있다.

 

서버 사용팁

클라이언트의 경우 코드를 수정하고 저장하면 수정된 코드까지 포함하여 처음부터 페이지에 렌더링된다.

즉 바로바로 작동하게 되는데,

위와 같이 서버를 사용하면 코드를 수정 후 저장하여도 재작동하지 않아서 서버를 끈 후에 다시 실행해야 한다.

이 불편함을 해결하는 것이 nodemon 이다.

 

nodemon을 설치하고,

script의 node를 nodemon으로 수정한다.

 

앞으로 서버단의 코드를 변경하면 재작동하게 되어 편하게 사용할 수 있다.

 

 

 

Proxy                                                                                              

위까지 환경을 구성했어도, 당장 클라이언트와 서버사이는 통신이 불가능하다.

proxy는 클라이언트와 서버 사이의 네트워크 통신을 '대리'로 수행하는 미들웨어이다.

 

Proxy 설치

 

proxy 설정을 위한 js를 src폴더에 생성

 

 

cross-origin resource sharing(CORS)                                                

일반적으로 하나의 페이지는 보안상 같은 포트를 사용하는 페이지에서만 접근할 수 있도록 구성(CORS)되어 있다.

현재 구성한 포트는 3000, 3001번 이므로 서로 데이터에 접근하게 되면 CORS를 위배하여 오류가 발생한다.

 

Nodejs에서는 이를 해결하기 위해 cors 모듈을 제공한다.

 

CORS 설치

 

server.js 에 cors 코드를 삽입

 

 

 

여기까지하면 React와 NodeJs(express)의 연동이 끝난다.

 

클라이언트와 서버가 데이터를 주고받는 방법은 여기!에서 포스팅하겠다.

 

 

 

 

 

'web > React' 카테고리의 다른 글

CSS 단위(responsive Units)  (0) 2020.09.16
React Hook  (0) 2020.09.15
fetch request 비동기통신  (0) 2020.09.01
바벨(babel)  (0) 2020.08.22
createElement 이해하기  (0) 2020.08.22

+ Recent posts