📝 오늘의 공부
- 리액트 심화 1회독 : 강의 내용 간략 정리
- redux toolkit, slice, json server, axios, interceptor, thunk, 리액트쿼리, throttling, debouncing, 인증/인가, JWT토큰
< 1강 >
yarn add @reduxjs/toolkit
npm install @reduxjs/toolkit
store 구성, action creator 간단하게 바꾸기 가능함!
creatstore 대신 : configureStore
로 store 만들기
리듀서 파일에서 쓰는 API
createSlice()
: action creator, reducer 한번에 생성할 수 있음
(createSlice 안에는 action creator, reducer 두개가 들어있는 것!)
따라서,
export 하려면 :
const counterSlice = createSlice({
// reducer의 이름, 초기 상태값
name: 'counter',
initialState: 'initialState',
// reducer들
reducers: {
addNumber: (state, action) => {
// state 변경하는 로직
state.number = state.number + action.payload;
},
minusNumber: (state, action) => {
// state 변경하는 로직
},
},
});
export default counterSlice.reducer;
export const { addNumber, minusNumber } = counterSlice.actions;
< 2강 >
reducer대신 slice
로 통합!~!~!
(action creator, reducer, action value까지 slice에 한번에 쓰는것!)
export로 action creator, reducer 두가지를 내보낼 수 있음!
// action creator 내보내기
export const { addTodo, removeTodo, switchTodo } = todoSice.actions;
// reducer 내보내기
export default todoSlice.reducer;
⭐️ npm i 에러 왜?
node_modules git ignore 안되는것도 이거때문인가?
강의에서도 yarn add 리덕스툴킷 해줬는데 그 다음에 npm i 하던데 왜 난 에러뜨지?
⭐️
redux toolkit 은 자동으로 불변성 유지해줌!!(immer라는 내장된 기능 덕분)
[...state, action.payload];
state.push(action.payload);
Redux Devtools
: redux toolkit에 내장되어있음
⭐️ 근데 자동으로 실행 안되는데? ㅠ ⭐️
Flux 패턴
⭐️ 첨부된 강의자료 필독 ⭐️
< 3강 >
json-server
간단한 DB, API서버 생성해주는 패키지
설치하기
npm install json-server
yarn add json-server
root 경로에 db.json file
만들기
(키가 "" 로 되어있으면 json 파일임. 객체형식 아님 json형식임)
json server
시작하기
가짜 서버가 리액트 local host 3001와 겹치지 않도록 '특정 포트'를 지정해주는게 좋음(--port 4000 이부분)
json-server --watch db.json --port 4000
브라우저에서 열기 : 이런식으로 접근하면 됨 (commetns의 1은 id)
local/host:4000/posts
local/host:4000/comments/1
< 4강 >
'통신' 이란 ? communication
웹 프로그래밍 세계에서의 대화! - 데이터로 이루어지는 대화
서버(웹 서버) <-> 클라이언트(웹 브라우저)
웹 통신은 약속이다! ( = 프로토콜
)
대화를 위해 미리 정해놓은 약속!
약속한대로 대화해야됨(정해진 방식대로 데이터 주고받기)
웹에서 서버 <-> 클라이언트 간에 대화할 땐 약속한대로 대화하자!
(정해진 방식대로 데이터를 주고받자)
=> http 프로토콜
요청(Request
)과 응답(Reponse
)
서버에게 데이터 요청
서버는 응답을 줌(데이터를 줌)
http 프로토콜의 메서드 - http 요청의 종류 (약속한걸 어떻게 쓸 것인가?)
GET
조회
POST
생성
PUT
, PATCH
수정(변경)
DELETE
삭제
...등등
상태코드 - 오류상태 보여주는 코드 ex) 404
(서버가 주는 응답이 갖는 상태코드)
맨 앞자리 숫자에 따라 종류가 정해짐
< 5강 >
Axios
란?
promise를 기초로 해서 http 통신을 할 수 있는 라이브러리
설치
yarn add axios
yarn add json-server
root폴더에 db.json
파일 생성
async await를 코드 전체가 기다려주는게 아님 주의!
async await 있어도 코드는 위에서 아래로 실행되기에, jsx부분이 먼저 실행될 수 있는 것임!
-> optional chanining 넣어주면 됨 ?.
ex) todos?.map((item)=>{})
📝 옵셔널 체이닝이 뭔데.....?
- 값을 읽어서 처리해야하는 로직인 경우,
원래는 값이 undefined 이면 오류가 나는데,
?.
옵셔널 체이닝을 사용하면 값이 undefined인 경우는 패스하고 넘김
(오류로 로직이 멈추는 것을 방지해줌)
참고 : https://anywhereim.tistory.com/35
< 6강 >
서버에 데이터 추가해줘 요청하기! POST
json 방식의 데이터베이스는 id속성이 자동으로 입력됨
-> 초기 dummy data시 id 키는 없어도 됨
form태그 안의 button
form태그 안의 button type은 기본적으로 submit타입이 들어가 있음
-> 버튼 클릭때마다 화면이 새로고침됨
-> 막아주려면
<form
onsubmit = {(e) => {
e.preventDefault();
}}
클릭시 실행되는 로직은 onClick으로 하지 않고,
form 태그 안에 prevent부분 아래에 함수 넣어주기
axios로 요청할 때는 모두 async await
로 감싸야 함!
(서버와 통신 -> 어떤 동작을 실행하는 순서로 진행해야 하기에 비동기 통신)
서버 가져오고싶어 요청하기 (GET
) - 조회
const { data } = await axios.get("http://localhost:4001/todos");
POST
) - 삽입axios.post("http://localhost:4001/todos", inputValue);
// inputValue - 새로 넣고 싶은 데이터
-> 서버에 데이터 넣음과 동시에 화면에서도 새로운 데이터로 렌더링 시키려면
-> POST로직 아래에서 state값도 같이 바꿔줘야함?!
(불변성 유지하면서)
-> 이렇게 하면 db에는 id가 자동으로 들어가지만, 렌더링할땐 id가 없이 나오는 오류
-> set으로 바꿔주지 말고 그냥 get으로 다시 db를 읽어오는 방식을 차용하자
DELETE
) - 삭제axios.delete(`http://localhost:4001/todos/${id}`);
setTodos(todos.filter((item)=>{
return item.id !== id;})
// id : onClick 함수에서 인자로 받아온 id
// POST 했을 때 state도 같이 바꿔줬던 것처럼, DELETE때도 state 같이 바꿔줘야함
(주의! 안에 ${ } 있으면 쌍따옴표 아니고 백틱!)
PATCH
) - 수정const onUpdateButtonClickHandler = async () => {
axios.patch(`http://localhost:4001/todos/${targetId}`, {
title: contents,
})
setTodos(todos.map((item) => {
if (item.id == targetId) { // 형이 다른 경우 '==' 동등연산자 사용
return { ...item, title: contents }
} else {
return item;
}
})
}
// 필요한 값은 state로 관리중이라 함수 인자로 안넣어도 됨
// targetId : state임, onChange에서 받아온 값
// patch의 두번째 인자 : 이거로 수정해주세요
// contents : state임, onChange에서 받아온 값
< 7강 >
fetch : axios와 같은 역할
js 내장 라이브러리
(axios는 설치해야되는 패키지)
단점
미지원 브라우저 있음
response가 불친절
< 8강 >
중간에서 가로챔
요청, 응답 사이에 가로채서 어떤걸 한다!
.env
파일 생성 (환경정보 파일)// .env
// (환경변수)
REACT_APP_SERVER_URL=http://localhost:4000
// 앞에 REACT_APP_ 이 부분은 꼭 있어야 함!
axios.delete(`${process.env.REACT_APP_SERVER_URL}/todos/${id}`)
(이렇게 변경해준 후에는 서버 한번 껐다 켜야됨)
변수
로 만들어주자!.env
파일에서 변수로 지정해 그 변수를 전역에서 사용해보자axios폴더
생성, api.js 파일
생성, axios instance
만들기axios interceptor
const instance = axios.create({
baseURL: process.env.REACT_APP_SERVER_URL,
})
export default instance;
=> axios import 필요없이,
axios
대신 api
라고 다 바꿔주기 // ✅ api.js
// ⭐️ 요청 부분(request)
instance.interceptors.request.use(
// 요청을 보내기 전 수행되는 함수
function(config){
console.log('인터셉터 요청 성공')
return config;
},
// 오류 요청을 보내기 전 수행되는 함수
function(error){
console.log('인터셉터 요청 오류');
return Promise.reject(error);
},
)
// ⭐️ 응답 부분(response)
instance.interceptors.response.use(
// 응답을 내보내기 전 수행되는 함수
function(reponse){
console.log('인터셉터 응답 받음')
return response;
},
// 오류 응답을 내보내기 전 수행되는 함수
function(error){
console.log('인터셉터 응답 오류 발생');
return Promise.reject(error);
},
)
< 9강 >
(가장 많이 사용되는 Redux 미들웨어 : Redux-thunk, saga)
미들웨어란 : 액션 -> 리듀서 사이에 내가 원하는 작업도 끼워넣을수 있게 해줌
서버와 통신할때 주로 사용함
redux 미들웨어 중 가장 많이 사용되는 미들웨어 중 하나!
dispatch
에 액션 객체가 아닌, 함수
를 전달할 수 있다!!
-> 이 함수를 통해 중간에 하고자 하는 작업을 넣을 수 있음
-> 이 함수가 바로 thunk 함수
thunk함수도 서버와 통신하는 함수이기 때문에 async, await
createAsyncThunk()
(reduxToolkit 내장 API)이름
: 큰뜻없음함수
(중간에 실행할 거 넣을 함수) : 얘도 2개 인자를 받음payload
: 컴포넌트에서 보내준 payloadthunkAPI
: thunk의 내장 기능 갖고 있는 객체thunk.dispatch(action creator(payload))
로 전달함creatSlice
안에 있는 extraReducer
수정 (thunk 등록)dispatch
(인자는 함수 0 액션 객체 x)< 11강 >
⭐️ 구조분해할당으로 const [ name, onChangeHandler ] = useInput();
이렇게 쓰는거야..? 인자로 넣는게 아닌데 어떻게 이게 useInput으로 사용할수 있게 되는거야...? ⭐️
< 12강 >
thunk 한계를 개선할 수 있는 대체재
기존 미들웨어의 한계
보일러 플레이트 -> 쳐야되는 코드가 너무 많아
리덕스가 비동기 데이터 관리를 위한 전문 라이브러리가 아님!
리액트 쿼리 장점
사용이 쉬움
보일러 플레이트 만들다가 오류날 일이 없음
주요 키워드
Query
: 문의, 의문(물어보는거 -> ex. axios의 get)Mutation
: 변경(어떤 데이터를 변경하는 것) -> 추가, 수정, 삭제Query Invalidation
: 무효화Query Invalidation
)axios, json-server, react-query
db.json 파일 생성
root 파일에서 <QueryClientProvider client={queryClient}>
로 <Router>
감싸주기
api폴더 생성 > todos.js
(axios 요청이 들어가는 모든 모듈 모아놓기)
useQuery();
: usequery 호출하기
< 14강 >
짧은시간 연속적인 이벤트 발생할때, 과도한 이벤트 핸들러 호출을 방지하는 기법
throttling
: 몇초동안 이벤트 안받아요~! (몇 초 후에는 실행시켜줌)
이벤트가 빠르게 연속적으로 발생하는 경우 delay기간을 주기
(delay시킨 다음 이벤트 발생시켜도 되고, 이벤트 발생 후 delay줘도 되는 등 3가지 타입이 있음)
Ex) 무한스크롤
Debouncing
: 여러번 누르는동안은 실행 안시켜줘(마지막꺼 실행해줄게)
짧게 여러번 이벤트 발생할때 마지막 이벤트로부터 일정기간 지난 후에 한번만 이벤트 발생하게 해주는 것
메모리 누수
throttling적용시, 다른페이지로 이동했는데도 아직도 혼자 delay 되다가 '이제 실행됩니다' 하는거 -> 다른페이지 왔으면 어쨌든 실행 끝나야지 아직도 영향 주고있는거 -> 메모리 누수
메모리 누수 막는 방법 : useEffect의 return문
useEffect(()=>{
return ()=>{
// 언마운트 시 로직 실행! (ex. 페이지 이동시(=언마운트시) 타이머 초기화하기)
};
})
< 15강 >
Lodash
: debouncing, throttling 관련 라이브러리_
로 importconst handleSearchText = _.debounce(함수, ms초);
-> useCallback
으로 감싸야함!
⭐️ 클로저 함수가 뭐였더라..? ㅠ ⭐️
< 16강 >
인증(Authenticaton)
: 등록된 회원인지 확인하기(로그인
)인가(Authorization)
: 권한
이 있는지 확인하기(카페 권한있는 레벨인지?, 카페장인지?, 마이페이지에 권한이 있는지 등)무상태 Stateless
비연결성 Connectionless
쿠키
: 무상태, 비연결성임에도, 서버가 클라이언트 인증 상태 기억하는것 처럼 구현하는 것< 17강 >
< 18강 > 🍀🍀 중요
암호화된 인증 정보
'header.payload.signature
형식으로 3가지 데이터로 구성됨// 예시
Set-Cookies: access Token=header.payload.signature; Path=/
Secret Key
에 의해서 JWT토큰
을 발급 (서버가)Response
로 전달JWT토큰
가지고 서버에 요청reponse
로 전달