요번 포스팅에서는 크게 플렛폼 별 스타일링과 flexbox에 대해서 알아봅니다. 

 

일단 안드로이드와 iOS의 화면 단위(포인트, DP)자체가 달라 CSS코드에 스타일 속성 적용 시 특정 단위를 넣지 않습니다.(px,dp)

 

그 이유는 아래와 같으나  React native에서 알아서 조절해 주고 있으니 굳이 이해할 필요는 없습니다. 

(맥북을 사려는 여자친구에게 레티나 디스플레이로 아는 척 오지게 할 때 유용합니다.)

 

픽셀

- 가장 작은 프로그래밍 화면 단위

- 해상도는 가로 X 세로 픽셀 수를 말함

- PPI : 인치당 픽셀 수(초기 아이폰 163PPI)

-> 같은 해상도의 다른 화면 크기라면 이미지의 선명도가 다르게 나옴

 

애플의 레티나 디스플레이는 기존 화면의 4배의 해상도를 가지므로 이론적으론 기존 이미지의 크기가 레티나에서는 4분의1 크기로 보이게 됩니다.(이미지의 크기는 이미 특정 픽셀로 고정이 되어 있으므로) 애플은 여기서 point라는 논리적인 개념을 도입해서 일반 디스플레이와 레티나 디스플레이에서 이미지를 봤을때 차이가 없도록 합니다.

* 반면 안드로이드는 DP라는 디바이스 독립적인 논리 개념을 도입(160PPI)하고 있습니다. 

 

결국 디스플레이 스펙 별, 플렛폼 별 눈에 보이는 요소의 크기를 일관성 있게 유지 해주기 위해 X2, X3의 논리적인 배수를 적용한다는 의미? 입니다. 

 

앞서 텍스트에 그림자 속성을 넣었듯이 View에 그림자 속성을 넣어 보겠습니다. 그림자가 대표적인 플렛폼 별 설정을 달리해야 하는 속성입니다.

iOS : shadowPropTypesIOS (shadowOffset, shadowOpacity, shadowRadius 같이 세부 속성으로 설정)

Android : elevation (겹쳐진 레이어의 우선 순위를 설정 그림자 레이어를 뒤에 실물 레이어를 앞에 두는 방식)

 

- Platform을 import

- ...Platform.select({ ios: {...}, android:{...} }) 를 통해 플렛폼 별 스타일 적용 코드를 추가

* 디버거를 붙인 상태에서 platform 유틸리티를 쓰려고 했더니 제대로 작동하지 않는 것 같았습니다. 잠시 디버거(크롬 개발자도구)를 끕니다. (백그라운드 디버거로 인한 작동 성능이 저조 할 수 있다는 경고 메세지가 emulator에 뜹니다.)

 

 

 

 

 

 

 

 

 

프로필 이미지, 카드 전체 아래에 그림자 효과가 적용된 것을 볼 수 있습니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반면 안드로이드에서는... 희미하게 적용된 그림자를 볼 수 있습니다.

 

 

 

 

 

 

 

 

 

Component 변형

component의 좌표 변경등을 통해 애니메이션 효과를 주기위한 속성들로 transform으로 시작하여 속성을 적용 가능합니다.

(e.g. transform: [{rotate: '90deg', scale: .5}])

*아래 다양한 변형 속성들을 배열 형태로 여러개 사용할 수 있으나 그 적용 순서에 따라 전혀 다른 결과가 만들어 질 수 있습니다.

- perspective : z-index를 조절하는 방식으로 3D 효과를 줄 수 있음

- translateX,Y : 요소의 평면 이동 아래, 우측이 + 수치임

- rotateX, Y, Z : 요소의 축회전 X(위아래), Y(좌우), Z(회전)

- backfaceVisibility : 요소가 회전했을때 반대면을 보여줄 것인가?에 대한 속성

- scale, X,Y : 요소의 크기를 조절, 기본 수치는 1

- skewX, Y: 요소를 변형하면서 기울임.. 직접 해보심이.. (안드로이드에서는 정상동작하지 않는다 함)

 

*ㅎㅎ.. 요소를 직접 다루는 대신 Yoga라는 layout engine을 쓴다고 합니다.

 

flexbox (View에 적용되는 기본적인 스타일 속성)

* 아래 공식 사이트에서 flexbox 속성의 예제 코드와 결과 이미지를 확인 할 수 있습니다. 

https://facebook.github.io/react-native/docs/flexbox#__docusaurus

 

- flex : 안드로이드의 weight와 비슷한 속성으로 부모 요소 대비 얼마의 비율로 요소의 크기(다른 요소 대비)를 확보할 것인가 결정

- flexDirection : 'row'를 주면 요소들의 배치 방향을 가로로 전환한다. (기본 main axis는 세로(column) 방향)

- justifyContext : 여러 자식 요소들의 자신의 크기대로 적절한 위치로 배치 하는 방식(center, flex-start,end, space-around, space-between)

