22.04.17(일) ~ 18(월)
스파르타코딩클럽 리액트 심화반 - 2주차 과정 - 1
function async1('a', function (err, async2){
if(err){
errHandler(err);
}else{
...
async2('b', function (err, async3){
...
}){
...
}
}
});
Promise
Promise 객체 만들기
const promise = new Promise((resolve, reject) => {
if(...){
...
resolve("성공!");
}else{
...
reject("실패!");
}
});
Promise의 상태값
Promise의 후속처리 Method
let promise_success = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000);
let promise_fail = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("오류!")), 1000);
});
promise_success.then(result => {
console.log(result); // 완료!
}, error => {
console.log(error); // 실행X
});
promise_fail.then(result => {
console.log(result); // 실행X
}, error => {
console.log(error); // 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";
async
async function myFunc() {
return "프라미스를 반환해요!"; // 프라미스가 아닌 걸 반환시
}
myFunc().then(result => {console.log(result)});
// 프라미스를 반환해요!
// Promise {<fulfilled>: undefined}
await
async function myFunc(){
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000);
});
console.log(promise); // Promise {<pending>}
let result = await promise;
console.log(promise); // 1초 후, Promise {<fulfilled>: '완료!'}
console.log(result); // 1초 후, 완료!
}
옛날 방법
OAuth2.0: 외부서비스의 인증 및 권한부여를 관리하는 프레임워크
클라이언트
와 서버
사이에 인증(로그인)을 하면 서버가 access_token
을 줍니다.클라이언트
는 access_token
을 이용해서 API 요청을 할 수 있어요.서버
는 API 요청을 받고, access_token
을 가지고 권한이 있나 없나 확인해서 결과를 클라이언트
에 보내줍니다.구글
로그인을 합니다. 구글
은 로그인할 때 유저가 입력한 정보(아이디, 비밀번호 등)을 보고 클라이언트(우리 웹사이트!)
에 접근 권한을 줍니다.클라이언트
는 이 권한을 가지고 Authorization server(권한 서버)
에 access_token
을 요청합니다.클라이언트
는 이 access_token
을 가지고 구글에서 유저 정보
를 가져올 수 있어요. 구글
은 클라이언트
가 보낸 access_token
을 가지고 권한이 있나 없나 확인해서 결과
를 클라이언트
에 보내줍니다.JWT: 데이터가 JSON 형태로 이루어져 있는 토큰
document.cookie = "MY_COOKIE=here;";
console.log(document.cookie); // 하나의 String 형태로 가져옴
// 개별 쿠키 나누기
document.cookie.split(";")
dateString = Date('2020-12-12').toUTCString()"
document.cookie = "MY_COOKIE=here; expires=${dateString}";
sessionStorage.setItem("MY_SESSION", "here"); // 설정
sessionStorage.getItem("MY_SESSION"); // 값 가져오기
sessionStorage.removeItem("MY_SESSION"); // 해당 값 삭제
sessionStorage.clear(); // 세션 스토리지 전부 지우기
localStorage.setItem("MY_LOCAL", "here"); // 설정
localStorage.getItem("MY_LOCAL"); // 값 가져오기
localStorage.removeItem("MY_LOCAL"); // 해당 값 삭제
localStorage.clear(); // 로컬 스토리지 전부 지우기
리덕스: 클라이언트에서 전역 데이터 관리를 용이하게 해줌
리덕스(redux) 설치
# 리덕스와 리덕스 모듈 내에서 경로 이동까지 하게 해줄 히스토리, 라우터와 히스토리를 엮어줄 모듈 포함
yarn add redux react-redux redux-thunk redux-logger history@4.10.1 connected-react-router@6.8.0
# redux-actions : 액션 만들기 등을 자동화
# immer : 불변성 유지를 편하게 해줌
yarn add immer redux-actions
// src > redux > modules > user.js
import { createAction, handleActions } from "redux-actions";
import { produce } from "immer";
import { setCookie, getCookie, deleteCookie } from "../../shared/Cookie";
// Action Type
const LOG_IN = "LOG_IN";
const LOG_OUT = "LOG_OUT";
const GET_USER = "GET_USER";
// action creators / Using redux-actions
const logIn = createAction(LOG_IN, (user) => ({ user }));
const logOut = createAction(LOG_OUT, (user) => ({ user }));
const getUser = createAction(GET_USER, (user) => ({ user }));
// initialState
const initialState = {
user: null,
is_login: false,
};
// Reducer / Using redux-actions immer
export default handleActions(
{
[LOG_IN]: (state, action) =>
produce(state, (draft) => {
setCookie("is_login", "success");
draft.user = action.payload.user;
draft.is_login = true;
}),
[LOG_OUT]: (state, action) =>
produce(state, (draft) => {
deleteCookie("is_login");
draft.user = null;
draft.is_login = false;
}),
[GET_USER]: (state, action) => produce(state, (draft) => {}),
},
initialState
);
// src > redux > configureSrore.js
import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createBrowserHistory } from "history";
import { connectRouter } from "connected-react-router";
import User from "./modules/user";
// History 만들기
export const history = createBrowserHistory();
// Reducer 묶기 + 만든 history를 Store와 묶기
const rootReducer = combineReducers({
user: User,
router: connectRouter(history),
});
// thunk 비동기 작업 처리
// withExtraArgument , thunk 에 다른 인수를 넘겨줌
const middlewares = [thunk.withExtraArgument({history:history})];
// 지금이 어느 환경인 지 알려줘요. (개발환경, 프로덕션(배포)환경 ...)
const env = process.env.NODE_ENV;
// 개발환경에서는 로거라는 걸 하나만 더 써볼게요.
// console에 스토어 데이터에 뭐가 담기는지, 액션으로 인해 변한게 찍힘
if (env === "development") {
const { logger } = require("redux-logger");
middlewares.push(logger);
}
// redux devTools 설정
const composeEnhancers =
typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
})
: compose;
// Middleware 묶기
const enhancer = composeEnhancers(
applyMiddleware(...middlewares)
);
// 스토어 만들기
let store = (initialStore) => createStore(rootReducer, enhancer);
export default store();
// index.js
import store from "./redux/configureStore";
import { Provider } from "react-redux";
ReactDOM.render(
<Provider store={store}> // Provider 세팅, store 주입
<App />
</Provider>,
document.getElementById("root")
);
// App.js
import { ConnectedRouter } from "connected-react-router";
import { history } from "../redux/configureStore";
...
function App() {
return (
<React.Fragment>
<Grid>
<Header></Header>
<ConnectedRouter history={history}> // ConnectedRouter로 변경, history 주입
<Route path="/" exact component={PostList} />
<Route path="/login" exact component={Login} />
<Route path="/signup" exact component={Signup}/>
</ConnectedRouter>
</Grid>
</React.Fragment>
);
}
...
import {actionCreators as userActions} from "../redux/modules/user";
import { useDispatch, useSelector } from "react-redux";
const Login = (props) => {
const dispatch = useDispatch();
const login = () => {
dispatch(userActions.login({user_name: "perl"})); // Action 실행
}
const is_login = useSelector((state) => state.user.is_login) // 값 가져오기
...
}