공부/App

리액트 네이티브 한달 완성 그 첫번째 수업

AiHo 2021. 7. 18. 00:14

리액트 네이티브란?

네이티브 애플리케이션:

  • 운영체제를 구성하는 언어와 같은 언어로 만들어지는 애플리케이션
  • 장점: 높은 성능
  • 단점: 개발에 투입되는 리소스가 많아짐

하이브리드 애플리케이션:

  • 하이브리드 앱은 모바일 웹 사이트를 감싼 네이트브 앱으로, Apache, Cordova 나 Ionic, Appcelerator Titanium을 이용
  • 웹뷰를 이용해 보여지는 영역에 HTML을 보여줌
  • HTML/CSS/JS를 이용한 화면 구현
  • 네이티브로 만들어진 앱 컨테이너로 네이티브 기능 연동
  • 장점: 웹 기술에 익숙하다면 빠른 개발 가능
  • 단점: 뷰 퍼포먼스 최적화가 힘듦

과연 리액트 네이티브는 네이티브인가 하이브리드인가?

→ 둘 다 아니다. 아래를 보자

크로스 플랫폼 네이티브 애플리케이션

  • 네이티브가 아닌 언어로 작성하지만 빌드 단계에서 네이티브로 변환됨
  • 리액트 네이티브, 유니티, 자미란, 플러터 등
  • 장점: 자신에게 익숙한 언어로 빠른 개발 가능
  • 단점: 네이티브 연동 기능이 많을 경우에는 효율성이 떨어짐

Unity(유니티)

화면 구성(UI): Unity Editor

로직: C#

Xamarin(자마린)

화면 구성: Xamarin.Forms

로직: C#

Flutter

화면 구성 & 로직: Dart

React Native

화면 구성: JSX (XML)

로직: JSX (JS)

JSX란?

  • JS + XML
  • ECMA Script 6 표준의 자바스크립트 사용
  • JSX 내에 스타일시트를 포함함
  • 웹의 CSS와 많은 개념을 공유하지만 독자적인 포맷 CSS 파일로 작성 불가

JSX의 예시

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

HTML과 XML과 유사점이 많다.

리액트의 랜더링

JSX → React(Virtual Dom) → HTML(View)

리액트 네이티브의 랜더링

JSX → React Native(Virtual Dom) → Android(View)

                                              → IOS(View)

어플리케이션의 구조

  • 데이터 처리는 자바스크립트가 수행하고 뷰와 자바스크립트 엔진을 연결하는 브릿지가 존재

Expo란?

리액트 학습하는 목적으로 주로 사용

Expo는 CLI보다 접근이 쉬움

import * as React from 'react';
import { SafeAreaView, Text, View, StyleSheet } from 'react-native'; // SafeAreaView 노치 부분을 제외하고 화면을 잡아줌 노치가 없는 경우는 그냥 뷰랑 똑같음
import Constants from 'expo-constants'; // 엑스포는 화면 전체를 사용한다. 스테이터스바 까지도

// 이미지, 텍스트 등 "컨텐츠" 이를 감싸고 있는 것이 "컨테이너"
export default function App() {
  // React.Fragment 실제 렌더링에 반영되지 않는 추상 컨테이너
  return ( // XML 문법  component마다 쓸수 있는 style이 있음
    <SafeAreaView style={styles.container}>
      <Text>Text</Text>
    </SafeAreaView>   
  );
}

const styles = StyleSheet.create({ // styleSheet 생성
  container: {
    flex: 1,
    paddingTop: Constants.statusBarHeight,
  }
});

// 뷰를 화면 꽉차게 잡아주는 작업을 제일 먼저 함 flex: 1 borderWidth: 1
// flex: 내가 사용할 수 있는 만큼의 크기를 가질거야

리액트 네이티브의 가장 기본 상태

로또 번호 예제

import * as React from 'react';
import { Button, SafeAreaView, Text, View, StyleSheet } from 'react-native'; // SafeAreaView 노치 부분을 제외하고 화면을 잡아줌 노치가 없는 경우는 그냥 뷰랑 똑같음
import Constants from 'expo-constants'; // 엑스포는 화면 전체를 사용한다. 스테이터스바 까지도
import _ from 'lodash';
import styled from 'styled-components/native';

let numbers = [];
// 1부터 45의 숫자 생성
_.times( 45, n => numbers.push( n+1 ));
// 그리고 6개의 숫자 섞음
// numbers = _.shuffle(numbers);