- alignItems : 부모 요소의 보조 축을 따라 자식 요소들을 어떻게 정렬할 것인지 결정(center, flex-start, end)

- alignSelf : 자식 요소 자신의 독립적인 alignItems 속성을 지정

- flexWrap : 'nowrap' 화면을 넘어가면 잘림, 'wrap' 잘리지 않고 다음줄에 표현, 적용 예는 아래 링크를 통해 확인해보자

(https://yogalayout.com/docs/flex-wrap/)

 

변형실습 (npm install immutability-helper --save 를 통해 component state update를 위한 helper 설치)

github/highstyle 참고

'React native' 카테고리의 다른 글

Animation  (0) 2020.01.05
Navigation  (0) 2020.01.02
Style  (0) 2019.12.27
Todo 2  (0) 2019.12.25
Todo 1  (0) 2019.12.25

Todo 예제에서 무작정 각 component에 style을 적용하는 코드를 추가했었습니다. 

 

이제 React native의 뷰 구조 분리 및 style 적용에 대해서 알아보도록 하겠습니다. 

 

style을 적용하는 방법은 직접 태그에 스타일 속성을 추가하는 인라인 스타일과 StyleSheet를 통한 정의 방식이 있습니다.

* 여러 component에 적용되는 스타일은 StyleSheet를 이용하여 적용하고 특정 component에 적용해야 하는 몇몇 속성들은 인라인 스타일을 사용하여 스타일 코드를 정리할 수 있다.

 

- 스타일을 한번에 여러개 적용 할 때는 <Text style={[ style, style ]}>과 같이 배열 형태로 작성

- 스타일을 여러개 적용 할 때 중복되는 property는 마지막의 것으로 적용 됨(앱 성능을 위해 중복 적용 주의)

- 스타일을 따로 정의하면 코드의 가독성이 올라가고 재사용으로 인한 전체적인 컨셉 수정에 용이(가독성 있는 스타일 네이밍 필요)

- component.js , style.js로 스타일 코드를 따로 분리하여 export, import하여 적용할 수 있음

- 스타일 속성에서는 전체 속성(borderWidth: 3)보다 세부 속성(borderLeftWidth:1)이 우선 순위가 높음

 

그럼 버튼을 눌렀을때 전체 테마를 바꾸는 예제를 스타일 파일을 분리하여 구현해 보도록 하겠습니다. 

 

https://github.com/action-intent/ReactNative/tree/master/Style

* AppStyle.js를 진입점으로 설정해주세요.

난해할 수 있는 부분은 코드에 주석으로 추가하였습니다. (참고로 react의 JSX 코드에는 주석을 넣을 수가 없습니다..)

 

 

 

 

 

 

 

 

위 코드를 다운받아 실행해 보면 White 버튼을 누르면 container와 button의 색이 바뀌고 button label도 변경됩니다.

 

 

 

 

 

 

 

 

 

 

 

이렇게 구현했을 때의 장점은 구현 그대로 앱의 전체 테마를 손쉽게 변경 할 수 있다는 점이고 스타일 코드를 모아 놓아 로직 코드가 간단해 지고 스타일 변경 시 확인해야 할 부분이 분명해 진다는 점입니다.

* 코드의 구조적 분리는 코드의 readability를 높여 유지 보수를 쉽게 하며 협업이 요구되는 프로젝트에서 큰 이점이 된다는 당연한 얘기를 해봅니다.

 

View component에 스타일 적용

view component는 html의 div 태그와 비슷한 것이라 생각하시면 됩니다. 

여기엔 다양한 스타일 속성을 적용할 수 있습니다. 프로필 카드 View 예제를 만들어 보면서 하나하나 알아 보도록 하겠습니다. 

* 같은 github에 AppView.js를 참고하세요.

 

1. 배경색 설정 : backgroundColor로 값은 rgb, rgba(알파), hsl(색상, 채도 명도), hsla, transparent, saturation, lightness

2. 테두리 설정 : borderColor, borderRadius(둥근테두리), borderStyle, borderWidth (e.g borderTopColor: 'red')

* 현재 borderStyle dashed, dotted 속성에 borderWidth를 부분 설정하려고 하면 오류가 난다고 하네요? 그런듯 합니다.

3. Image 가져오기 : <Image> 태그를 이용하고 source={require('image path')} 형태로 불러옴(import에 Image component 추가)

 

 

 

 

 

 

 

 

지금까지 반영한 스타일 코드를 띄우면 다음과 같습니다. 

아.. 뭔가 되려고 함..

 

 

 

 

 

 

 

 

 

 

 

4. margin, padding, position

* 모든 기능이 그렇지만 스타일 적용 후 iOS, 안드로이드 모두 테스트를 해봐야 합니다.  같은 속성이 플렛폼에 따라 다르게 표현될 수 있기 때문..

- margin은 부모 요소와의 간격 padding은 자식 요소와의 간격

- {position: 'absoulte', right: 0, bottom: 0} 부모 요소의 오른쪽 아래에 위치

 

 

 

 

 

 

 

 

cardContainer, cardImageContainer에 alignItems, marging, padding 속성을 추가하고 훨씬 보기 편안해진 모습입니다.

 

 

 

 

 

 

 

 

 

 

 

5. Text style

Text와 위에서 배운 View의 속성은 공통점이 많습니다. View의 대부분의 속성을 Text에서도 사용할 수 있습니다. 

- font의 경우 플렛폼 마다 지원하는 종류가 다를 수 있음. ...platform.select로 플렛폼 별로 스타일 속성을 설정할 수 있음 

- fontSize, fontStyle, fontWeight등의 속성을 사용할 수 있음

 

 

 

 

 

 

 

 

텍스트 스타일 속성을 통해 텍스트가 훨씬 보기 좋아졌음을 알 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

6. 텍스트 장식

텍스트 장식은 플렛폼 마다 지원하는 속성이 다를 수 있습니다.

- lineHeight: Text 높이 지정 

- textAlign: Text 수평정렬

- textDecorationLine: 밑줄, 취소선 등

- textDecorationColor, textDecorationStyle은 iOS만 지원하는 속성으로 밑줄등의 스타일 속성

- textShadowColor, textShadowOffset(음영의 위치), textShadowRadius(투명도)

 

 

 

 

 

 

 

 

 

마지막으로 name에 그림자 속성을 추가해 보았습니다. 작지만 큰 차이가 느껴지는 속성입니다. 

 

 

 

 

 

 

 

 

 

 

지금까지 component의 기본 스타일을 적용하는 방법에 대해서 알아 보았습니다.

 

다음 포스팅에서는 고급 스타일링 기법에 대해서 알아보도록 하겠습니다. 

'React native' 카테고리의 다른 글

Navigation  (0) 2020.01.02
고급 Style  (0) 2019.12.29
Todo 2  (0) 2019.12.25
Todo 1  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25

지난 Todo1에서 todo item을 state에 추가하는 것 까지 진행 되었습니다. 요번엔 추가된 item이 렌더링 되어 리스트에 추가되는 것을 포함하여 Todo 예제를 마무리 해보도록 하겠습니다. 

 

1. Todo.js, TodoList.js 추가, App.js에 TodoList 추가

- 하나의 todo 아이템을 표현하는 component

- todos.map을 통해 각각의 todo component를 만들고 key, todo를 props로 전달

- const { inputValue, todos } = this.state  todos를 props로 전달하기 위해 추가

- <TodoList todos={todos} />  TodoList추가 todos를 props로 전달

 

 

 

 

 

 

 

전과는 달리 todo 입력 후 submit을 누르면 todo list에 추가 되는 것을 볼 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2. Todo item에 delete, complete button 달기

- App.js에 deleteTodo, toggleComplete 메서드를 추가

- 추가된 메서드를 클래스 생성자에서 바인딩

 

3. TodoButton.js 파일 생성

- 버튼 component는 props에 따라 delete, complete 버튼으로 전환된다.

 

4. App.js > TodoList.js > Todo.js 로 deleteTodo, togglecomplete props 전달

- App.js의 <TodoList>에 toggleComplete, deleteTodo를  props로 전달

- TodoList.js의 <Todo>에 toggleComplete, deleteTodo를  props로 전달

- Todo.js에 Done, Delete <TodoButton> 추가 (import TodoButton ...)

 

 

 

 

 

 

 

Todo를 추가하고 Done을 누르면 버튼 스타일이 변경됨

Delete 버튼을 누르면 Todo가 삭제 됨

 

 

 

 

 

 

 

 

 

 

 

 

 

5. TabBar.js추가

- App.js에 type 속성을 설정하는 setType 메서드 추가

- TabBar.js는 App.js로부터 setType, type props를 받는다.

- <TabBarItem>의 border props는 왼쪽 테두리 스타일 추가 여부

 

6. TabBarItem.js추가

- selected,border 등 props의 값에 따라 style을 지정

- type과 title props이 같으면 텍스트 스타일을 bold로 지정

 

7. App.js에 TabBar component 추가

- import TabBar

- TodoList에 type props추가

- type, setType props와 함께 <TabBar>추가

 

8. TodoList.js에 type filter 추가

- type, todos props를 이용하여 todos 목록을 complete의 값에 따라 필터링하는 getVisibleTodos 메서드 생성

- getVisibleTodos를 호출하여 todos의 목록을 갱신 하도록 호출

 

 

 

 

 

 

 

화면 하단에 TabBar가 생성되었고 Active, Complete에 따라 Todo 목록이 필터링 됨

 

 

 

 

 

 

 

 

 

 

 

 

 

여기까지 간단?한 할 일 관리 서비스를 React native로 만들어 보았습니다. 

 

이정도 예제만 완벽하게 이해했다면 이를 응용하여 다른 서비스도 충분히(수많은 검색과 삽질을 동반) 만들 수 있다고 생각되네요.

'React native' 카테고리의 다른 글

고급 Style  (0) 2019.12.29
Style  (0) 2019.12.27
Todo 1  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25
Project 생성 및 빌드  (0) 2019.12.25

https://github.com/action-intent/ReactNative/tree/master/Todo

* 예제를 바로 받아서 빌드 하실 때는 index.js의 진입점(App.js)를 './Todo/App' 으로 변경하고 진행하세요

 

본 포스팅은 위 링크에서 코드를 받으시고 코드와 함께 보시면서 이해하면 좋습니다.

 

요번엔 책에서 소개하는 간단한 할 일 관리 서비스를 만들어 봅니다. 

 

 Heading, Input, TodoList, Button, TabBar의 Component 지향 개발을 적용합니다. 

 

1. App.js로 Main component를 생성

- keyboardShoudPersistTaps='always'

ScrollView의 속성으로 키보드를 닫고 화면에서 onPress이벤트를 받을 수 있도록 합니다.

- style 속성 중 flex:1의 경우 상위 컨테이너의 영역 전체를 채우도록 함(match_parent와 비슷)

 

2. index.js를 수정하여 진입점을 1에서 생성한 App.js가 되도록 수정

 

3. Heading.js로 Heading component(stateless) 생성하여 todos 타이틀을 생성

-  stateless의 경우 const로 생성하는 방식을 기억하자

- style 속성 중 color , fontWeight를 참고하자

 

4. App.js의 render내에 Heading component를 가져와 타이틀이 표시되도록 한다.

 

5. Input.js로 텍스트 입력 Component를 생성

- TextInput의 placeholder 속성은 텍스트 입력 전 보여주는 문구

- selectionColor는 커서의 색을 변경

 

개발자 메뉴 열기

console.log()를 통해 디버깅 하기 위한 내장 메뉴 

 

 

 

 

 

 

 

emulator에서

iOS : Cmd + D

android : Cmd + M

 

Inspector : 요소의 스타일 조사

Perf Monitor : RAM, 성능 관련 정보

* Debug를 눌러 크롬의 개발자 도구를 통해 디버깅이 가능하도록 한다.

 

 

 

 

 

 

 

6. Input과 App 연결

 

Input.js

const Input = ({inputValue, inputChange}) => (  ... )

- props로 inputValue(입력값)과 inputChange(입력 시 호출 함수)를 받는다.

onChangeText={inputChange}

- TextInput의 속성으로 onChangeText가 호출 될 때 props 함수인 inputChange가 호출 되도록 한다.

 

App.js

inputChange(inputValue) { }

- 콘솔을 통해 입력값을 확인할 수 있도록 하고 state의 inputValue를 수정

- 아래 코드를 통해 Input.js를 가져다 쓰면서 props를 전달

<Input
	inputValue={inputValue}
	inputChange={(text) => this.inputChange(text)} />

 

 

 

 

 

 

 

 

 

실행 결과 화면

TextInput에 입력 할 때 마다 아래 크롬 개발자 도구에 로그가 찍히는 것을 볼 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7. Submit button

 

App.js에 submit 버튼, 메서드 추가

import Button from './Button'
let todoIndex = 0
...
submitTodo() {
        if(this.state.inputValue.match(/^\s*$/)) { //inputValue가 비어있는 경우
            return
        }
        const todo = {  //todo item 생성
            title: this.state.inputValue,
            todoIndex,
            complete: false
        }
        todoIndex++
        const todos = [...this.state.todos, todo]   //새로 생성한 todo item을 todos state에 추가
        this.setState({ todos, inputValue: ''}, () => { //state를 갱신하고 콜백 함수로 로그를 남긴다.
            console.log('State: ', this.state)
        })
    }

Button.js 생성(stateless) : TouchableHighlight

- underlayColor는 눌렸을때 배경색

- submitTodo 메서드를 구조 분해 할당

- onPress={submitTodo} 버튼을 누르면 부모의 메서드 작동

 

App.js에 Button 추가

- this.submitTodo = this.submitTodo.bind(this) 생성자의 메서드 변수에 바인딩

- <Button submitTodo={this.submitTodo} /> Button component 추가

 

 

 

 

 

 

 

Text를 입력하고 Submit을 누르면 InputText가 비워지고 개발자 콘솔에 추가된 todo 정보가 출력된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

'React native' 카테고리의 다른 글

Style  (0) 2019.12.27
Todo 2  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25
Project 생성 및 빌드  (0) 2019.12.25
React native intro  (0) 2019.12.25

본 포스팅의 관련 예제는 아래 github 참고

https://github.com/action-intent/ReactNative/tree/master/StateProps

 

State(mutable)

- React에서 데이터를 만들고 다루는 방식

- Component가 생성될때 선언

- setState 함수 내에서 갱신

 

State를 정의하고 이벤트를 받아 갱신해보는 예제를 실행해 봅시다.

import React, { Component } from 'react';
import { Text, View } from 'react-native';

export default class MyComponent extends Component {
  constructor(){  // 1. 생성자에서 State 선언 및 초기화
    super()
    this.state = {
      year: 2018
    }
  }
  updateYear() {  // 2. render() 위에 사용자 정의 함수
    this.setState({ // * this.sate.year = 2019 처럼 직접 갱신하지 않는다.
      year: 2019
    })
  }
  render() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text onPress={() => this.updateYear()}> // 3. Text 터치 시 updateYear 함수 호출
          The year is: { this.state.year }
        </Text>
      </View>
    );
  }
}

