Flipper 불완전 정복
Flipper 소개와 플러그인 맛보기
Flipper 불완전 정복
Flipper 소개와 플러그인 맛보기
안세원,
GDG Pangyo / 카카오모빌리티
kingori
다룰 내용
● Flipper 소개
● Flipper 플러그인 제작 맛보기
Flipper 소개
Flipper란?
● Facebook에서 만든 애플리케이션 동작 모니터링 도구
● 독립된 데스크탑 클라이언트를 이용해 모니터링 수행
● iOS와 안드로이드 지원
● 안드로이드 모니터링 도구인 Stetho의 후계자
https://fbflipper.com/
데스크탑 클라이언트 살펴보기
데스크탑 클라이언트 살펴보기
연결된 디바이스 선택
스크린샷 / 화면 녹화
앱 플러그인
디바이스
플러그인
데스크탑 클라이언트와 앱 사이의 통신
Flipper 탑재 앱Flipper 데스크탑 클라이언트
1. 등록된 플러그인 정보 제공
2. 플러그인 커넥션 연결
3. 커넥션을 이용해 통신
● 메시지 전달
● 메시지 구독
● 디바이스 플러그인 : 설정하지 않아도 기본적으로 동작
○ CrashReporter : 크래시 발생 시 OS의 알림으로 알려주고, 크래시 내역 표시
○ Logs: 로그캣. 필터링도 가능함
● 앱 플러그인 : 앱에서 직접 등록해야 함
○ Databases: DB 조회. SQL 실행 가능
○ NetworkPlugin : OkHttp 네트워크 로깅
○ SharedPreferenceView : SharedPreference 조회
○ Layout : Activity 뷰 레이아웃 조회
기본 제공 플러그인
앱 설정 - Gradle 의존관계 추가
repositories {
jcenter()
}
dependencies {
debugImplementation 'com.facebook.flipper:flipper:0.28.0'
debugImplementation 'com.facebook.soloader:soloader:0.8.0'
releaseImplementation 'com.facebook.flipper:flipper-noop:0.28.0'
}
앱 설정 - Application 설정
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
if (FlipperUtils.shouldEnableFlipper(this)) {
val client = AndroidFlipperClient.getInstance(this)
//plugin 추가
client.addPlugin(...)
client.addPlugin(...)
client.start()
}
}
}
Stetho와 비교
구분 Flipper Stetho
데스크탑 클라이언트 전용 애플리케이션
Chrome 브라우저의
Inspector 도구
지원 앱 플랫폼 iOS/ 안드로이드 안드로이드
플러그인
전용 애플리케이션에
GUI 로 등록됨
커맨드라인 기반
Stetho와 비교
● Chrome이 아닌 별도 클라이언트를 설치해야 해서 번거로움
○ 하지만 커넥션이 더 안정적이고
○ 웹에 끼워맞추느라 어색했던 표현이 훨씬 자연스러워졌음
● 플러그인이 커맨드라인이 아닌 GUI 기반으로 바뀜
○ Stetho와 달리 앱과 클라이언트 양쪽에 플러그인을 개발해야 함
○ 아무래도 GUI 이니 더 강력한 느낌적인 휠링?
Stetho는 단종되나요?
● 아직까지는 단종 계획 없음
Stetho will continue to work and we are not abandoning it so you can
choose the tool that fits your needs best.
https://fbflipper.com/docs/stetho.html
이슈
● 일부 안드로이드 기종에서 플러그인 인식되지 않음. 근데 하필 삼성이라는…
https://github.com/facebook/flipper/issues/92
○ 개발자 모드에서 디버그 대상 앱으로 지정하면 된다는 얘기도 있지만 안되는
경우도 있음
○ … 폰을 바꾼다!
이슈
● SoLoader가 문제를 일으킨다!
Stetho에서 넘어가야 할까?
● SoLoader 가 문제가 될 환경이라면 위험하다
● dumper plugin 을 잘 쓰고 있었다면 굳이 옮겨갈 필요가 있을까?
● Chrome Inspector의 연결 문제 때문에 짜증이 났다면 Flipper가 매력적이다
● GUI 기반 플러그인이 맘에 든다면 Flipper가 매력적이다
Flipper 플러그인 제작 맛보기
커스텀 Flipper 플러그인
● 기본 제공 플러그인의 기능이 부족하다면 직접 만들자!
● 앱 용 플러그인과 클라이언트 용 플러그인을 모두 만들어야 함
○ 안드로이드 : FlipperPlugin 클래스를 확장한 클래스를 작성한 후, Flipper 초기화 시 등록
○ 클라이언트 : 웹앱 형태로 작성
커스텀 Flipper 플러그인
● 기본 제공 플러그인의 기능이 부족하다면 직접 만들자!
● 앱 용 플러그인과 클라이언트 용 플러그인을 모두 만들어야 함
○ 안드로이드 : FlipperPlugin 클래스를 확장한 클래스를 작성한 후, Flipper 초기화 시 등록
○ 클라이언트 : TypeScript와 React로 만들어진 웹앱 형태로 작성
플러그인 제작 준비
● 데스크탑 클라이언트 설치 후, ~/.flipper/config.json 에 커스텀 플러그인 작업 경로 추가
● 적절한 에디터 설치 ex) VS Code
{
"pluginPaths": [
"~/.flipper/custom-plugins/"
],
...
}
HelloWorld 플러그인 만들기
● 아무 기능 없이 그냥 “HelloWorld” 만 찍는 플러그인
HelloWorld 플러그인 만들기
● 안드로이드 플러그인 작성: id 만 신경쓰자
client.addPlugin(object : FlipperPlugin {
override fun onConnect(connection: FlipperConnection?) {}
override fun runInBackground() = false
override fun getId() = "helloworld"
override fun onDisconnect() {}
})
{
"name": "helloworld",
"version": "1.0.0",
"description": "hellworld flipper plugin",
"main": "index.tsx",
"author": "kingori",
"license": "MIT",
"title": "HelloWorld",
"dependencies": {
"flipper": "latest"
}
}
HelloWorld 플러그인 만들기
● 데스크탑 플러그인 : helloworld/package.json
생성
○ name : 플러그인 식별자. 앱 플러그인의 id 와
매칭
○ main : index.tsx 로 고정
○ title : 클라이언트의 메뉴에 표시되는 이름
HelloWorld 플러그인 만들기
● 데스크탑 플러그인 : index.tsx 작성. 일단 그냥 따라해보자
import {
Text,
FlipperPlugin
} from 'flipper';
import React from 'react';
export default class HelloWorld extends FlipperPlugin<any, any, any> {
render() {
return (
<div>
<Text>HelloWorld</Text>
</div>
)
}
}
HelloWorld 플러그인 만들기
● 앱과 클라이언트를 실행해서 제대로 표시되는 지 확인
package.json 에서
지정한 title
render() 에서 만든 뷰
HelloWorld 플러그인 만들기
● index.tsx 코드 다시 보기
import {
Text,
FlipperPlugin
} from 'flipper';
import React from 'react';
export default class HelloWorld extends FlipperPlugin<any, any, any> {
render() {
return (
<div>
<Text>HelloWorld</Text>
</div>
)
}
}
1. UI 컴포넌트 임포트
2. FlipperPlugin를 확장하는
클래스를 선언해야 함
3. 순서대로 State, Action,
PersistedState의 타입 지정
Flipper의 UI 컴포넌트
● 기본적인 컴포넌트는 대부분 제공함
○ 문서가 부실하니, 소스코드도 보는 것을 권장
● HTML 태그들도 동작함 ( div , p 등등 )
https://fbflipper.com/docs/extending/ui-components.html
Flipper의 UI 컴포넌트
● 문서보기 귀찮다면 샘플 프로젝트의 UI Showcase 플러그인 & 소스코드 참고
State, Action, PersistedState
● 플러그인이 기반을 두고 있는 React는 상태 기반으로 동작
○ State : 플러그인 내부의 상태값. 플러그인 초기화 시 초기화 됨
ex) form에 입력된 값, 테이블의 선택된 row Id, 각종 뷰의 표시 여부
○ PersistedState : 플러그인 내부의 상태값. 클라이언트 초기화 시 초기화 됨
ex) 앱이 전송한 각종 데이터
○ Action : dispatch되는 액션의 타입
State, Action, PersistedState
● Echo 플러그인 예시
○ State: 앱으로 보낼 메시지
입력폼의 값이기도 함
○ Action: 해당 내용 없음
○ PersistedState: 앱이 보낸 메시지
State, Action, PersistedState
type State = { msg: string | null };
type PersistedState = { responses: Array<string> };
export default class Echo extends FlipperPlugin<State, any, PersistedState> {
static defaultPersistedState: PersistedState = {
responses: []
};
state: State = {
msg: null as string | null
}
...
}
클라이언트와 앱의 통신
● 앱 쪽
○ 이벤트 받기: FlipperConnection.receive()
○ 이벤트 보내기: FlipperConnection.send()
클라이언트와 앱의 통신
● Echo 플러그인 예시 : 앱 쪽
class EchoPlugin : FlipperPlugin {
override fun onConnect(connection: FlipperConnection) {
connection.receive("echo") { params, responder ->
responder.success( FlipperObject.Builder().put("resp", "ok").build())
connection.send(
"message",
FlipperObject.Builder().put("msg", params.getString("msg").build()
)
}
}
...
}
클라이언트와 앱의 통신
● 클라이언트 쪽
○ 이벤트 보내기 : Client.call()
○ 이벤트 구독 : Client.subscribe()
○ 백그라운드에서 PersistedState 이용한 구독 : persistedStateReducer 필드 사용
클라이언트와 앱의 통신
● Echo 플러그인 예시 : 클라이언트 쪽
//플러그인 초기화 시 구독 시작
init() {
this.client.subscribe("message", (echo:Object)=> {
this.appendResponse( echo.time +":"+ echo.msg);
});
}
//전송 버튼 클릭 시 앱에 메시지 보냄
sendMessage() {
this.client
.call('echo', {msg : this.state.msg })
.then((params) => { this.appendResponse("Success:"+params.resp); })
.catch((err) => { this.appendResponse("Error:"+err.resp); });
}
클라이언트 코드 디버깅
● 클라이언트에 탑재된 개발자 도구의
디버거 이용 가능함
그래서, 이거 개발할 만 한거 맞나요?
● Kotlin 개발만 하다 타입스크립트 개발하려니 매우 힘들다!
● 하지만 대부분 간단한 UI 작업 필요 ⇒ 비슷비슷한 패턴
● 익숙해지면 아주 괴롭진 않음
● 문제는 배포!
○ 앱 플러그인은 앱 빌드에 포함되어 있으니 별도 배포가 필요없음
○ 클라이언트 플러그인은 각 사용자가 알아서 설치해야 함
■ npm 서버에 올리는 방법도 있다지만 대게 사내 프로그램일텐데…?
참고문서
● Flipper 홈페이지: https://fbflipper.com/
● 샘플 프로젝트: https://github.com/kingori/flipper_plugin_example
● flexbox로 만들 수 있는 10가지 레이아웃 :
https://d2.naver.com/helloworld/8540176
● css refernce.io / flexbox: https://cssreference.io/flexbox/

Flipper 불완전 정복

