[항해99] React 심화 강의

니나노개발생활·2021년 7월 5일
0

🏃🏻‍♀️bootcamp

목록 보기
18/18

1주차

컴포넌트 쪼개기

☝🏻 컴포넌트를 쪼개는 방법은 사람마다 방식이 달라 내가 편한 쪽으로 쪼개면 OK!
단, 너무 작게 쪼개면 만들기 힘들고, 너무 크게 쪼개면 재활용이 힘들다.

  • 페이지마다 반복되는 부분을 찾자
    : 페이지마다 공통으로 사용하는 부분을 컴포넌트로 빼주면 다른 페이지를 만들 때 반복하지 않고 재활용이 가능!

필드의 구조

  • build : 빌드 후 결과물이 생성
  • node_moduled : 설치한 패키지들이 들어있음
  • public : 가상 돔이 들어갈 빈 껍데기 html이 들어있는 폴더
  • src : 실제 소스 코드가 들어갈 폴더
    -> /elements : 최소 단위 컴포넌트
    -> /components : elements의 컴포넌트를 조합해 우리가 쪼갠 컴포넌트를 만들어 넣을 폴더
    -> pages : 페이지 시작점, components에 있는 컴포넌트를 조합해 페이지를 꾸릴 폴더
    -> redux : 리덕스 모듈과 스토더
    -> shared : 공용으로 사용할 코드 (App.js, firebase.js 등 전역으로 쓸 객체)

커뮤니티 만들며 이해하기!

1. 가장 먼저 메인 컴포넌트를 쪼개보자!

  • 포스트 목록 페이지는 헤더와 포스트 컴포넌트로 나눌 수 있다.

☝🏻 defaultProps : 페이지를 그리는데 꼭 필요한 데이터를 담아두면 데이터가 없어서 나는 오류를 방지할 수 있다. (음,, initialState의 느낌?)

Post.defaultProps = {
  user_info: {
    user_name: 'fall_of_jul',
    user_profile: profile,
  },
  img_url: profile,
  contents: '귀여운 김가을!',
  comment_cnt: 10,
  insert_dt: '2021-07-05 10:44:00',
}

2. 최소 단위 컴포넌트를 만들자!

☝🏻 안에 들어가는 형식은 비슷하나 각 최소 단위 컴포넌트별로 적용해야하는 css가 달라서 참고!
elements 깃허브

index.js (최소 단위 컴포넌트 묶음)

☝🏻 최소 단위 컴포넌트가 너무 많아지면 components에 import해야하는 부분이 많아져 코드가 복잡해진다!
따라서, index.js 파일을 생성하여 한 곳에 최소 단위 컴포넌트를 묶어주면 간단하게 사용할 수 있다.

import Grid from "./Grid";
import Image from "./Image";
import Text from "./Text";
export {Grid, Image, Text}

2주차

콜백

  • 자바스크립트가 비동기 처리를 하기 위한 패턴 중 하나

콜백 헬

  • 꼬리에 꼬리를 무는 비동기 처리가 늘어나면 호출이 계속 중첩되고, 코드가 깊어지고, 관리가 어려워진다.
    이러한 깊은 중첩을 콜백 헬 또는 멸망의 피라미드라고 부른다.

☝🏻 콜백 헬은 왜 발생할까?

  • 비동기 처리 시 실행 완료를 기다리지 않고 바로 다음 작업을 실행하기 때문에 순서대로 코드를 짠다고 해서 우리가 원하는 순서로 작업이 이루어지지 않는다.
  • 비동기 처리 함수 내에서 처리 결과를 반환하는 걸로는 원하는 동작을 하지 않으니 콜백 함수를 사용해 원하는 동작을 하게 만든다. 하지만 이 콜백 함수 내에서 또 다른 비동기 작업이 필요할 경우 중첩이 생기며 또 콜백 헬이 발생한다..

Promise

  • 자바스크립트는 싱글 쓰레드로 동작하는 언어(메인 쓰레드 + 콜스택)이며 비동기 작업을 동시에 할 수 있다.

    ☝🏻 어떻게 동시 실행을 할까?
    -> 자바스크립트는 코어 엔진만 가지고 돌아가는게 아닌 실행환경(런타임)의 도움을 받아 동시 실행한다.

  • 비동기 연산이 종료된 이후 결과를 알기 위해 사용하는 객체

  • 프라미스를 쓰면 비동기 메서드를 동기 메서드처럼 값을 반환할 수 있다.
    -> 비동기 처리 시점을 좀 더 명확하게 표현할 수 있다.

Promise 생성

  • 생성자 함수를 통해 생성하며 비동기 작업을 수행할 콜백 함수를 인자로 받아 사용한다.
// 프라미스 객체를 만듭니다. 
// 인자로는 (resolve, reject) => {} 이런 excutor 실행자(혹은 실행 함수라고 불러요.)를 받아요.
// 이 실행자는 비동기 작업이 끝나면 바로 두 가지 콜백 중 하나를 실행합니다.
// resolve: 작업이 성공한 경우 호출할 콜백
// reject: 작업이 실패한 경우 호출할 콜백
const promise = new Promise((resolve, reject) => {
	if(...){
		...
		resolve("성공!");
	}else{
		...
		reject("실패!");
	}
});