* state를 직접 수정하면 render()가 호출되지 않아 갱신되지 않습니다. 대신 this.forceUpdate()를 통해 강제 호출하는 방법이 있습니다.

 

 

 

 

 

 

 

 

실행하면 다음과 같이 텍스트가 나타나며 클릭 시 2019로 변경

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Props(immutable)

- Component 파라미터로 전달 됨(부모에서 자식으로 전달)

- Component 내에서 갱신되지 않음

 

Props를 이해하기 위한 코드 예제

* const를 사용하여 this.state, this.props 등 반복코드를 제거한 것을 참고(네이밍 통일)

import React, { Component } from 'react';
import { Text, View } from 'react-native';

export default class LotsOfGreetings extends Component { //부모 Component export
  constructor(){
      super()
      this.state = {
          username: 'Rexxar'
      }
  }
  updateName(){
      this.setState({ username: 'Jaina'})
  }
  render() {  //name과 updateName을 props로 전달
    const { username } = this.state
    return (
      <View style={{alignItems: 'center', top: 50}}>
        <Greeting 
          updateName={ () => this.updateName() }
          name= { username } /> 
      </View>
    );
  }
}

class Greeting extends Component { //자식 Component : props를 쓴다.
  render() {
    const { name, updateName } = this.props //props를 
    return (
      <View style={{alignItems: 'center'}}>
        <Text onPress={ updateName }> Hello {name}!</Text>
      </View>
    );
  }
}

