React Native를 위한 안드로이드 설정하기

맥북에서 안드로이드 스튜디오를 이용해 안드로이드 시뮬레이터를 열기까지의 과정을 정리한다.

1. node와 watchman 설치

리액트 네이티브를 위해 노드가 필요하다. 또한 watchman은 페이스북에서 만든 파일시스템의 변경사항을 추적할 수 있는 툴이다. 더 나은 퍼포먼스를 위해서 설치하는 것은 매우 추천한다고 한다.

1
2
brew install node
brew install watchman

2. JDK 설치

맥을 사용한다면 brew를 통해 JDK를 설치할 수 있으며 오라클JDK 또는 OpenJDK를 설치하면 된다. 본 정리에서는 OpenJDK8을 설치한다.

1
2
brew tap AdoptOpenJDK/openjdk
brew cask install adoptopenjdk8

사실 먼저 9버전을 설치하고 시뮬레이터를 사용하려고 했는데 알 수 없는 에러로 인해서 실패했다. JDK 버전을 8로 내렸더니 문제 없이 사용할 수 있었다.

3. 안드로이드 개발 환경 설정

3-1. 안드로이드 스튜디오 설치

안드로이드 스튜디오를 설치하고 SDK 및 AVD를 설치해주어야 한다. 안드로이드 스튜디오 설치 시에 custom 옵션을 통해 아래의 네 가지 옵션을 체크해주어야 한다.

  • Android SDK
  • Android SDK Platform
  • Performance (Intel ® HAXM) (See here for AMD)
  • Android Virtual Device

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

기본적으로 안드로이드 스튜디오를 설치할때 가장 최신 버전의 안드로이드 SDK를 설치하게 된다. 하지만 리액트 네이티브 앱을 빌드하기 위해서 안드로이드 9(Pie) 버전의 SDK가 필요하다. 다른 버전의 안드로이드 SDK가 필요하다면 SDK Manager를 통해 설치할 수 있다.

아래의 SDK를 설치한다. 만약 Intel x86과 같은 옵션이 보이지 않는다면 Show Package Details 을 눌러서 디테일 페이지를 살펴보면 된다.

  • Android SDK Platform 28
  • Intel x86 Atom_64 System Image

3-3. ANDROID_HOME 경로 지정하기

안드로이드에 관련된 경로를 PATH에 추가해주어야 한다. 본인이 사용중인 쉘의 설정파일에 등록하자.

1
2
3
4
5
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

3-4. 시뮬레이터 설정

시뮬레이터로 사용하고자 하는 디바이스를 추가한다.


4. 마무리

새로운 리액트 네이티브 프로젝트를 생성하고 시뮬레이터를 사용할 수 있다.

1
2
3
4
5
# 리액트 네이티브 프로젝트 생성
npx react-native-cli init sampleProj

cd sampleProj
npx react-native run-android # 안드로이드 오픈

[참고]
https://facebook.github.io/react-native/docs/getting-started.html#android-development-environment
https://findstar.pe.kr/2019/01/20/install-openjdk-by-homebrew/
https://dev-yakuza.github.io/ko/react-native/install-on-mac/#jdk-%EC%84%A4%EC%B9%98

Share

[파이썬]제너레이터와 코루틴

코루틴은 제너레이터를 이용해서 만들 수 있기 때문에 제너레이터와 매우 유사하다. 큰 차이점으로는,

  • 제너레이터는 데이터를 생산
  • 코루틴은 생산과 소비 둘 다 가능

하다는 것이다.

특징

코루틴은 싱글 스레드 안에서 동시성을 구현하기 위해 사용된다고 한다. 그렇기 때문에 CPU의 컨텍스트 스위칭이 일어나지 않으며 코루틴 스케쥴링 작업의 스케쥴링 오버헤드가 매우 적다.

asycio와 같이 동시성을 필요로하는 파이썬 패키지들에서 많이 사용되고 있다고 한다.

코루틴의 간단한 예제를 보자.

1
2
3
4
def coroutine1():
print('coroutine start')
num = yield
print('coroutine end, value:', num)

제너레이터에서 봐왔던 패턴이랑은 조금 다른 것을 알 수 있다. num 변수는 외부로부터 들어오는 값이고 아래의 print를 이용해 값을 출력했다. 만약 외부에 값을 생성하고 외부로부터 값을 받고 싶다면 아래와 같이 하면 된다.

1
2
3
4
def coroutine2():
print('coroutine start')
num = yield 'Coroutine!!!'
print('coroutine end, value:', num)

먼저 외부로 값을 생성하고, 다음 루틴을 기다린다. 즉, ‘Coroutine!!!’ 이라는 문자열을 외부로 먼저 생성한 뒤 값이 num으로 들어 오기를 기다린다는 것이다. 외부에서 코루틴으로 값을 보내고 싶다면 아래와 같이 한다.

1
2
3
a = coroutine2()
next(a)
a.send(123) # 메인 루틴에서 코루틴으로 값 주입하기

두 번째 줄에서 볼 수 있듯이 코루틴을 생성하고나서 바로 시작할 수는 없다. yield 문에서 실행될 수 있도록 next() 함수를 꼭 실행해 주어야 한다.

코루틴에 값 주입하기

send함수를 통해서 코루틴에 값을 넣을 수 있다.

1
2
a.send(123)
a.send(456)

StopIteration

