리액트 네이티브 2/E 5주차 강의자료

.slide_bg_img { opacity: 1 !important; }

로고

리액트 네이티트 2/E 5주차

코드종의 클래스

bg


지난 주 내용 다시 보기

:clock10: Just 10 min 지난 내용 질문

  • 9장 디버깅과 개발자 도구
    • 디버깅 : JS, Native
    • 테스트 : Jest, Flow
    • 기타 도구 : eslint와 prettier
  • 10장 대규모 애플리케이션의 내비게이션과 구조
    • react에서의 navigation

:telescope: 오늘 다룰 내용은?

  • :gift: 함수
    • 함수와 순순 함수
    • props와 state
  • 11장 대규모 애플리케이션에서의 State 관리
    • ==redux의 개념 이해==
  • 기타 유용한 도구 소개

:pray: 오늘만큼은!!

각종 개념을 꼭 이해하고 가시길 바랍니다.

모든 질문을 :heart: 사랑합니다.

bg


시작하기전 기반 다지기

함수


:thinking: 함수란 무엇인가?


A. 함수는…

  • 입력 => (do something) => 출력

  • 입력은 인자, 출력은 리턴 값

    function add(a, b){
      return a+b;
    }
    

:thinking: Pure Function이란?


A. Pure Function은…

  • :droplet: 순수 함수? 뭐가 순수하다는 걸까?
    • 수학 함수 f(x) = x * 2
    • 변덕이 없다. 한결 같다.
    • 입력이 같으면 결과가 같다.
    • 외부의 무언가를 변경해선 안된다.

어떻게 순수할 수 있나?


순수하지 못한 경우를 보자 1/3

호출할 때마다 달라지는 값

  function notPure(a, b){
    return a+b+Math.random();
  }
  notPure(1,2);
  notPure(1,2);

순수하지 못한 경우를 보자 2/3

주변에 따라 값이 달라질 수 있는 함수

var x = 3;
function dirty(a, b){
  return a+b+x;
}
dirty(1,2);
x= 4;
dirty(1,2);

순수하지 못한 경우를 보자 3/3

출력값은 같으나 외부를 변경하는 함수

var count = 0;
function messUp(a, b){
  count++;
  return a+b;
}

어떻게 순수할 수 있나?

  • 원칙 1
    • 출력값에 영향을 주는 모든 것를 입력으로 받는다.
  • 원칙 2
    • 함수 내부의 코드에서 함수 외부의 변수를 접근하지 않는다.
  • 원칙 3
    • 외부의 변화는 외부에서 알아서 정해서 할 수 있도록 길을 열어 둠 (예. callback)

순수하게 바꿔보자 1/4

  • 내부에서 random 처럼 가변적인 내용을 제거한다.

  • 필요하다면 가변적인 부분을 밖으로 분리한다.

    function notPure(a, b){
     	 return a+b+Math.random();
    }
    
    function nowPure(a, b, extra){
     	 return a+b+extra;
    }
    
    nowPure(a, b, Math.random());
    nowPure(a, b, Math.random());
    // 입렵이 달라진 것, 입력이 같을 때는 출력이 항상 같음
    

순수하게 바꿔보자 2/4

  • 내가 하는 일은 모두 내 안에서!

  • 내부에서 외부(예. global)의 값을 참조하지 않는다.

    // 예 2
    var x = 3;
    function dirty(a, b){
      return a+b+x;
    }
    
    function notDirty(a, b, extra){
      return a+b+extra;
    }
    
    notDirty(1, 2, x);
    x = 4;
    notDirty(1, 2, x);
    // 입렵이 달라진 것, 입력이 같을 때는 출력이 항상 같음
    

순수하게 바꿔보자 3/4

  • 외부의 내용을 바꾸지 않아야하며 결과를 받아서 밖에서 처리하도록

    var count = 0;
    function messUp(a, b){
      count++;
      return a+b;
    }
    
    function notMessUp(a, b, count){
      return {
        value: a+b,
        count: count++
      };
    }
    
    const result = notMessUp(1, 2, count);
    count = result.count;
    
    

순수하게 바꿔보자 4/4

  • 외부의 변화이니 외부가 알아서 하도록 callback에 지정하도록 해준다.

    function notMessUp2(a, b, callback){
      callback();
      return a+b;
    }
    
    var count = 0;
    
    notMessUp2(1, 2, ()=>{
      count++
    });
    

어디서 많이 보던 모습?

class CountButton extend Component {
  count = 0
  onPress(){
    alert(`${++this.count}번 눌렀어!`);
  }
  render() {
    return <Button
      onPress={this.onPress}
      title="Learn More"
      color="#841584"
    />;
  };
}

:droplet: 순수하면 뭐가 좋은가?

  • 입력이 있을 때 결과를 예측할 수 있다.
  • 예측하면 추가적으로 테스트를 쉽게 할 수 있다.
    • 예측이 충분히 되기에 예측과 다른지를 비교하도록 테스트 코드 작성

:thinking: 리액트 컴포넌트 === 함수?


A. YES! 리액트 컴포넌트는 함수이다.

  • ==입력== : props
  • ==출력==
    • 의미적 출력 : render의 return 값(View)
    • 실제 출력 : 함수의 return 값
      • Stateless Component의 경우 : return 값(View)
      • 일반 Component의 경우 : 객체
        • 라이프 사이클
        • render 함수

웬 라이프 사이클인가?

  • 내부의 state가 있다는 것은 동적, 살아있다는 의미. 외부 자극이 없어도 스스로 변할 수 있는 객체
  • props(입력)이 바뀔 때만 결과(View)가 달라지는 것이 아니라
    내부적으로도 무언가(state) 변하면 결과(View)가 변한다.