조금 복잡해 보일 수 있으나 결국 LotsOfGreetings에서 정의한 state를 Greeting에 props로 전달하여 사용할 수 있도록 하는 과정

 

 

 

 

 

 

 

 

 

왼쪽과 같은 결과 화면과 텍스트를 눌렀을때 이름이 업데이트 됨

 

 

 

 

 

 

 

 

 

 

 

 

Stateless component props(함수형 component)

기존 class 정의 형태에서 const Greeting = (props) => { ... } 형태로 코드를 간결하고 재사용성을 높일 수 있다.

 

배열 개체 받기

배열 형태의 props는 아래와 같은 형태로 핸들링 할 수 있다.

let topics = props.topics.map((topic, i) => {
  return <Text>{ topic }</Text>
})

 

생명주기 메서드

Component의 특정 주기(생성, 갱신, 파기)에 자동으로 호출되는 메서드

- getDerivedStateFromProps : props가 변경되어 갱신 시 호출

- componentDidMount : Component가 로딩되고 바로 한번

- shouldComponentUpdate : 새로운 state, props로 render의 호출 여부를 결정

- componentDidUpdate : Component가 재 렌더링 된 후 한번 호출(이전 state, props)

- componentWillUpdate : Component가 파기되기 전에 호출(리스너, 타이머 정리)

 

