Just Do IT!
[React] 처음 만난 리액트 강의 내용 정리 본문
728x90
반응형
리액트 소개
- 사용자 인터페이스를 만들기 위한 자바스크립트 라이브러리
- 라이브러리 : 자주 사용되는 기능들을 정리해 모아 놓은 것
- 사용자 인터페이스(User Interface, UI) : 사용자와 컴퓨터가 서로 상호작용하기 위해 중간에서 서로간의 입력과 출력을 제어해주는 것
- 사용자 인터페이스를 위한 라이브러리 = UI 라이브러리 (화면을 만들기 위해 모아놓은 것)
- Angular.js, React, Vue.js 등
- 웹사이트의 작동 원리와 흐름을 함께 이해하는 것이 중요하다.
- 리액트의 장점
- 빠른 업데이트(화면이 바뀌는 속도) & 렌더링 속도 ⇒ Virtual DOM 사용
- 화면 업데이트 = DOM이 수정된다
- 업데이트할 최소한의 부분만 update한다.
- Component-Based
- 모든 페이지가 컴포넌트로 구성되어 있다 (레고블록을 조립하듯이 컴포넌트들을 모아서 개발)
- 쉽고 재사용 가능한 형태로 개발하는 것이 좋다
- 재사용성(Resuability) : 다시 사용이 가능한 성질
- 개발 기간이 단축된다
- 유지 보수가 용이함
- Meta라는 지원군이 있다
- 활발한 지식 공유 & 커뮤니티
- React Native를 사용해 앱을 만들 수 있다
- 빠른 업데이트(화면이 바뀌는 속도) & 렌더링 속도 ⇒ Virtual DOM 사용
- 리액트의 단점
- 방대한 학습량
- 계속 무언가 바뀌기 때문에 계속 학습해야 한다
- 높은 상태관리 복잡도: state를 잘 관리하는 것 (redux 등 외부 라이브러리를 이용한다)
- 상태 관리의 기본 개념을 제대로 이해하자
JSX
JSX의 정의와 역할
- JSX (a syntax extension to JavaScript) : 자바스크립트 확장 문법
- javascript + XML / HTML
- JSX를 쓰는게 필수는 아니지만 장점들이 많아서 편리하다
JSX의 장점 및 사용법
- 장점
- 간결한 코드
- 가독성 향상
- 버그를 발견하기 쉬움
- Injection Attacks 방어 (해킹 방어)
- 사용법
const name = '소플'; const element = <h1>안녕, {name}</h1>; ReactDOM.render( element, document.getElementById('root') ); // 태그의 속성(attribute)에 값을 넣는 방법 // 큰따옴표 사이에 문자열 넣기 const element = <div tabIndex="0"></div>; // 중괄호 사이에 자바스크립트 코드 넣기 const element = <img src={user.avatarURL}></img>;
- XML/HTML { JavaScript 코드 } XML/HTML
Rendering Elements
Elements의 정의와 생김새
- Element: 리액트 앱을 구성하는 가장 작은 블록들
- DOM element: 화면을 나타내는 내용을 기술하는 자바스크립트 객체
- React element : DOM element의 가상 표현 (상대적으로 크고 무거움)
- elements는 화면에서 보이는 것들을 기술
- React elements는 자바스크립트 객체 형태로 존재 (불변성을 가짐)
Elements의 특징 및 렌더링하기
- 불변성(immutable) ⇒ Elements 생성 후에는 children이나 attributes를 바꿀 수 없다
- 렌더링: virtaul DOM에서 실제 DOM으로 이동
- 새로운 element를 생성해서 기존 element와 교체
Components and Props
Components와 Props의 정의
- Component
- 함수와 비슷하나 조금 다르다
- React Component : 속성(props)을 입력받아서 react element를 출력해주는 것
- 틀만 있으면 계속 새로운 element를 만들 수 있다
- Props
- Component의 property (속성)
- 눈에보이는 특성을 바꾸고 싶을 때 props를 바꾸면 된다
- 붕어빵 틀에 쓰이는 재료와 비슷한 의미
Props의 특징 및 사용법
- 읽기 전용 (값을 변경할 수 없다)
- 새로운 값을 컴포넌트에 전달하여 새로 element를 생성 (다시 렌더링)
- 모든 리액트 컴포넌트는 그들의 Props에 관해서는 pure함수 같은 역할을 해야 한다.
- ⇒ 모든 리액트 컴포넌트는 props를 직접 바꿀수 없고 같은 pros에 대해서는 항상 같은 결과(react element)를 보여줄 것
- 함수가 pure하다 = 입력값(input)을 변경하지 않으며 같은 입력값에 대해서는 항상 같은 출력값(output)을 리턴
- pure하지 않음 = 입력값(input)을 변경
- props 사용법
- function App(props) { return ( <Profile name="소플" introduction="안녕하세요, 소플입니다." veiwCount={1500} /> ); } // props를 사용할 때도 {} 사용 // JSX 사용시 컴포넌트에 props를 넣을 수 있다
Component 만들기 및 렌더링
- 리액트에서는 보통 hook을 사용
- function component
- 리액트 컴포넌트를 함수로 생각하면 된다.
- 간단한 코드가 장점
function Welcome(props) { return <h1>안녕, {props.name}</h1>; }
- class component
- React.Component를 상속 받는다
class Welcome extends React.Component { render() { return <h1>안녕, {this.props.name}</h1>; } )
- 컴포넌트 이름은 항상 대문자로 시작해야 한다. (소문자는 html 태그로 인식)
- 컴포넌트 렌더링 : 컴포넌트가 실제로 렌더링 되는 게 아니라 element가 렌더링되는 것
Component 합성과 추출
- 컴포넌트 안에 또다른 컴포넌트 사용 가능 ⇒ 복잡한 화면을 여러 개의 컴포넌트로 나눠서 구현 가능
function Welcome(props) {
return <h1>안녕, {props.name}</h1>;
}
// Welcome 컴포넌트 사용 가능 (각기 다른 props를 가지고 있음)
function App(props) {
return (
<div>
<Welcome name="Mike" />
<Welcome name="Steve" />
<Welcome name="Jane" />
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
- 컴포넌트 추출 : 큰 컴포넌트를 추출해서 작은 컴포넌트로 나뉘기 때문에 재사용성이 올라가게 된다
- 기능별로 추출하면 좀 더 쉽게 컴포넌트를 사용할 수 있다.
State and Lifecycle
State와 Lifecycle의 정의
- State : 리액트 component의 상태
- 리액트 component의 변경 가능한 데이터
- 개발자가 정의한다
- 정의할 때 주의할 점 : 렌더링이나 데이터 흐름에 사용되는 값만 state에 포함시켜야 한다
- staet는 자바스크립트 객체이다
- 직접 수정할 수 없다 (setState함수를 통해 수정해야 한다)
class LikeButton extends React.Component { constructor(props) { super(props); // state this.state = { liked: false }; } ... }
- Lifecycle (생명주기)
- 생성 (constructor 실행) - 호출(렌더링, update 과정) - 사라짐
- 상위 컴포넌트에서 현재 컴포넌트를 더이상 렌더링 하지 않을 때가 사라지는 때
- 컴포넌트가 계속 존재하는 것이 아니라, 시간의 흐름에 따라 생성되고 업데이트 되다가 사라진다
Hooks
Hooks의 개념과 useState, useEffect
- hooks 이용하면 함수 컴포넌트도 클래스 컴포넌트처럼 이용 가능
- 갈고리처럼 하고 사용하고 싶은 함수에 갈고리를 걸어 필요할 때 사용하게 하는 것
- 각 기능을 사용하겠다는 의미로 use를 붙여서 사용한다.
- 개발자 마음대로 custom hook을 만들 수 있다 (그래도 use를 붙여서 사용)
- useState()
- state를 사용하기 위한 Hook
- const [변수명, set함수명] = useState(초기값);
- 변수 각각에 대해 set 함수가 따로 존재한다
import React, { useStae } from 'react'; function Counter(props) { var [count, setCount] = useState(0); return ( <div> <p>총 {count}번 클릭했습니다.</p> <button onClick={() => setCount(count + 1)}> 클릭 </button> </div> ); }
- useEffect()
- side effect를 수행하기 위한 hook
- side effect : 리액트에서는 그냥 효과, 영향을 의미한다
- effect라 부르는 이유 ⇒ 다른 컴포넌트에 영향을 미칠 수 없으며 렌더링 중에는 작업이 완료될 수 없기 때문
- useEffect(이펙트함수, 의존성 배열); >> 배열이 하나라도 변경되었을 때 이펙트함수 사용
- useEffect(이벡트 함수, []); >> mount, unmount 시에 단 한번씩만 실행된다
- 의존성 배열을 생략하면 컴포넌트가 업데이트 될 때마다 호출된다
useMemo, useCallback, useRef
- useMemo()
- Memoized value를 리턴하는 hook
- Memoization : 연산량이 많은 함수를 저장했다가 호출되면 바로 호출하는 것 (최적화 관련)
- 렌더링 중에 실행되는 함수는 useMemo()에 넣으면 안된다.
- 의존성 배열을 넣지 않을 경우, 매 렌더링마다 함수가 실행된다 (아무 의미 없음)
- 의존성 배열이 빈 배열인 경우, 컴포넌트 마운트 시에만 호출된다 (마운트 이후에는 값 변경 x)
const memoizedValue = useMemo( () => { // 연산량이 높은 작업을 수행하여 결과를 반환 return computeExpensiveValue(의존성 변수1, 의존성 변수2); }, [의존성 변수1, 의존성 변수2] );
- useCallback()
- useMemo() Hook과 유사하지만 값이 아닌 함수를 반환
- 의존성 배열의 값이 바뀌는 경우에만 함수를 새로 정의해서 return 해주는 것
const memoizedCallback = useCallback( () => { doSomething(의존성 변수1, 의존성 변수2); }, [의존성 변수1, 의존성 변수2] );
- useRef()
- Reference를 사용하기 위한 Hook
- reference : 특정 컴포넌트에 접근할 수 있는 객체
- refObject.current ⇒ 현재 참조하고 있는 element
- 변경가능한 current라는 걸 가진 하나의 상자와 같다.
- 내부의 데이터가 변경되었을 때 별도로 알리지 않는다 (재렌더링 x)
- dom 내부의 변경을 알려면 Callback ref를 사용해야 한다
const refContainer = useRef(초기값);
Hook의 규칙과 Custom Hook 만들기
- Hook은 무조건 최상위 레벨에서만 호출해야 한다 (반복문, 조건문 등에서 호출 x)
- 컴포넌트가 렌더링될 때마다 매번 같은 순서로 호출되어야 한다
- 리액트 함수 컴포넌트에서만 hook을 호출해야 한다 (자바스크립트에서는 x)
- state와 관련된 모든 로직은 소소트리를 통해 모두 확인 가능해야 한다.
- hook의 규칙과 관련된 패키지 ⇒ eslint-plugin-react-hooks (문제 패턴을 분석)
- Custom Hook 만들기
- 여러 컴포넌트에서 반복적으로 사용되는 로직을 hook으로 만들어 재사용하기 위함
- 이름이 use로 시작하고 내부에서 다른 hook을 호출하는 하나의 자바스크립트 함수이다
- hook의 규칙도 적용
- 여러 개의 컴포넌트에서 하나의 custom hook을 사용할 때 컴포넌트 내부에 있는 모든 state와 effects는 전부 분리되어 있다.
- 각 custom hook 호출에 대해서 분리된 state를 얻게 된다
- 각 custon hook의 호출 또한 독립적이다
Handling Events
Event의 정의 및 Event 다루기
- event : 특정 사건을 의미 (ex. 버튼 클릭 이벤트)
- DOM의 event : onclick을 통해 전달
- react의 event : onClick={} (카멜 표기법으로 쓰여있음) ⇒ 함수 그대로 전달
- event handler (=event listener): 어떤 사건이 발생하면 사건을 처리하는 역할
- 함수 내부에서 이벤트 핸들러 사용하기
- 함수 안에 함수로 정의
- arrow function을 사용하여 정의
- Arguments(함수에 전달할 데이터) 전달하기
- parameter (매개변수) 전달하기
Conditional Rendering (조건부 렌더링)
Conditional Rendering의 정의와 Inline Conditions
- 조건부 렌더링 : 어떠한 조건에 따라서 렌더링이 달라지는 것
- (예) 버튼을 누르면 true, 누르지 않으면 false
- Javascript의 Truthy와 Falsy
- Truthy: true는 아니지만 true로 여겨지는 값
- Falsy : false는 아니지만 false로 여겨지는 값
// truthy true {} (empty object) [] (empty object) 42 (number, not zero) "0", "false" (string, not empty) // falsy false 0, -0 (zero, minus zero) On (BigInt zero) '', "", `` (empty string) null undefined NaN (not a number)
- element variables : element를 변수처럼 다루는 것 (변수처럼 사용 가능)
- Inline Conditions : 조건문을 코드 안에 집어넣는 것
- Inline If : In문의 경우 && 연산자를 사용
- 결과가 정해져있으면 굳이 불필요한 계산을 하지 않게 하는 용도로 쓰인다
/* true && expression -> expression false && expression -> false */ function Mailbox(props) { const unreadMessages = props.unreadMessages; return ( <div> <h1>안녕하세요</h1> {unreadMessages.length > 0 && ( <h2>현재 {unreadMessages.length}개의 읽지 않은 메시지가 있습니다.</h2> )} </div> ); }
- Inline If-Else : ? 연산자를 사용
- conditon ? true : false (삼항연산자)
function UserStatus(props) { return ( <div> 이 사용자는 현재 <b>{props.isLoggedIn ? '로그인' : '로그인하지 않은'}</b> 상태입니다. </div> ) }
- Inline If : In문의 경우 && 연산자를 사용
- Component 렌더링 막기 : null을 리턴하면 렌더링 됟지 않음
List and Keys
List와 Key
- List : 같은 아이템을 순서대로 모아놓은 것
- Array : Javascript의 변수나 객체들을 하나의 변수로 묶어 놓은 것
- key : 각 객체나 아이템을 구분할 수 있는 고유한 값 (아이템들을 구분하기 위한 고유한 문자열)
여러 개의 Component 렌더링 하기
- map() : 배열에 들어 있는 변수에 어떠한 처리를 한 뒤 return 하는 것
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
)
- list의 item은 무조건 key를 가지고 있어야 한다.
List의 Key
- key : list의 어떤 아이템이 변경, 추가 또는 제거되었는지 구분하기 위해 사용
- key의 값은 같은 list에 있는 elements 사이에서만 고유한 값이면 된다
- key로 값을 사용하는 경우
- key로 id를 사용하는 경우
- index를 사용하는 경우 (item의 순서가 바뀌는 경우에는 권장하지 않는다)
- map() 함수 안에 있는 elements는 꼭 key가 필요하다
Forms
Form와 Controlled Component
- Form : 사용자로부터입력을 받기 위해 사용
- Controlled Component : 사용자가 입력한 값에 접근하고 제어할 수 있도록 하는 컴포넌트 (통제 = 리액트)
- 값이 리액트의 통제를 받는 Input Form Element
- 사용자의 입력을 직접적으로 제어할 수 있다
다양한 Forms
- textarea 태그 : 여러 줄에 걸쳐 긴 텍스트를 입력받기 위한 HTML 태그
- select 태그 : drop-down 목록을 보여주기 위한 HTML 태그 (여러 개의 옵션 선택 가능)
- file input 태그 : 디바이스의 저장 장치로부터 하나 또는 여러 개의 파일을 선택할 수 있게 해주는 HTML 태그
- ⇒ uncontrolled comonent (리액트의 동작을 받지 않음)
- multiple inputs : 여러 개의 state를 선언하여 각각의 입력에 대해 사용
Lifting State Up
Shared State
- state에 있는 데이터를 여러 개의 하위 컴포넌트에서 공통적으로 사용하는 경우
- 하위 컴포넌트가 공통된 부모 컴포넌트의 state를 공유하여 사용하는 것
- 하위 컴포넌트의 state를 공통 상위 컴포넌트로 올림
하위 컴포넌트에서 State 공유하기
Composition vs Inheritance
Composition 방법과 Inheritance
- composition : 여러 개의 컴포넌트를 합쳐서 새로운 컴포넌트르 만드는 것
- 여러 개의 컴포넌트들을 어떻게 조합할 것인가?
- Containment : 하위 커포넌트를 포함하는 형태의 합성 방법
- Sidebar나 Dialog 같은 box 형태의 컴포넌트는 자신의 하위 컴포넌트를 미리 알 수 없다 ⇒ containment 사용
- children이라는 prop을 사용해서 조합
- 여러 개의 children 집합이 필요한 경우 ⇒ 별도로 prop를 정의해서 각각 원하는 컴포넌트를 넣어주면 된다
- Specialization : 범용적인 개념을 구별이 되게 구체화 하는 것
- 기존의 객체지향 언어에서는 상속(Inheritance)을 사용하여 Specialization을 구현
- 리액트에서는 합성(Composition)을 사용하여 구현한다
- Containment와 Specialization을 같이 사용하기
- props.children 사용 , 직접 정의한 prop를 사용
- Containment : 하위 커포넌트를 포함하는 형태의 합성 방법
- Inheritance : 다른 컴포넌트로부터 상속을 받아서 새로운 컴포넌트를 만드는 것 ⇒ 그다시 추천 방법은 아님
- 복잡한 컴포넌트를 쪼개서 여러 개의 컴포넌트로 만들고, 만든 컴포넌트들을 조합해서 새로운 컴포넌트를 만들자
Context
Context란?
- 기존에는 컴포넌트의 props를 통한 데이터 전달 방법을 사용했다.
- 여러 컴포넌트에 걸쳐 굉장히 자주 사용되는 데이터의 경우 기존 방식을 사용하면 코드도 너무 복잡해지고 사용하기 어려웠다.
- context : 컴포넌트의 트리를 통해 곧바로 컴포넌트로 전달하는 것 (더 효율적인 방법)
- 언제 Context를 사용해야 할까?
- 여러 개의 component들이 접근해야 하는 데이터 ⇒ 로그인 여부, 로그인 정보, UI 테마, 현재 언어 등
- context를 사용하기 전에 고려할 점
- 재사용성이 떨어지기 때문에 위의 경우가 아닌 경우에는 기존의 방법을 사용하는 것이 좋다
Context API
- React.createContext() : context 생성하기
- 만약 상위 레벨에 매칭되는 provider가 없다면 기본값이 사용된다
- 기본값으로 undefined를 넣으면 기본값이 사용되지 않음
- Context.Provider : 하위 컴포넌트들이 해당 컴포넌트의 데이터를 받을 수 있도록 하는 것
- 하위 컴포넌트들을 provider로 감싸주면 해당 컴포넌트의 데이터에 접근 가능하다
- consuming component : 하위 컴포넌트들이 데이터를 소개한다는 의미
- context를 지켜보다가 값이 변경되면 재렌더링된다
- 여러 개의 consuming 컴포넌트와 연결 가능, prop이 바뀔 때마다 재렌더링된다
- Provider value에서 주의해야 할 사항
- provider 컴포넌트가 재렌더링될 때마다 모든 하위 consumer 컴포넌트가 재렌더링된다 (의도치 않은 재렌더링 발생 가능)
- state를 사용하여 불필요한 재렌더링을 막아야 한다
- Class.contextType : provider 하위에 있는 class component에서 context의 데이터에 접근하기 위해 사용하는 것
- ⇒ 현재는 거의 사용하지 않음
- Context.Consumer : context의 데이터를 구독하는 컴포넌트 (함수 컴포넌트에서 사용)
- function as a child : 컴포넌트의 자식으로 함수를 사용하는 방법
- // children이라는 prop을 직접 선언하는 방식 <Profile children={name => <p>이름: {name}</p>} /> // Profile 컴포넌트로 감싸서 children으로 만드는 방식 <Profile>{name => <p>이름: {name}</p>}</Profile>
- Context.displayName : 문자열 속성을 가진다
- 리액트 크롬 개발자 도구에서 consumer를 표시할때 이 displayName을 함께 표시한다
- 여러 개의 Context 사용하기
- context.provider를 중첩해서 사용하기
- useContext() : hook을 통해 함수 context를 쉽게 사용할 수 있다
- 파라미터로 컨텍스트 객체를 넣어줘야 한다
function MyComponent(props) { const value = useConetxt(MyContext); return ( ... ) }
Styling
stlyed-components
- css 문법을 그대로 사용하면서 결과물을 스타일링된 컴포넌트 형태로 만들어주는 오픈소스 라이브러리이다.
- 컴포넌트 개념이라 리액트에서 자주 사용
- styled-components 설치
# npm을 사용하는 경우
npm install --save styled-componetns
# yarn을 사용하는 경우
yarn add styled-components
- 기본 사용법
- tagged template literal을 사용하여 구성 요소의 스타일을 지정한다
- template literal : 자바스크립트에서 제공하는 문법 중 하나
- literal : 소스 코드의 고정된 값
- literal를 template 형태로 사용하는 방법
- 백틱(``)을 사용해 문자열을 작성하고 그 안에 대체 가능한 expression을 넣는 방법
- styled-componetns 사용 예시
- `` 안에 css 속성을 넣는다
import React form 'react'; import styled from 'styled-components'; const Wrapper = styled.div ` padding: 1em; background: grey; `;
- stlyed-components의 props 사용하기
- `` 안에 css 속성을 넣는다
import React form 'react';
import styled from 'styled-components';
const Button = styled.button`
color: ${props => props.dark ? "white" : "dark" };
background: ${props => props.dark ? "balck" : "white"};
border: 1px solid black;
`;
function Sample(props) {
return (
<div>
<Button>Normal</Button>
<Button dark>Dark></Button>
</div>
)
}
export default Sample;
무료강의이고, 리액트를 한번 쭉 훑어보기 좋을 것 같아서 수강했는데 잘한 결정이었다고 생각한다.
이제 다시 반복하면서 복습해야겠다.
728x90
'개발 공부 > React' 카테고리의 다른 글
[React] react-toastify 사용하기 (0) | 2022.12.19 |
---|---|
[React] React의 생명주기 (LifeCycle) 이해하기 (0) | 2022.12.15 |
[React] Redux(리덕스) 이해하기 (1) | 2022.12.13 |
[React] 스파르타코딩 내일배움캠프 React 숙련 내용 정리 (0) | 2022.12.12 |
[React] 스파르타코딩 내일배움캠프 React 입문 내용 정리 (0) | 2022.12.06 |