이번 글에서는 간단한 UI를 적용해 보겠습니다.

 

React native 설치 및 프로젝트 세팅 방법은 앱 개발 - 01 을 참고하시기 바랍니다.

 

앱 개발 - 01 에서 생성한 firstApp 생성된 프로젝트가 있다고 가정한 상태로 설명하겠습니다. 프로젝트가 생성되지 않았다면 앱 개발 - 01를 참고해서 우선 프로젝트를 생성하고 다시 이 글로 돌아와 주세요.

 

이 글에서는 UI를 다룰 때 필요한 주요 기능을 예제를 통해 정리해 보겠습니다. 순서는 아래와 같습니다. 

 

  • React Native Elements 로 UI 구현
  • Layout 설정
  • React Native Navigation 사용하기
  • Popup 구현

React Native Elements 로 UI 구현

 

UI 객체 구현은 React Native Elements (이하 RNE) 을 사용했으며, 설정 절차와 사용 방법만 간단히 언급하겠습니다.

 

생성한 프로젝트의 root에서 RNE를 아래와 같이 설치해 주세요.

# react native elements를 설치합니다.
npm i react-native-elements --save

# vector icons을 설치합니다.
npm i --save react-native-vector-icons

# 사용하는 react native version은 0.61.5 버전이라 link 과정은 생략합니다.

 

처음으로 버튼을 화면에 하나 그려보겠습니다. 

 

App.js 파일을 열어 아래와 같이 고쳐보세요.

import React from 'react';

import {
  SafeAreaView,
} from 'react-native';

import { Button } from 'react-native-elements';

const App: () => React$Node = () => {
  return (
      <SafeAreaView>
         <Button title="Hello World!!" />
      </SafeAreaView>
  );
};

export default App;

SafeAreaView 키워드는 어떤 디바이스에서든 기본 화면 안쪽에 출력할 수 있는 영역을 의미합니다. 그 외 여러 키워드들이 앞으로 쓰여질텐데 이 글에서는 Interface를 사용하는데 필요한 부분만 설명을 하도록 하겠습니다. 그 외 키워드들은 공식 문서를 참고하시기 바랍니다.

 

실행하면 아래와 같은 결과를 볼 수 있습니다.

 

공식 문서 중 Customization 부분은 꼭 확인해 보시고 다음으로 넘어가세요.

 

Layout 설정

다음에는 화면을 1:1:2로 삼 분할 하고 중앙 레이어에 버튼을 넣어보겠습니다. 

 

일단 테스트 코드를 먼저 복사해서 테스트 해보시기 바랍니다. 

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

import { Button } from 'react-native-elements';

const App: () => React$Node = () => {
  return (
      <SafeAreaView style={{marginTop : 50, flex: 1}}> // (1)
        <View style={{flex: 1, backgroundColor:'#EE2C38'}}>  // (2-1)
        </View>

        <View style={{flex: 1, backgroundColor:'#FAA030'}}>  // (2-2)
          <Button raised title="Hello World!!" /> 
        </View>

        <View style={{flex: 2, backgroundColor:'#32B76C'}} /> // (2-3)
      </SafeAreaView>
  );
};

export default App;

flex는 아이템을 어떻게 화면을 채울지를 결정하는 키워드입니다. 값은 화면의 비율을 설정합니다. 2-1/2/3을 보면, 같은 depth에 세 개의 flex가 있고 각각이 1, 1, 2 라고 설정되어 있다면 해당 영역을 1:1:2의 화면 비율로 나누겠다는 설정입니다.

 

레이아웃에 대한 보다 상세 내용은 이 링크 를 참고하세요.

 

화면 레이아웃을 잡아 봤으니 이제 페이징 처리를 해보겠습니다. 

 

React Native Navigation 사용하기

모바일은 보통 단일 화면으로 구성되기 때문에, React Native 에서는 화면 전환을 위해 React Native Navigation이라는 모듈을 주로 사용합니다. 

 

우선 필요한 모듈을 설치합니다. 

npm install @react-navigation/native @react-navigation/stack

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

# ios일 경우 cocoapods로 필요한 라이브러리를 설치해야 합니다.
cd ios
pods install
cd ..

추가 모듈을 설치할 때 에뮬레이터는 끄고 설치 후 재실해 하시기 바랍니다. 

 

App.js에 아래 코드를 복사한 후 재실행 해보시기 바랍니다. 

import 'react-native-gesture-handler';
import * as React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import {
  SafeAreaView,
  View,
  Text
} from 'react-native';
import { Button } from 'react-native-elements';