예제 코드를 통해서 React native의 주요 요소에 대해서 이해?했으나 한번 봐서는 난해하긴 마찬가지 입니다. 젠장..

이해가 될때까지 위 내용은 숙지를 하시고 다음 포스팅에서는 예제 앱을 만들어 보겠습니다. 

 

'React native' 카테고리의 다른 글

Todo 2  (0) 2019.12.25
Todo 1  (0) 2019.12.25
Project 생성 및 빌드  (0) 2019.12.25
React native intro  (0) 2019.12.25
첫 애플리케이션 만들기  (0) 2019.04.14

이제 기본적인 프로젝트를 생성 및 빌드 할 수 있도록 개발 환경을 조성해보자.

 

http://facebook.github.io/react-native/docs/getting-started

 

React Native · A framework for building native apps using React

A framework for building native apps using React

facebook.github.io

기본적인 프로젝트 생성은 위 공식 가이드를 따르도록 한다. (React Native CLI 탭에서 참고)

-> 어떤 플랫폼에서(윈도우, 맥) 개발할 건지, 어느 플랫폼에서(안드로이드, iOS) 실행할 건지 골라서 필요한 툴을 모두 설치 하도록 하자

-> 혹시 제대로 진행이 되지 않는다면 가이드에서 얘기하는 툴들의 최소 버전 등을 잘 확인하자

(영어는 잘 못 읽어도 숫자는 비교 할 수 있지 않은가)

 

* 본인은 맥 유저임에 따라 iOS 베이스로 설치

 

1. npm(node package manager) 설치가 선행 되어야 함

* watchman : react native에서 사용하는 파일 감시도구

2. Xcode(CLI, simulator, cocoapods) 설치