:thinking: 컴포넌트의 propsstate란 무엇인가?


A. propsstate는…

  • ==props== : View 계층구조에서 부모가 나에게 넘겨주는 것

    • 외부에서 컴포넌트 내부로 무언가를 전달하는 유일한 길
    • 밖에서 넘겨준 것을 바꾸지 않는다. 사용할 뿐!
  • ==state== : 해당 컴포넌트가 알아서 관리해야하는 데이터

    • 외부에서 직접 변경 못하는 내부에서 사용하는데 데이터: state가 변하면 이에따라 render하는 View(결과값)가 달라져야하는 데이터

컴포넌트 간의 데이터 전달은 단방향

  • prop을 이용하여 부모에서 자식으로~

앱 전체에서 사용되는 공통 state

  • 로그인 정보
  • 환경 설정 정보
    • 언어 설정

이럴 때 어떤 불편함이 생기나?

  • state의 전달
  • state의 변경

어려움 예시 : state의 전달

function Header(props){
  return (
    <View>
      <SearchView/>
      <RightProfileView/>
    </View>
  );
}

function RightProfileView(props){
  return (
    <View>
      <Image source={{uri: props.loginUserProfile}}/>
    </View>
  );
}

Class AppView extends Component{
  constructor(props){
    super(props);
    this.state = {
      loginUserName,
      loginUserProfile
    }
  }
  async login(){
    // ... 
    // 로그인 후 정보를 state에서 관리
    const user = await API.login('myId','myPassword');
    this.setState({
      loginUserName: user.name
      loginUserProfile: user.profile
    });
  }
  render() {
    return (
      <View>
        <Header />
        <MainView />
      </View>
    );    
  }
}

어려움 예시 : state의 변경


:wrench: 상태관리도구는 이러한 문제를 해결하기 위한 도구


11장 대규모 애플리케이션에서의 State 관리


redux의 3대 개념

  • store
  • action
  • reducer

store

  • 단일 객체
  • 컴포넌트의 props로 내용을 전달
  • store의 초깃값은 reducer에서 결정 됨

action

  • store의 변화를 이끌어 내는 역할
  • 앱에서 일어나는 일에 해당
export const stopReview = () => {
  return { type: STOP_REVIEW, data: {} };
};

reducer

  • 액션에 따른 state를 어떻게 바꿔야 할지 나타낸 것
  • input 발생 기존 state와 action
  • output 새로운 state
  • :droplet: 순수 함수
  • store 초기값 결정
  • 여러 reducer를 combine하여 하나의 store를 여러개인 듯
const reducer = (state = [], action) => {
  console.warn("Changes are not persisted to disk");
  switch (action.type) { 
    case ADD_DECK:
      return state.concat(action.data);   
    }
  return state; 
};

:anguished: 3대는 개념은 아니지만…

  • dispatch() 함수 : actionreducer에게 전달하여 reducer가 실행되도록 하는 함수
    • store 변화를 일으키는 시작 점

설정 1단계 : createStore

  • createStore로 스토어 생성
    • store는 recuer가 결정
    import { createStore } from "redux";
    import { reducer } from "../reducers/index";
    
    let store = createStore(reducer);
    
  • 일반적으로 앱 구동코드에서 실행

설정 2단계 : <Provider>

  • <Provider><App/>최상위 컴포넌트를 감싸기
  • 이는 하위 모든 컴포넌트에 자동으로 store(리덕스의 state)가 전달 되도록 함

설정 3단계 : connect()

  • Provider로 부터 전달되는 store로 부터 필요한 사항을 연결해주는 새로운 컴포넌트 생성 (HOC)
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(DecksScreen);
  • mapStateToProps : store의 어떤 state를 props으로 전달할지 결정
  • mapDispatchToProps : dispatch를 실행하는 함수를 props로 전달
    • 이를 지정하지 않으면 this.props.dispatch로 접근하여 dispatch함수를 직접 사용 가능

완전한 분리

내가 할일은 내가, 니가 할일은 니가 알아서

  • 우리가 만드는 Component는 단순 해짐

    1. 어떤 props에 따라 보여주는 모습 달라지게
    2. 내부에서 어떤일이 일어나면 props의 특정 함수가 실행되도록
  • redux가 해주는 일

    • store의 특정 값을 i) 단계의 props으로 제공
    • Component의 내부에서 어떤일이 일어날 때 특정 action이 dispatch되도록

:gift: 배포를 위한 도구


fastlane

  • 앱을 빌드 및 배포 관련 자동화 (사용법 참고 글)
  • 실제 디바이스에서 배포 버전 테스트 할 때
    • iOS의 testflight 이용하면 편리
    • testlfight으로 보내기 위하 여러 단계를 한방에

code-push-react-native

  • 네이티브 코드 변화 없는 앱 코드 수정일 경우 앱 심사 거치지 않고 기존 사용자에게 deploy하는 기능 제공
  • InstallMode : 배포된 것이 반영되는 시점
    • IMMEDIATE, ON_NEXT_RESTART,
      ON_NEXT_RESUME, ON_NEXT_SUSPEND
// 기억해야할 함수들
codePush.sync({ deploymentKey: 'XXXXX' });
codePush.disallowRestart();
codePush.allowRestart();
codePush.notifyAppReady();


기타



오늘 내용 정리

오늘 배운 내용에서 궁금한 점 물어보세요.

  • 함수와 순수 함수
  • props와 state
  • redux : store, action, reducer

:tada: 축하합니다.

책 한권을 마스터 했습니다!


준비한 내용은 여기까지

:pray: 함께 해주셔서 진심으로 감사합니다.

좋아요 2