[수업 목표]
- 토큰에 대해 알아본다.
- 파이어베이스를 사용해서 로그인 기능을 구현해본다.
- 로그인을 유지하는 방법에 대해 알아본다.
- 로그인 권한을 체크하는 컴포넌트를 만들어본다.
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.)
- 클라이언트와 서버 사이에 인증(로그인)을 하면 서버가 access_token 을 줍니다.
- 클라이언트는 access_token을 이용해서 API 요청을 할 수 있어요.
- 서버는 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 |
댓글