* 안드로이드의 경우 jdk, android studio (sdk, path설정) 등의 과정이 필요

3. 프로젝트 생성 > npx react-native init AwesomeProject

4. 프로젝트 시작 > 프로젝트 폴더 이동 후 > npx react-native run-ios

* 안드로이드의 경우 npx react-native run-android

5. Editor의 경우 Brackets을 사용하는데 더 좋은 툴이 있으면

 

* Mac에서 phones sdk관련 오류가 날 경우

sudo xcode-select --switch /Applications/Xcode.app

Pod install

 

위 설치 가이드 3번을 실행하면 해당 폴더에 아래 기본 파일이 있습니다. 

index.js (앱의 진입 포인트 : 안드로이드의 application class)

App.js ( 메인 : 안드로이드의 main activity)

 

설치 가이드 4번 프로젝트 실행을 통해 아래와 같은 결과 화면을 확인할 수 있습니다. 

* 새로운 프로젝트를 실행 시 꼭 새로운 emulator를 실행해 주시기 바랍니다. 

 

앞으로 진행되는 포스팅의 예제 코드는 아래 github을 참고하시길 바랍니다.

https://github.com/action-intent/ReactNative

 

github 코드를 땡기신 후 프로젝트에 필요한 모듈들을 설치해야 합니다. 

프로젝트 폴더로 이동 후 npm i 명령을 통해 npm모듈들을 자동으로 설치해 주도록 합니다.

* 설치되는 모듈의 목록은 package.json 파일에 있습니다. 참고하세요.

 

'React native' 카테고리의 다른 글

Todo 1  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25
React native intro  (0) 2019.12.25
첫 애플리케이션 만들기  (0) 2019.04.14
React native 설치  (0) 2019.04.14

한참 안드로이드 개발을 할 때 하이브리드 앱이라는 개념을 접했고 당시 크로스 플랫폼을 지원하는 프레임웤을 사용하여 테스트 앱을 만들어보고 발전 가능성의 한계를 느꼈던 시절이 있었습니다. 

 

그리고 몇년만에 React native라는 녀석을 다시 접하면서 하이브리드 앱에 대한 관심이 다시 생겼네요.

 

Facebook이 개발, 다양한 서비스 업체가 지원하고 있으며 종종 관련 기술 경험자를 찾는 회사도 보입니다. 

 

고 차원의 플렛폼 의존도가 높은 서비스가 아닌 데이터 인입 차원의 서비스라면 네이티브 개발을 대신하는 좋은 방안이 될 것으로 보입니다. 

 

https://www.manning.com/books/react-native-in-action

 

React Native in Action

Learn how to utilize your existing JavaScript skills to create rich cross-platform mobile apps.

www.manning.com

본 포스팅은 위 책을 베이스로 진행 할 예정입니다. React native 초기(2017년?)에 발간된 책을 처음 봤었는데 이미 많은 업데이트가 진행되어 설치부터 수 많은 삽질을 하다가 나가 떨어진 기억이 있습니다. 

* 특히 보편화되지 않은 기술에 대한 책을 고를땐 되도록 최신 발간된 것을 참고하고 공식 사이트를 통해 영어 공부?도 병행하심이..

https://lowcrash.tistory.com/23?category=783777 (옛 삽질의 흔적)

 

  iOS(Object C or Swift), Android(Java or Kotlin)을 따로 개발 할 필요 없다.

React native의 경우 기존 하이브리드 앱(웹 뷰 렌더링) 프레임워크와 달리 컴파일을 통해 자바스크립트 코드를 네이티브 코드로 변환하여 고성능 하이브리브 앱을 개발할 수 있다.

- iOS, Android 개발자가 따로 필요하지 않다

- 빌드가 빠르다. 코드 수정 후 저장하면 바로 결과 화면에 반영된다.

 

Component : 가장 중요한 키워드로 앱을 구성하는 조립 블럭 (stateful(속성 값이 있는), stateless(재사용)로 구분)

 

* React native의 기본적인 code snippet (주석 부분만 보고 넘어가자)

import React, { Component } from 'react'  // 1. react library에서 React와 Component를 가져온다.
import {
  AppRegistry,
  StyleSheet,
  View,
  Text
} from 'react-native' // 2. 다양한 UI component를 가져온다.
import API from './api' // 3. import other component

class blankRNApp extends Component {
  constructor () {
    super()
    this.state = { name: 'chris' }  //stateful
  }
  componentDidMount () { // 4. last method of lifecycle
    API.getName().then((data) => {
      this.setState({ name: data })  // 5. call render() 
    })
  }
  render () { // 6. rendering
    return ( //render must return native item or null or false
        <View> // JSX

            <Text> Hello there, {this.state.name} </Text>

        </VIew>
    )
  }
}

const styles = StyleSheet.create({ // 7. style 선언
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF'
  }
})

 

Lifecycle method : constructor, componentDidMount, render 등 클래스가 생성되면서 실행되는 일련의 메소드

 