const Stack = createStackNavigator();

const App: () => React$Node = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{title: 'Welcome'}}
        />
        <Stack.Screen name="Second" component={SecondScreen} options={{title: 'SecondPage'}}/>
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;

function HomeScreen({navigation}) {
  return (
    <Button
      title="Go to Second Page"
      onPress={() => navigation.navigate('Second', {name: 'Parameter_1'})}
    />
  );
}

function SecondScreen({navigation}, param) {
  return (
    <SafeAreaView style={{marginTop:50, flex:1}}>
      <View style={{flex:2}} />
      <View style={{flex:2}} />
      <View style={{flex:1, justifyContent:'flex-end'}}>
        <Button title="Back"  onPress={() => navigation.goBack()} />
      </View>
    </SafeAreaView>
  );
}

 

우선 App 코드를 NavigationContainer로 전체를 감쌉니다. 그리고 Stack.Navigator 안에 사용할 스크린 화면 내용을 정의 합니다. 

 

Stack.Screen의 속성 중 name은 코드에서 지정자처럼 사용할 이름이며, component는 해당 화면에 대한 모듈명을, option의 title에는 각 페이지의 타이틀 명으로 사용됩니다. option에 대한 상세 정보는 이 링크를 참고하세요.

 

마지막 두 개의 함수는 세부 화면을 정의한 코드입니다. 

 

Popup 구현

이 예제에서는 이전에 다루지 않은 몇 가지 중요 개념이 나오기 때문에 우선 샘플 코드(원본 링크)로 테스트를 해 보시고 아래 설명을 읽어보시기 바랍니다.

import React, { Component } from 'react';
import {
  Modal,
  View,
  Text,
  TouchableHighlight,
  StyleSheet
} from 'react-native';
import { Button } from 'react-native-elements';

testModalVisible = false;

const App: () => React$Node = () => {
  return (
    <ModalExample />
  )
}
export default App;

class ModalExample extends Component {
  state = {
    modalVisible: false
  }
  toggleModal(visible) {
      this.setState({ modalVisible: visible });
  }
  render() {
    return (
       <View style = {styles.container}>
          <Modal animationType = {"slide"} transparent = {false}
             visible = {this.state.modalVisible}
             onRequestClose = {() => { console.log("Modal has been closed.") } }>
             
             <View style = {styles.modal}>
                <Text style = {styles.text}>Modal is open!</Text>
                
                <TouchableHighlight onPress = {() => {
                   this.toggleModal(!this.state.modalVisible)}}>
                   
                   <Text style = {styles.text}>Close Modal</Text>
                </TouchableHighlight>
             </View>
          </Modal>
          
          <TouchableHighlight onPress = {() => {this.toggleModal(true)}}>
             <Text style = {styles.text}>Open Modal</Text>
          </TouchableHighlight>
       </View>
    )
  }
}

const styles = StyleSheet.create ({
   container: {
      alignItems: 'center',
      backgroundColor: '#ede3f2',
      padding: 100
   },
   modal: {
      flex: 1,
      alignItems: 'center',
      backgroundColor: '#f7021a',
      padding: 100
   },
   text: {
      color: '#3f2949',
      marginTop: 10
   }
})

 

React 공식 페이지에는 "A JavaScript library for building user interfaces"라는 문구가 있습니다. 그리고 중앙에 "Component-Based"라는 문구가 떡 하니...!

 

위 예제의 정확한 이해를 위해 Component와 state 그리고 props에 대한 정확한 이해가 필요한데, 예제 중심의 이 글에서 이들을 설명하기는 너무 길어지기 때문에 제가 찾았던 글들 중 가장 잘 설명이 되어 있다고 생각하는 링크들를 아래에 기록했으니 여러분도 꼭 읽어보시기 바랍니다. 

 

절대 설명하기 귀찮아서 그런건 아니...

 

지금까지 React-Native 에 필요한 UI 중요 요소 네 가지를 예제로 알아보았습니다. 

 

다음은 유용한 UI 객체들을 살펴보겠습니다.

React Native는(이하 RN) React를 이용해 Android와 iOS 네이티브 앱을 개발할 수 있는 Framework이며 2020년 2월 현재 0.61 버전입니다. 버전이 1이 안되는데도 불구하고 많은 개발사들이 사용하는걸 보면 Facebook에서 지속적으로 발전시키고 있다는 의미일 겁니다. 

 

이 글은 아래와 같은 내용을 담고 있습니다. 

 

  • 필요한 개발 툴들 
  • React Native CLI 로 프로젝트 생성하기
  • 앱 실행 해보기

