Archive

2021-02-09 TIL

|

2021-02-09 TIL


  • 오늘 한 것

    1. 리액트 공부 Redux - 지금까지 배운 Redux를 토대로 Burger builder tutorial project에 추가해보았다. 역시 예제를 통해서 직접 해봤을때 습득이 더 잘되는 것 같다.
    2. 학원 비대면 수업(15:30~22:00) Javascript - HTML / CSS로 간단한 웹 페이지 예제를 해보고 Javascript 기초 수업을 들었다. 강의 자료 자체가 오래되었고 지금은 쓰이지 않는 문법도 다수 있었지만 기본 동작 원리 등에 대해서는 그래도 건질만한건 있었다.



  • 내일 할 것
    1. 리액트 공부 - React The complete Guide
    2. 학원 비대면 수업(15:30~22:00) Javascript



  • 끝으로

설 연휴동안 공부 많이 해야지.

오늘의 한 줄 총평 : 최근 공부량이 줄었다. 반성.


2021-02-08 TIL

|

2021-02-08 TIL


  • 오늘 한 것

    1. 리액트 공부 Redux - 여러 개의 리덕스를 combining 하여 사용하는 방법을 배웠다. 꼭 리덕스로만 모든 state를 다루기보다는 global로 필요한 state만 리덕스로 다루고 local UI에서 쓰이는 state는 local에서 다루는 등 복합적으로 사용할 수 있다는 것을 알았다.
    2. 학원 비대면 수업(15:30~22:00) CSS - 아주아주 기초적인 css styling 방법을 배웠다.



  • 내일 할 것
    1. 리액트 공부 - React The complete Guide
    2. 학원 비대면 수업(15:30~22:00) Javascript



  • 끝으로

리액트 어렵다..

오늘의 한 줄 총평 : 리액트 어렵다


React.js Redux

|