CLI, npm, Xcode, ES2015, MVC, SPA... 알고 있으면 좋지만 필수는 아니다.. 어쩌란 말인가..

(e.g. : ES2015에서는 const 대신 import를 사용)

 

JSX : XML 처럼 보이는 자바스크립트 구문 확장 (e.g. : <Text> Hello </Text> )

React : 기존 DOM 처리 방식에서 in memory DOM을 통해 필요 부분만 갱신하여 성능 향상

Bridge : 리액트-네이티브 계층과의 통신 채널

단방향 데이터 흐름 : 최상위 컴퍼넌트의 데이터가 변경되면 자식 컴포넌트는 props로 변경된 데이터를 전달 받고 갱신됨

hot reloading : 개발시 변경된 부분만 빠르게 반영

transpilation : transpiler(바벨)가 특정 언어로 작성된 코드를 다른 언어로 변환. 언어의 최신 기능 사용

 

Custom component 만들기(기본)

class Home extends Component { ... }

-> import한(위 code snippet 주석 1) Component(객체 구조 분해 할당)를 상속하여 Home instance 생성

 

Render 함수

다른 함수의 실행

Exports

export default Home

-> 다른 Component에서 Home을 사용하려고 할 때

 

Stateless Component

const Header = () => (

    <View>

        <Text>HEADER</Text>

    </View>

)   

-> render() { ... <HEADER /> } 이런식으로 다른 component에서 재사용 가능

 

이것으로 React native의 기본적인 개념은 정리?를 하였고 다음 포스팅에서는 기본 프로젝트를 돌려보겠습니다.

* 본 포스팅에서 Bold된 내용은 꼭 숙지해 주세요. 새로운 개념을 익힐때는 그 안에서 사용하는 키워드에 익숙해지는게 1순위 입니다.

'React native' 카테고리의 다른 글

Todo 1  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25
Project 생성 및 빌드  (0) 2019.12.25
첫 애플리케이션 만들기  (0) 2019.04.14
React native 설치  (0) 2019.04.14

O'Reilly의 책을 참고하고 있으므로 아래 샘플앱 코드를 참고

https://github.com/bonniee/learning-react-native

 

본 내용은 가능한 윈도우 기반으로 설명토록 하겠습니다.

 

윈도우 커맨드를 통해 WeatherProject 생성

react-native init WeatherProject

 

WeatherProject폴더 밑에 index.android.js 생성

* iOS를 사용한다면 index.ios.js 생성

import { AppRegistry } from 'react-native'

import WeatherProject from './WeatherProject_Part1'; //class import

AppRegistry.registerComponent('WeatherProject', () => WeatherProject);

 

깃허브의 src/Weather에서 WeatherProject_Part1.js 파일을 로컬 WeatherProject로 다운로드

 

# WeatherProject_Part1 간략 코드 설명

  constructor(props) {
    super(props);
    this.state = { zip: "" };
  }

//render 함수 이전에 zip 변수 초기화

 

_handleTextChange = event => {
    this.setState({ zip: event.nativeEvent.text });
  };

//Text change event의 결과를 zip 변수에 저장

 

render() {

style={styles.input}

onSubmitEditing={this._handleTextChange}

// render()내 onSubmitEditing에 _handleTextChange을 연결

}

const styles = StyleSheet.create({
  container: { .. }

})

// render내 스타일 속성 정의

 

WeatherProject내에서 react-native WeatherProject 실행

 

 

zip code를 입력받아 날씨 정보를 서버로부터 받아 보여주는 코드를 추가해본다.

 

깃허브의 src/Weather에서 Weather.js, Forecast.js, open_weather_map.js, flowers.png 파일을 로컬 WeatherProject로 다운로드

* index.android.js의 import WeatherProject from './WeatherProject_Part1';를 './Weather';로 수정

 

iOS image file 추가 : Images.xcassets/ 폴더 선택 -> New Image Set

* Image Set은 파일 이름과 동일 하게 설정

 

안드로이드 image file 추가 : WeatherProject/android/app/src/main/res의 모든 하위폴더에 이미지 파일 추가

 

# Weather.js 코드 설명

 

import React, { Component } from "react";
import { StyleSheet, Text, View, TextInput, ImageBackground } from "react-native";

//Image가 패치되어 ImageBackground를 사용
import Forecast from "./Forecast"; 

//날씨 정보의 결과를 저장하는 객체
import OpenWeatherMap from "./open_weather_map";

//서버에서 날씨정보를 받아오는 모듈

 

_handleTextChange = event => {
    let zip = event.nativeEvent.text;
    OpenWeatherMap.fetchForecast(zip).then(forecast => {
      this.setState({ forecast: forecast });
    });
  };

//zip code를 입력받으면 zip 변수에 저장하고 날씨 정보를 받아 forecast 형태로 저장

 

render() {
    let content = null;
    if (this.state.forecast !== null) {
      content = (
                  main={this.state.forecast.main}
          description={this.state.forecast.description}
          temp={this.state.forecast.temp}
        />
      );
    }
    ...

} //forecast 객체가 채워지면 content에 담는다.

 