필요한 개발 툴들 

본격적으로 알아보기 전에 먼저 설치해야 할 개발툴들이 있습니다. 이를 알아보고 진행해 보겠습니다.

 

Node.js : React는 Javascript Runtime인 Node.js를 사용합니다. 

 

npm : Node.js의 패키지를 관리하는 툴입니다.

 

React Native CLI : React native 앱을 빌드하고 실행하는데 필요한 툴입니다.

 

Watchman : MacOS에서 어떤 파일의 변화를 감지하는데 사용하기 위해 Facebook에서 개발한 툴입니다.

 

Native SDKs :XCodeAndroid Studio 들은 네이티브 앱 빌드를 위해 필요한 SDK입니다.

 

CocoaPods : Swift  Objective-C 코코아 프로젝트의 종속성 관리자입니다. RN으로 프로젝트를 initialize할 때 CocoaPods가 설치되어 있으면 Android와 iOS빌드에 필요한 종속된 라이브러리들을 초기화해 주며, 추후에도 필요한 라이브러리들을 관리할 때 지속적으로 사용됩니다. 

 

(* react-native init project_name으로 실행하면 위와 같은 iOS, Android 빌드에 대한 설정 후 실행 방법을 안내해 줍니다.)

 

React Native CLI 로 프로젝트 생성하기

React Native 프로젝트를 세팅하고 관리하는데 사용합니다. 터미널을 열어 아래 명령을 실행하여 설치할 수 있습니다. 

npm install -g react-native-cli

이후 설치가 잘 되었는지 아래와 같이 테스트 해보세요.

react-native --version

##output
react-native-cli: 2.0.1

 

이제 샘플 프로젝트를 생성해 보겠습니다. 

react-native init firstApp

 

생성된 프로젝트 주요 파일들 중 알고 가야할 내용을 살펴보겠습니다.

 

index.js : 기기 혹은 시뮬레이터에서 첫 번째로 호출하는 entry point이며, App.js를 호출하게 됩니다.

 

app.json : index.js에서 호출되며 앱의 이름을 정의하는데 사용합니다. 

 

App.js : 모바일 디바이스 화면에 출력되는 첫 번째 파일입니다. 

 

android/ : 안드로이드 앱을 위한 코드와 관련 파일들이 포함되어 있습니다. 

 

ios/ : ios 앱을 위한 코드와 관련 파일들이 포함되어 있습니다. 

 

 

앱 실행 해보기

Mac에서 iOS이라면 간단히 빌드/실행 할 수 있습니다.

react-native run-ios

# 이와 같이 시뮬레이션 할 디바이스를 선택해서 실행 가능하다.
react-native run-ios --simulator="iPad Pro"

# 아래 명령으로 테스트 가능한 디바이스 정보를 확인할 수 있다.
xcrun simctl list devices

Android 를 위한 빌드/실행을 위해 Android Studio 가 설치되어 있어야 합니다. 안드로이드 에뮬레이터 실행을 위해서는 $ANDROID_HOME 이라는 path가 설정되어 있는지 확인합니다. 

echo $ANDROID_HOME

# 만약 등록되어 있지 않다면 자신의 계정 홈 디렉토리로 가서 
cd $HOME

# ANDROID_HOME과 추가 path를 등록합니다. 
vi .bash_prifile

# 아래 내용을 복사하여 추가하세요.
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

# 저장 후 콘솔에서 $ANDROID_HOME가 정상적으로 출력되는지 확인 하시면 됩니다.

위 내용이 확인되었다면 이제 android 애뮬레이터를 실행할 수 있습니다.

react-native run-android

 

이제 개발을 시작할 준비가 모두 마무리 되었습니다. 

 

다음에는 실제 앱 개발에 도움이 될 수 있는 모듈들을 하나씩 적용해 보겠습니다.

최근 본격적으로 AWS에 서비스를 구축하면서 자잘하게 부딪혔던 작은 문제들을 정리하는 김에 저처럼 처음 접해보시는 분들께 도움이 되길 바라며 공개해 봅니다.

 

앞으로 몇 번에 걸쳐 간단한 샘플을 만들어보면서 실제 서비스 인프라를 구축하기 위해 어떤 과정들이 필요한지 하나씩 정리해 보겠습니다.

 

이번에 제작할 샘플은 REST API를 통해 Redis에 정보를 저장하는 과정을 만들어 보겠습니다. 

 

서비스는 아래와 같이 구성해 보겠습니다.

 

 

작업은 크게 네 단계로 진행합니다. 

 