  • 2.
    Flipper 불완전 정복 Flipper소개와 플러그인 맛보기
  • 3.
    Flipper 불완전 정복 Flipper소개와 플러그인 맛보기 안세원, GDG Pangyo / 카카오모빌리티 kingori
  • 4.
    다룰 내용 ● Flipper소개 ● Flipper 플러그인 제작 맛보기
  • 5.
  • 6.
    Flipper란? ● Facebook에서 만든애플리케이션 동작 모니터링 도구 ● 독립된 데스크탑 클라이언트를 이용해 모니터링 수행 ● iOS와 안드로이드 지원 ● 안드로이드 모니터링 도구인 Stetho의 후계자 https://fbflipper.com/
  • 7.
  • 8.
    데스크탑 클라이언트 살펴보기 연결된디바이스 선택 스크린샷 / 화면 녹화 앱 플러그인 디바이스 플러그인
  • 9.
    데스크탑 클라이언트와 앱사이의 통신 Flipper 탑재 앱Flipper 데스크탑 클라이언트 1. 등록된 플러그인 정보 제공 2. 플러그인 커넥션 연결 3. 커넥션을 이용해 통신 ● 메시지 전달 ● 메시지 구독
  • 10.
    ● 디바이스 플러그인: 설정하지 않아도 기본적으로 동작 ○ CrashReporter : 크래시 발생 시 OS의 알림으로 알려주고, 크래시 내역 표시 ○ Logs: 로그캣. 필터링도 가능함 ● 앱 플러그인 : 앱에서 직접 등록해야 함 ○ Databases: DB 조회. SQL 실행 가능 ○ NetworkPlugin : OkHttp 네트워크 로깅 ○ SharedPreferenceView : SharedPreference 조회 ○ Layout : Activity 뷰 레이아웃 조회 기본 제공 플러그인
  • 11.
    앱 설정 -Gradle 의존관계 추가 repositories { jcenter() } dependencies { debugImplementation 'com.facebook.flipper:flipper:0.28.0' debugImplementation 'com.facebook.soloader:soloader:0.8.0' releaseImplementation 'com.facebook.flipper:flipper-noop:0.28.0' }
  • 12.
    앱 설정 -Application 설정 class MyApplication : Application() { override fun onCreate() { super.onCreate() SoLoader.init(this, false) if (FlipperUtils.shouldEnableFlipper(this)) { val client = AndroidFlipperClient.getInstance(this) //plugin 추가 client.addPlugin(...) client.addPlugin(...) client.start() } } }
  • 13.
    Stetho와 비교 구분 FlipperStetho 데스크탑 클라이언트 전용 애플리케이션 Chrome 브라우저의 Inspector 도구 지원 앱 플랫폼 iOS/ 안드로이드 안드로이드 플러그인 전용 애플리케이션에 GUI 로 등록됨 커맨드라인 기반
  • 14.
    Stetho와 비교 ● Chrome이아닌 별도 클라이언트를 설치해야 해서 번거로움 ○ 하지만 커넥션이 더 안정적이고 ○ 웹에 끼워맞추느라 어색했던 표현이 훨씬 자연스러워졌음 ● 플러그인이 커맨드라인이 아닌 GUI 기반으로 바뀜 ○ Stetho와 달리 앱과 클라이언트 양쪽에 플러그인을 개발해야 함 ○ 아무래도 GUI 이니 더 강력한 느낌적인 휠링?
  • 15.
    Stetho는 단종되나요? ● 아직까지는단종 계획 없음 Stetho will continue to work and we are not abandoning it so you can choose the tool that fits your needs best. https://fbflipper.com/docs/stetho.html
  • 16.
    이슈 ● 일부 안드로이드기종에서 플러그인 인식되지 않음. 근데 하필 삼성이라는… https://github.com/facebook/flipper/issues/92 ○ 개발자 모드에서 디버그 대상 앱으로 지정하면 된다는 얘기도 있지만 안되는 경우도 있음 ○ … 폰을 바꾼다!
  • 17.
  • 18.
    Stetho에서 넘어가야 할까? ●SoLoader 가 문제가 될 환경이라면 위험하다 ● dumper plugin 을 잘 쓰고 있었다면 굳이 옮겨갈 필요가 있을까? ● Chrome Inspector의 연결 문제 때문에 짜증이 났다면 Flipper가 매력적이다 ● GUI 기반 플러그인이 맘에 든다면 Flipper가 매력적이다
  • 19.
  • 20.
    커스텀 Flipper 플러그인 ●기본 제공 플러그인의 기능이 부족하다면 직접 만들자! ● 앱 용 플러그인과 클라이언트 용 플러그인을 모두 만들어야 함 ○ 안드로이드 : FlipperPlugin 클래스를 확장한 클래스를 작성한 후, Flipper 초기화 시 등록 ○ 클라이언트 : 웹앱 형태로 작성
  • 21.
    커스텀 Flipper 플러그인 ●기본 제공 플러그인의 기능이 부족하다면 직접 만들자! ● 앱 용 플러그인과 클라이언트 용 플러그인을 모두 만들어야 함 ○ 안드로이드 : FlipperPlugin 클래스를 확장한 클래스를 작성한 후, Flipper 초기화 시 등록 ○ 클라이언트 : TypeScript와 React로 만들어진 웹앱 형태로 작성
  • 22.
    플러그인 제작 준비 ●데스크탑 클라이언트 설치 후, ~/.flipper/config.json 에 커스텀 플러그인 작업 경로 추가 ● 적절한 에디터 설치 ex) VS Code { "pluginPaths": [ "~/.flipper/custom-plugins/" ], ... }
  • 23.
    HelloWorld 플러그인 만들기 ●아무 기능 없이 그냥 “HelloWorld” 만 찍는 플러그인
  • 24.
    HelloWorld 플러그인 만들기 ●안드로이드 플러그인 작성: id 만 신경쓰자 client.addPlugin(object : FlipperPlugin { override fun onConnect(connection: FlipperConnection?) {} override fun runInBackground() = false override fun getId() = "helloworld" override fun onDisconnect() {} })
  • 25.
    { "name": "helloworld", "version": "1.0.0", "description":"hellworld flipper plugin", "main": "index.tsx", "author": "kingori", "license": "MIT", "title": "HelloWorld", "dependencies": { "flipper": "latest" } } HelloWorld 플러그인 만들기 ● 데스크탑 플러그인 : helloworld/package.json 생성 ○ name : 플러그인 식별자. 앱 플러그인의 id 와 매칭 ○ main : index.tsx 로 고정 ○ title : 클라이언트의 메뉴에 표시되는 이름
  • 26.
    HelloWorld 플러그인 만들기 ●데스크탑 플러그인 : index.tsx 작성. 일단 그냥 따라해보자 import { Text, FlipperPlugin } from 'flipper'; import React from 'react'; export default class HelloWorld extends FlipperPlugin<any, any, any> { render() { return ( <div> <Text>HelloWorld</Text> </div> ) } }
  • 27.
    HelloWorld 플러그인 만들기 ●앱과 클라이언트를 실행해서 제대로 표시되는 지 확인 package.json 에서 지정한 title render() 에서 만든 뷰
  • 28.
    HelloWorld 플러그인 만들기 ●index.tsx 코드 다시 보기 import { Text, FlipperPlugin } from 'flipper'; import React from 'react'; export default class HelloWorld extends FlipperPlugin<any, any, any> { render() { return ( <div> <Text>HelloWorld</Text> </div> ) } } 1. UI 컴포넌트 임포트 2. FlipperPlugin를 확장하는 클래스를 선언해야 함 3. 순서대로 State, Action, PersistedState의 타입 지정
  • 29.
    Flipper의 UI 컴포넌트 ●기본적인 컴포넌트는 대부분 제공함 ○ 문서가 부실하니, 소스코드도 보는 것을 권장 ● HTML 태그들도 동작함 ( div , p 등등 ) https://fbflipper.com/docs/extending/ui-components.html
  • 30.
    Flipper의 UI 컴포넌트 ●문서보기 귀찮다면 샘플 프로젝트의 UI Showcase 플러그인 & 소스코드 참고
  • 31.
    State, Action, PersistedState ●플러그인이 기반을 두고 있는 React는 상태 기반으로 동작 ○ State : 플러그인 내부의 상태값. 플러그인 초기화 시 초기화 됨 ex) form에 입력된 값, 테이블의 선택된 row Id, 각종 뷰의 표시 여부 ○ PersistedState : 플러그인 내부의 상태값. 클라이언트 초기화 시 초기화 됨 ex) 앱이 전송한 각종 데이터 ○ Action : dispatch되는 액션의 타입
  • 32.
    State, Action, PersistedState ●Echo 플러그인 예시 ○ State: 앱으로 보낼 메시지 입력폼의 값이기도 함 ○ Action: 해당 내용 없음 ○ PersistedState: 앱이 보낸 메시지
  • 33.
    State, Action, PersistedState typeState = { msg: string | null }; type PersistedState = { responses: Array<string> }; export default class Echo extends FlipperPlugin<State, any, PersistedState> { static defaultPersistedState: PersistedState = { responses: [] }; state: State = { msg: null as string | null } ... }
  • 34.
    클라이언트와 앱의 통신 ●앱 쪽 ○ 이벤트 받기: FlipperConnection.receive() ○ 이벤트 보내기: FlipperConnection.send()
  • 35.
    클라이언트와 앱의 통신 ●Echo 플러그인 예시 : 앱 쪽 class EchoPlugin : FlipperPlugin { override fun onConnect(connection: FlipperConnection) { connection.receive("echo") { params, responder -> responder.success( FlipperObject.Builder().put("resp", "ok").build()) connection.send( "message", FlipperObject.Builder().put("msg", params.getString("msg").build() ) } } ... }
  • 36.
    클라이언트와 앱의 통신 ●클라이언트 쪽 ○ 이벤트 보내기 : Client.call() ○ 이벤트 구독 : Client.subscribe() ○ 백그라운드에서 PersistedState 이용한 구독 : persistedStateReducer 필드 사용
  • 37.
    클라이언트와 앱의 통신 ●Echo 플러그인 예시 : 클라이언트 쪽 //플러그인 초기화 시 구독 시작 init() { this.client.subscribe("message", (echo:Object)=> { this.appendResponse( echo.time +":"+ echo.msg); }); } //전송 버튼 클릭 시 앱에 메시지 보냄 sendMessage() { this.client .call('echo', {msg : this.state.msg }) .then((params) => { this.appendResponse("Success:"+params.resp); }) .catch((err) => { this.appendResponse("Error:"+err.resp); }); }
  • 38.
    클라이언트 코드 디버깅 ●클라이언트에 탑재된 개발자 도구의 디버거 이용 가능함
  • 39.
    그래서, 이거 개발할만 한거 맞나요? ● Kotlin 개발만 하다 타입스크립트 개발하려니 매우 힘들다! ● 하지만 대부분 간단한 UI 작업 필요 ⇒ 비슷비슷한 패턴 ● 익숙해지면 아주 괴롭진 않음 ● 문제는 배포! ○ 앱 플러그인은 앱 빌드에 포함되어 있으니 별도 배포가 필요없음 ○ 클라이언트 플러그인은 각 사용자가 알아서 설치해야 함 ■ npm 서버에 올리는 방법도 있다지만 대게 사내 프로그램일텐데…?
  • 40.
    참고문서 ● Flipper 홈페이지:https://fbflipper.com/ ● 샘플 프로젝트: https://github.com/kingori/flipper_plugin_example ● flexbox로 만들 수 있는 10가지 레이아웃 : https://d2.naver.com/helloworld/8540176 ● css refernce.io / flexbox: https://cssreference.io/flexbox/