본 문서는 생활코딩 강의(Redux 4, Redux 5.1, Redux 5.2)를 통해 리덕스(Redux)를 공부한 내용을 정리하였습니다.
1. Redux를 써야하는 이유
- Redux를 사용하면 효율적임
- 아래 어플리케이션을 Redux로 만들어보면 Redux를 써야하는 이유를 알 수 있음
리덕스(redux)리덕스(redux)
2. Redux 사용이란
- Redux를 사용한다는 것은 아래와 같음
(1) Store 생성함
(2) State 생성됨
(3) Reducer 함수를 만들어 Store에 주입함
안녕? 나는 Redux야 우리집엔 Store 라는 창고가 있구, 그 창고안에는 State라는 금고가 있지 그 금고안에 있는 다이아몬드 있찌렁~
금고는 나말고는 아무도 손 못대게 해놨는데, 내가 요즘 다른일이 많아서 내 고양이한테 금고를 여는 방법을 알려줬엉. 이제 내 고양이는 나를 대신해서 금고에 귀중품을 넣고 뺄수 있지롱!
근데 고양이에게 금고 일을 부탁할 때는 Dispatch란 고양이 언어 번역 어플을 다운받아야해 그리고 번역기를 사용해서 두 가지를 알려줘야해 (1) State : 현재 금고에 뭐가 있는지. (예, 다이아몬드) (2) Action : 뭘 넣을지 (예. 금) 위 두 가지를 알려주면 고양이는 금고안에서 다이아몬드를 금으로 교체해줄꺼야. * Store : 창고 * State : 금고안에 현재 다이아몬드가 있음 * Dispatch : 고양이 언어 번역 어플 * Action : 금
3. Store 생성
- Store는 아래와 같이 생성가능함
리덕스(redux)
4. Reducer 생성
- Reducer는 State와 Action을 이용해 새로운 State값을 만들어 줌
- 초기 값을 지정해줘야함
리덕스(redux)
5. getState
- getState를 이용해서 store에 state의 초기값이 yellow인걸 확인할 수 있음
리덕스(redux)리덕스(redux)
6. state 사용하기
- <div>의 색깔을 변경해줄때 ${state.color}를 사용하여 변경할 수 있음
리덕스(redux)
7. Dispatch
- 기존에 만들었던 누르면 색깔이 바뀌는 코드를 dispatch 함수를 사용하여 재코딩함
- Dispatch라는 함수를 호출할때 객체({중괄호})를 넣어야함
- 이때 객체안에 꼭 들어가야할 property는 type임
- 클릭하면 store의 state가 red로 변하도록 하는 것이 목적임
리덕스(redux)리덕스(redux)
- dispatch를 호출하면 reducer를 호출함
- 그때 dispatch는 reducer에게 아래의 인자를 줌
리덕스(redux)
- 아래와 같이 클릭했을때 dispatch가 reducer에게 {type: 'Change_Color', color:'red'}를 넣어준것을 확인할 수 있음
리덕스(redux)
- 이제 인자를 reducer에서 처리하는 로직을 만들어야함
- 아래는 인자를 받았을때 그 type이 같다면 state의 color를 바꾸는 로직임
- 다만, 아래 방법을 사용하면 추후에 중요한 기능들을 사용할 수 없음 (불변성)
리덕스(redux)
- 현재 로직 : Dispatch --> (state, action) --> state값 변경 --> 새로운 state 값 반환
- 추천 로직 : Dispatch --> (state, action) --> state값 복제 --> 복사본 state값을 변경 --> 변경된 state 값 반환
8. 불변성
- 이 전에는 원본의 값을 직접 변경했는데, 이제는 복제하고 그 복제본의 내용을 변경하고 그 변경된 복제본을 반환함
- 그러면 reducer가 실행될 때마다 새로운 state를 반환함
- 다만, 각각 의 state값들이 서로 완전히 독립된 복제된 결과들이 반환됨.
- 객체를 복제할 때는 Object.assign 함수를 사용하면 됨
- 첫 째 인자 : 빈 객체 {}
- 두번째 인자 : 빈 객체 {} 의 복제할 속성을 가진 객체
리덕스(redux)
- assign은 빈 객체 name 속성은 'Cat'이라고 하는 값을 복제함
리덕스(redux)
- 첫 번째 인자는 빈 객체가 되어야 하는 이유는 object.assign의 반환 값은 첫 번쨰 인자인 객체이기 때문임
리덕스(redux)
- state의 property 들이 첫 번째 인자인 빈 객체 {}에 복제됨
- 그 복제본이 Return 됨 --> {color : 'yellow'}
- 아래와 같이 state 옆에 {color : 'red'} 를 쓰면 복제된 것에 {color : 'red'}로 덮어쓸 수 있음
[리액트, Node.js, SQL, CRUD] 처음부터 끝까지 기초만 한번 훑어보자! #2 (Feat. 생활코딩)
#4. 배포하기(Deploy)
#5. 컴포넌트 (Component)
#6. Props
#7. State
#4. 배포하기(Deploy)
다른 사람들이 쓰게끔 배포할때 어떻게 해야하는지 알아보자. 우리가 만든 폴더와 코드들을 몽땅 웹서버에다가 넣으면 용량이 너무 많아진다. 이를 해결하기 위해서 npm run build를 command에서 실행해보자.
그러면 build라는 폴더가 생긴다. 이는 우리가 만들었던 모든 것들을 build라는데 넣어준다. 용량도 많이 줄여준다. 즉, 웹서버의 최상위 폴더에 build안에 있는 파일들을 복사 붙여넣기 하면 서비스를 제공할 수 있다.
로컬에서 웹서버를 설치해서 실행해보고 싶다면 오른쪽 커멘드를 실행시키자. npx serve -s build (웹서버를 다운받은 후 build폴더를 다큐먼트 루트로 설정, 즉 웹페이지 최상위 폴더로 설정). 쉽게 풀어서 말하면 npx에게 serve 라는 프로그램을 다운받고 실행시키라고 부탁한다음 최상위 폴더를 build로 설정해달라는 명령어이다.
그러면 컴퓨터가 어디로 들어가야되는지 주소를 준다. 그러면 그 주소대로 들어가면 우리의 첫 뻔째 어플이 나오는걸 확인할 수 있다.
#5. 컴포넌트 (Component)
(1) 정의
컴포넌트(Component)
컴포넌트 기능을 이용하면 UI를 독립적이고, 재사용가능한 조각으로 나눌 수 있고, 각 부분들을 개별적으로 생각하며 코딩을 할 수 있다. 인풋("props")을 받고 리액트 요소(화면에 보여지는 것)를 반환한다.
(2) 예제
건물을 지을때 미리 만들어 놓은 층을 쌓아서 지은다면 얼마나 편할까? 아래 예시와 같이 웹엡 또는 웹사이트 개발시 우리는 여러 층(=컴포넌트)을 다양하게 만들어 놓고 쌓아서 웹사이트를 개발할 수 있다.
웹앱 또는 웹사이트를 개발하다보면 정말 코드가 길어지고 어수선하다. 나중에 수정하려고 하면 정말 눈과 머리가 터진다. 만약 반복되는 코드들을 뭉쳐서 <mytag></mytag>와 같이 우리가 정의를 내리고 필요한 위치에 마다 가져다 쓰면 얼마나 편할까? 이 기능이 가능하고 이 기능을 컴포넌트 기능이라고 한다.
어느 파일에다가 컴포넌트들을 만들어 줘야하나요? App.js파일에 가서 우리가 원하는 컴포넌트들을 만들어주면 된다. 아주 간단한 예시는 아래와 같다.
(3) 파일로 관리
컴포넌트가 우리의 코드를 정리해주고 유지보수를 쉽게 만드는 기능이지만 컴포넌트 또한 많아지면 눈이 아프고 머리도 복잡해진다. 그렇기 때문에 컴포넌트를 파일단에서 만들어 정리하고 관리를 해놓으면 머리가 덜 복잡하다.
이렇게 관리하면 또 다른 파일에서도 해당 컴포넌트를 불러올때 편하다. 왼쪽은 App.js인데 어느 파일에서 컴포넌트를 가져올지 정해줘야한다. (import Mycomponent1 from '.components/Mycomponent1';). 그리고 오른쪽은 이전에 만들었던 컴포넌트를 Mycomponent1.js라는 파일을 만들어 복사 붙여넣기 한 파일이다.
외쪽: App.js, 오른쪽: Mycomponent1.js
#6. Props
Props
일단 정의부터 알아보자. Props란 부모가 자식 컴포넌트에 주는 값이고 자식은 그 값을 수정할 수 없다. State는 컴포넌트 내에서 선언 및 수정을 할 수 있다. 라고 하면 이해가 안간다. 아래 그림을 봐보면 Props를 간단히 이해할 수 있다.
쉽게 말해 우리가 정의한 태그(tag)에 다가 값을 전달해 주는 것이다. 빌딩 한층 한층 만들었는데 각 층이 모두 틴테리어가 같다면 안된다. 각 층의 틀이 컴포넌트라면 우리는 props 기능을 통해 각 층별 인테리어를 바꿀 수 있다. 여기서 인테리어가 props의 개념이다.
예시를 보며 한층 더 쉽게 이해해보자. 여러번 반복하는 코드를 Mycomponent1이라고 만들었다. 그러나 쓸때마다 조금씩 다른 값들(인테리어)을 넣고 싶다면 어떻게 해야할까? 이때 우리는 Props기능을 쓴다. 다른게 아니라 Mycomponent1을 부를때 name="넣고 싶은 값"을 넣어주면 이 값이 Mycomponent1에 있는 {this.props.name} 값으로 전달된다. 쉽게 생각해서 함수를 만들고 그 함수에 값을 넣어준다고 생각하면 된다.
Props의 값("[미리 만든 빌딩 7층]")을 컴포넌트에 넣어주는 예시다.
컴포넌트와 Props 예시
#7. State
(1) 기초
State
Props에서 어떤것을 배웠나? 우리는 데이터를 컴포넌트(Component)에 넣는 것을 배웠다. State 또한 똑같다고 보면 된다. 위에 흐름을 확인해보자. 앞서 Props으로 값을 컴포넌트에 전달했다. 그 전단계를 하나 더 만든것이다. 우리는 State라는 형태로 데이터를 저장해놓고 Props에서 끌고와서 컴포넌트에 전달한다. 그리고 최종적으로 웹앱 화면에 띄운다.
State를 사용하는 방법을 알아보자. 일단 아래 코드와 같이 constructor함수를 이용해서 State를 사용한다. Constructor라는 함수는 컴포넌트가 실행될때 가장 먼저 실행되는 함수(render함수보다 먼저 실행된다.)이며 state값을 초기화 한다. 그리고 상위에서 하위 컴포넌트로 데이터를 넘긴다.
그렇다면 Props와 State의 차이점은 무엇일까? Props는 사용자와 개발자 모두를 위한 것이지만 State는 개발자를 위한 것이다. 컴포넌트 내부적으로 사용하는 것으로 외부에서 알 수 없다.
State와 Props
(2) Props가 있는데 왜 State라는 개념을 만들었을까?
State라는 기능은 여러개의 데이터를 다룰때 유용하기 때문에 필요하다. 또한, 동적인 웹사이트를 만들기 위해 필요하다. 영화 제목 및 평점을 리스트한다고 생각해보자. 단 3개의 영화 평점을 넣는데 Movie.js 컴포넌트에 줄이 엄청 길어진다. 그리고 데이터가 바뀔시 코드를 고쳐줘야하는 단점이 있다. 아래 예시를 보자. Movie.js를 보자. Iron Man 1, Iron Man 2, Iron Man 3의 평점을 넣는데 <td>태그를 몇번 써야하는가?
데이터도 매번 바꿔줘야한다. 예를 들어 Iron Man 3를 Iron 3라고 잘못쳐서 고치고 싶을때도 해당 부분을 찾아야한다. 또는, 데이터를 추가해야할때 다른 태그들도 써줘야한다. <tr><td></td></tr> 한번만 쓰고 데이터가 업데이트될때마다 자동으로 업데이트된다면 얼마나 편할까?
state
이전과 결과는 같으나 state를 사용하여 효율적으로 코드가 바뀐걸 볼 수 있다. 예를 들어, state 안에 Movie라는 데이터를 변경, 삭제, 추가하면 결과 값이 변한다. 예를 들어 "Avengers" 10/10점 이렇게 넣으면 테이블 아래에 바로 추가된다. <td></td>를 여러번 적어주지 않아도 데이터 갯수대로 <td></td>를 리액트가 찍어낸다. 여러개의 태그를 자동으로 생성할때 key 값을 문법상 적어줘야한다.
컴포넌트 파일 Movie.js를 확인해보자. List에는 아무것도 없다. Movie.js의 data는 props값이다. 그리고 이 props값은 App.js에서 data = {this.state.Movie} 으로 정의해줬고 그걸 가져왔다. data는 아래와 같다. 이제 while 문으로 0 부터 1씩 증가해주면서 비어있는 list에 넣어준다. 그리고 최종적으로 <tbody>에 {list}를 넣어주면 된다.