React.js Redux


  1. Redux 개요

    • Redux는 애플리케이션 state를 관리하기 위한 오픈소스 Javascript 라이브러리이다
    • Redux는 Javascript App을 위한 예측가능한 state container이다
    • Redux는 React의 작동 원리인 state에 대한 변화를 쉽게 예측할 수 있도록 도와준다
    • React 뿐만 아니라 Angular, jQuery, Vanilla JS 등 다양한 곳에서 적용이 가능하다
    • 앱의 규모가 커질수록 local state를 props의 형태로 전달하기 위해서는 연결된 chain layer들을 모두 거쳐야 한다
    • 위와 같은 경우 Context API를 쓸 수도 있다. 다시 말해, Redux만이 유일한 수단은 아니다
    • Redux의 3 원칙
      1. Single source of truth : global state는 트리 구조에서 하나의 저장소에 저장된다
      2. State is read-only : state를 변경하는 유일한 방법은 action을 발생시키는 것이다
      3. Changes are made with pure functions : action에 의한 state tree 변환을 지정하려면 pure reducer를 작성해야 한다. 즉, 리듀서는 action과 state를 받아서 다음 state를 반환하는 순수 함수여야한다

    작동원리

    출처 : Udemy / React - The Complete Guide


  2. Redux 기본 사용법

    • npm install –save redux (redux 패키지)
    • npm install –save react-redux (react와 redux를 연결)
    • Provider는 리액트의 컴포넌트들이 Redux store에 접근할 수 있도록 연결해준다 (상위 컴포넌트에서 사용)
    • store는 애플리케이션의 state를 저장하는 객체이다
    import { createStore } from 'redux';
    import { Provider } from 'react-redux';
    import reducer from 'path/reducer';
       
    // store 생성, reducer를 넣어준다
    const store = createStore(reducer);
       
    ReactDOM.render(
        // 하위 컴포넌트를 Provider로 감싸고 store 연결
    	<Provider store={store}>
        	<App />
        </Provider>
        document.getElementById('root')
    );
    
    • reducer는 현재 state와 action을 취하고 새로운 state를 반환하는 순수 함수이다. state는 불변성을 유지해야한다. 즉, state의 직접 수정 없이 복사본을 만들어 수정해야한다. 그 이유는 redux의 변경 감지 알고리즘에 있는데, 자세한 것은 링크 참조.
    const initialState = {
        counter: 0,
    };
       
    // ES6 default parameter, state가 undefined일 경우 initialState로 초기화
    const reducer = (state = initialState, action) => {
        if(action.type === 'INCREMENT') {
            return {
                counter: state.counter + 1,
            }
        }
        return state;
    };
       
    export default reducer;
    
    • action은 일반 객체로 state의 변화가 필요할 때, action을 발생시킨다. type 필드를 필수적으로 가지고 있어야한다. 일반 객체이기 때문에 얼마든지 함수로 생성하여 사용할 수 있다.
    • dispatch는 store의 내장 메소드로 action을 파라미터로 받아 store의 reducer에 넘겨주는 역할을 한다.
    • connect() 메소드는 Provider 컴포넌트로 감싼 하위 컴포넌트들이 store에 접근하게 하는데 하위 컴포넌트에서 사용한다
      • mapStateToProps : connect 메소드의 첫번째 인자로 들어가는 함수, store의 state를 조회해서 props로 넣어준다. 파라미터로 state를 받아온다. null 값으로 자동 호출을 막을 수 있다.
      • mapDispatchToProps : connect 메소드의 두번째 인자로 action을 dispatch하는 함수를 만들어 props로 넣어준다, dispatch를 파라미터로 받는다.
      • 이름은 꼭 저게 아니어도 되지만 일반적으로 통용되는 것으로 맞춰주는게 좋다
    import React from 'react';
    import { connect } from 'react-redux';
       
    class Counter extends React.Component {
        redner() {
            return (
            	<button onClick={this.props.onIncrementCounter}>
                    {this.props.ctr}
                </button>
            );
        }
    }
       
    const mapStateToProps = state => {
        return {
            ctr: state.counter,
        };
    }
       
    const mapDispatchToProps = dispatch => {
        return {
            onIncrementCounter: () => dispatch({ type: 'INCREMENT'}),
        };
    }
       
    export default connect(mapStateToProps,mapDispatchToProps)(Counter);
    


  3. payload

    • 위 코드에서는 reducer의 action 실행문에 의해 state의 값이 1씩 증가하게 된다. 하지만, 저렇게 하드코딩 되어있는 부분을 사용자가 지정한 임의의 값이 증가되도록 하려면 어떻게 해야될까?
    • action은 일반 객체라고 했다. action을 dispatch할 때, 단순히 type 외의 다른 필드 값을 넘겨주고 reducer에서 받아서 사용하기만 하면 된다
    const mapDispatchToProps = dispatch => {
        return {
            onIncrementCounter: () => dispatch({ type: 'INCREMENT', value: 5}),
        };
    }
    
    const reducer = (state = initialState, action) => {
        if(action.type === 'INCREMENT') {
            return {
                counter: state.counter + action.value,
            }
        }
        return state;
    };
    


    • 저렇게 해도 작동은 잘 된다. 하지만, type 이외의 전달하고 싶은 값들은 되도록 payload 필드명을 이용하여 전달하는 것이 좋다. 그렇게 통일되어 있으니깐. createAction 메소드를 이용하여 action을 생성할 때도 두 번째 인자값으로 paylaod 값을 받도록 설정되어 있다.
  4. Updating State Immutably

    • Redux의 핵심 규칙 중 하나는, state는 read-only이기에 불변성(immutable)을 유지해야 한다고 했다.
    • 위의 코드들과 달리 state가 복수개 존재한다면 기존 state를 통으로 복사해 필요한 부분만 수정하면 될 것이다.
    • 여기서 ES6의 Object Spread Operator가 사용된다. Object.assign()으로 객체 복사를 해도 된다.
    const initialState = {
        counter: 0,
        result: [],
    };
       
    const reducer = (state = initialState, action) => {
        if(action.type === 'INCREMENT') {
            return {
                ...state, // 객체 복사
                counter: state.counter + action.value,
            }
        }
        if(action.type === 'STORE') {
            return {
                ...state, // 객체 복사
                results: state.results.concat({
                    // id는 임시 id
                    id: new Date(), value: state.counter }),
            }// 기존배열을 직접 수정하지 않기 위해 concat 사용
        }
        return state;
    };
       
    export default reducer;
    


  5. Constant Action Type

    • 위의 코드들은 action을 하드코딩해서 직접 써넣었다
    • 이것을 상수로 설정하여 오타 등 에러가 날 확률을 미연에 방지할 수 있다
    export const INCREMENT = 'INCREMENT';
    export const DECREMENT = 'DECREMENT';
       
    // 상수가 담긴 js 파일, 사용처에서 import하여 사용한다
    
    import * as actionTypes from 'path/actions';
       
    const reducer = (state = initialState, action) => {
        if(action.type === actionTypes.INCREMENT) { // 상수 사용
            return {
                ...state, // 객체 복사
                counter: state.counter + action.value,
            }
        }
    
    import * as actionTypes from 'path/actions';
       
    const mapDispatchToProps = dispatch => {
        return {
            onIncrementCounter: () => dispatch({ type: actionTypes.INCREMENT, value: 5}),
        };
    }
    


  6. Combining Multiple Reducers

    • 애플리케이션의 규모가 커짐에 따라 한 개의 리듀로서만 모든걸 다루기에는 한계가 있다
    • 리듀서를 쪼개서 하나의 리듀서처럼 사용할 수 있다
    • 이를 위해서는 redux 패키지의 combineReducers가 필요하다
    // store를 정의한 최상위 컴포넌트에서
    import { createStore, combineReducers } from 'redux'; 
    import counterReducer from 'path/counter';
    import resultReducer from 'path/result';
       
    const rootReducer = combineReducers({
        ctr: counterReducer,
        res: resultReducer,
    });
       
    const store = createStore(rootReducer);
    
    const mapStateToProps = (state) => {
      return {
        // state의 블럭 단위가 한 단계씩 늘어난다
        ctr: state.ctr.counter,
        storedResults: state.res.results,
      };
    };
    
    • reducer를 쪼개면 그에 따라 state도 나뉘게 된다. 자신에게 없는 state 값이 필요한 경우엔 어떻게 해야할까?
    • 리듀서는 함수 안에서 global state에 접근할 수 없기때문에 값을 받아와야한다
    • 하나의 방법으로 action을 이용하여 값을 전달할 수 있다
    <button onClick={() => this.props.onStoreResult(this.props.ctr)}></button>
       
    const mapDispatchToProps = (dispatch) => {
        return {
            onStoreResult: (result) => dispatch({ 
                type: actionTypes.STORE, result: result })
        }// action을 이용하여 state를 전달
    }
    
    const reducer = (state = initialState, action) => {
      if (action.type === actionType.STORE) {
        return {
          ...state,
          results: state.results.concat({
            id: new Date(),
            value: action.result,
          }),
        };
      }
    }
    





참고 자료


reactjs.org - 공식홈페이지

Udemy - React The Complete Guide

redux 공식 홈페이지

React에 Redux 적용하기

리덕스(Redux)의 리듀서(reducer)가 순수 함수여야만 하는 이유

Redux-React의 기본

2021-02-05 TIL

|

2021-02-05 TIL


  • 오늘 한 것

    1. 리액트 공부 Redux - 리덕스의 기초적인 개념을 배웠는데 아직은 감이 잘 오지 않는다. 이론적인 부분을 다 나가고 실제로 사용해보면서 익혀야겠다.

    2. 학원 비대면 수업(15:30~22:00) HTML - 학원 진도가 늦어 초스피드로 하루 만에 HTML을 끝내버렸다. 자료가 옛날 자료라 지금 웹표준에 맞지 않는 부분도 많은데 그래도 다시 한 번 HTML을 정리해 볼 수 있었다.



  • 내일 할 것
    1. 리액트 공부 - React The complete Guide



  • 끝으로

학원 커리큘럼에 자바스크립트도 포함되어 있지만 이틀 배우고 끝이다. 메인 언어가 자바라서 아쉽다. 자바스크립트를 주 언어로 사용하고 싶은지라 이쪽 생태계의 라이브러리나 프레임워크는 내가 알아서 공부해야지.

오늘의 한 줄 총평 : 수박 겉 핥기..


2021-02-04 TIL

|

2021-02-04 TIL


  • 오늘 한 것
    1. 학원 비대면 수업(15:30~22:00) 개인 프로젝트 발표 - 비대면으로 발표를 하는 진귀한(?) 경험을 했다. 화면 공유해서 마이크로 설명했다. 다른 친구들이 만든 프로젝트를 유심히 봤는데 잘하는 친구들은 정말 잘했는데 그 반대인 친구들이 많았다. 안타깝게도 아예 완성조차 못한 친구들도 많았다. 수료할때쯤이면 팀을 꾸려서 팀 프로젝트도 하게 될텐데 이번에 눈여겨본 친구들과 같이 팀을 짜서 서로 시너지가 발휘되었으면 좋겠다.



  • 내일 할 것
    1. 리액트 공부 - React The complete Guide
    2. 학원 비대면 수업(15:30~22:00) HTML



  • 끝으로

다행히 발표를 무사히 마쳤지만 절대 자만하지 않고 그냥 원래 하던대로 내 하루 공부량 채우면서 꾸준히 가자.

오늘의 한 줄 총평 : 개인 프로젝트 종료