const Row = styled.View`
  flex-direction: row;
  margin-bottom: 24px;
`;
const Ball = styled.View`
  width: 50px;
  height: 50px;
  border-radius: 25px;
  background: ${ props => {
    if( props.value < 11){
      return '#e5e251';
    }
    else if( props.value < 21){
      return '#517FE5';
    }
    else if( props.value < 31){
      return '#E54036';
    }
    else if( props.value < 41){
      return '#e5e5e5';
    }
    else{
      return '#43BF74'
    }
  } };
  justify-content: center;
  align-items: center;
`;
const Label = styled.Text`
  font-size: 20px;
  color: #000000;
  font-weight: bold;
`;
const Container = styled.SafeAreaView`
  flex: 1;
  justify-content: center;
  align-items: center;
  padding-top: ${ Constants.statusBarHeight }px 
`; // template literals
// 스타일드 컴포넌트 px을 사용해야함

// 이미지, 텍스트 등 "컨텐츠" 이를 감싸고 있는 것이 "컨테이너"
export default function App() {
  // 상태 변화 state
  const [displayNumbers, setNumbers] = React.useState(_.shuffle(numbers)); // hook
  // displayNumbers - 상태의 읽기 전용값
  // setNumbers - 상태를 변경하기 위한 업데이트 함수
  // React.Fragment 실제 렌더링에 반영되지 않는 추상 컨테이너
  return ( // XML 문법  component마다 쓸수 있는 style이 있음
    <Container>
      <Row>
        <Ball value={ displayNumbers[0]}>
          <Label> {displayNumbers[0]}</Label>
        </Ball>
        <Ball value={ displayNumbers[1]}>
          <Label>{displayNumbers[1]}</Label>
        </Ball>
        <Ball value={ displayNumbers[2]}>
          <Label>{displayNumbers[2]}</Label>
        </Ball>
        <Ball value={ displayNumbers[3]}>
          <Label>{displayNumbers[3]}</Label>
        </Ball>
        <Ball value={ displayNumbers[4]}>
          <Label >{displayNumbers[4]}</Label>
        </Ball>
        <Ball value={ displayNumbers[5]}>
          <Label >{displayNumbers[5]}</Label>
        </Ball>
      </Row>
      <Button title="다시 뽑기" onPress={()=>setNumbers(_.shuffle( numbers ))}/>
    </Container>   
  );
}

const styles = StyleSheet.create({ // styleSheet 생성
  container: {
    flex: 1,
    paddingTop: Constants.statusBarHeight,
    justifyContent: 'center',
    alignItems: 'center',
  },
  row:{
    flexDirection: 'row',
    margin: 24,
  },
  ball:{
    width: 50,
    height: 50,
    backgroundColor: "#e5e5e5",
    borderRadius: 25,
    justifyContent: "center",
    alignItems: 'center',
  },
  text: {
    fontSize: 20,
    color: '#000000',
    fontWeight: 'bold',
  }
});

// 뷰를 화면 꽉차게 잡아주는 작업을 제일 먼저 함 flex: 1 borderWidth: 1
// flex: 내가 사용할 수 있는 만큼의 크기를 가질거야
// 리액트 네이티브는 단위를 안쓰고 모든 단위는 px로 고정 되어 있다
// 50, '50%' 중하나

시계 예제

App.js

import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import styled from 'styled-components/native';
import Container from './components/Container';
import Row from './components/Row';
import moment from 'moment';

// window, document 참조하는 라이브러리 사용 불가 ex) Jquery

const Label = styled.Text`
  font-size: 36px;
  font-weight: bold;
`;
export default function App() {
  // moment() 현재 시각 생성
  const [now, setNow] = React.useState( moment() );
  // 유스이펙트가 실행될때
  // 1. 이 컴포넌트가 처음으로 표시될 때
  // 2. 주시하는 대상이 변화가 일어날 때 
  React.useEffect( ()=>{
    //동작
    setInterval( () => {
      setNow(moment());
    }, 1000) // 1초마다 setNow 실행
  }, [/*주시 대상 */] );
  return (
    <Container>
      <Row>
        <Text>{now.format('ddd / MMM Do / YYYY')}</Text>
      </Row>
      <Row>
        <Label>{now.format('HH')}</Label>
        <Label>{parseInt( now.format('s'), 10) % 2 === 1 ? ':' : ' '}</Label>
        <Label>{now.format('mm')}</Label>
        <Label>{parseInt( now.format('s'), 10) % 2 === 1 ? ':' : ' '}</Label>
        <Label>{now.format('ss')}</Label>
      </Row>
    </Container>
  );
}

./components/Row.js

import styled from 'styled-components/native';

const Row = styled.SafeAreaView`
  flex-direction: row;
`;

export default Row;

./components/Container.js

import styled from 'styled-components/native';

const Container = styled.SafeAreaView`
  flex: 1;
  justify-content: center;
  align-items: center;
`;

export default Container;

오늘의 추천 검색어

  • react-navigation
  • lodash
  • flexDirection
  • justifyContent: 'flex-end'
  • alignItems: 'center'
  • MDN arrow function
  • 프롭스
  • 컴포넌트
  • MDN export import
  • MDN template literals
  • flexbox 공부: flexbox frogyy