1. VPC 구성하기

2. Redis 구성하기

3. Lambda 함수 제작

4. API Gateway 구성하기

 

따라하기 식으로 구성했으니 편하게 진행해 보시기 바랍니다. 바로 시작해 보겠습니다. 

 

1. VPC(Virtual Private Cloud) 구성하기

중요한 정보를 저장하는 저장소이므로 VPC를 구성하여 외부의 무분별한 접근을 차단하도록 하겠습니다. (2013년부터 AWS에 구축되는 모든 인프라는 VPC안에 구축되도록 강제되고 있습니다. 필수 과정이니 가능한 상세하게 짚고 넘어가도록 하겠습니다.) 이 과정에서는 VPC를 구성하고 서브넷(VPC 내부에서 서비스 목적에 따라 IP 범위를 나누어 구분하기 위한 설정), 보안 설정을 하게 됩니다. Redis를 외부에서 직접 접근하지 못하게 막아야 하므로 Public IP나 Elastic IP를 사용하지 않고 Private IP로만 설정하겠습니다. (public ip를 할당할 수는 없습니다. ^^a)

 

1-1. VPC 생성하기

마법사로 생성하지 않고 필요한 과정 전부를 직접 만들면서 진행하겠습니다.

 

우선 VPC 탭에서 "VPC 생성" 버튼을 누릅니다. "이름 태크"에는 "test-vpc"로 명명하겠습니다. 

IPv4 CIDR(Classless Inter-Domain Routing) 블록에는 VPC 안에서 사용할 주소 범위를 지정해야 합니다. 세 개의 subnet으로 관리해야 한다는 가정으로 설정하겠습니다. "192.168.0.0/16"으로 입력합니다. IPv6 블록은 없음으로 하겠습니다.

 

VPC와 함께 기본적으로 "라우팅 테이블"(Routing Table-라우터가 이를 사용해 최적의 경로를 결정하고 패킷을 전송합니다.), "네트워크 ACL"(Access Control List-오고 가는 패킷을 분석하여 정해진 규칙에 따라 패킷을 전송/차단합니다.)에 새로 생성한 VPC를 위한 항목이 자동 생성됩니다. 

 

1-2. 서브넷 설정

다음으로 서브넷(Subnet-네트워크 영역을 분리)을 생성해 보겠습니다.

 

DB, Service, Management 영역으로 구분하겠습니다. 그럼 아래와 같은 구조를 가지게 될겁니다. 

 

[db 영역]

CIDR 블럭 : 192.168.10.0/24

가용 ip 대역 : 192.168.10.4 ~ 192.168.10.253 (251개)

 

[Service 영역]

CIDR 블럭 : 192.168.20.0/24

가용 ip 대역 : 192.168.20.4 ~ 192.168.20.253(251개)

 

[Management 영역]

CIDR 블럭 : 192.168.30.0/24

가용 ip 대역 : 192.168.30.4 ~ 192.168.30.253(251개)

 

더보기

AWS는 가용 ip 대역 중 처음 4개 IP주소와 마지막 1개 IP주소를 예약하여 사용합니다.

첫 번째 ip는 subnet id, 마지막 한 개는 broadcast addr, 그리고 두 번째에서 네 번째 ip는 NAT Gateway로 활용됩니다.

