Github 체크아웃 방법, fetch 와 pull, 병합시 사용하는 merge 와 rebase, 브랜치 다루는 방법은 아래 포스팅을 참고하세요. 

👉https://gosasac.tistory.com/72

 

[Git] - Github 체크아웃, fetch 와 pull, merge 와 rebase, 브랜치 다루기

git - 프로젝트 관리시작, commit, push, 프로젝트 원격지로 올리는 법, 원격지 연결 해제 방법은 아래 포스팅을 참고하세요 👉https://gosasac.tistory.com/71 git - 프로젝트 관리시작, 브랜치명 변경, 커밋,

gosasac.tistory.com

 

 

🟥 파일의 삭제와 이동

* 삭제

파일은 그냥 삭제하면 Working directory에 남아있습니다.

git rm 파일명

git rm 으로 삭제하면 파일의 삭제가 Staging area에 있습니다.  

 

* 이동(or 이름변경)

mv 명령어를 이용하면 이동이나 이름변경이 가능합니다.

git mv 원본파일명 변경할파일명

 

 

 

🟥 커밋하지 않은 파일 되돌리기 [reset]

 

* 파일을 Staging area 에서 Working directory로 되돌리기

git restore --staged 파일명

 

 

* add가 안된 상태에서 파일을 수정 이전상태로 되돌리기

git restore 파일명

 

* stage에 올라가지 않은 모든 변화들 원복시키기

git restore .

 

* stage안에 있는것들 까지 모두 되돌리기

git reset --hard

❗ reset의 세가지 옵션

1. --soft : repository에서 staging area로 이동

2. --mixed(default) : repository에서 working directory로 이동

3. --hard: 수정사항 완전히 삭제

 

 

 

* 특정 파일만 git의 특정과거 시점으로 되돌리기(Working directory의 파일만 가능합니다)

git restore --source=해시값 파일명

* 특정 리비전에 대한 해시값은 아래 reflog를 통해 확인할 수 있습니다.

 

 

 

🟥 reset 되돌리기 [reflog]

* reset으로 커밋 15개 되돌리기

git reset --hard HEAD~15

각 브랜치에서 가장 마지막(최신의) 커밋 위치를 HEAD 라고 표현합니다. 

HEAD에 물결(~)을 붙이면 HEAD를 기준으로 뒤로 이동하고 윗꺾새(^)를 붙이면 앞으로 이동한다는 의미입니다. 

(reset으로 삭제한 건 git log로도 볼 수 없습니다. )

 

 

* 모든 깃 작업내용 보기 (특정 리비전의 해시값 확인)

git reflog

빨간 박스 안에 보이는 문자열이 각 리비전의 해시id 입니다.

해당 해시값을 이용해 원하는 시점으로 되돌아 갈 수 있습니다.

 

 

* reset 전 해시값을 이용해 다시 reset

git reset --hard 해시값

git - 프로젝트 관리시작, commit, push, 프로젝트 원격지로 올리는 법, 원격지 연결 해제 방법은 아래 포스팅을 참고하세요

👉https://gosasac.tistory.com/71

 

git - 프로젝트 관리시작, 브랜치명 변경, 커밋, 푸쉬, 원격저장소 올리는법

git - 설치 방법은 아래 링크 참고 👉https://gosasac.tistory.com/69 git - 설치(CLI와 GUI[sourcetree])와 최초 설정 방법 🟥 윈도우 Git 설치 https://git-scm.com/ 에서 Git을 다운로드 합니다. ⭐설치과정에서 Git Bash

gosasac.tistory.com

 

 

 

🟥 GItHub에서 프로젝트 다운받기

 github 페이지에서 checkout 받고자하는 프로젝트의 [< > Code ] 탭과 [< > Code ]  버튼을 찾아가면, 

아래와 같은 HTTPS URL확인이 가능합니다. 

우측의 버튼을 눌러 복사합니다. 

 

 

이제 로컬에서 터미널이나 Git Bash에서 체크아웃 받고자 하는 대상 폴더로 이동한 후에 아래 명령을 실행합니다. 

git clone 원격지주소

이후 아래 fetch 와 pull 명령어를 통해 소스를 가져옵니다. 

 

❗ checkout 명령어가 Git 2.23 버전부터 switch, restore로 분리되었습니다. 

git switch 브랜치명

 

 

 

 

🟥 fetch vs. pull

fetch : 원격 저장소의 최신 커밋을 로컬로 가져오기만 합니다.

pull : 원격 조장소의 최신 커밋을 로컬로 가져와 merge 또는 rebase를 진행합니다.

 

즉, pull에는 기본적으로 fetch가 포함되어 있습니다.

 

fetch를 이용하면 원격지의 새 branch(ex. new-branch) 내용을 바로 내 작업본에 pull하지 않고, 소스를 확인만 하는 것이 가능합니다.

 

git fetch
git pull

 

🔸 pull할 것이 있을 때 push를 하게 되면 ?

원격 저장소에 먼저 적용된 새 버전이 있는 경우에는 push가 불가능합니다. 

pull을 이용해 원격의 버전을 받아온 이후에 비로소 push를 할 수 있습니다. 

 

 

 

🟥 브랜치를 합치는 두 가지 방법. [merge 와 rebase]

 

* merge 방식

두 개의 가지를 이어 붙이는 작업으로 대상 브랜치에 적용시, 커밋이 한 번 더 생기게됩니다. 