더이상 반복할 yield가 없다면 StopIteration 예외를 발생시킨다.

코루틴의 현재 상태 알아보기

inspect 모듈의 getgeneratorstate 함수를 통해 현재 어떠한 상태일 지 알아볼 수 있다. 아래의 네 단계로 나누어진다.

  • GEN_CREATED - 처음 대기 상태
  • GEN_RUNNING - 실행 상태
  • GEN_SUSPENDED - yield 대기 상태
  • GEN_CLOSED - 실행 완료 상태
1
2
3
4
5
6
7
8
9
10
11
12
13
from inspect import getgeneratorstate

def co3():
a = yield
b = yield

test = co3()
print(getgeneratorstate(test)) # GEN_CREATED
next(test)
print(getgeneratorstate(test)) # GEN_SUSPENDED
test.send(1)
print(getgeneratorstate(test)) # GEN_SUSPENDED
test.send(2) # StopIteration 예외 발생

예외 처리 및 종료

throw() 함수로 예외를 던질 수 있다. 그리고 close() 함수로 코루틴을 종료할 수 있다.

1
2
a.throw(Exception)
a.close() # GEN_CLOSED

데코레이터로 만들기

먼저 한 번 실행해야 한다는 불편함을 해소하기 위해 데코레이터로 만들 수 있다. 코루틴을 생성하고 next()를 한 번 해주는 데코레이터를 만들어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def coroutine(func):
def inner(*args, **kwargs):
cr = func(*args, **kwargs)
next(cr)
return cr
return inner

@coroutine
def test_co():
print('start')
num = yield 'Coroutine!!!'
print('end', num)

a = test_co()
a.send(123)

맨 위에서 작성했던 코드와 똑같이 동작한다. 차이점은 a를 생성 후 next()로 한 번 실행하지 않아도 바로 코루틴을 사용할 수 있다는 것이다.

yield from 키워드

파이썬 3.3 버전부터 yield from 이라는 키워드를 사용할 수 있다. 다른 제너레이터에게 작업을 위임할때 사용하며 흐름을 넘겨받을 다른 제너레이터가 필요하다.

1
2
3
4
5
6
7
8
9
10
11
12
def func_a():
for item in ['a', 'b', 'c']:
yield item

def func_b():
yield from func_a()

aa = func_b()
next(aa)
next(aa)
next(aa)
next(aa) # StopIteration

func_b 제너레이터는 func_a 제너레이터에게 작업을 위임했다. func_a는 리스트를 순회하면서 상위 제너레이터에게 값을 전해준다. 상위 제너레이터인 func_b에 next 함수가 없다는 것이 특징이다.

결론

  • 제너레이터와 다르게 값을 생성하고 소비할 수 있다. -> 그래서 동시성 프로그래밍에 사용될 수 있다.
  • 값을 입력 받을 수 있는 제너레이터 -> 코루틴

제너레이터는 yield 키워드를 통해 값을 메인 루틴으로 생성해 줄 수 있지만, 코루틴은 메인루틴으로 값을 생성할 뿐만 아니라 메인 루틴으로 부터 받은 값을 소비할 수 있다는 큰 차이점이 있다. 그리고 이러한 차이로 인해서 동시성 프로그래밍을 할 수 있다는 것을 알아두자!!


[참고]
https://hamait.tistory.com/830
https://ddanggle.gitbooks.io/interpy-kr/ch22-Coroutines.html
https://github.com/Gyubin/TIL/blob/master/Python/coroutine.md
https://sjquant.tistory.com/13
https://sjquant.tistory.com/14
https://poppy-leni.tistory.com/entry/%EB%8F%99%EC%8B%9C%EC%84%B1-vs-%EB%B3%91%EB%A0%AC%EC%84%B1
https://umbum.tistory.com/445

Share

[파이썬]호출가능한 객체로 만들어 주는 __call__ 함수

더블 언더스코어(__)로 시작하는 매직메소드를 통해 클래스가 특별한 동작을 수행할 수 있도록 만들 수 있다. 함수를 호출하는 것처럼 클래스의 객체도 호출할 수 있게 만들수 있는데 이때 필요한 매직메소드가 __call__이다.

리스트에서 랜덤하게 번호를 추출하는 기능을 인스턴스 메소드와 객체 호출 두 가지 방법으로 구현하면서 __call__ 함수에 대해서 정리하자.

인스턴스 메소드로 구현하기

1
2
3
4
5
6
7
8
9
10
11
12
13
import random

class RandomPick:

def __init__(self):
self._numbers = [n for n in range(1, 101)]

def pick(self):
random.shuffle(self._numbers)
return sorted([random.choice(self._numbers) for _ in range(10)])

obj = RandomPick()
print(obj.pick())

객체 호출로 구현하기

1
2
3
4
5
6
7
# 아래 함수를 클래스에 추가
def __call__(self):
return self.pick()

a = RandomPick()
a() # [7, 9, 10, 11, 36, 37, 52, 71, 80, 100]
a.pick() # [4, 18, 31, 36, 46, 50, 52, 70, 93, 94]

위의 __call__ 함수를 추가해주면된다.

객체가 호출가능한지 판단하기

callable 함수를 써서 해당 객체가 호출 가능한지 판단할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
class A:
def __call__(self):
return 'haha'

class B:
pass

a = A()
b = B()

callable(a) # True
callable(b) # False
Share