(이에 대해서는 https://aws.amazon.com/ko/vpc/faqs/ 에서 찾을 수 있었으며, 5개의 ip는 AWS에의해 예약되었기 때문에, 사용자가 사용할 수 없다고 나와 있으나 각각이 정확히 무엇에 활용되는지에 대한 내용은 찾을 수 없었습니다. 알게 되면 글을 수정해 두겠습니다.)

 

서브넷 영역을 어떻게 사용할지 계획을 세웠으니, 실제로 생성해 보겠습니다.

서브넷 생성화 화면 에서 "이름 태크"에는 영역별로 알맞은 이름을 넣어주세요. "test-vpc-subnet-"을 prefix로 두고 영역별 이름을 db, service, management로 명명해 보겠습니다. 

 

IPv4 CIDR 블럭은 위에 정리했던 내용대로 입력하시면 됩니다. 가용 영역을 선택하지 않으면 AWS가 알아서 설정하게 됩니다.

 

이제 서브넷 설정을 모두 마치면 아래와 같은 결과를 보실 수 있습니다. 

 

 

2. Redis 구성하기

이번에는 Redis를 구성하기 위해서 ElastiCache로 가보겠습니다. 확장성과 안정성을 고려해 Cluster 모드로 설정하겠으나 테스트 용도이니 가장 저렴한 노드로 구성하겠습니다.

 

2-1. Redis 생성하기

 

이름을 "test-redis"로 입력하고 노드 유형을 "cache.t3.small"로 지정하겠습니다. 샤드 당 복제본도 기본설정 2에서 1로 조정했습니다. 

 

그리고 서브넷 그룹에서 "새로 생성"을 선택하고, test-vpc를 위한 그룹을 "test-vpc-group"로 생성합니다. 서브넷은 위에서 "test-vpc-subnet-db" 라고 명명한 서브넷을 선택합니다.

 

나머지는 기본 값으로 두고 생성을 완료합니다. 생성 완료까지는 약 5분 ~ 10분 정도 소요됩니다. 

 

2-2. redis-cli로 Redis 접속해보기

현재 생성된 Redis는 VPC안에 생성되어 있으며, 설정된 보안 그룹에서 inbound에 예외처리를 하지 않아 직접 접근할 수 없는 상태입니다. 또한 RDS와 달리 ElastiCache는 AWS 외부에서 접속 할 수 없도록 되어 있습니다. 이를 위해 ElastiCache-Redis가 설정된 VPC 내부에 EC2를 추가하여 접근해 Redis로 접속할 수 있습니다. 

 

그럼 EC2를 생성, 원격접속하여 redis-cli를 설치 후 Redis로 접속을 시도해 보겠습니다.

 

EC2 생성 과정은 간단히 텍스트로 정리하겠습니다. 

 

1) "Amazon Linux 2 AMI (HVM), SSD Volume Type" 선택

2) "t2.micro" 선택 

3) 인스턴스 구성에서 ..

   3-1. 네트웍크에서 test-vpc 선택

   3-2. 서브넷은 test-vpc-subnet-management 선택

4) 스토리지 추가 , 태그 추가 - 기본 설정

5) 보안 그룹 구성 -> 기존 보안 그룹 선택 -> test-vpc 보안 그룹 선택

6) "검토 및 시작" -> "시작하기" 버튼 선택

7) 기존 키 페어 선택 또는 새 키 페어 생성 -> "새 키 페어 생성" -> "키 페어 이름"에 "test-vpc-key-pair" 입력 -> "키 페어 다운로드" 선택 (다운로드된 키 페어는 EC2에 원격접속할 때 사용됩니다.)

8) "인스턴스 시작" 선택

 

이제 EC2로 접속하여 Redis로 연결해보겠습니다. 외부에서의 접속을 위해 public ip와 라우팅 설정을 추가하겠습니다. 

 

우선 생성된 인스턴스 상태를 살펴보겠습니다. 

 

현재는 public dns가 설정되지 않은 걸 확인 할 수 있습니다.

 

이제 VPC로 다시 가서 "인터넷 게이트웨이"를 선택 후 "인터넷 게이트웨이 생성"을 누르고 생성을 시도합니다. name tag에는 "igw-test-vpc-management"라고 명명합니다. 생성 직후에는 상태가 "detached"로 되어 있습니다. 이제 생성한 igw를 선택 후 "작업" -> "VPC에 연결"을 선택합니다. 그리고 "test-vpc"에 연결합니다. 

 

그리고 EC2 화면에서 생성한 인스턴스를 선택 후 하단 "설명"탭의 "서브넷 ID"를 선택하면 VPC 화면으로 전환됩니다. 이후 하단의 "라우팅 테이블"탭을 선택하고 하단의 "서브넷 연결"을 선택, "서브넷 연결 편집"을 선택 후 "test-vpc-subnet-management" 서브넷을 선택 후 "저장"하세요. 그리고 "작업" 버튼에서 "라우팅 편집"을 선택하고 "라우팅 추가" 버튼을 눌러 라우팅 정보를 추가합니다. 

각 대상에는 "0.0.0.0/0"를 입력하고 "igw-test-vpc-management"를 찾아 선택합니다. 그리고 다시 인스턴스 설정 화면을 돌아옵니다.

 

다음으로 외부에서 접속할 수 있는 public ip를 elastic ip 탭에서 할당해 보겠습니다.

 

"탄력적 IP"라는 메뉴를 선택한 후 "탄력적 IP 주소 할당" 버튼을 선택하여 퍼블릭 주소를 하나 할당합니다. 그리고 "Actions" 버튼을 눌러 "탄력적 IP 주소 연결"을 선택한 후 생성한 인스턴스에 연결해 줍니다.