-merge 방식으로 pull하는 명령어

git pull --no-rebase

 

* rebase 방식

브랜치의 마디 커밋들을 대상 브랜치로 모두 옮겨붙이는 것입니다. 

- rebase 방식으로 pull하는 명령어

git pull --rebase

 

merge방식과 rebase 방식의 결과물은 동일하지만, 브랜치의 사용 내역을 남길 필요가 있다면 merge.

브랜치 사용내역이 별로 중요하지 않고, 히스토리를 깔끔하게 유지하고 싶다면 rebase를 진행하면 됩니다.

 

 

 

* merge로 합치기 

main브랜치에 sub 브랜치를 merge 하기.

git switch main
git merge sub
git branch -d sub  // sub 브랜치 삭제

 

 

* rebase로 합치기

sub 브랜치를 main 브랜치로 rebase 하기.

git swtich sub    // ⭐ merge 때와는 달리 rebase시킬 브랜치로 이동합니다.
git rebase main

여기까지 진행 후, 소스트리와 같은 GUI툴로 상태를 확인해 보면, main 브랜치는 뒤쳐져 있는 상황이 됩니다. 

따라서 main 브랜치로 다시 이동해서, sub의 시점으로 fast-forward 작업이 필요하죠.

merge할 때와 동일한 방식으로 진행하면 됩니다. 

git switch main
git megre sub
git branch -d sub

 

 

 

🟥 브랜치 다루기

브랜치는 프로젝트를 하나 이상의 모습으로 관리할 때 와 

여러 작업들을 각각 독립적으로 진행할 때 사용합니다.

 

- new-branch 라는 브랜치 생성

git branch new-branch

 

- 생성된 브랜치 확인

git branch

 

- 모든 브랜치 확인(원격지에 있는 브랜치까지) [-a]

git branch --all
git branch -a

 

- old-branch 라는 브랜치로 이동

git switch old-branch

*checkout 명령어가 Git 2.23버전부터 switch, restore로 분리되었습니다. 

 

 

- 브랜치(baby-branch) 생성과 동시에 이동하기 [-c]

git switch -c baby-branch

 

 

- 브랜치 삭제하기 [-d]

git branch -d 브랜치명

지울 브랜치에 다른 브랜치로 적용되지 않은 내용의 커밋이 남아있을 시에는 -D(대문자) 옵션을 이용해 강제 삭제합니다. 

 

 

- 브랜치명 변경하기 [-m]

new-branch라는 브랜치 생성 후 baby-branch로 변경 

git branch new-branch
git branch -m new-branch baby-branch

 

 

 

🟥 원격 브랜치 다루기

원격지의 새 브랜치 받아오기

git fetch
git switch -t origin/new-branch

로컬에 원격지의 'new-branch' 브랜치를 생성하여, 연결하고 switch 합니다. 

 

 

원격지 브랜치 연결해제

원격지 origin에 로컬 main을 다시 push하는 방법입니다. 

git remote remove origin
git push -u -f origin main

 

 

원격지 브랜치 소스 올리기

로컬과 원격지가 동일 브랜치명으로 연결되어야 push가 가능합니다.

git branch new-branch  // new-branch 라는 브랜치 생성
git switch new-branch  
git push -u origin new-branch

 

원격지 브랜치 삭제

git push origin --delete 원격지브렌치명

* origin은 원격지의 이름입니다. 

git - 설치 방법은 아래 링크 참고 

👉https://gosasac.tistory.com/69

 

git - 설치(CLI와 GUI[sourcetree])와 최초 설정 방법

🟥 윈도우 Git 설치 https://git-scm.com/ 에서 Git을 다운로드 합니다. ⭐설치과정에서 Git Bash 를 포함하는 것이 좋습니다. 그 이유는 Git Bash가 Git사용에 적합한 터미널 이기 때문입니다. 또, Git Bash는

gosasac.tistory.com

 

 

 

 

🟥 프로젝트의 default 브랜치명 변경 방법

 

1. default 브랜치명 확인

git config init.defaultBranch

 

2. default 브랜치명 변경 (main으로 변경)

git config init.defaultBranch main

 

 

3. 현재 브랜치의 브랜치 명 변경 (master → main으로 변경)

git branch -m master main

예전에는 master, salve를 많이 사용했으나, 역사적 관점에서 불편한 용어이기 때문에 master → main 으로 대체되었다.

 

 

 

🟥 프로젝트 생성 & git관리 시작

적당한 위치에 원하는 이름으로 폴더를 생성하고 VS Code 를 오픈합니다.