Promise의 상태값

  • pending : 비동기 처리 수행 전
  • fulfilled : 수행 성공(resolve)
  • rejected : 수행 실패(reject)
  • settled : 성공 or 실패

후속 처리

  • 프라미스로 구현된 비동기 함수를 호출하는 측에서는 이 프라미스 객체의 후속 처리 메서드를 통해 비동기 처리 결과를 받아 처리한다.
  • .then(성공 시, 실패 시)
    -> 첫 인자는 성공 시 실행, 두번째 인자는 실패시 실행된다.(첫 번째 인자만 넘겨도 됨)
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
	setTimeout(() => resolve("완료!"), 1000);
});

// resolve
promise.then(result => {
	console.log(result); // 완료!가 콘솔에 찍힐거예요.
}, error => {
	console.log(error); // 실행되지 않습니다.
});
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
	setTimeout(() => reject(new Error("오류!")), 1000);
});

// reject
promise.then(result => {
	console.log(result); // 실행되지 않습니다.
}, error => {
	console.log(error); // Error: 오류!가 찍힐거예요.
});
  • .catch(실패 시)
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
	setTimeout(() => reject(new Error("오류!"), 1000);
});

promise.catch((error) => {console.log(error};);

promise chaining

  • 후속 처리 메서드를 체이닝해서 여러 개의 프라미스를 연결할 수 있다.
    -> 콜백 헬 해결!!!
new Promise((resolve, reject) => {
	setTimeout(() => resolve("promise 1"), 1000);
}).then((result) => { // 후속 처리 메서드 하나를 쓰고,
	console.log(result); // promise 1
	return "promise 2";
}).then((result) => { // 이렇게 연달아 then을 써서 이어주는 거예요.
	console.log(result);
	return "promise 3";
}).then(...);

async, await

  • 프라미스 사용을 엄청 편하게 만들어 줌!!

async

  • 함수 앞에 붙여서 사용하며 항상 프라미스를 반환
    -> 프라미스가 아닌 값이라도 프라미스로 감싸서 반환
// async는 function 앞에 써줍니다.
async function myFunc() {
	return "프라미스를 반환해요!"; // 프라미스가 아닌 걸 반환해볼게요!
}

myFunc().then(result => {console.log(result)}); // 콘솔로 확인해봅시다!

await

  • async의 짝꿍(async없이는 못씀)
  • async 함수 안에서만 동작하며 프라미스가 처리될 때가지 기다렸다가 그 이후에 결과를 반환한다.
async function myFunc(){
	let promise = new Promise((resolve, reject) => {
		setTimeout(() => resolve("완료!"), 1000);
	});

    console.log(promise);

	let result = await promise; // 여기서 기다리자!하고 신호를 줍니다.

    console.log(promise);

	console.log(result); // then(후처리 함수)를 쓰지 않았는데도, 1초 후에 완료!가 콘솔에 찍힐거예요.
}

토큰 기반 인증

OAuth2.0

  • 외부서비스의 인증 및 권한부여를 관리하는 프레임워크(인증과 허가를 포함함)

☝🏻 JWT vs OAuth

  • 로그인에 많이 쓰이는 두 인증 방식으로 비교하긴 조금 애매하다.
    JWT는 토큰의 한 형식이고 OAuth는 프레임워크이기 때문
    (OAuth에서 토큰으로 JWT 사용 가능)

웹 저장소(토큰)

  • http는 한 번 요청을 하고 응답을 받으면 연결이 해제되기 때문에 access_token을 클라이언트 어딘가에 저장해두어야 한다.

쿠키

  • 클라이언트 로컬에 저장되는 key:value 형태의 저장소로 약 4KB 정도 저장할 수 있다.
  • 쿠키를 삭제하려면 만료일을 이전으로 돌려서 지우는 방법을 많이 쓴다.
  • 쿠키 만들기
// key는 MY_COOKIE, value는 here, 
document.cookie = "MY_COOKIE=here;";
  • 쿠키 가져오기
console.log(document.cookie);
  • 쿠키를 삭제하기 : 만료일을 이전으로 돌려서 지우는 방법을 많이 쓴다.
document.cookie = "MY_COOKIE=here; expires=new Date('2020-12-12').toUTCString()";

세션 스토리지

  • 쿠키와 마찬가지로 key:value형태로 저장한다.
  • 브라우저를 닫으면 제거된다
    -> 자동 로그인이나 장바구니같은 유지해야하는 데이터는 넣기 어려움
  • 추가하기
// key는 MY_SESSION, value는 here인 세션을 만들어요.
sessionStorage.setItem("MY_SESSION", "here");
  • 가져오기
// key값으로 쉽게 가져올 수 있어요 :) 
sessionStorage.getItem("MY_SESSION");
  • 삭제하기
// 하나만 삭제하고 싶다면, 이렇게 키를 통해 삭제합니다.
sessionStorage.removeItem("MY_SESSION");

// 몽땅 지우고 싶을 땐 clear()를 쓰면 됩니다. :) 
sessionStorage.clear();

로컬 스토리지

  • 쿠키와 마찬가지로 key:value형태로 저장한다.
  • 따로 삭제하지 않으면 계속 브라우저에 남아있다.
    -> 아이디, 비밀번호같은 중요한 정보를 넣어두기엔 위험
  • 쿠키보다 더 많은 정보를 저장할 수 있다.(5MB)
  • 쿠키처럼 모든 http 통신에 딸려들어가지 않는다.
  • 추가하기
// key는 MY_LOCAL, value는 here인 데이터를 저장해요.
localStorage.setItem("MY_LOCAL", "here");
  • 가져오기
// key값으로 쉽게 가져올 수 있어요 :) 
localStorage.getItem("MY_LOCAL");
  • 삭제하기
// 하나만 삭제하고 싶다면, 이렇게 키를 통해 삭제합니다.
localStorage.removeItem("MY_LOCAL");

// 몽땅 지우고 싶을 땐 clear()를 쓰면 됩니다. :) 
localStorage.clear();

☝🏻 프로젝트의 성향에 맞춰 저장 장소는 때마다 달라져야한다!

리덕스 추가 패키지

☝🏻 immer 패키지

  • 객체는 const로 선언해도 내용이 수정될 수 있다.(기본 강의에서 정리함) 그래서 스프레드 문법({...})을 통해 수정되지 않게 작성한다. 하지만, 객체 구조가 복잡해지면 코드를 짜기가 번거로워 Immer가 불변성 관리를 대신 해줌으로써 불변성을 신경쓰지 않아도 됨!
//임포트 후 사용
import {produce] from 'immer';
  • 첫번째 파라미터에는 수정하고 싶은상태, 두번째 파라미터에는 어떻게 업데이트 하고 싶은 지 정의하는 함수를 넣어줌
const state = {
  number: 1,
  dontChangeMe: 2
};
const nextState = produce(state, draft => {
  draft.number += 1;
});
console.log(nextState);
// { number: 2, dontChangeMe: 2 }

☝🏻 redex-actions 패키지

  • 좀 더 편한 액션 관리를 위해 사용
    (createAction, handleActions)
//임포트 후 사용
import { createAction, handleActions } from "redux-actions";

3주차

옵셔널 체이닝

const a = {b:2};
let a_value = a ? a.b : 0; 
//= let a_value = a?.b;

debounce와 throttle

  • 이벤트를 관리할 수 있는 방법

lodash

  • 자바스크립트 유틸리티 라이브러리
  • 배열관리, 모듈화, 성능 향상과 관련된 것까지 많은 기능을 제공함
  • 물론! debounce와 throttle도!
    공식 문서
import _ from "lodash"; // lodash 부르기

debounce

  • 이벤트가 일어나면, 일정 시간을 기다렸다가 이벤트를 수행
  • 일정 시간 내에 같은 이벤트가 또 들어오면 이전 요청은 취소
  • 검색을 한다고 가정했을 때 입력할 때마다 이 전 요청은 취소하여 검색이 모두 끝난 후 일정 시간을 기다렸다가 이벤트가 수행됨
// shared/Search.js
import React from "react";
import _ from "lodash"; // lodash 부르기

const Search = () => {
  const debounce = _.debounce((k) => console.log("디바운스! :::", k), 1000);
  const keyPress = React.useCallback(debounce, []);

  const onChange = (e) => {
    keyPress(e.target.value);
  };

  return (
    <div>
      <label>Search:</label>
      <input onChange={onChange} />
    </div>
  );
};

export default Search;

throttle

  • 일정 시간 동안 일어난 이벤트를 모아서 주기적으로 1번씩 실행
// shared/Search.js
import React from "react";
import _ from "lodash"; // lodash 부르기

const Search = () => {
  const throttle = _.throttle((k) => console.log("쓰로틀! :::", k), 1000);
  const keyPress = React.useCallback(throttle, []);

  const onChange = (e) => {
    keyPress(e.target.value);
  };

  return (
    <div>
      <label>Search:</label>
      <input onChange={onChange} />
    </div>
  );
};

export default Search;

4주차

무한 스크롤

동작 원리

  • 게시글을 한 번에 여러개 가져오면 페이지 로드 속도가 느려진다
  • 화면에 담기지 않는 게시글은 불러오지 않고 있다가, 스크롤이 아래로 내려가서 보통 마지막이나 마지막 1개 전 게시글에 스크롤이 닿았을 때 다음 게시글을 불러온다.

정렬

정렬
쿼리

let query = postDB.orderBy("insert_dt", "desc").limit(2);
//desc > 내림차순 / 없으면 올림차순

생각할 것

  • 게시글을 가져올 때 어디서 가져왔는지, 다음엔 뭐부터 가져올 지 페이징 정보
  • 게시글을 가져오는 중인지, 아닌지 구분해야겠다!(스크롤이 내려가서 불러오는 중인데 계속 다시 시도하면 안되니까! -> 스피너

스크롤

화면 크기 관련 내용

profile
깃헙으로 이사중..

0개의 댓글