나머지 render 코드 내용은 아래와 같다.

- Image component가 하위 component를 가질 수 없도록 패치가 되어 ImageBackground를 사용

- 레퍼런스 코드의 TextInput의 속성에 대한 결과가 예상과 달라 아래와 같이 StyleSheet 수정

* Style 속성 값 추후 수정 필요

 

 

결과 화면

 

'React native' 카테고리의 다른 글

Todo 1  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25
Project 생성 및 빌드  (0) 2019.12.25
React native intro  (0) 2019.12.25
React native 설치  (0) 2019.04.14

O'Reilly의 책을 보며 기본 환경 설정을 해봤는데 맥 기준이라(iOS는 책 따라하면 잘 됨) 윈도우 기반 환경 설정에 대한 검색이 따로 필요 할 수 있다.(Hello world는 언제나 중요하다.)

 

React native의 개발은 expo와 react-native 두 가지 방식이 있다.(npm 패키지)

* 처음에 두개가 같은 건 줄 알고 검색을 통해 윈도우에 expo를 설치하곤 책을 따라 가다가 아차 싶었음..

 

react-native : iOS, Android base코드가 함께 있어 단말이나 에뮬레이터를 통해 컴파일을 거쳐 결과를 확인

expo : 개발 PC에 node 서버를 작동시켜 프로젝트를 활성화 시키고 단말의 expo앱을 통해 접속하여 결과 확인하는 방식(PC와 단말이 같은 네트워크에 묶여 있어야 함)

 

위 책을 통해 공부를 하실 분들은 react-native를 쓰시면 될 것 같다. 

*공통적으로 JDK는 필요

 

#맥(react-native 책 방식 수정)

0.homebrew 설치 

https://brew.sh/index_ko

 

1. node, watchman, flow 설치

brew install node

brew install watchman

brew install flow

 

2. react command-line 설치

npm install -g react-native-cli

 

3-1. iOS개발자 계정, xcode 설치

3-2. 안드로이드 Studio 설치

https://developer.android.com/studio

android studio 실행 후 SDK 매니저 실행 (SDK Build-tools, API, Support Repository, Intel x86 패키지 설치)

* Sutdio, SDK 설치 후 SDK 경로를 ANDROID_HOME으로 환경변수 추가(~/.bash_profile)

 

4. 프로젝트 생성 : react-native init test-app

 

5-1. 아이폰에서 프로젝트 실행

iOS폴더 xcode에서 열고 run

* 실패 시 test-app폴더에서 npm install, npm start 실행

* iOS packager가 실행 되고 실제 단말에서 테스트하기 위해서는 단말등록, 앱 배포 인증 필요... 

 

5-2. 안드로이드에서 프로젝트 실행

android studio를 통해 테스트 할 avd 생성 후 실행 or 단말 연결

test-app 폴더에서 react-native run-android

* 가끔 .. Device is UNAUTHORIZED를 포함한 에러를 일으키는데 adb server restart를 통해 

adb server를 재시작 하여 단말 연결을 다시 해본다. (emulator -list-avds 로 연결 단말 확인)

 

 

#윈도우(react-native android only)

1. node.js 설치

 

2. react command-line 설치

npm install -g react-native-cli

 

3. 프로젝트 생성 : react-native init test-app

 

4. 안드로이드 스튜디오, SDK 설치 

android studio 실행 후 SDK 매니저 실행 (SDK Build-tools, API, Support Repository, Intel x86 패키지 설치)

 

5. 안드로이드의 device manager 실행, 테스트 단말 생성, 실행 or 테스트 단말 연결

 

6. 윈도우 커맨드 실행하여 test-app이동 후 react-native run-android 실행

 

* 윈도우 시스템 환경변수에 JAVA_HOME 추가 필요 (같은 식으로 ANDROID_HOME도 추가)

 

* 그 외 run-android가 안되는 경우 위 맥의 5-2를 참고(안드로이드 스튜디오에서 테스트 단말이 제대로 연결 되었는지 확인 필요)

 

#expo 방식

1. node.js 설치

2. npm을 통한 express(expo포함) 설치

npm install express 
npm init -y

* package.json의 version 수정 (6.4.1)

3. react native 프로젝트 생성

expo init test-app

 -> blank, tab 스타일 선택, 타이틀 이름 설정 후 엔터

4. 프로젝트 실행

cd test-app

npm start

5. 핸드폰에 expo 앱 설치

6. expo앱으로 4의 QR코드 스캔 (같은 네트워크에 개발 단말, 데스크탑 연결)

'React native' 카테고리의 다른 글

Todo 1  (0) 2019.12.25
State, Props, Lifecycle  (0) 2019.12.25
Project 생성 및 빌드  (0) 2019.12.25
React native intro  (0) 2019.12.25
첫 애플리케이션 만들기  (0) 2019.04.14

+ Recent posts