다시 인스턴스 정보 화면으로 넘어가면 생성한 IP가 public ip에 세팅된 것을 확인할 수 있습니다. 혹시 "퍼블릭 DNS"에 할당된 정보가 없다면 VPC에서 "DNS 호스트 이름"을 활성화하여 저장하면 됩니다.

마지막으로 보안 그룹에서 SSH 포트(22)에 대한 인바운드 규칙을 추가하겠습니다.

 

이제 SSH를 사용하여 인스턴스에 연결해 보겠습니다.

 

위에서 다운받은 ppm(Privacy Enhanced Mail)파일을 그대로 사용할 수 있으며, putty 혹은 ssh client에서 사용하려면 ppk(Putty Privite key) 파일로 변경해야 하는데 이에 대해서는 여기서 상세히 다루지는 않겠습니다.

ssh -i your_pem_file ec2-user@ec2_public_dns 형태로 접속을 시도하면 됩니다. 

 

더보기

"WARNING: UNPROTECTED PRIVATE KEY FILE!" 에러가 발생한 적이 있는데 windows에서는 이상하게 다운받은 c:\Users\내계정명\Downloads에서는 문제 없는데, 다른 드라이브로 옮겨서 테스트 했을 때는 이 에러가 발생했었습니다. 에러 내용은 해당 파일에 접근할 수 있는 권한이 너무 많이 열려 있다는 내용인데, 저와 같은 현상이 발생하는건 애매하네요 -_-a

 

이제 redis-cli를 설치해서 접속해 보겠습니다.

 

우선 gcc가 없다면 먼저 설치해 주세요.

sudo yum install -y gcc

그리고 redis를 다운받아 설치합니다. 

sudo wget http://download.redis.io/redis-stable.tar.gz

sudo tar xvzf redis-stable.tar.gz 

cd redis-stable 

make distclean; make MALLOC=libc; make

sudo cp src/redis-cli /usr/bin/

생성된 Redis를 선택해서 아래 정보를 보시면 기본 엔드포인트가 비어 있는 걸 확인할 수 있습니다.

이는 위에서 클러스터 모드로 설정했기 때문인데, 클러스터 이름을 선택하여 아무 샤드나 선택하여 들어간 후 내부 노드 하나를 선택하면 엔드포인트가 있습니다. (클러스터 모드가 아닌 경우 기본 엔드포인트를 바로 확인할 수 있습니다.)

 

이 엔드포인트를 복사해서 아래와 같이 접속하면 정상적으로 접근 가능합니다. 

redis-cli -h your_redis_node_endpoint

이제 저장소에 대한 설정이 마무리되었습니다. 다음으로는 서비스 영역을 제작할 차례입니다.

3. Lambda 함수 제작

Redis Cluster에 점수를 기록하는 함수를 제작해 보겠습니다.

 

우선 nodejs를 사용해 setScore라는 이름의 람다 함수를 하나 만듭니다.

 

ioredis module이 필요하기 때문에 실제 필요한 코드와 module은 zip으로 압축해서 올려야 합니다. 로컬에서 폴더를 만들어 모듈을 설치하고, index.js 파일에 아래 소스를 붙여 넣으세요.

 

npm install ioredis
// index.js

'use strict';
var Redis = require('ioredis');

exports.handler = (event, context, callback) => {
    var client = new Redis.Cluster([
        { 
            host: "your_redis_endpoint_1",	
            port: 6379
        },
        { 
            host: "your_redis_endpoint_2",
            port: 6379
        }
    ]);

   var key = event.id;
   var score = event.score;
   client.set(key, {"score": score}, (err, ret) => {
        if(err)
            console.info("err = ", err);
        else
            console.info("ret = ", ret);
        client.quit(()=> {
            callback(err, {body:  "Result : " + ret});    
        });
    })  
}

그리고 해당 폴더의 내용을 zip으로 압축 후 "업로드", 그리고 해당 함수를 저장합니다.

redis 주소는 위에서 생성한 세 노드 모두 입력해 두시면, 추후 특정 노드에서 문제 발생 시 별도 처리 없이 즉각 대응 가능합니다. 아래와 같이 설정된 redis 주소를 입력해 두시기 바랍니다. 

이제 이 함수가 Redis가 있는 VPC에 접근할 수 있도록 허용해야 합니다.

 

IAM에서 "역할" -> "역할 만들기"를 선택합니다.

그리고 Lambda를 선택 후 "AWSLambdaVPCAccessExecutionRole"역할을 선택합니다.

