[React Native] TO-DO 앱 만들기 #5

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@anpigon·
0.000 HBD
[React Native] TO-DO 앱 만들기 #5
![](https://ipfs.busy.org/ipfs/QmSZVWfqBV5yJMzscYstd4iEJffFRDTpPAPeLnTGMhn2Fg)

*리액트 네이티브(React Native)로 할 일 관리앱(To-Do App)을 만들기* 마지막 강좌입니다. 이번에는 로컬 스토리지에 데이터를 저장하고 불러오는 기능을 구현하고, 앱 배포하는 방법을 알아봅니다. 

[이전 강좌](https://busy.org/@anpigon/react-native-todo-4-1544540786908)에서 계속 이어지는 내용입니다. 
- [[React Native] TO-DO 앱 만들기 #1](https://steemit.com/kr/@anpigon/react-native-todo-1-1543931900794)
- [[React Native] TO-DO 앱 만들기 #2](https://steemit.com/kr/@anpigon/react-native-todo-2-1544357245729)
- [[React Native] TO-DO 앱 만들기 #3](https://steemit.com/kr/@anpigon/react-native-todo-3-1544444494475)
- [[React Native] TO-DO 앱 만들기 #4](https://busy.org/@anpigon/react-native-todo-4-1544540786908)

<br>

<br><center>* * *</center><br>

# Storage에 데이터 저장하고 불러오기

<hr>

<br>저장소(Storage)를 사용하기 위해는 `AsyncStorage`를 import 해야한다. App.js 파일에서 `import {} 'react-native'` 를 아래와 같이 수정한다.

```js
import { StyleSheet, View, Text, AsyncStorage } from 'react-native';
```

<br>

**App 컴포넌트**에 `componentDidMount()` 함수를 입력한다.

```js
  componentDidMount = () => {
    AsyncStorage.getItem("todos").then(data => {
      const todos = JSON.parse(data || '[]');
      this.setState({ todos });
    });
  };
```
> `AsyncStorage.getItem()` 함수를 사용하여 저장소에서 **todos** 데이터를 불러온다. 참고로 저장소(storage)에는 **String**만 저장 가능하다.

<br>

그리고 **App 컴포넌트**에서 다음 함수들을 수정한다.

```js
addTodo = (todo) => {
  const newTodo = {
    id: Date.now(),
    text: todo,
    completed: false,
  } 
  this.setState(prevState => {
    const todos = [
      newTodo,
      ...prevState.todos
    ];
    AsyncStorage.setItem("todos", JSON.stringify(todos));
    return { todos }
  });
}
```

```js
checkTodo = (id) => {
  this.setState(prevState => {
    const [ todo ] = prevState.todos.filter(e => e.id === id);
    todo.completed = !todo.completed;
    const todos = [
      ...prevState.todos
    ];
    AsyncStorage.setItem("todos", JSON.stringify(todos));
    return ({ todos })
  });
}
```

```js
removeTodo = (id) => {
  this.setState(prevState => {
    const index = prevState.todos.findIndex(e => e.id === id);
    prevState.todos.splice(index, 1);
    const todos = [
      ...prevState.todos
    ];
    AsyncStorage.setItem("todos", JSON.stringify(todos));
    return ({ todos })
  });
}
```
> 데이터가 변경될 때마다 `AsyncStorage.setItem()`를 호출하여 Storage에 데이터를 저장한다.

<br><br>

# 앱 빌드&배포하기

<hr>

마지막으로 앱을 빌드하고 배포하는 방법을 알아보자.

<br>

### app.json 수정하기

**app.json**를 수정하여 배포 환경을 설정한다. ios와 android의 package를 입력한다.

```json
{
  "expo": {
  
    // ... 생략 ...
    
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.yourcompany.yourappname"
    },
    "android": {
      "package": "com.yourcompany.yourappname"
    },
  }
}
```
> 패키지명은 고유해야한다. 기존에 존재하는 패키지명을 입력하면 앱 배포가 불가능하다. 패키지명으로 도메인을 많이 사용한다.

<br>

### exp 설치하기

앱을 빌드하고 배포하기 위해서 **exp**를 설치한다.

```bash
$ npm install -g exp
```

<br>

### 앱 빌드하기

안드로이드면 `exp build:android` , 아이폰이면 `exo build:ios` 를 입력한다. 그럼 각각 `.ipa` 파일과 `.apk` 파일이 생성된다.



우선 안드로이드앱을 빌드 해보자. `exp build:android`를 입력한다.

![](https://ipfs.busy.org/ipfs/QmVKFZfrikWmVqYSJ5fhZBNUJKHgY4cGPjVzoNgJJg9PcB)

>  Expo 계정이 없으면 *Make a new Expo account*를 선택하여 계정을 생성하자.

<br>

나도 계정이 없어서 아래와 같이 Expo 신규 계정을 생성하였다.

![](https://ipfs.busy.org/ipfs/QmRFqNCvZfweQiV9DbFWM217rm1DsHLzNxYKRTTFoaaXd4)

<br>다음은 인증서(keystore) 관련 내용이다. expo에서 알아서 하도록 하고 싶으면 1번을 선택한다. 하지만 기존 인증서로 앱을 서명하고 싶으면 2번을 선택한다. 

![](https://ipfs.busy.org/ipfs/QmXj58by1R2iqjGFna5Xdnt6cygG5veiBVxyj5URkS8VqV)

이제 우리가 구현한 코드가 expo 서버에 업로드되고 빌드되는 과정이다. 시간이 매우 오래 걸린다.

![](https://ipfs.busy.org/ipfs/QmQVTJW5kXX61KVTp5fWtReKWTd78vj1YWN3khSHaXFzUn)

조금 기다리면 아래와 같이 특정 URL을 알려준다.

![](https://ipfs.busy.org/ipfs/QmdusBPqSj3TR7c3PXU4dV3cvFWQTM6DDjzfYDyvcL9ktX)

알려준 URL(https://expo.io/builds/e95fc55b-9c4b-4938-9274-fe712ccc0de1) 을 접속하면 아래와 같은 페이지가 나타난다. 

![](https://ipfs.busy.org/ipfs/QmW8FSKs48QLR5sCQq3Hn4UVyYd5kuqCWBP8sB6Xk4TT8V)

`Android build` 가 **Queued** 에 등록되어 있는 것을 볼 수 있다. 아직은 빌드 대기 상태이다.

<br>이 페이지에서 조금 더 기다리면, 빌드되는 과정이 로그로 출력된다.

![](https://ipfs.busy.org/ipfs/QmYi39AUVkaBUddw7oieUManSfpyKLPkfHcNP8tPWLWEew)

빌드가 완료되면 아래 화면과 같이 `Download` 버튼이 활성화 된다. 이제 `Download` 버튼을 클릭하면  `.apk` 파일을 다운로드 받을 수 있다.

![](https://ipfs.busy.org/ipfs/QmXTmRGa8eRh9RoxEc6Fm3NbyqwFqcz3w8hTNn5XpkfAnG)


<br>

안드로이드폰은 그냥 `.apk` 파일을 스마트폰에 복사하여 설치하면 된다. 하지만 아이폰은 [Testflight](https://developer.apple.com/kr/testflight/)를 이용하여 스마트폰에 설치해야한다.

<br>

이제부터는 앱을 업데이트 하는 경우, 코드를 수정하고 그냥 **Publish**만 하면 된다. 그러면 수정 내용이 앱에 바로 반영된다. 마켓에 앱을 다시 배포하는 과정이 필요없기 때문에 매우 편하다.

![](https://ipfs.busy.org/ipfs/QmUtpDP1uWPVTstU7KfiG4JA6pXTjL5KT1DujxcDfmTaGo)

<br>

apk 파일은 드롭박스에서 다운받을 수 있습니다.
https://www.dropbox.com/s/y0ldnmkg7waj1je/todo-app-157f74bedd054b02bc59b03916513326-signed.apk?dl=0

그리고 모든 소스는 깃허브에 공개되어 있습니다. 
https://github.com/anpigon/react-native-todo-app

<br><center>* * *</center><br>

저도 expo를 통한 앱 빌드는 처음 해보았습니다. 매우 간단하네요. 저는 리액트 네이티브를 공부한지 약 3주 정도 되었습니다. 관심있는 분들과 같이 공부 할 수 있으면 좋겠습니다. 다음 강좌에서는 `redux`, `mobx`, `conetxt API` 사용 방법을 공부하고 포스팅 하도록 하겠습니다. 

<br>여기까지 읽어주셔서 감사합니다.


---

#####  <sub> **Sponsored ( Powered by [dclick](https://www.dclick.io) )** </sub>
[![dclick-imagead](https://steemitimages.com/0x0/https://cdn.steemitimages.com/DQmSwkE4cySARFCKdemZWVwyk8dxh7HeDNiqwuVmWR3RBXE/Group%205.png)](https://api.dclick.io/v1/c?x=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjIjoiYW5waWdvbiIsInMiOiJyZWFjdC1uYXRpdmUtdG9kby01LTE1NDQ2MjQ4MjI2NjkiLCJhIjpbImktMiJdLCJ1cmwiOiJodHRwczovL3d3dy5kY2xpY2suaW8iLCJpYXQiOjE1NDQ2MjQ4MjIsImV4cCI6MTg1OTk4NDgyMn0.DI6ZuFjeHeIB7rEZAL_ImzFX5oMCnSzMvhS7qyChhvk)
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,