반응형
Notice
Recent Posts
Recent Comments
Link
NOW OR NEVER
[10주차] 2. 리액트 Router & Redux 본문
반응형

리액트 Router
리액트 라우터 라이브러리
- Single Page Application(SPA)
- 라우팅을 클라이언트가 담당
- 단점
- 앱의 규모가 커지면 JS 파일의 크기가 너무 커질 수 있다.(해결책 : Code Splitting)
- 브라우저에서 자바스크립트가 구동되지 않으면 UI를 볼 수 없다.(해결책 : Server Side Rendering)
ex) 검색엔진에서 크롤링 불가능 - 라우팅 : 어떤 주소에 어떤 UI를 보여줄지 규칙을 정하는 작업
- 리액트 라우터는 컴포넌트를 기반으로 라우팅을 한다.
- react-router-dom 설치
주요 컴포넌트
- BrowserRouter : HTML5 History API 사용, 주소만 바꾸고 페이지는 다시 불러오지 않음, 가장 많이 사용
- HashRouter : 옛날에 사용 하던 방식, example.com/#/path/route로 #을 사용함, 못생김, 옛날 브라우저 전용
- MemoryRouter : 브라우저 주소와 전혀 관계 없어서 브라우저가 아닌 환경에서 쓰기 좋음, 임베디드 웹앱, 리액트 네이티브 등에서 사용, 가상의 주소를 MemoryRouter가 들고 있음
- StaticRouter : 서버사이드 렌더링에서 사용하는 용도
- Route : 라우트를 정의할 때 사용하는 컴포넌트, 즉 어떤 경로를 들어왔을 때 어떤 컴포넌트를 보여줄 것인지 설정
- path : 경로 주소, 주소가 ‘/’ 일때는 exact 넣어줘야 함
- component : path 경로로 들어올 시 보여주고자 하는 컴포넌트
- exact : true 일시 브라우저 경로 주소가 path 경로 주소와 완전히 일치할 때만 보여줌
- render : parameter 없을 시 보여질 내용 출력, 위에 있는 값 바로 {}로 사용 가능
- Link : 사용한 Router의 주소를 바꿈(a태그는 새로고침(아예 새로 페이지 불러옴)하는 방식이지만 이건 새로고침 안함)
라우터 주요 기능
파라미터와 쿼리
- 주소를 통해서 어떤 동적인 값을 받아올 때 사용
- 값을 불러올 때 해당 결과값이 문자열로 가져와진다.(그래서 문자열로서 비교해야 한다.)파라미터 Parameter
- URL Parameter일 경우 어떤 아이디, username 등 딱 정해진 특정 데이터 조회할 경우 많이 사용
- 예시 : /profiles/laura
- { match } : 해당 값을 조회할 때 match라는 props 사용, Route 컴포넌트에서 사용(자동)
- const { 추출하고픈 것} = match.params : Route 컴포넌트에 match 안에 params라는 값이 있는데 그안에 넣어주고 싶은 URL parameter가 들어있다.
- Router 컴포넌트에 path로 ‘/경로/:이름’ 작성시 :뒤에 오는 이름이 const { 추출하고픈 것} = match.params에서 const 중괄호 안의 것이 되는 것이다.
- 여러 개의 parameter 쓰고 싶을 시 path로 ‘/경로/:이름/:이름’ 이런식을 반복해서 여러 개의 parameter를 가져올 수 있다.
쿼리 Query
- 다양한 옵션을 줘서 조회할 경우 많이 사용, 주로 검색 등을 할 때 많이 사용
- 예시 : /filter?type=book&sort_by=date => book이라는 type을 가진 것들을 날짜 순으로 정렬해서 보여줘라는 요청을 할 때 쿼리 사용
- 쿼리를 조회할 때는 컴포넌트 props를 통해서 location을 받아와서 조회할 수 있다
- yarn add qs
- location.search은 물음표가 포함되어 있는 문자열이기 때문에 파싱(그(location)안에 있는 것들을 추출하는 것)이 필수이므로 qs 라이브러리 사용
- const query = qs.parse(location.search, {
ignoreQueryPrefix: true,
}) - ignoreQueryPrefix: true 필수로 작성해야 맨앞에 있는 물음표가 삭제됨
서브 라우트
- 라우트 안에 들어있는 또다른 라우트
- 라우트를 사용한 컴포넌트 내부에서 라우트를 한번 더 쓰면 된다.
- 특정 페이지에 탭이 있는 경우 서브라우트를 사용해서 만들면 편하다
- 태그 선택시에도 활용하면 편하다.
라우터 부가 기능
- 알아두면 좋은 console 단어
- action : 라우터에서 가장 마지막으로 발생한 action을 알려주는 것
- PUSH : 이동
- POP : 앞/뒤 이동
- block : 사용자가 페이지 이탈하는 것을 방지하는 데 사용
- createHref : location 형태의 객체를 가지고 주소를 만드는 역할
- go : 앞으로 혹은 뒤로 가는 것, go(-1) : 뒤로 한캄 감, go(1) : 앞으로 한칸 감
- goBack : 뒤로 감
- goForward : 앞으로 감
- length : 방문 기록의 길이가 어느정도 되는지
- listen : 경로에 변동이 생겼을 때 특정 함수 호출하고 싶은 경우 사용
- location : 현재 자신이 있는 곳, 자신의 경로에 대한 정보를 지니고 있음
- push : 특정 주소로 이동
- replace : 특정 주소로 이동하되 push랑 차이점은 방문기록을 남기지 않음
history 객체
- 라우터로 사용되는 컴포넌트에게 props로 전달 됨
- 이 객체 사용시 컴포넌트에서 라우터에 직접적인 접근 가능
- 특정 함수 호출시 특정 경로로 이동하거나 또는 뒤로 가거나 페이지 이탈을 방지할 수 있음
- 페이지 이탈 방지 확인 누르면 비활성화 : history.block(‘페이지 이탈하려 할 때 방지 문구’)
withRouter
- 라우터로 사용되지 않은 컴포넌트에서 조건부로 이동을 해야할 때 자주 사용
ex) 로그인 성공시 특정 경로로 이동하고 성공하지 않았을 때 가만히 있고 싶을 때 - 하나의 함수로 라우터 컴포넌트가 아닌 곳에서 match, location, history를 props로 받아와서 사용할 수 있게 해줌
- 컴포넌트 내보내기 전에 사용 즉 export default withRouter(컴포넌트); 이렇게 사용
- 그 컴포넌트가 라우터 용으로 제작된 것이 아니더라도 match, location, history를 props로 받아와서 사용할 수 있게 해줌
- JSON.stringify(객체) : JSON으로 이루어져있는 객체를 숫자열로 변환 해 주는 것, 객체와 함께 쉼표로 구분하여 null, 2 작성 시 들여쓰기가 이루어진다.
- match와 location 차이점 : location의 경우 어디에서 불러오든 똑 같은 정보를 불러옴, match는 현재 자신이 렌더링된 위치를 기준으로 match 값을 받아온다.
Switch 컴포넌트
- 여러 라우트 컴포넌트 중 가장 먼저 매칭된 라우트 컴포넌트 하나만 보여줌.
- <Switch>Route 컴포넌트들</Switch>
- 페이지를 못찾았을 때 not found 페이지(404페이지)를 보여줄 때 사용하면 된다. 아무것도 매칭되지 않았을 땐 맨 밑으로 내려가다가 path가 없어 모든 상황에 렌더링 되는 라우트 컴포넌트을 렌더링하게 된다.
NavLink
- Link와 비슷한 컴포넌트인데 해당 링크의 주소가 현재 브라우저에서 가리키는 주소와 일치한다면 특별한 스타일을 지정해줄 수 있다.
- 특정 스타일 지정 : activeStyle = {{css 속성}}
- 특정 클래스 지정 : activeClassName=’클래스이름’
- isActive 함수 사용(특정 조건에 맞게 출력하고 싶을 때) : isActive{(match,location) =>{return 값이 true 반환시 activeStyle이나 activeClassName이 적용}}
Prompt
- 이 컴포넌트는 history.block을 컴포넌트 형태로 구현
- when 중괄호에 특정 조건 입력시 사용자 이탈하는 것을 방지할 수 있는 컴포넌트
Redirect
- 해당 컴포넌트를 렌더링하게 되면 렌더링하는 순간 다른 경로로 이동하게 됨
- history.push와 같은 기능
Roust Config
- 기존에 라우트 설정시 라우트 컴포넌트랑 해당 컴포넌트의 props로 경로랑 경로 일치했을 때 보이는 컴포넌트를 설정해줬었다. 기존 방식과 달리 Route Config는 routes라는 배열을 작성해서 사전 정의하고 한꺼번에 설정하는 기능이다.
- 꼭 쓸 필요는 없지만 vue나 angular의 경우 이런 상태로 작동하는 것들이 있다.
리액트 Redux
- 리액트 생태계에서 사용율이 높은 상태관리 라이브러리
- 리덕스 사용시 만들게될 컴포넌트의 상태관리 로직들을 다른 파일들로 분리시켜 더욱 효율적으로 관리할 수 있고 grobal 상태 관리도 손쉽게 할 수 있다.
- Context API , useReducer와 비슷
- 무조건 리액트와 함께 사용할 필요는 없다.
- yarn add redux
- getState() : 현재 state 조회
- yarn add react-redux : Provider 사용 위해
Context와의 다른 점
-
- 미들웨어 사용 가능
- 주요 사용 이유 : 비동기 작업을 더욱 체계적으로 관리 가능
- 특정 조건에 따라 액션이 무시되게 만들 수 있음
- 액션을 콘솔에 출력하거나 서버쪽에 로깅 할 수 있음
- 액션이 디스패치 됐을 때 이를 수정해서 리듀서에게 전달되도록 할 수 있음
- 특정 액션이 발생했을 때 이에 기반하여 다른 액션이 발생되도록 할 수 있음
- 특정 액션이 발생했을 때 특정 자바스크립트 함수를 실행시킬 수 있음
-
- 유용한 함수와 Hook를 지원받을 수 있음
- connect 함수 : 전역적인 상태와 액션을 디스패치하는 함수들을 props로 받아와서 사용 가능
- useSelector, useDispatch, useStore 같은 hooks를 사용해서 리덕스에서 관리하고 있는 상태를 쉽게 조회하거나 액션을 쉽게 디스패치 할 수 있다(Context의 경우 이런 것들 하나하나 만들어 줘야 했음)
-
- 기본적인 최적화가 이미 되어있다
- 상태를 받아와서 사용하게 될 때 기본적인 최적화가 어느정도 되어있어서 필요한 상태가 바바뀔 때 리렌더링 되는 기능을 탑재하고 있음. Context의 경우 따로 직접해야할게 존재
-
- 하나의 커다란 상태
- ContextAPI를 사용하여 global 상태를 관리해야하는 경우 기능 별로 context를 만들어서 사용하는 것이 일반적이다. 반면 리덕스에서는 모든 global 상태를 하나의 커다란 객체에 넣어서 사용하는 것이 필수다. 매번 context를 만드는 수고로움을 덜어 줄 수 있음
-
- DevTools
- 리덕스에는 아주 유용한 개발자 도구 존재
- 현재 상태를 한번에 볼 수 있고 지금까지 어떤 변화가 있었는지 볼 수도 있고 특정 시점으로 상태를 되돌릴 수도 있다.
-
- 이미 사용중인 프로젝트가 많다
- 장점이 될 수도 있고 단점이 될 수도 있다.
리덕스 언제 써야 할까
- 프로젝트 규모가 클 때
- 비동기 작업을 자주 할 때
- 리덕스가 편하게 느껴질 때
리덕스 키워드
- 액션 Action : 어떤 업데이트를 하게 될 때 어떻게 업데이트를 해야 되는지 정의하는 객체이다. 상태에 어떠한 변화가 필요하게 될 때 action을 발생 시킴. 이는 하나의 객체로 표현되고 type 이라는 값이 필수적으로 있어야 함. 리덕스에서 상태 업데이트시 type을 보고 어떻게 업데이트 할지 정한다. action type의 경우 대문자로 작성
- 액션 생성함수 Action Creater : 액션 객체를 만들어주는 함수이고 action type과 동일한 이름을소문자로 작성하고 _이 있을 경우 카멜 표기법으로 작성한다. 단순히 파라미터를 받아와서 액션 객체를 만들어준다. 화살표 함수로도 생성 가능, 리덕스에서는 액션 생성 함수를 사용하는 것이 필수 적이지는 않음, 다만 액션 생성 함수 만들면 나중에 편하게 액션 객체 만들 수 있음. 액션 생성함수 사용하지 않는다면 액션을 발생시킬 때마다 직접 액션 자체를 작성해주면 됨
- 리듀서 Reducer : 새로운 상태를 만들어주는 함수이다. useReducer hook과 완전히 같음, 변화를 일으키는 함수이다. state, action 두 파라미터를 가져옴. action.type을 가지고 action.type이 무엇이냐에 따라서 다른 업데이트 작업을 한다. 리듀서에서는 불변성을 꼭 유지해줘야 함. (state가 객체이거나 배열이거나 할 때는 spread 연산자나 object assign 혹은 배열 내장함수 concat 등을 사용해서 기존에 있는 객체나 배열을 건드리지 않고 새로운 배열이나 객체를 만들어서 반환해줘야 함). useReducer의 경우 default 부분에 에러 발생시키는 것이 일반적인데 리덕스의 리듀서에서는 default 부분에서는 state를 그대로 반환하는 형태로 작성해야 한다(리덕스 사용시 여러 개의 리듀서를 만들고 이를 합쳐서 root 리듀서 라는 것을 만들 수 있기 때문이다. 그 root 리듀서 안에 들어가는 작은 리듀서들은 서브 리듀서라고 부른다.)
- 스토어 Store : 리덕스 사용시 한 애플리케이션 당 하나의 스토어만 만들게 된다. 스토어 안에는 현재 앱의 상태와 리듀서가 들어있고 추가적으로 몇 개의 내장함수들이 들어 있다.
- createStore : store를 만들어주는 함수
- 디스패치 dispatch : 스토어에 들어가는 내장함수들 중 하나이다. 액션을 발생시키는 것이다. 액션을 스토어한테 전달하는 것이다. 액션 객체를 만들어서 디스패치 함수의 파라미터로 넣어서 호출해준다. 호출해주면 리듀서 함수로 전달되어 리듀서 함수에서 새로운 상태를 반환해주면 스토어의 상태가 새로워짐
- 구독 subscribe : 액션이 발생되서 상태가 업데이트 됐을 때 특정 함수를 호출 시킬 수 있다. 스토어의 내장 함수들 중 하나이다. subscribe 함수 호출 시 파라미터로 특정 함수 넣어주면 액션이 디스패치 될 때마다 설정한 함수가 호출된다. 스토어의 상태가 업데이트 될 때마다 특정 함수 호출 가능, 리액트 리덕스에서 subscribe 함수를 직접 사용하는 일은 없지만 그대신에 리액트 리덕스에서 제공하는 connect 함수, useSelector hook을 사용해서 스토어의 상태가 업데이트 되면 컴포넌트가 리렌더링 되는 작업을 대신 처리해줌. 그래서 컴포넌트를 만들게 되면 컴포넌트가 리덕스에 구독을 하게 되는 것이다.(리덕스의 상태가 업데이트 되면 컴포넌트도 리렌더링됨)
리덕스의 꼭 지켜줘야 하는 3가지 규칙
-
- 하나의 애플리케이션엔 하나의 스토어만 있다
-
- 상태는 읽기전용이다(불변성을 지켜줘야 한다.)
- 불변성을 지켜야만 컴포넌트가 제대로 리렌더링 됨
-
- 변화를 일으키는 함수 리듀서는 순수한 함수여야 함
- 순수한 함수 : 동일한 인풋이 있을 땐 동일한 아웃풋이 나타나야 한다. 리듀서 함수는 이전 상태와 액션객체를 파라미터로 받는다. 이전의 상태는 절대로 직접 변경하지 않고 변화를 일으킨 새로운 상태 객체를 만들어서 반환한다.(불변성 유지) 똑 같은 파라미터로 호출된 리듀서 함수는 언제나 똑 같은 결과값을 반환해야만 한다.
- 호출할 때 마다 다른 값을 가져오는 new Date(), Math.random() 함수나 axios.get() 같은 네트워크 요청하는 함수들, 그리고 리듀서 밖에 있는 변수(상수는 상관 없음)에 의존하는 것도 사용하면 안됨 - > 미들웨어로 처리 가능
- 리듀서에서 새로운 상태를 만들 때에는 파라미터로 전달된 state와 action 만 의존해서 새로운 상태를 만들어줘야 함
리덕스 모듈
- 액션 타입, 액션 생성함수, 리듀서 모두가 들어있는 자바스크립트 파일(각각 다른 폴더에 저장도 가능)
- Ducks 패턴 : 액션 타입, 액션 생성함수, 리듀서를 하나의 파일에 몰아서 작성하는 것
- 규칙 : 액션타입 선언>액션 생성 함수 선언(내보내 줄 때 export default) > 초기상태 선언> 리듀서 선언(내보낼 때 export)
- 한꺼번에 불러올 수 있고 각각 다른 파일로 불러 올 수도 있음
- action 타입 사용시 접두어(‘모듈이름/action이름’) 사용 : 다른 모듈과 이름이 중복되지 않기 위해서
'강의 > 제로베이스 프론트엔드 99일' 카테고리의 다른 글
[10주차] 4. 리액트 Redux Middleware (0) | 2021.10.11 |
---|---|
[10주차] 3. 리액트 Redux(2) (0) | 2021.10.08 |
[10주차] 1. 리액트 API 연동 (0) | 2021.10.04 |
[9주차] 5. 리액트 컴포넌트 스타일링(2) (0) | 2021.10.01 |
[9주차] 4. 리액트 컴포넌트 스타일링 (0) | 2021.09.30 |