그리고 역할 이름을 "lambda-vpc-execution-role"로 입력하여 할당한 후 람다 함수로 돌아가 하단의 "실행 역할"에서 "lambda-vpc-execution-role"를 선택합니다. 

 

그리고 하단의 VPC 항목으로 가서 "test-vpc"를 선택하고 서브넷 항목에 db, management 서브넷을 선택합니다. 보안 그룹은 default를 선택한 후 람다 함수를 저장합니다.

이제 잘 작동하는지 테스트 해보겠습니다.

위와 같이 설정 후 테스트를 시도하면 아래와 결과를 확인할 수 있습니다.

ssh로 접속해서 잘 입력되었는지 확인 해보세요. :)

 

4. API Gateway 구성하기

REST API로 선택, "새 API" 선택, API 이름에는 "leaderboard"라는 이름으로 입력하겠습니다.

 

"leaderboard"API 화면에서 리소스를 생성하고, 리소스 이름은 "put-score"로 지정하세요.

 

그리고 메서드를 "POST"로 생성합니다.

그리고 "Lambda 함수"를 선택 후 위에서 생성한 "setScore" 람다 함수를 지정합니다.

 

이제 생성한 리소스를 배포할 차례입니다. "작업" 버튼을 눌러 "API 배포"를 선택하고 "배포 스테이지"에서 "새 스테이지"를  선택 후 "스테이지 이름"에는 "prod"라고 입력합니다. 

이제 스테이지로 가면 호출할 수 있는 URL을 확인 할 수 있습니다. curl을 이용해서 정상 작동하는지 확인해 보겠습니다.

curl -L -v -d "{\"id\": \"test_id2\", \"score\" : 1000}" -H "Accept: application/json" -H "Content-Type: application/json" path_your_url

 

수고하셨습니다. 최종 테스트를 한번에 잘 완료되셨길 바랍니다. 

 

"따라하기" 처럼 해볼 수 있도록 정리해 봤는데 도움이 되었나 모르겠네요. 어쨌든 나중에 까먹으면 다시 보려고 정리를 시작한 글인데 생각보다 꽤 오래 걸렸네요. 

 

무사히 잘 마치셨길 바라며 다음에는 DynamoDB 사용하면서 정리한 글로 다시 뵙겠습니다. :)

 

 

 

 

이전에서는 LED를 주기적으로 깜밖이는 것만 했었다. 이번에는 두가지를 복합적으로 해봐야겠다. 


이거 다음엔 바로 인터넷 라디오로 간다. -0-a


일단 오늘의 보드는 아래와 같이 설정한다.




LED : 11번 핀에서 입력을 받아 330옴 저항을 통해 LED의 긴다리(+)로 연결되고 짧은다리(-)에서 GND로 나간다. 


YELLOW BUTTON : 3.3V로 전원이 들어가고 10K옴을 통해 버튼으로 들어간다. 위 그림에서 위 오른쪽 다리 방향으로 GND로 이어지고, 버튼의 입력은 18번 핀으로 받도록 설정했다. 


Raspberry pi2 이름로 각 핀의 wiringpi 번호는 아래와 같다. 



개발 목표는 버튼을 누르면 10초간 LED가 켜지고, 지정한 사운드를 출력하도록 한다. 출력 중 입력이 다시 들어오면 기존의 사운드를 중지하고 다시 출력하도록 하자. 


코드는 아래와 같다. 

#include <stdio.h>

#include <stdlib.h>

#include <wiringPi.h>


int main (void)

{

  int SWITCH = 5; //  pin 18

  int LED = 0; // pin 11

  int sndPID = 0;

  

  if(-1 == wiringPiSetup())

    return 1;

  pinMode( SWITCH, INPUT); // 버튼의 입력을 받는다.

  pinMode (LED, OUTPUT) ;  // LED에 신호를 보낸다.


  for (;;)

  {

    digitalWrite (LED, 0) ;

    if( digitalRead(SWITCH) == 0)

    {

       digitalWrite (LED, 1) ;

       sndPID = fork();

       if(sndPID == 0)

       {

          // 사운드 출력에는 mplayer를 사용한다. 기존에 출력 중이라면 중지시킨다.

          system("killall mplayer");

          execlp("/usr/bin/mplayer", " ", "/home/pi/media/sound/dragon.wav", NULL);  

       }


       delay(10000); // ms. 10초간 불을 켜둔다.

    }

  }

  return 0 ;

}


mplayer 설치법은 여기 를 참고하길 바란다.


테스트 사운드는 아이가 가지고 노는 요괴워치 중 하나를 녹음 한거라 음질이 엄청 나쁘니 양해 바란다. ^^a





