본문 바로가기
React

리액트 심화 2주차 정리

by imagineer_jinny 2021. 3. 29.

[수업 목표]

  • 토큰에 대해 알아본다.
  • 파이어베이스를 사용해서 로그인 기능을 구현해본다.
  • 로그인을 유지하는 방법에 대해 알아본다.
  • 로그인 권한을 체크하는 컴포넌트를 만들어본다.

 

Promise

 

비동기: 작업 하나 요청하고 나는 다른거 해. 그러다 요청해놓은게 결과를 주면 다른거 하는거. 

ex) 파이어베이스, 외부 api 쓰는 것: 비동기 작업

 

 

자바스크립트는 싱글 쓰레드로 동작하는 언어입니다. (메인 쓰레드 하나와 콜스택 하나로 구성되어 있어요!) 그리고 비동기 작업을 동시에 할 수 있어요. 오잉?🤢 1번에 1개의 작업만 할 수 있는데, 어떻게 동시 실행을 할까요? → 자바스크립트는 코어 엔진만 가지고 돌아가지 않아요! 실행환경(런타임)의 도움을 받아 동시 실행을 합니다. (WebAPI(dom, ajax, setTimeout...), Task Queue, Event Loop 등과 함께 동작합니다.)

 

-콜백이란?

콜백은 자바스크립트가 비동기 처리를 하기 위한 패턴 중 하나입니다! 전통적인 콜백 패턴은 일명 콜백 헬로 불리는 엄청난 중첩 문제가 생기기 쉽습니다.

 

콜백 함수는? 어떤 함수에 인수로 넘겨주는 함수.

비동기처리에서 말하는 콜백은 자바스크립트가 비동기 처리를 하기 위한 패턴 중 하나.

여기서 말하는 콜백은 콜백 패턴이다 라고 생각하기~

 

1. 콜백 헬

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

 

이런 콜백 헬이 발생하는 이유?

  • 비동기 처리 시에는 실행 완료를 기다리지 않고 바로 다음 작업을 실행해요.
  • 즉, 순서대로 코드를 쭉 적는다고 우리가 원하는 순서로 작업이 이뤄지지 않습니다.
  • 비동기 처리 함수 내에서 처리 결과를 반환하는 걸로는 원하는 동작을 하지 않으니, 콜백 함수를 사용해 원하는 동작을 하게 하려고 콜백 함수를 씁니다.
  • 이 콜백 함수 내에서 또 다른 비동기 작업이 필요할 경우 위와 같은 중첩이 생기면서 콜백 헬이 탄생하죠. 😢

-프라미스란?

콜백 헬을 해결할 방법 중 하나!

비동기 연산이 종료된 이후 결과를 알기 위해 사용하는 객체입니다! 프라미스를 쓰면 비동기 메서드를 마치 동기 메서드처럼 값을 반환할 수 있어요. 전통적인 콜백 패턴으로 인한 콜백 헬 때문에 ES6에서 도입한 또다른 비동기 처리 패턴입니다. 비동기 처리 시점을 좀 더 명확하게 표현할 수 있어요!

 

1. 프라미스 생성

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

2. 프라미스의 상태값

  • pending: 비동기 처리 수행 전(resolve, reject가 아직 호출되지 않음)
  • fulfilled: 수행 성공(resolve가 호출된 상태)
  • rejected: 수행 실패(reject가 호출된 상태)
  • settled: 성공 or 실패(resolve나 reject가 호출된 상태)

3. 프라미스 후속 처리 메서드

  • 프라미스로 구현된 비동기 함수는 프라미스 객체를 반환하죠!
  • 프라미스로 구현된 비동기 함수를 호출하는 측에서는 이 프라미스 객체의 후속 처리 메서드를 통해 비동기 처리 결과(성공 결과나 에러메시지)를 받아서 처리해야 합니다.
  • then의 첫 인자는 성공 시 실행, 두번째 인자는 실패 시 실행됩니다. (첫 번째 인자만 넘겨도 됩니다!)

setTimeout()에서 첫번째 인자는 함수, 두번째는 시간.

// 프라미스를 하나 만들어 봅시다!
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(프라미스 체이닝)

프라미스는 후속 처리 메서드를 체이닝해서 여러 개의 프라미스를 연결할 수 있습니다! (이걸로 콜백 헬을 해결할 수 있어요!)

  • 체이닝이 뭔데? 그걸 어떻게 하는 건데?
  • 후속 처리 메서드 (then)을 쭉쭉 이어 주는 거예요.
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

앞으로 정말정말 많이 보고 쓸 문법입니다. 프라미스 사용을 엄청 편하게 만들어줘요! 🙂