해당 폴더에서 터미널 열고 (윈도우 단축키 Ctrl + ` )

git init

폴더에 숨김모드로 .git 폴더가 생성된 것을 확인할 수 있습니다. 

(*.git 폴더를 지우면 git에서 관리해온 정보가 다 날아갑니다. )

git status

현재 폴더의 상황을 git관점에서 보여줍니다.

 

 

 

🟥 git 관리에서 특정 파일/폴더 제외 (.gitignore)

 보안상 민감한 파일이나 자동으로 생성 또는 다운로드 되는 파일들(빌드 결과물, 라이브러리)은 .gitignore 파일을 사용해 형상 관리에서 제외시킬 수 있습니다. 

 

.gitignore 파일 예시

# 이렇게 #를 사용해서 주석

# 모든 file.c
file.c

# 최상위 폴더의 file.c
/file.c

# 모든 .c 확장자 파일
*.c

# .c 확장자지만 무시하지 않을 파일
!not_ignore_this.c

# logs란 이름의 파일 또는 폴더와 그 내용들
logs

# logs란 이름의 폴더와 그 내용들
logs/

# logs 폴더 바로 안의 debug.log와 .c 파일들
logs/debug.log
logs/*.c

# logs 폴더 바로 안, 또는 그 안의 다른 폴더(들) 안의 debug.log
logs/**/debug.log

더 상세한 .gitignore 형식은 

👉https://git-scm.com/docs/gitignore 참고

 

 

 

🟥 커밋 (commit)

* Git의 3가지 공간

출처: 얄코 Git 강의

1. Working directory

 - Untracked: Add된 적 없는 파일이나 ignore 된 파일

 - Tracked : Add된 적 있고 변경내역이 있는 파일

 - git add 명령어로 Staging area로 이동합니다. 

 

2. Staging area

 - 커밋을 위한 준비 단계입니다. 

 

3. Repository

 - 최종 커밋된 상태로 원격저장소를 의미합니다. 

 


- 먼저 git status 명령을 통해 변경 파일을 확인합니다.

git status

 

- 파일 하나 stage에 담기

git add 파일명

 

- 모든 파일 stage에 담기

git add .

 

- 커밋으로 로컬 저장소로 올리기 

git commit

git commit 까지만 입력하면 vi 편집기 입력모드로 진입합니다.

커밋 메시지를 입력한뒤 저장하고 종료를 해서 vi 편집기를 빠져나옵니다.

vi편집기 단축키

i : 입력시작

ESC : 입력종료

q : 저장없이 종료 

q! : 저장없이 강제종료

wq : 저장하고 종료

 

 

- vi 편집기를 통하지 않고 커밋 메시지와 함께 커밋

git commit -m "메시지"

 

아래 명령어로확인 

git log

 

- add와 commit을 한 번에

git commit -am "메시지"

위 방법은 새로 추가된(untracked) 파일이 없을 때만 사용합니다.

 

 

 

🟥 git push

 git 프로젝트 원격지(깃헙)로 올리는 방법

add와 commit까지 완료가 된 상태에서 아래 명령어를 입력해 원격지 저장소(깃헙)에 소스를 올릴 수 있습니다.

git remote add origin 깃헙주소
git push -u -f origin main

git remote add origin 깃헙주소

로컬 git 저장소에 원격 저장소로의 연결을 추가하는 명령줄입니다.

 

git branch -m main

기본 브랜치명 이름을 main으로 변경하세요. (github 권장 내용입니다.)

 

git push -u origin main

로컬 저장소의 커밋 내역을 원격으로 업로드합니다. 

현재 브랜치를 default로 어떤 원격지 어떤 브랜치에 연결할지 지정하는 것으로 , 

위 명령줄 입력 이후로는 git push 만 입력하면 main에서의 push는 원격지의 main 브랜치로 올라갑니다.

 

git remote

현재 프로젝트와 연결된 원격지 목록을 볼 수 있습니다. 

 

❗ 원격지 브랜치명과 로컬 브랜치명이 다른경우

깃헙에 올릴 때는 로컬과 원격지에 동일 브렌치명 연결 설정이 필요합니다.

git branch from-local
git switch from-local
git push -u origin from-local

 

❗ 연결된 remote origin 연결 해제 

git remote add origin 잘못된주소

위와 같이 원격지 연결을 잘못 한경우 연결을 해제하는 방법입니다. 

 

원격지 origin에 로컬 main을 push하는 방법.

git remote remove origin
git push -u -f origin main

 

🟥 윈도우 Git 설치

 

https://git-scm.com/ 에서 Git을 다운로드 합니다.

 

⭐설치과정에서 Git Bash 를 포함하는 것이 좋습니다.

그 이유는 Git Bash가 Git사용에 적합한 터미널 이기 때문입니다. 

 

또,  Git Bash는 리눅스/맥(유닉스)에서 사용되는 CLI명령어들을 윈도우에서 사용 가능하게 해줍니다.

❗ 윈도우용 터미널은 명령어 체계가 리눅스와 다르기 때문입니다.

나머지 기본 설정은 그대로 설치 진행하면 됩니다.

 

 

 

 

🟥 SourceTree설치 (Git용 GUI)

https://www.sourcetreeapp.com  - Git을 GUI로 다룰 수 있도록 해주는 툴 입니다.

 

기타다른 툴 [ GitHub Desktop(비추 : 기능이 많이없음), GitKraken (유료) ] 도 있습니다.

SourceTree 설치 과정중에 Bitbucket을 등록하라고 나오는데, Bitbucket은 GitHub과 같은 종류의 서비스로 건너뛰기 하면 됩니다. (Mercurial도 마찬가지)

 

✅ CLI vs. GUI  ?? 

CLI는 Command Line Interface - 명령줄 입력 방식의 인터페이스 입니다.

GUI는 Graphic User Interface - 좀 더 쓰기 편하게 그래픽으로 제공되는 서비스 입니다.

 

⭐ 결론적으로 둘 다 사용할 줄 아는것이 좋습니다.

IDE상에서 간단히 처리할 땐 CLI사용하고, 전체적인 흐름을 보고 싶을 때 GUI가 편합니다.

 

 

 

 

🟥 Git 최초 설정하기

다음은 Git 전역으로 사용되는 사용자 이름과 이메일 주소를 설정하는 방법입니다. 

❗❗ GitHub 계정과는 별개 이며, 히스토리 추척시 연락망 용도로 이용됩니다. 

git config --global user.name "본인 이름"
git config --global user.email "본인 이메일"

 

확인 방법. 

git config --global user.name
git config --global user.email

 

 

 

⭐협업시 윈도우와 맥에서 엔터 방식 차이로 인한 오류를 방지하는 명령어

git config --global core.autocrlf true

 


기본 브랜치 명을 main으로 변경

git config --global init.defaultBranch main

 

이후로 git.init을 통해 로컬에서 생성하는 리포지토리의 default branch는 main으로 생성됩니다.

 

👀 원래 master & salve 용어를 사용했는데, 서양의 역사 관점에서 비추어볼때 표현이 불편해 matser에서 →  main/trunk 로 변경되는 분위기입니다.

🟥 훅 (Hooks)

리액트 v16.8 부터 도입된 개념으로

원래 함수형 컴포넌트에서는 state관리가 불가능했으나,

함수형 컴포넌트에서도 상태관리를 할 수 있도록 도입된 기술입니다.

 

 

useState, useEffect, useReducer, useMemo, useCallback

🔸 useState

상태를 관리하기 위한 가장 기본적인 훅 입니다.

...
const [count, setCount] = useState(0);  //useState의 인자로는 초기값을 넘겨줍니다. 

onClick = () => {
  setCount(count+1);
}
return (
  <>
    <div>{count}</div>
    <button onClick={onClick}</button>
  </>
)
...

useState의 인자로는 상태관리를 위한 초기값을 넘겨줍니다. 

그러면 배열이 반환되는데, 첫번째 인자는 현재의 상태(state)를 나타내고, 두번째 인자는(setCount)는 상태를 업데이트할 때 실행되는 함수명입니다. 

 

 

 

🔸 useEffect

컴포넌트가 실제 DOM에 렌더링된 직후마다 실행됩니다.

클래스형 컴포넌트에서 사용하는 componentDidMountcomponentDidUpdate를 합친 형태로 보아도 무방합니다.

 

  • 마운트 될 때만 실행하고 싶을 때

함수의 두 번째 파라미터로 빈 배열을 넣어주면 최초 마운트 될 때만 한 번 실행 됩니다.

useEffect( () => {
  console.log("마운트될 때만 실행됩니다.");
}, []);

 

  • 특정 값이 업데이트될 때만 실행하고 싶을 때

함수의 두 번째 파라미터로 검사하고 싶은 state값을 넣어주면 됩니다. 

아래 내용은 name의 상태가 변경될 때 마다 log를 찍는 로직입니다.

useEffect( () => {
  console.log("name");
}, [name]);

 

  • 뒷정리하기

컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떤 작업을 필요로 하는 경우, useEffect함수 내에서 후처리를 위한 함수를 반환해 주어야 합니다.

useEffect( () => {
  console.log("effect");
  return () => {
    console.log('cleanup');
  }
}, [] ); // 오직 언마운트시에만 후처리 함수를 호출하고 싶다면 두번째 파라미터에 빈배열을 넘긴다.

 

 

 

🔸 useReducer

useReduceruseState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트하고 싶을 때 사용하는 Hook입니다.

 

카운터 구현하기

import { useReducer } from 'react';

function reducer(state, action) {
  swtich (action.type) {
    case 'INCREMENT' :
      return { value : state.value + 1 }
    case 'DECREMENT' :
      return { value : state.value - 1 }
    default :
      // 아무것도 해당되지 않으면 기존상태 반환
      return state;
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, { value: 0});
 
  return (
    <div>
      <p>
        현재 카운터 값은 <b>{state.value}</b>입니다. 
      </p>
      <button onClick={ () => dispatch({type : 'INCREMENT'})}>+1</button>
      <button onClick={ () => dispatch({type : 'DECREMENT'})}>-1</button>
  );
};

export default Counter;

useReducer에 첫 번째 파라미터로는 리듀서 함수를 넣고, 두 번째 파라미터에는 해당 리듀서의 기본값을 넣어줍니다.

이 훅을 사용하면 state 값과 dispatch 함수를 받아오는데, 여기서 state는 현재 카리키는 상태이고, dispatch는 액션을 발생시키는 함수입니다.

useReducer 사용시 가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수 있다는 것입니다.

 

 

 

🔸 useCallback

 성능 최적화를 위해 사용되는 훅 중 하나입니다.

useCallback을 이용하면 함수를 메모이제이션해 함수 인스턴스의 재사용이 가능합니다. 

 

함수컴포넌트 안에서 함수를 만들어 사용하면, 컴포넌트가 렌더링될 때 마다 새로 만들어진 함수 인스턴스를 사용하게 되며, 이는 성능에 악영향을 줄 수 있습니다. 

따라서 최적화가 필요한 상황에 사용합니다.

const memoizedCallback = useCallback(callbackFunction, dependencyArray);

첫 번째 파라미터로는 메모이제이션 하고자하는 함수를 전달하고, 두 번째 파라미터로는 상태 변경 모니터링이 필요한 stateprops를 전달합니다. 

 

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

function Counter() {

  const [ count, setCount ] = useState(0);

  const handleClick = useCallback( () => {
    setCount(count+1);
  }, [count]);

  return (
   <div>
     <p>Counter: {count}</p>
     <button onClick={handleClick} />
   </div>
  );
}

count가 변경되지 않는 한, 같은 함수 인스턴스가 재사용되어 불필요한 리렌더링을 방지할 수 있습니다. 

 

 

 

🔸 useMemo

useCallback과 같이 성능 최적화를 위해 사용되는 훅 중 하나입니다. 

useCallback이 컴포넌트의 함수 인스턴스를 재 사용하기 위해 사용한다면, useMemo는 연산 비용이 높은 계산 결과를 메모이제이션하기 위해 사용합니다. 

const memoizedValue = useMemo(() => computeValue, dependecyArray);

 

useMemo는 값을 캐시하므로, 이전 계산 결과를 재사용해 성능을 향상시킬 수 있습니다.

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

function ExpensiveComponent({data}) {
  const expensiveResult = useMemo(() => {
    // data 배열 요소들을 모두 합산하는 연산 (고비용)
    return data.reduce((sum, num) => sum+num, 0);
  }, [data] );

  return <div>Expensive Result: {expensiveResult}</div>;
}

 

위의 예시에서 data 배열이 변경될 때 마다 expensiveResult를 다시 계산합니다. 

그렇지 않으면, 캐시된 결과를 사용해 비용을 아끼고 성능을 향상시킵니다. 

 

data가 변경되지 않는 한, 이전 결과를 그대로 사용하기 때문에 중복된 계산을 피할 수 있습니다. 

🟥 컴포넌트의 라이프 사이클

 

모든 리액트 컴포넌트는 라이프사이클을 가지고 있습니다.

 

리액트 컴포넌트는 버튼 하나로 표현될 수도 있고, 페이지 전체로 표현될 수도 있다고 했죠.

컴포넌트는 "UI조각"이기 때문에 실제 DOM에 나타나기도 하고(생성), DOM에서 사라지기도 합니다.(소멸)

즉, 컴포넌트의 생성부터 소멸까지를 라이프 사이클이라고 합니다.

컴포넌트의 라이프사이클

 

라이프 사이클은 마운트, 업데이트, 언마운트 총 세가지 카테고리로 나뉩니다.

 

[마운트]

실제 DOM이 생성되서 화면에 그려지는 것을 마운트라고 합니다.

호출 순서는 다음과 같습니다.

  1. Constructor - 컴포넌트를 새로 만들때마다 호출되는 클래스 생성자 메서드입니다.
  2. render - UI를 렌더링하는 메서드 입니다.
  3. componentDidMount - 브라우저에 실제 DOM 이 그려진 후에 호출되는 메서드입니다.

 

[업데이트]

컴포넌트는 아래와 같이 총 네 가지 경우에 업데이트 합니다.

  1. state가 바뀔 때
  2. props가 바뀔 때
  3. 부모 컴포넌트가 리렌더링될 때
  4. this.forceUpdate로 강제로 렌더링을 발생시킬 때

그리고 업데이트 작업이 끝나면, componentDidUpdate 메서드가 실행됩니다.

 

[언마운트]

마운트의 반대 과정. 즉 컴포넌트가 DOM에서 사라지기 전에 호출하는 메서드입니다.

componentWillUnmount

 

 

 

🟥 라이프사이클 메서드

라이프 사이클에서 사용 가능한 메서드들이 있습니다.

 

Will접두사가 붙은 메서드는 어떤 작업을 작동하기 전에 실행되고,

Did접두사가 붙은 메서드는 어떤 작업을 작동한 후에 실행됩니다.

 

❗ 라이프 사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있고,
 함수형 컴포넌트에서는 Hooks 를 사용해 비슷한 작업을 처리할 수 있습니다.

 

🔶 return 메서드

리액트 요소를 반환하며, 화면을 그리는 역할을 담당합니다.

해당 메서드 안에서 propsstate에 접근할 수 있습니다.

아무것도 보이고 싶지 않다면 null이나 false를 리턴한면 됩니다.

주의사항으로는, 이벤트 설정이 아닌 곳에서 setState를 사용하면 안되며, 브라우저 DOM에 접근해서도 안됩니다. DOM정보를 가져오거나 state에변화를줄 때는 componentDidMount에서 처리해야 합니다.

 

 

🔶 constructor 메서드

컴포넌트의 생성자 메서드로 컴포넌트를 만들 때 처음으로 실행됩니다.

 

 

🔶 static getDerivedStateFromProps 메서드 

props로 받아온 값을 state에 동기화시키는 용도로 사용하며, 컴포넌트가 마운트 될 때와 업데이트 될 때 호출됩니다.

static getDerivedStateFromProps(nextProps, prevState) {
  if(nextProps.value !== prevState.value) { //조건에 따라 특정값 동기화
    return { value : nextProps.value };
  }
  return null; // state를 변경할 필요가 없다면 null을 반환
}

 

🔶 componentDidMount 메서드

컴포넌트를 만들고, 첫 렌더링을 다 마친 후 실행합니다.

이 안에서 다른 자바스크립트 라이브러리 또는 프레임워크의 함수를 호출하거나 이벤트 바인딩, setTimout, setInterval, 네트워크 요청 같은 비동기 작업을 처리하면 됩니다.

 

 

🔶 shouldComponentUpdate 메서드

이것은 props또는 state를 변경했을 때, 리렌더링을 시작할지 여부를 지정하는 메서드입니다.

이 메서드에서는 반드시true값 또는 false값을 반환해야 합니다.

 

컴포넌트를 만들때 이 메서드를 따로 생성하지 않으면 기본적으로 항상 true를 반환합니다.

이 메서드 안에서 현재 propsstatethis.propsthis.state로 접근하고, 새로 설정될 props또는 statenextPropsnextState로 접근할 수 있습니다.

 

 

 

🔶 getSnapshotBeforeUpdate 메서드

getSnapshotBeforeUpdate(prevProps, prevState) {..}

render 메서드에서 만들어진 결과물이 브라우저에 실제 반영되기 직전에 호출됩니다.

이 메서드에서 반환하는 값은 componentDidUpdate 에서 세 번째 파라미터인 snapshot 값으로 전달받을수 있는데요, 주로 업데이트 하기 직전의 값을 참고할 일이 있을때 사용됩니다.(예: 스크롤 위치 유지 등)

 

 

 

🔶 componentDidUpdate메서드

componentDidupdate(prevProps, prevState, snapshot) {..}

리렌더링을 완료한 이후 실행합니다.

prevProps, prevState를 사용해 컴포넌트가 이전에 가졌던 데이터에 접근할 수 있습니다.

세번째 파라미터인 snapshot에는 getSnapshotBeforeUpdate 의 리턴정보가 들어있습니다.

 

 

 

🔶 componentWillUnmount 메서드

컴포넌트를 DOM에서 제거할 때 실행합니다.

componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM이 있으면 여기서 제거 작업을 해야합니다.

 

 

 

🔶 componentDidCatch 메서드

컴포넌트 렌더링 도중에 에러 발생시 어플리케이션이 먹통되지 않고, 오류 UI를 보여줄 수 있게 해줍니다.

componentDidCatch(error, info) {
  this.setState({
    error : true
  });
  console.log({error, info});  //console.log대신 서버 API를 호출해 로그 수집도 가능합니다.
}

error는 파라미터에 어떤 에러가 발생헀는지 알려주며, info는 어디에 있는 코드에서 오류가 발생했는지에 대한 정보를 줍니다.

그러나 컴포넌트 자기 자신의 에러는 잡아낼 수 없고, 자식 컴포넌트에서 발생하는 에러를 잡아낼 수 있습니다.

 

 

 

출처 및 참고자료

김민준님 저 - 리액트를 다루는 기술

🟥 Props

 

properties를 줄인 표현으로 컴포넌트의 속성을 설정할 때 사용합니다.

props값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정할 수 있습니다.

컴포넌트의 필수 props를 지정하거나 props의 타입(type)을 지정할 때는 propTypes를 사용합니다.

 

App.js

...
  return <MyComponent name="리액트" age={10}/>;
...

 

MyComponent.js

import PropTypes from 'prop-types';  // PropTypes 사용을 위해 추가

const MyComponent = {name, age}=> {
  return <div> 안녕하세요, 제 이름은 {name}입니다. 제 나이는 {age}입니다.</div>;
};

// defaultProps 설정 방법
MyComponent.defaultProps = {
  name : '지상렬'
};

// PropTypes지정 방법
MyComponent.propTypes = {
  name : PropTypes.string
  age : PropTypes.number.isRequired  // 필수 값 isRequired
};

export default MyComponent;

 

defaultProps와 propTypes 지정은 필수는 아니지만, 대규모 어플리케이션 개발 프로젝트 진행시 또는 협업시 개발 능률 향상을 위해 사용을 권장합니다.

 

 

🟥State

컴포넌트 내부에서 바뀔 수 있는 값을 의미합니다.

props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며,

컴포넌트 자신은 해당 props를 읽기전용으로만 사용할 수 있습니다.

 

props를 바꾸려면 부모 컴포넌트에서 바꾸어 주어야 합니다.

❗ props를 사용한다고 해서 값이 무조건 고정되는건 아닙니다.
부모 컴포넌트의 state를 자식 컴포넌트의 props로 전달하고,
자식 컴포넌트에서 특정 이벤트가 발생했을 때 부모 컴포넌트의 메서드를 호출하면 props도 유동적으로 사용할수 있습니다.

 

 

클래스형 컴포넌트에서 state 초깃값은 객체 형태로 넣어주어야 합니다.

🔶 setState

this.setState를 사용할 때는 함수를 인자로 넣을수도 있습니다.

형식은 다음과 같습니다

this.setState((prevState, props) => {
  return {
    // 업데이트 하고싶은 내용
  }
});

prevState는 기존 상태이고, props는 현재 지니고 있는 props를 가리킵니다.

만약 업데이트 과정에서 props가 필요하지 않다면, 생략 가능합니다.

 

class Counter extends Component {
	state = {
	  number: 0;
	}
	
	return() {
	  ...
	  <button onClick={() => {
	    this.setState(prevState => {
	      return {
	        number : prevState.number+1
	      };
	    });
	    // 위 코드와 아래 코드는 완전히 똑같은 기능을 합니다. 
	    // 아래 코드는 함수에서 바로 객체를 반환한다는 의미입니다.
	    this.setState(prevState => ({
	      number: prevState.number+1
	    }));
	  ... 
	  }
	}
}

 

onClick에서 두번째로 this.setState함수를 사용할 때는 화살표 함수에서 바로 객체를 반환하도록 했기 때문에 prevState ⇒ ({ }) 와 같은 형태로 코드가 이루어집니다.

 

this.setState의 두 번째 파라미터로는 콜백함수를 등록해 작업을 처리할 수 있습니다.

 

 

클래스형 컴포넌트에서 setState를 사용하며, 함수형 컴포넌트에서는 Hook중 하나인 useState를 사용합니다. 

 

🔶 useState

useState 함수의 인자에는 상태의 초깃값을 넣어 줍니다.

클래스형 컴포넌트는 초깃값을 무조건 객체 형태로 넣어주어야 하지만,

함수형 컴포넌트의 초기값의 형태가 자유롭습니다.

 

함수를 호출하면 배열이 반환되는데, 첫 번째 원소는 현재의 상태이고, 두 번째 원소는 상태를 변경해주는 함수입니다.

이 함수를 세터(Setter)라 부릅니다.

 

그리고 배열 구조분해 할당을 통해 자유롭게 네이밍이 가능합니다.

아래는 avengers와 setAvengers로 네이밍 한 예입니다.

let [avengers, setAvengers] = useState(["Spider", "Hulk", "Thor"]);

return() {
  ...
  <button onClick={() => {
    // state 안바뀜
    avengers[0] = "Ironman";
    setAvengers(avengers);  	    // state 안바뀜

    let copy = avengers;
    copy[0] = "Ironman";
    setAvengers(copy);            // 마찬가지로 state 안바뀜

    let copy = [...avengers];
    copy[0] = "Spiderman";
    setAvengers(copy);            // avengers = ["Spiderman", "Hulk", "Thor"]
  }}>
  버튼
  </button>
  ... 
}

state 변경 함수는 setAvengers는 ( ) 소괄호 안에 넣은걸로 기존 state를 갈아치웁니다.

 

🔶 state 사용시 주의사항

state값을 바꾸어야 할 때는 setState 혹은 useState를 통해 전달받은 세터함수를 사용해야 합니다.

 

❗배열이나 객체의 state 변경

state가 array나 object면 독립적 카피본을 만들어서 수정해야 합니다.

array도 결국 object입니다.

백날 데이터를 변경해봤자, 변수에 저장되어있는 객체를 가리키는 주소값은 달라지지 않기 때문입니다.

 

 

배열은 배열의 내장함수를 활용하는 방법도 있습니다.

const object = { a:1, b:2, c:3 };
const nextObject = {...object, b: 4}; // 사본을 만들어서 b값만 덮어쓰기


const array = [
  { id:1, value: true },
  { id:2, value: true },
  { id:3, value: false}
];

let nextArray = array.concat({ id: 4}); // 새항목 추가
nextArray.filter(item => item.id !== 2) // id가 2인 항목 제거
nextARray.map(item => item.id === 1 ? {...item, value: false} : item); //id가 1인 항목의 value를 false로 설정

🟥 리액트는 무엇이고, 왜 사용할까 ?

리액트는 자바스크립트로 UI 개발을 하기위한 라이브러리입니다.

 

❓ 전통적인 웹 개발에서의 JavaScript
전통적인 자바스크립트는 웹 페이지에서 동적인 처리만을 담당했습니다.

웹 화면은 HTML과 CSS로 표현되고 화면 내에서 동적인 처리가 필요한 경우에 자바스크립트를 사용했습니다.
딱딱 역할 분담이 잘 되어있었는데, 왜 굳이 자바스크립트로 UI 개발을 하려는 것일까요?

 

웹 어플리케이션의 규모가 점점 더 커짐에 따라, 그만큼 어플리케이션 자체의 용량도 많이 늘어나게 되었고, 이로인해 속도는 갈수록 느려지기 시작했습니다.

 

보다 interactive하게 동적으로 동작하는 웹 사이트를 만들기 위해서 DOM(Doucment object Mode) 제어는 필요합니다.

하지만, 문제는 DOM 조작 API를 너무 자주 호출하는 것은 성능에 악영향을 준다는 것입니다.

 

CSS 계산, 레이아웃 잡기, 화면 리렌더링의 비용이 많이 발생하므로, 속도성능문제가 발생하는데 이를 리액트팀이 VirtualDOM 으로 해결했습니다.

VirtualDOM은 메모리상에 있는 DOM의 복사본인 '자바스크립트 객체'로, 화면 전환이 발생하면 as-is와 to-be 버전의 VirtualDOM을 비교하여 변경된 부분만 최소한의 DOM 조작을 통해 실제 UI에 적용합니다.

 

 

 

🟥컴포넌트 

리액트 앱은 컴포넌트로 만들어 집니다.

 

컴포넌트는 로직을 가지는 일종의 UI의 조각을 의미합니다.

컴포넌트는 버튼 하나로 표현될 수도있고, 페이지 전체로 표현될 수도있으며 재사용이 가능합니다.

 

 

컴포넌트는 마크업(Mark Up)을 반환하는 "자바스크립트 함수"입니다.

 

선언한 컴포넌트를 사용할 때는 항상 대문자를 사용해야 합니다. <MyButton />

export default 키워드는 파일에서 메인 컴포넌트에 지정합니다.

 

마크업 문법은 JSX를 사용합니다. optional이지만, 대부분의 리액트 프로젝트에서 사용하며 편리합니다.

 

ReactDOM.render를 이용해 리액트 컴포넌트를 실제 DOM에 렌더링합니다.

ReactDom은 react-dom 모듈을 불러와 사용할 수 있습니다.

리액트 버전 v17 이후부터는

React.createElement 를 사용해 리액트 컴포넌트를 실제 DOM에 렌더링합니다.

 

컴포넌트는 함수형 컴포넌트클래스형 컴프넌트 두 가지로 나뉩니다.

 

🔸 클래스형 컴포넌트

import { Component } from 'react';

class App extends Component {
  render() {
    const name="리액트";
    return <div className="react">{name}</div>;
  }
}

export default App;

클래스형 컴포넌트의 경우 state 기능 및 라이프 사이클 관리 기능을 사용할 수 있다는 것과 임의 메서드를 정의할 수 있다는 장점이 있습니다.

또 클래스형 컴포넌트는 "render함수가 꼭 있어야 하고", 그 안에서 보여 주어야 할 JSX를 반환해야합니다.

 

🔸 함수형 컴포넌트

function App() {  // 화살표 함수도 가능
  const name = "리액트";
  return <div className="react">{name}</div>;
}

export default App;

함수형 컴포넌트의 장점은 우선 클래스형 컴포넌트보다 선언하기가 훨씬 편합니다.

큰 차이는 없지만, 메모리 자원도 클래스형보다 덜 사용하고요.

 

단점은 state라이프사이클 API 사용이 불가능하다는 점인데,

이 단점은 리액트 v16.8 업데이트 이후 Hooks라는 기능이 도입되면서 해결되었습니다.

 

return 문에서는 리액트 엘리먼트를 반환해야 합니다.

공식문서에서는 함수형 컴포넌트Hooks를 사용하도록 권장하고 있습니다.

 

 

 

🟥 JSX

JavaScript 확장 문법으로 얼핏보면 HTML 같지만 실제로는 JavaScript입니다.

JavaScript정식문법은 아니며, Babel을 통해 JSX가 Javscript로 변환됩니다.

 

JSX는 HTML보다 엄격합니다.

태그는 무조건 닫아야하고(예. <br />), 꼭 하나의 최상의 태그로 감싼후 반환해야 합니다.

<div>...</div> 를 사용하거나 프래그먼트(<>...</>)를 사용합니다.

(이유는 리액트가 컴포넌트의 변화를 효율적으로 감지하려면 DOM Tree구조가 유지되어야 한다는 규칙이 있기 때문입니다.)

 

JSX를 사용하는 파일의 상단에는 항상 React import가 필요합니다.

import React from “react”;

 

❗리액트 17 버전 이후부터 package.json에서 바벨 프리셋 설정을 아래와 같이 진행하면 위에 import 구문은 생략 가능합니다. 

//"runtime" :"automatic"을 설정.
//리액트 컴포넌트마다 최상단에 react import구문 생략가능 
...
"babel": { 
  "presets": [ 
     [ "@babel/preset-react", 
       { "runtime": "automatic" } 
     ]
   ] 
 }
 ...

 

JSX 내부에 자바스크립트 표현식을 쓸 수 있습니다.

중괄호 { } 로 감싸면 됩니다.

 

JSX 에서 style 과 CSS class는 className으로 설정합니다.

인라인 스타일은 객체 형태로 작성 & camelCase 형태로 네이밍합니다.

 

예시 )

export default function Profile() {
  return (
    <>
      <h1>{user.name}</h1>
      <img
        className="avatar"
        src={user.imageUrl}
        alt={'Photo of ' + user.name}
        style={{
          width: user.imageSize,
          height: user.imageSize
        }}
      />
    </>
  );
}

스타일이 자바스크립트 변수에 의존하는 경우 style속성을 사용할 수 있습니다.

위 JSX에문에서 style속성 지정시에는 {{}} 중괄호가 두겹으로 되어있는데,

스타일 속성은 객체{ } 형태로 지정하며 JSX의 중괄호{ } 문법으로 지정한 것입니다.

 

 

🔸 JSX의 조건부 렌더링

  1. if문은 JSX안에서는 동작이 안되고, return 문 밖에서 사용 가능합니다.
  2. .JSX안에서는 3항 연산자나 && 연산자를 활용한 조건부 렌더링이 가능합니다.

 

AND 연산자(&&)를 사용한 조건부 렌더링

return (<div> { name === '리액트' && <h1>리액트입니다.</h1>}</div>);

 

❗ 주의사항으로 falsy한 값인 0은 화면에 노출됩니다.

const number = 0;
return (<div> { number && <h1>숫자입니다.</h1>}</div>); // 0 노출

 

 

🔸 리스트 렌더링

for 루프 및 arraymap()함수를 이용해 구성요소를 순회할 수 있습니다.

리스트를 순회해서 <li>와 같은 요소를 생성하는 경우 key속성을 필수로 지정해야 합니다.

 

이유는 가상돔이 변경 점을 찾는 시간을 단축시키기 위함입니다.

key속성의 값은 유니크한 숫자나 문자열로 지정해야 합니다.

...
return (
    <ul>
      {userList.map((user) => (
        <li style={{ listStyle: 'none' }} key={user.id}>
          {user.name}
        </li>
      ))}
    </ul>
  )
  ...

 

🔸 JSX내부의 주석

{/* 이런 형태로 */}

열리는 태그 내부에서는 // 이런 형태로도 가능

 

 

-참고 및 출처

김정환님 인프런 리액트 강의

김민준님 리액트를 다루는 기술

+ Recent posts