이상. 다음은 인터넷 라디오 프로토타입으로 하단의 "인터넷 라디오" 카테고리에 업데이트 됩니다. ^^

'개발 이야기 > RaspberryPi' 카테고리의 다른 글

버튼으로 LED, Sound 처리하기  (0) 2015.05.01
blink 샘플 실행  (0) 2015.04.29
기본적이지만 중요 정보 몇가지  (0) 2015.04.18
드디어 왔다!!  (0) 2015.04.17

gpio의 helloworld 예제인 블링크를 wiringPi를 이용해 샘플을 실행해 봤다.


일단 wiringPi lib 설치부터... 아래와 같다. 


설치


1. git 설치

sudo apt-get install git-core


2. wiringPi 프로젝트 다운

git clone git://git.drogon.net/wiringPi


3. build

clone한 위치에 wiringPi안에 들어가서 ./build 실행.

빌드가 이상없이 되었다면 "find / -name "gpio"를 실행해 보자. 

"/usr/local/bin"과 방금 빌드한 곳, 두 곳에 gpio를 발견할 수 있다.

빌드한 곳 gpio 폴더 안에서 ./gpio -v 한 결과와, 

gpio -v 한 결과가 다르다면 gpio 파일을 "/usr/local/bin"에 복사해주라. 

build하면 복사될 줄 알았는데 안된 듯. pi2라서 gpio old version에서 제대로 인식을 못해서 한참 원인을 찾다보니 이거였어.


4. raspberryPi의 핀 번호 및 역할 보기

gpio를 활용하면 보드에 핀 번호를 어떻게 보는지 쉽게 알 수 있다.

"gpio readall" 을 해보면 아래와 같은 결과를 볼 수 있다.     

보드에는 두 줄의 핀이 있는데 rapberryPi2는 위와 같은 순서로 구성되어 있다. 위 표 중앙에 Physical 부분이 보드의 핀 순서와 일치한다. (1,2번이 보드의 전원램프 쪽. 39,40이 usb가 위치한쪽)

Physical을 중심으로 양쪽의 컬럼명이 일치하는 것을 볼 수 있다. (노란색 라인을 참고할 것!)

각 컬럼의 정보는 다음과 같다. 

 BCM 

 Broadcom의 BCM2835 칩에서 사용하는 핀번호

 wPi 

 WiringPi 라이브러리의 핀번호

 Name 

 GPIO의 이름

 Mode 

 IN - 입력모드 ,  OUT - 출력모드

 V

 핀의 값. 1 - 전압이 High상태, 0 - Low상태

 Physical

 핀헤더의 번호

붉은색 라인 부분을 보자.

wiringPi의 blink 샘플을 보면 pin값을 0으로 사용한다. wiringPi에서 0은 wPi가 0인 것이며, 핀헤더 번호는 11번, 핀의 위치는 전원램프 쪽에서 6번째에 위치하다는 걸 알 수 있다. 

이제 샘플 코드를 보자. 


5. 샘플 코드

#include <wiringPi.h>

int main (void)

{

  int PIN = 0;

  wiringPiSetup () ;

  pinMode (PIN, OUTPUT) ;

  int max_count = 5;

  int cnt = 0;

  for (;;)

  {

    digitalWrite (PIN, HIGH) ;

    delay (500) ;

    digitalWrite (PIN,  LOW) ;

    delay (500) ;

    ++cnt;

    if(cnt>=max_count)

        break;

  }

  return 0 ;

}

기존의 샘플 코드에서 LED의 깜밖임이 5번 반복 후 종료하도록 수정했다. PIN변수는 wPi값을 의미한다. 


빌드는 아래와 같이 하면된다.

gcc -o blink blink.c -l:libwiringPi.so.2.25 -I/usr/local/include -L/usr/local/lib

어떤 샘플에서 lib 링크할 때 -lwiringPi 로 되어 있는데 libwiringPi.so 를 링크하겠다는 이야기다. 
새로 받아 빌드한 경우 버전명이 lib 끝에 붙는데 이를 정확히 사용하기 위해서는 위와 같이 입력하면 된다

6. 실행
./blink를 실행해보자. 아래와 같은 결과를 볼 수 있다.




'개발 이야기 > RaspberryPi' 카테고리의 다른 글

버튼으로 LED, Sound 처리하기  (0) 2015.05.01
blink 샘플 실행  (0) 2015.04.29
기본적이지만 중요 정보 몇가지  (0) 2015.04.18
드디어 왔다!!  (0) 2015.04.17

+ Recent posts