[더 알면 좋은 내용] 강의에서 다루지 않지만 제네레이터라는 함수와 이터러블을 알면 더더 좋습니다.

 

1. async

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

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

2. await

  • async의 짝꿍이에요. (async 없이는 못씁니다!)
  • async 함수 안에서만 동작합니다.
  • await는 프라미스가 처리될 때까지 기다렸다가 그 이후에 결과를 반환해요!
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초 후에 완료!가 콘솔에 찍힐거예요.
}

await를 만나면, 실행이 잠시 중단되었다가 프라미스 처리 후에 실행을 재개합니다!

즉, await를 쓰면 함수 실행을 기다리게 하는거예요.

 

<파일 가져올 때>

 

yarn install 하면 package.js 에 있는 모든 것들 다 install 됨!

 

 

1. 토큰 기반 인증

 

[옛날 이야기 - 세션 기반 인증]

예전에는 사용자의 로그인 상태를 서버가 전부 가지고 있었어요. 서버의 세션에 사용자 정보를 넣고 이 사람이 로그인을 했다 안했다를 전부 기록하고 기억했습니다. 이 세션은 서버의 메모리나 데이터베이스 등에 저장해두는데, 로그인한 사용자가 많아지면 서버에 부하가 많이 오겠죠? 그렇다고 서버를 여러개 놓자니 관리가 까다로워지고요.

 

→ 그래서 최근에는 오늘 배울 토큰 기반 인증 방법을 많이 사용해요!

 

그래서 토큰 기반 인증 방식이란?

유저가 로그인을 할 때 로그인한 인증 정보를 서버의 어딘가에 넣어두는게 아니라,

사용자가 로그인을 하면 서버가 유저에게 토큰을 줘서 유저가 API요청들을 할 때 마다 토큰을 요청이랑 묶어서 사이트에 전달해주는 방식!

 

1) OAuth2.0

외부서비스의 인증 및 권한부여를 관리하는 프레임워크

 

  • OAuth 동작 방식 (간단 ver.)
    1. 클라이언트와 서버 사이에 인증(로그인)을 하면 서버가 access_token 을 줍니다.
    2. 클라이언트는 access_token을 이용해서 API 요청을 할 수 있어요.
    3. 서버는 API 요청을 받고, access_token을 가지고 권한이 있나 없나 확인해서 결과를 클라이언트에 보내줍니다.

2) JWT(Json Web Token)

토큰의 한 형식. 데이터가 JSON 형태로 이루어져 있는 토큰.

  • 동작 방식: 토큰 기반 동작 방식
  • 유저가 로그인을 시도하면,
  • 서버가 요청을 확인하고 secret key를 가지고 access_token을 발급합니다.
  • 클라이언트에 JWT를 전달하고
  • 클라이언트는 API 요청을 할 때 Authorization header에 JWT를 담아서 보냅니다.
  • 서버는 JWT의 서명을 확인하고 payload에서 정보를 확인해서 API 응답을 보냅니다.

2. 웹 저장소(feat. 토큰)

Http는 1번 요청을 하고 응답을 받으면 연결이 해제됩니다!

즉, 우리가 access_token을 클라이언트 어딘가에 저장을 해두어야한단 이야기예요!

그럼 이 토큰을 어디에 저장하면 좋을 지, 클라이언트에서 쓸 수 있는 저장소를 알아봅시다

 

1)클라이언트 저장소

개발자도구 → Application 탭 → 좌측 Storage 확인!

 

2)쿠키

클라이언트 로컬에 저장되는 key:value 형태의 저장소

document.cookie = "MY_COOKIE=here;";

3)세션 스토리지

HTML5에서 추가된 저장소. 쿠키와 마찬가지로 key:value 형태의 저장소.

세션 스토리지에 저장된 데이터는 브라우저를 닫으면 제거됨.

자동 로그인이나, 장바구니같은 다음에 브라우저를 열었을 때도 유지해야하는 데이터는 넣기 어렵겠죠!

 

4)로컬 스토리지

HTML5에서 추가된 저장소. 쿠키와 마찬가지로 key:value 형태의 저장소.

로컬 스토리지는 따로 지워주지 않으면 계속 브라우저에 남아 있음. 따라서 유저의 아이디, 비밀번호같은 중요한 정보를 넣어두면 아주 위험함.

 

 

 

'React' 카테고리의 다른 글

클론코딩 첫 주 - 프로그래머스 사이트  (0) 2021.04.05
파이어베이스 배포 안될 때  (0) 2021.04.02
리액트 심화 4주차 정리  (0) 2021.04.01
리액트 심화 3주차 정리  (0) 2021.03.30
리액트 심화 1주차 정리  (0) 2021.03.27

댓글