플러터(Flutter)를 공부하며 앱을 만들어 봤습니다.

플러터(Flutter)는 구글에서 만든 Dart 언어 기반의 멀티 플랫폼 개발도구 입니다. 개인적으로 발표 시점부터 꾸준히 지켜보고 있었는데 조만간 뭔가 하나 만들어야지.. 하다가 한해가 넘어가 버렸습니다.

이전글(http://practical.kr/?p=53)에서도 이야기 한적이 있지만 멀티 플랫폼에 대한 환상(?)을 가지고 있어서 페이스북에서 나온 ReactNative(이하 RN)로 프로젝트를 진행한적이 있고(http://practical.kr/?p=19) 네이티브(주로 iOS) 개발을 하고 있기 때문에 네이티브 개발과 멀티플랫폼 개발툴간의 장단점을 조금은 안다고 생각하고 개발 과정을 한번 정리해 봤습니다.

UI 디자인

좋아하던 Xcode를 싫어하기 시작한게 아마도 Auto Layout이 나오기 시작한 시점이이 아닌가 싶은데요. 맞춰놓으면 작은 변경에도 Layout 전체를 조정해야 하는 Auto 스럽지(?) 않은 Xcode가 최근에 SwiftUI라는 Flex 스러운 UI 디자이너를 만들어서 모바일 개발에서 UI를 만드는 일이 사실 전체적으로 비슷한 기조로 가고 있는듯 싶습니다

Flutter 의 UI 디자인은 코드로 해야 합니다. 그래픽 디자인 도구가 없어요. 하지만 Flex 디자인의 구조를 차용한 Cascade 구조를 사용해서 모듈화를 할 수 있습니다. 컴포넌트를 좀 더 잘게 구성하고 모듈화 시키면 디자인 화면에 cascade된 UI Design Tree의 복잡성을 줄일 수는 있습니다만 코드와 통합된 UI 코드는 꽤 복잡하게 보일 수도 있지만 어렵지 않게 화면을 구성할 수 있습니다. 그리고 개인적으로는 RN의 CSS 구조보다는 좋다고 생각합니다. 그건 아마도 제가 CSS를 좀 싫어(?)해서 그런건지도 모르겠습니다. CSS를 잘 쓰시는 분들은 CSS 재사용 구조가 더 좋을 수도 있습니다. 절대적으로 개취(?)입니다.

컴포넌트 혹은 패키지

재사용 가능한 라이브러리를 플러터에서는 패키지라고 부릅니다. Node가 먼저인지 CocoaPod이 먼저인지 아니면 그전에도 패키지 매니저가 있었는지 잘모르겠습니다만 플러터에도 패키지 매니저가 내장되어 있습니다. pubspec.yaml 파일에 https://pub.dev 에서 검색한 패키지를 추가하고

> flutter get pub

위와 같이 실행하면 패키지를 설치해 줍니다. 다 찾아본건 아닙니다만 이젠 필요한건 거의 있는것 같습니다. 이번 앱 개발하면서도 여러개 테스트 해봤는데 보는 눈만 좋다면 코드를 상당히 줄일 수 있습니다. pub.dev 페이지에서 인기도를 참조하면 신뢰성 있는 패키지를 고룰 수 있습니다. 저는 15개나 사용했네요. 제가 페북에 패키지 설치를 의존성주입이라는 말을 썻더니 그게 아니라고 하시더라구요. 사실.. 아닐수도 있고 맞을 수도 있는 말입니다만 패키지는 그냥 설치라고 해두죠 ^^;

디버깅

Flutter는 개발도구를 Android Studio를 씁니다. 아마 구글 입장에서도 새 도구를 만드는것보다 이렇게 하는게 쉬웠을것 같네요. 익숙하기도 하구요. 그래서는 아니지만 디버깅 도구가 RN에 비해서 월등히 좋습니다. 물론 Xcode에 비할바는 아니지만 브레이크 포인트를 걸어서 스택데이터를 볼 수 있다는것만 해도 정말 좋습니다. 당연한거지만 RN으로 개발해 보면 이게 왜 좋은지 알게 됩니다.

문서화

이것도 RN과 비교할 수밖에 없는데 너무 빈약한 문서로 고생했던 기억이 있는데요. 그에 반해 구글답게 개발문서가 아주 잘 정리되어 있습니다. 게다가 이제 버전이 꽤 올라와 있는 상황이라 StackOverFlow에도 Flutter 관련 Q/A가 필요한만큼(?) 있습니다.

그래서

평소에 앱 혹은 프로그램을 하나 만드는게 가장 빠른 언어 공부 방법이라고 생각하고 있었습니다. 그래서 앱을 하나 만들었습니다. 대략 3주 정도 걸린것 같습니다. 딱히 별 아이디어가 없어서 만들기 쉬운걸로 만들었습니다. QRCode를 생성하고 읽어서 저장하고 조회하는 기본적인 기능을 가진 앱을 하나 만들었습니다.

앱을 만드는데 가장 기본적으로 필요한 라이브러리들을 선정하고 사용법을 읽히는 일은 기존에 네이티브앱을 만들때 하던 방식과 동일 할 수 밖에 없습니다. 기본 라이브러리를 쓸것인지 아니면 외부 패키지를 사용할 것인지를 선택하고 기능에 적절하게 구현하는 행위를 반복하다보면 앱이 하나 완성되어 있는거죠 ^^;

UI와 관련해서는 기본적으로 필요한 거의 대부분의 컴포넌트가 이미 만들어져 있습니다. 아래와 같은 화면을 구성하려면 화면 하단의 TabBar, 화면 상단의 TitleBar, 리스크 구조의 스크롤 그리드, 이미지를 보여기기 위한 Image 컴포넌트등 다양한 기본 컴포넌트와 그 구조를 정의 하기위한 Layout 컴포넌트들 준비되어 있습니다.

그외에 기본으로 지원되지 않거나 기본으로 지원되는 것들이 예쁘지(?) 않다면 외부 패키지를 설치해서 사용할 수 있습니다. 제경우 Store, QRCode Reader, 다국어 지원 등을 위하여 외부 패키지를 사용 했습니다.

제가 사용한 기본적인 몇가지 패캐지 리스트는 아래와 같습니다. 이외에도 몇가지가 더 있습니다만 대략 입맛에 맞게 고르시면 됩니다.

Data Store  - https://pub.dev/packages/provider
http 통신 - https://pub.dev/packages/http
다국어지원 - https://pub.dev/packages/easy_localization
QRCode - https://pub.dev/packages/qrcode
컬러피커 - https://pub.dev/packages/flutter_colorpicker

아이폰용앱은 아래 링크에서 다운 받으실 수 있습니다. 안드로이드용은 스토어 승인단계에 있는데 요즘은 안드로이드가 애플스토어보다 승인이 느리군요. 승인되면 링크 올릴께요. (5일만에 승인이 났습니다. 요즘은 아이폰이 더 빠릅니다)

아이폰앱 다운로드 - https://apps.apple.com/app/id1523448616
안드로이드 다운로드 - https://play.google.com/store/apps/details?id=com.rtlink.qscanner

결론

2020년에 앱개발은 굉장히 다양한 선택지가 있습니다. 업무의 특성에 따라 혹은 개발팀의 리소스, 혹은 취향에 맞게 다양한 개발도구를 선택 할 수 있습니다. 개인적으로 소프트웨어 개발의 가장 중요한 요소는 생산성이라고 생각하는 편이라 이런 도구가 많이 나오는건 환영하고 대부분 확인해 보는 편입니다만 그중에서도 Flutter는 굉장히 매력적인 도구라고 해야 할것 같습니다. 그리고 아마도 상당기간 사용하게 될것 같다는 생각을 했습니다.

아참! 앱은 무료! 공짜! 입니다. 그리고 개발의뢰 환영합니다. ^_^

Dart Cheat Sheet는 뽀너스!

2020년 7월 21일 박병일

iOS/Swift – iCloud Drive에 파일 업로드 하기

2011년 4월에 애플 앱스토어에 업로드한 Fake Location이 어뷰징 요소가 있다는 이유로 2020년 4월에 스토어에서 강제로 퇴출당했다. 이걸 마지막으로 앱스토어에 판매중인 앱이 한개도 남지 않게되어 새로운 앱을 하나 만들기로 했다.

그날 페북에 올린글

몇일간 남는 시간을 쪼개어 그럭저럭 보이스를 녹음하고 플레이하는 작업을 하고 있었는데 알수 없는 문제에 봉착했다. 녹음된 보이스 파일은 아이폰에 저장되어야 하고 옵션으로 iCloud Drive에 저장되어야 해서 iCloud에 저장하는 기능을 추가 했는데 파일은 분명히 저장이 되고 원격 플레이까지 정상적으로 되는데 iCloud Drive에 폴더와 파일이 보이지 않는 문제가 발생했다.

알고보면 간단한 문제였지만 문제라는게 항상 그렇듯 모르면 괴로울 뿐이다. 게다가 코드 문제라기보단 설정(?) 문제라면 해결후 허무함까지 동반한다.

아이폰 로컬 폴더 얻기

아이폰 로컬 도큐먼트 폴더를 얻는 방법은 아래의 코드로 저장할 파일을 생성 할 수 있다. 생성된 audioFilename을 AVAudioRecorder에 넘겨주면 녹음이 완료된후 파일이 생성되는 것을 확인 할 수 있다. 아래 코드의 결과로 대략 이런 로케이션이 얻어진다.

file:///var/mobile/Containers/Data/Application/9F57DEC2-3A40-40AA-9EC5-5D104E94053F/Documents/voice.m4a

let saveFilename = "voice.m4a"
let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let audioFilename = path!.appendingPathComponent(saveFilename) 

iCloud Drive 원격 폴더 얻기

원격 폴더를 얻는 방법은 약간의 설정작업을 해야한다. Xcode의 Signning & Capability탭에서 +Capability 탭을 선택하여 iCloud 사용설정을 해야한다. 물론 이걸 하려면 개발자 계정이 필요하다.

설정방법

위와 같은 설정을 해주면 .entitlement 파일이 생성된다. 그리고 아래 코드를 이용하면 iCloud Drive 폴더에 파일을 생성 할 수 있다. 파일명이 아래처럼 생성된다. 레코딩 결과가 생성된 파일명으로 잘 저장되었다.

file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~*****/Documents/voice.m4a

let saveFilename = "voice.m4a"
let path = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents")
let audioFilename = path!.appendingPathComponent(saveFilename) 

그런데 폴더가 보이지 않는다

iCloud Drive에 파일을 업로드 했으니 당연히 나의 맥북 Finder 에 iCloud Drive에 오디오 파일이 보여야 하는데 보이지 않았다. 여기에 보이지 않으면 파일을 복사하거나 이동 시킬 수 없다. 난감하네… 그래서 3일을 까먹었다. 결론적인 이야기지만 클라우드에 파일을 업로드 하고 사용자가 손대지 못하게 하려면 여기까지만 하면 된다. 물론 아이폰의 설정 – iCloud – 저장공간관리 – (앱) – 에서 삭제 할 수는 있다.

문제의 해결은 매우 간단했다. info.plist에 아래와 같은 Key값을 추가 해주면 된다. 물론 key는 각자의 것을 사용해야 한다. 개발자가 코드로 문제를 해결 못하고 설정때문에 몇일씩 까먹고 나면 매우 허무해진다. ^^; 이건 아래의 stackoverflow 링크의 중간쯤에 ‘난 이렇게 해결했어’ 가 있었는데… 글타래가 길어서 대충 읽고 넘어가느라 못본거 였던것 뿐이었다. 결국 3일째 모든 대답들을 다시 꼼꼼히 읽고 다 시도해 보고서야 문제를 찾을 수 있었다. 교훈은 좀 더 꼼꼼해 져야 한다.. 정도?

<key>NSUbiquitousContainers</key>
<dict>
    <key>iCloud.net.redacted.docTest</key>
    <dict>
        <key>NSUbiquitousContainerIsDocumentScopePublic</key>
        <true/>
        <key>NSUbiquitousContainerSupportedFolderLevels</key>
        <string>Any</string>
    </dict>
</dict>

https://stackoverflow.com/questions/25203697/exposing-an-apps-ubiquitous-container-to-icloud-drive-in-ios-8

이 설정을 추가하면 아이폰의 파일앱 그리고 계정이 연결된 맥북 또는 다른 컴퓨터에서 생성된 폴더와 파일을 확인 할 수 있다.

이 프로젝트는 현재 대략 20% 정도 진행되었다. 시작만 해놓고 마무리는 하지 못한 일들이 너무 많아서 이제는 외부에 공표를 해가며 스스로를 채찍질을 해보려고 하고는 있지만 과연 마무리를 할 수 있을지는 잘 모르겠다. 블로그 한개 썻으니 그나마 보람이 있는것일까?

2020/05/05 박병일

React Native 다시 공부하기

React Native는 이미 2017년에 버즈아트에서 나름 빠르게 도입해서 프로젝트에 성공적으로 적용했던 적이 있었다. 링크참조(http://practical.kr/?cat=6) 그때 버전이 v0.45 수준이었는데 3년이 지난 지금도 React Native는 v0.61에 머물러 있다. 대체 언제쯤 v1.0을 내놓으려나…

2020년 현재 여전히 크로스(멀티)플랫폼(iOS, Android)을 지원하는것은 매력적이고 그동안 꽤 많은 기술적 진보가 있었을 것이라는 생각을 염두에 두고 다시 한번 공부를 시작해 볼까? 하는 생각에 연습용 프로젝트를 하나 만들기 시작했다. 이글을 쓰는 이유는 프로젝트를 만들고 보니 기억 나는게 하나도 없어서 뭘 했는지 정리하기 위함이다.

모바일 멀티플랫폼

잠시 멀티 플랫폼 이야기를 하고 넘어가보자. 최근 2~3년 사이에 모바일 플랫폼 개발과 관련한 프레임워크는 전통적인 Swift기반의 Xcode, Java & Kotlin 기반의 Android Studio와 더불어 Dart 기반의 Flutter, C# 기반의 Xamarin 등이 쏟아지며 개발툴 전성시대가 열린것 같다. 성능도 많은 향상을 보여서 거의 네이티브 성능을 따라오는 수준까지 도달한 것으로 보인다. 어떤것을 선택해도 크게 문제가 없을것으로 생각된다. 하지만 역시 가장 좋은것은 손에 익은것이 아닐까 싶다.

나 개인적으로는 오래도록 사용해온 Obj-C 기반의 Xcode가 가장 좋지만 이건 멀티 플랫폼이 아닌지라(iOS만지원) 제외하고 최근 2~3년간 JavaScript 특별히 Vue.js / Node.js를 사용해 오고 있었기 때문에 JS 기술을 그래도 활용할 수 있는 React Native에 끌리는건 당연한 선택일 수 밖에 없다. 하지만 처음 접하는 모바일 멀티 플랫폼 개발이라면 Dart/Flutter이 좀더 낫지 않을까 하는 생각인데 이유는 구글의 개발자 문서 지원이 매우 좋고 React Native에 비하여 좀 더 좋은 실행 성능을 내고 있다고 알려져 있기 때문이다.

Getting-Started

프로젝트 시작은 여기서 한다. Expo를 이용하는 방법과 Cli 툴을 이용하는 방법이 있는데 나는 Cli 툴을 이용하여 프로젝트를 생성 했다. Expo를 쓰면 폰에 직접 앱을 올려서 바로 결과를 볼 수 있고 Cli툴을 쓰면 Xcode 및 각종 도구를 깔아서 시뮬레이터에서 테스트를 할 수 있다. 나중에 스토어용으로 빌드를 하기 위해서 후자의 방법으로 설치하는 것이 좋다. 하지만 간단한 테스트는 Expo가 훨씬 편하다.

https://reactnative.dev/docs/getting-started

Navigation

앱을 만들려면 기본적으로 메뉴 시스템이 있어야 한다. 모바일 시스템에서 메뉴 시스템은 보통 Tabbar – Navigation, Drawer – Navigation 두가지 중에서 선택하는 것이 일반적인 선택이다. 한동안 Drawer 메뉴가 유행을 하다가 최근 다시 Tabbar 시스템이 유행인것 같아서 나는 Tabbar 시스템 기반으로 했다.

네비게이션 라이브러리는 ReactNavigation을 사용했다. 아마 개발자들이 가장 많이 사용하는 메뉴 시스템이고 Tabbar와 Drawer를 모두 지원한다.

https://reactnavigation.org/docs/getting-started

import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

import Home from './src/Home';
import Profile from './src/Profile';
import Settings from './src/Settings';

const Tab = createBottomTabNavigator();

export default function App() {

  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Home" component={Home}/>
        <Tab.Screen name="Profile" component={Profile}/>
        <Tab.Screen name="Settings" component={Settings}/>
      </Tab.Navigator>
    </NavigationContainer>
  );
}

코드의 결과로 아래와 같은 메뉴 시스템이 나왔다. 메뉴에 아이콘을 넣거나 좀더 예쁘게 꾸미려면 https://reactnavigation.org/docs/tab-based-navigation 를 참조하자.

Rest API Communication

Rest API 서버에서 데이터를 가지고 와서 목록 형태로 보여주는 것은 axios를 이용한다. https://github.com/axios/axios 를 참조한다. 컴포넌트가 마운트 될때 API 서버에서 데이터를 가져와서 state에 저장했다.

import axios from "axios";

...

componentDidMount() {
 axios.get("https://jsonplaceholder.typicode.com/users")
  .then(res =>{
   this.setState({ persons:res.data });
  });
}

FlatList – 목록보여주기

모바일 화면의 대부분은 목록(List)이다. 상하스크롤을 통하여 데이터 리스트를 조회 하고 화면을 선택하면 상세화면으로 진입하는 구성이 대부분이다. 이 리스트는 스크롤이 계속되는 특성상 화면에 보이는 만큼만 메모리 관리를 하지 않으면 너무 많은 메모리를 사용해서 앱을 다은 시키는 원인이 된다. React Native의 FlatList는 자동으로 메모리 관리를 해주기 때문에 필수적으로 쓰는 컴포넌트이다.

대략 아래와 같이 연결한다.

function Item({item, navigation}) {
 return (
   <View>
    <Text>{item.name}</Text>
   </View>
 )
}
....

render() {
 return (
  <View>
   <FlatList
    data={this.state.persons}
    renderItem={({item})=><Item item={item}/>}
    keyExtractor={item=>item.id}
   />
  </View>
 )
}
FlatList 결과화면

상태관리(Store)

React Native의 상태 관리는 Redux로 하는것이 기본이다. 하지만 Redux의 구조와 사용법이 직관적이지 않아서 좀더 직관적으로 쓸 수 있는 MobX를 사용했다. Redux와 MobX의 비교와 관련해서 우아한 형제의 기술블로그에 좋은 자료가 있어서 링크에서 자세한 정보를 얻을 수 있다.

https://woowabros.github.io/experience/2019/01/02/kimcj-react-mobx.html

MobX는 매우 직관적으로 Store를 사용할 수 있는데 이것은 마치 Vue.js의 Store 처럼 단순하게 사용할 수 있다. 사실 그에 비하면 Redux는 너무 복잡한 구조를 가진것이 사실이다. 대략 아래와 같은 코드를 이용하여 두개의 페이지에서 동일한 값의 증가를 확인 할 수 있다.

import {observable} from 'mobx';

class CounterStore {
 @observable counter = 0;
 
 increment() {
  this.counter++;
 }

 decrement() {
  this.counter--;
 }
}
export default new CounterStore();
import React, {Component} from 'react';
import { observer } from 'mobx-react';
import { StyleSheet, Text, View, Button } from 'react-native';

import CounterStore from '../../mobx/store'

@observer
export default class HomeScreen extends Component {
 render() {
  return (
   <View >
    <Text style={{fontSize: 60}}>
     {CounterStore.counter}
    </Text>
    <Button
     title="Increase"
     onPress={() => CounterStore.increment()}
    />
   </View>
  )
 }
}

Source Code – GitHub

아래 링크에서 위의 셈플 프로젝트의 소스코드는 아래 링크에서 다운로드 할 수 있다.

https://github.com/bipark/react_native_study

관련 링크

React 스터디 – https://ko.reactjs.org/docs/hello-world.html

Components – https://reactnative.dev/docs/activityindicator

Navigation – https://reactnavigation.org/docs/getting-started

Axios – https://github.com/axios/axios

Awesome React Native – https://github.com/jondot/awesome-react-native

리액트 프로젝트에서 MobX 사용하기 – https://velog.io/@velopert/MobX-2-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90%EC%84%9C-MobX-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-oejltas52z

React에서 Mobx 경험기 (Redux와 비교기) – https://woowabros.github.io/experience/2019/01/02/kimcj-react-mobx.html

카카오 로그인 모듈 – https://github.com/react-native-seoul/react-native-kakao-login

Practical / 대표개발자 박병일

라즈베리 파이에서 MPU-6050 자이로 가속도 센서 모듈 제어하기

GY-521모듈은 MPU-6050 칩 기반으로 만들어진 가속도와 자이로 센서 모듈이다. 가속도와 각속도를 측정할 수 있다. 6축 – X, Y, Z축 자이로스코프 + 3축 – 가속도를 측정한다. 최근엔 주로 드론의 자세제어용으로 많이 사용한다고 한다. 나도 드론의 자세를 제어 할 수 있다는 말을 듣고 구입했다. 구입은 아래 링크에서 했고 가격은 1,600원이다. 무지 싸다.

https://www.devicemart.co.kr/goods/view?no=1247052

라즈베리파이와의 연결은 아래와 같다.

Pin No.1 –> VCC

Pin No.3 –> SDA

Pin No.5 –> SCL

Pin No.6 –> GND

라즈베리파이에서 이 모듈과 통신을 하기 위해서는 I2C 통신을 이용하는데 이게 뭔지는 (https://m.blog.naver.com/yuyyulee/220323559541) 여기서 보고 라즈베리파이에는 I2C통신을 위한 모듈을 설치하면 데이터를 받을 수 있다. 커맨드 라인에서 아래와 같이 설치한다.

> sudo apt-get install i2c-tools

제대로 연결이 되었는지는 아래의 커맨드로 확인 가능하다.

> sudo i2cdetect -y 1

위 그림과 같은 결과가 나타나면 제대로 연결된 것이다. 파이썬으로 이 모듈과 통신하려면 파이썬 라이브러리가 필요한데 아래와 같이 설치 할 수 있다

> sudo apt-get install python-smbus

데이터를 얻기 위해 사용한 코드는 아래와 같다. 대략 웹서핑해서 얻은 코드인데 문제없이 잘 작동 했다.

import smbus
import math

# Power management registers
power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

def dist(a,b):
    return math.sqrt((a*a)+(b*b))

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)



bus = smbus.SMBus(1) 
address = 0x68       

# Now wake the 6050 up as it starts in sleep mode

bus.write_byte_data(address, power_mgmt_1, 0)

while True:
    print "gyro data"
    print "---------"
    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)

    print "gyro_xout: ", gyro_xout, " scaled: ", (gyro_xout / 131)
    print "gyro_yout: ", gyro_yout, " scaled: ", (gyro_yout / 131)
    print "gyro_zout: ", gyro_zout, " scaled: ", (gyro_zout / 131)

    print
    print "accelerometer data"
    print "------------------"

    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)

    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0

    print "accel_xout: ", accel_xout, " scaled: ", accel_xout_scaled
    print "accel_yout: ", accel_yout, " scaled: ", accel_yout_scaled

    print "accel_zout: ", accel_zout, " scaled: ", accel_zout_scaled
    print "x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)
    print "y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled)

코드의 결과로 아래와 같은 화면을 연속적으로 얻을 수 있었다.

그런데 코드에서 상수로 표현된 131과 16384가 무었인지 궁금했다. 검색을 해보니 자이로센서, 가속센서 Scale Factor가 센싱범위가 +/- 250 degree/second, 2g일때 131, 16384 상수라고 한다. 무슨말인지 모르겠지만 이 값으로 나눠주면 된단다. 좀더 자세한 내용은 아래 링크 참조

https://github.com/FabLabSeoul/WingProject/wiki/Gyro-Accel-MPU-6050

GraphQL + MySQL 데이터 가져오기 스터디

네이버에 개발자 모집 공고를 보다가 React Native 개발자를 구하는데 GraphQL 기반의 백엔드 프로그래밍 역할도 필요하다는 것을 보고 놀랐다. 세상이 진짜 변하긴 했다.

물론 프론트 개발자가 백엔드를 동시에 작업할 수 있으면 매우 생산성이 높고 문서작업 & 협의 과정 없이 빠르게 서비스를 만들수 있다. 나는 Node.js 와 Vue.js를 이용해서 그런방식으로 작업을 하고 있는데 매번 프론트에서 엔드포인트가 필요할때마다 Node에서 api를 만들고 그걸 받아서 쓰고 있지만 프론트에서 이걸 끝내는 방법이 없나 하는 생각은 늘 하고 있던 차였다.

GraphQL이 이걸 해줄 수 있다고 해서 공부를 해봐야지 한게 벌써 두해를 넘기고 있기도 하고 여러가지 문서를 읽어 봤지만 역시 만들어 보는게 최고라… 그게 뭔지는 대충 아래 링크로 퉁치고 Hello World 와 좀 더 실제적인 Mysql DB에서 데이터를 읽어와서 뿌려주는데까지 한번 해보기로 했다.

Node.js & Express.js 로 서버를 구성하면 빠른방법으로 Hello World를 찍어 볼 수 있다.

> express --view=pug
> npm install express-graphql graphql

Express Generator를 이용해 프로젝트를 생성하고 npm으로 express-graphql, graphql을 설치했다.

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

var app = express();

var schema = buildSchema(`
  type Query {
    hello: String
  }  
`);

var root = {
  hello: ()=>{
    return 'Hello World'
  },
};

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

코드를 실행하고 http://localhost:3000/graphql 에 접속하면 다음과 같은 화면을 볼 수 있다. 이것은 app.use() 에서 graphiql 옵션을 true로 셋팅하면 나타나는 화면으로 GraphQL의 테스트 인터페이스이다. 여기서 api를 미리 테스트 해볼 수 있다. 자동완성 기능도 지원한다.

Hello World는 찍었다. 대충 이제 다 알았다…는 아니고 현재 가장 많이 쓰고 있는 DB인 MySQL에 연결해서 데이터를 가져오는데 까지 해야한다. Node에서 MySQL 연결과 기타 과정은 생략하고 아래와 같은 코드를 작성 했다.

var app = express();
var schema = buildSchema(`
  type Query {
    user: [User]
  }
  
  type User {
    name: String
    age: Int
    sex: String
  }  
`);

var root = {
  user: ()=>{
    return new Promise(function (resolve) {
      pool.query('select * from users', function (err, res) {
        resolve(res);
      });
    });
  },
};

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

의의 코드를 실행한 결과로 아래와 같은 화면을 얻었다.

분명 데이터는 나왔는데 뭔가 잘못한게 아닌가 싶은 생각이 들었다. 타입도 서버에서 선언해 줘야 하고 쿼리도 서버에서 실행시킨다면 이게 기존의 REST API와 무었이 다른가? 그저 한개의 엔드 포인트를 쓴거 말고 다른게 있나 싶은 생각이 들었다.

그래서 좀 더 검색을 해봤다. 아래 링크에서 하나의 엔드포인트가 중요한 차이점이며 Query의 요청과정에서 파라메타의 차이로 결과를 다르게 가져올 수 있다는 점이 중요하다고 알려줬다.

https://www.holaxprogramming.com/2018/01/20/graphql-vs-restful-api/

결론

나는 이걸 어떻게 써야 하나 하는 문제가 고민이었는데 어차피 현재 Node.js 를 서버로 쓰고 있기 때문에 기존의 REST API에 GraphQL을 더 붙여 써도 괜찮지 않을까 하는 생각을 했다.

개발자들이 뭔가 바꾸고 싶으면 아주 갈아엎는(?) 나쁜 습성이 있지만 그러지 않아도 된다면 엔드 포인트 한두개씩 GraphQL로 바꿔도 무방할지 않을까 싶다.

소스코드는 아래 링크에 있습니다.

https://github.com/bipark/graphql_study

2020/12/10 박병일

OpenCV를 이용한 Face Detection & Blur

Face Detection & Blur

OpenCV 공부중에 주말 프로젝트로 만들어본 Go 언어 기반 얼굴인식 기능 및 블러 처리 프로그램입니다.

얼굴인식 – 이미 학습된 Caffe 기반의 딥러닝 얼굴인식 모델을 활용하여 인식하고 인식된 얼굴 부분을 블러 처리하여 웹요청에 응답합니다.

API 서버 – Go Gin 기반으로 웹 프론트에 용청에 응답을 처리

프론트 – Vue.js & Axios 등으로 Go 서버에 이미지를 전송하고 결과를 받아서 화면에 뿌려줍니다.

Open Source

이 프로젝트의 소스코드는 아래 링크를 참조하세요.

https://github.com/bipark/go-opencv-caffe-facedetect-blur

의존성

실행방법

Flutter 새버전(V1.5)이 나왔는데

2019 구글 IO에서 플러터(Flutter) 새버전이 발표 되었다. 새버전 발표는 늘 있는 일이지만 이번 버전은 그동안 모바일플랫폼(iOS, Android)에서 벗어나 웹과 임베디드까지 지원하겠다고 발표 하면서 좀 더 관심을 가져야겠다고 생각하게 되었다.

image2

개인적으로 개발자의 입장에서 멀티 플렛폼에 대한 환상은 꽤 오래되었지만 그게 현업에서 쓸만하다고 느낀건 ReactNative(이하 RN)가 처음 이었다. 웹 서비스는 React 로 모바일은 ReactNative로 개발해서 iOS와 Android를 한번에 빌드해서 릴리즈 할 수 있었다. 하지만 개발은 꽤나 힘들었다. 개발자 리소스가 부족한 작은 회사에서 멀티 플렛폼을 지원하는 도구에 대한 관심은 어쩔 수 없는 현실이다. 그 차원에서 계속 관심을 가지고 보고 있었는데 마침 오늘 새버전 릴리즈가 있어서 읽으며 아래에 정리 해봤다.

원문링크

https://developers.googleblog.com/2019/05/Flutter-io19.html

아마도 다음에 통합 프로젝트를 기획해야 하는 일이 생긴다면 플러터로 하지 않을까 싶은데 가장 큰 이유는 잘 정리된 문서와 Android Studio에 통합된 디버깅 시스템 때문이라고 말하고 싶다.

2019-05-08 박병일

인텔 뉴럴 컴퓨트 스틱 구입 및 삽질기

페북에서 인텔 뉴럴 컴퓨트 스틱을 보고 무작정 구입을 했다.  가격은 119,000원 DHL을 통해서 배송해 주는데 주문한지 3일만에 도착 했다. 배송비는 공짜다!!

구입링크 – https://kr.mouser.com/ProductDetail/intel/ncsm2485dk/?qs=byeeYqUIh0OB4GXNqgW8aw%3D%3D&countrycode=KR&currencycode=KRW

구입의 목적은 라즈베리파이에서 머신러닝 기반의 Object Detection 을 하고 싶었기 때문이다. 근데 그게 가능 하다는 생각을 한 계기는 아래 링크에서 그게 가능 하다고 봤기 때문이다.

https://raspberrypi4u.blogspot.com/2019/04/raspberry-pi-openvino-intel-movidius.html?fbclid=IwAR193UYVmTEq9HhBFbhJ5zxeQvMZln_DPQVpZslLEXEMFoZWui-pNoPFB40

장비를 받아서 위의 튜토리얼을 따라 해봤다. 튜토리얼을 실행 하기 위해서는 인텔의 OpenVino라는 툴킷이 필요한데 아래 링크에서 툴킷을 OS별로 다운로드 해서 설치 할 수 있다. 일단 튜토리얼은 잘 작동 했다.

https://docs.openvinotoolkit.org/latest/index.html

어! 이거 괞찮은데? 하고 다음 단계가 가능할지 테스트를 계속 했다.

사실… 이 작업의 목적은 Go 언어를 이용해서 이 작업이 가능할지를 알아보고 싶었기 때문이다. 그리고 최근 본 어떤 프로젝트에서 Go언어 기반의 OpenCV를 프로젝트를 보고 잘 결합하면 쓸만한 솔루션이 나오겠다고 생각한것도 이유이다.

Go언어와 OpenCV를 결합한 프로젝트인 gocv 프로젝트는 아래 링크 참조

https://gocv.io

https://github.com/hybridgroup/gocv/tree/master/openvino

게다가 이 프로젝트의 세부에는 OpenVino를 지원하는 코드도 있었기 때문에 모든 문제가 일시에 해결 될것 처럼 보였다.

삽질은 약 일주일간 계속 되었고 Go 언어와 연결하는 것은 실패했다. 위의 링크에서 Python으로 해본 튜토리얼은 내가 따라 해도 잘 되었기 때문에 OpenVino & 뉴럴컴퓨트 스틱이 라즈베리 파이에서 연결이 좋지 않은것은 아니다. 순전히 gocv 에서 지원하는 OpenVino 소스가 오류이거나 버전이 맞지 않아서 생긴 문제라고 추측하고 있다.

혹시 해결하신분이 계시면 도움주세요 ^^;

사실 삽질을 좀 더 하고 싶은 생각은 많지만 너무 많은 시간을 잡아 먹고 있어서 여기까지 하고 뉴럴 컴퓨터 스틱은 포기를 할 참이다. 목적을 달성하는 방법은 많고 꼭 한가지 방법을 고집해야 할 이유도 없기 때문이다.

인텔 뉴럴 컴퓨트 스틱은 기 학습된 모델 데이터를 기반으로 GPU가 없는 IoT 장비 혹은 낮은 컴퓨팅 환경에서 추론(nference) 하는 과정에 성능을 높이는 목적으로 사용하면 전체적으로 장비의 비용을 낮추는 효과를 발휘 할 수 있다고 한다.

2019-05-05 어린이날

박병일

개발자 프로필

안녕하세요 프랙티컬(주) 대표 컨설턴트 & 개발자 박병일입니다. 축적된 IT 지식과 스타트업 컨설팅 및 개발 경험을 기반으로 프랙티컬한 솔루션을 제안하고 개발합니다.

Results-oriented software developer and research professional with 25 years experience in both development and research positions. I make it my goal to create software with the user in mind, creating applications with a useable and intuitive user interface experience. I also understand the importance of creating highly readable and easily maintainable source code. I am constantly striving to learn new technologies and look to ways to better myself in this rapidly changing industry.

보유기술

개발언어(최근 가장 많이 쓰고있는 언어순)

  • Java Script
    • Node.js
      • Vue.js
      • React.js
  • Objective-C
  • Swift
  • C++
    • OpenCV
  • SQL
  • Python
  • Go
  • Delphi(Object Pascal)

주로쓰는 개발툴

  • WebStorm – JS 개발툴
  • XCode – iOS앱 개발툴
  • Goland – Go 언어 개발툴
  • Pycharm – Phthon 개발툴
  • Delphi – Object Pascal(Windows Platform)

플랫폼

  • Mac & OSX – 주로쓰는 OS
  • Ubuntu – 주로쓰는 서버 OS
  • AWS – 주로 사용하는 Cloud

개발경험

기술 관련

  • Productivity(생산성)
    • 개발에 있어서 생산성은 20대때부터 개인적으로 고민해 오던 오래된 화두입니다. 아래에 나열된 기술목록들은 가능한 더 높은 생산성을 가진 도구를 찾기 위한 저의 노력의 과정이라고 할 수 있습니다. 적은 시간으로 더 좋은 결과를 얻게 된다면 비즈니스의 영역에서 비용을 줄일 수 있고 개발자 입장에서는 더 많은 시간을 확보할 수 있습니다. 시간을 어떻게 쓰는가는 개인의 역량 문제겠지만요.
  • iOS(iPhone)
    • 스티브잡스가 했던 첫번째 아이폰 프레젠테이션을 기억합니다. 제 개발자 인생의 전환점이었습니다. 2008년 가을 한국에서 아이폰을 살 수 없어서 아이팟과 맥미니를 바로 구입했고 아이폰 개발자의 길로 접어들었습니다.
  • Objective-C
    • Obj-C는 쉽지 않습니다. 하지만 확실히 직관적입니다. 이 언어를 배우기 위해 3개월을 두문불출하고 정진했습니다. 2009년 4월에 첫번째 앱을 앱스토어에 업로드했습니다. 개인적으로 앱 다운로드 기록은 [오늘의 명언]이 국내에서 누적 100만 다운로드 이상을 경험한 적이 있습니다. 이후 개인앱으로 앱스토어에 업로드한 앱 개수는 약 60여개입니다.
  • Swift
    • 개인적으로 늦게까지 Obj-C를 고수하고 있었습니다. 이유는 Swift 문법의 변화가 너무 심했고 컴파일 속도가 느린것도 한몫 했지요. 다만 최근 많은 안정화 과정을 거쳐서 성능도 좋아졌다는 판단이 서 BBuzzArt의 가장 최근 버전 앱에 도입하여 개발했습니다.
      • 간결한 코드를 유지하면서도 직관성을 유지하려는 Apple의 노력은 인정하지만 미래를 기대하는 것은 쉽지 않다는 개인적 생각입니다.
  • Native App & Hybrid App
    • Native App 개발을 오래 해왔지만 배포가 불편하다는 문제는 소프트웨어가 늘 변화해야만 한다는 명제와 상충합니다. 요구사항은 늘 변하고 빠르게 그 요구사항에 대응해야하지만 성능 역시 보장이 되어야 한다는 아이러니를 늘 안고 개발을 하게 됩니다.
      • 개인적인 경험에 비추어 본다면 어떤 선택을 해야 하는가는 어떤 서비스를 만들 것인가와 관계있습니다. 저는 그동안 컨텐츠 관련 비즈니스가 많았던 관계로 Native에서 Hybrid의 방향으로 계속해서 변화를 모색해왔으며, 2017년 React Native를 도입해서 iOS와 Android를 통합했고 2018년 iOS, Android, Web을 완전히 통합하는 서비스 개발을 마무리했습니다.
  • JavaScript
    • JavaScript의 중요성은 최근 수년간 하늘 높은줄 모르고 올라가고 있습니다. 과거 Jquery 기반의 DOM Controller에서 벗어나 Angular, React, Vue 등등 성공한 프레임워크들이 등장했으며 Node.js에 이르러 서버 개발에까지 손을 뻗치고 있습니다.
      • 특히 React Native는 iOS, Android를 넘어서 Oculus등 다른 플랫폼에 이식되면서 사용성을 늘리고 있습니다. 열심히 더 공부해야 합니다.
  • JQuery
    • 이젠 안씁니다. 아예~ 이말을 하고 싶었습니다. 제발 쓰지 맙시다.
  • AWS
    • 이제는 클라우드 없는 서비스는 생각할 수도 없습니다. 특별히 글로벌로 비즈니스 계획이 있다면 AWS의 선택은 필수적입니다.
      • 아래의 기능들과 연계하면 완전한 시너지를 낼 수 있습니다. 전부 서비스에서 사용해 봤습니다.
      • 지난 2년간 DDOS 때문에 느려진 적은 있었지만 장애가 난 적은 한번도 없었습니다. 너무 AWS 광고한 느낌이긴 하지만 스타트업에서 서비스 인프라에 신경쓰기 시작하면 끝이 없습니다 그돈으로..
      • AWS S3 Storage
      • 생각보다 비싸지 않습니다. 데이터 유실이나 백업 걱정 없이 운영 가능 합니다.
      • AWS CloudFront (CDN)
      • 글로벌 서비스라면 필수 항목입니다. 아카마이와 비교해도 성능이 떨어지지 않습니다.
      • AWS Lambda
      • 마이크로 서비스 구현하기 좋습니다. 아직 개발 생산성이 좋지 않습니다만 Alexa 연동 때문에 써봤습니다.
      • AWS ELB
      • 제 생각에 로드발란서에는 두가지 목적이 있습니다. 서비스 사용자의 폭주에 대비하여 트래픽을 분산하는 효과도 있지만 서버 업그레이드에도 굉장히 유용합니다. 로드발란서를 앞단에 놓고 서비스를 업데이트하면 중단 없이 업데이트를 진행할 수 있어, 낮에도 아무때나 서비스를 변경할 수 있습니다.
      • AWS RDS
      • RDS 기반으로 MySQL을 주로 사용했습니다. DB서버를 RDS를 사용한 이유는 역시 관리의 용이성과 안정성 때문입니다. 백업 걱정이 없고 데이터 유실의 걱정이 없습니다.
  • Google
    • Google Vision API
      • 이미지 컨텐츠가 많은 기업이라면 필수입니다.
      • 모든 기업들이 머신러닝 시스템을 개발하려고 애쓰고 있는데 머신러닝이 비즈니스의 목적이 아니라면 사서 쓰는게 이익이라고 생각합니다.
      • 많이 비싸지 않더군요.
      • https://bipark.github.io/3
    • Google Natural Language API(자연어분석)
      • 비전과 마찬가지로 텍스트 컨텐츠에 대하여 자연어를 머신러닝 방식으로 분석해줍니다. 문법, 문장의 감정, 키워드의 강도 등을 데이터로 뽑아줍니다.
      • 컨텐츠 업체에서 진짜로 해야 하는 머신러닝은 위의 두가지 결과를 기반으로 사용자의 Activity를 연결해서 경향성을 파악하는 용도로 개발하는 것이 가장 좋다고 생각합니다.
    • Google Firebase
      • 만약 서비스를 새로 개발하려고 한다면 추천해 드립니다.
      • 위에 AWS 인프라가 전혀(거의) 필요없습니다.
      • 서비스 개발을 위한 종합 선물세트입니다.
      • 이런게 있는데 왜 안쓰는지 모르겠습니다. 뭐.. 저도 일부만 써봤습니다.
    • Google GA
      • Google Analytics는 필수이지만 키워드와 이벤트를 적절히 사용하면 사용자와 이벤트를 잘 추적할 수 있습니다.
      • Google Tag Manager라는 것도 있는데 개발자 입장에서는 옥상옥 느낌입니다. 마케팅에서 이런 저런 요구를 하는데 그때그때 소스에 이벤트 추적 코드를 넣는게 귀찮습니다. 하지만 아직 뾰족한 방법을 못 찾았습니다.
  • Amazon Alexa
    • 보이스 컨트롤을 이용한 Canvas 컨텐츠 컨트롤을 위해 사용해 봤습니다.
      • 회원을 특정하기 위해서는 OAuth 시스템을 서비스 내에 갖추고 있어야 합니다.
      • 그것을 위해 OAuth를 개발하던 도중에 퇴사했습니다. ㅠ.ㅠ
  • Java Spring
    • 레거시가 있어서 어쩔 수 없이 썼습니다.
      • 하지만 큰 문제 없이 잘 돌아가더군요.
      • 사실 잘 모릅니다. 그래서 전문가를 뽑았습니다.
  • Web(HTML5)
    • React.js
      • 개인적으로는 2015년 부터 사용 경험이 있습니다.
      • 상태 관리를 위한 Redux 사용합니다.
      • 현재 가장 HOT한 프레임워크
      • 페이스북에서 개발하고 밀고 있어서 장기적인 확장 가능성이 높고 사용자가 많습니다.
      • React Native
      • React Framework를 기반으로 iOS, Android에서 Native 성능을 낼 수 있는 하이브리드 Framework
      • 최근 1년간 이 프레임워크를 이용하여 앱을 개발했습니다.
      • https://bipark.github.io/2
      • Next.js
      • React.js가 SPA(Single Page Application)라서 SSR이 안되는 문제를 해결하기 위해 사용되는 서버용 React 프레임워크
      • React.js로 개발할때 검색엔진 또는 소셜 공유를 위한 Bot에 대응하기 위해 사용합니다.
      • Vue.js
      • 최근 가장 떠오르는 Web UI Framework
      • 백오피스 프로젝트 및 스몰 토이 프로젝트에 다수 사용했습니다.
      • 개발이 용이하고, 상태관리가 React에 비해 쉬워서 빠른 구현을 할 수 있습니다.
      • Nuxt.js
      • Vue.js를 위한 SSR용 서버 프레임워크
  • SSR
    • 최근 SPA 기반으로 Web 서비스를 개발하게 됨에 따라 검색엔진 Bot이나 공유 엔진에 대응할 수 없는 문제를 해결하기 위해 개발되었습니다.
    • 검색엔진 & 소셜공유에 대응하기 위해서는 필수적으로 요구되는 기능입니다.
  • SEO
    • Search Engine Optimization
      • 마케팅 활동의 가장 중요한 진입점으로 검색엔진에 대한 대응은 매우 중요합니다.
      • 구글을 비롯한 검색엔진 그리고 소셜 네트워크 공유등에 대한 기술적 및 기능적 대응이 필요합니다.
      • SEO를 잘하면 마케팅 비용을 많이 줄일 수 있습니다.
      • 하지만 SEO는 단시간에 결과를 얻기 힘들고 조심스럽게 오래도록 Optimazation 하는 것이 좋습니다.
      • 블로그 참조 https://bipark.github.io/7
  • Facebook
    • 페이스북은 소셜뿐만이 아니라 프레임워크로 생각해야 합니다.
      • 고객의 유입, 추적, 분석 등의 유저 액티비티와 서비스 결합도를 높이는 쪽으로 개발을 진행하는 것이 좋습니다.
  • 분석, 모니터링
    • 개발 시점에서 Query 성능 분석을 통하여 향후 발생할 수 있는 병목을 미리 제거할 수 있어야 합니다.
      • 운영 상황에서의 실시간 성능 분석은 실제 상황에서 빠르게 대응방법을 찾아낼 수 있습니다.
      • Whatap.oi, Jennifer 등의 분석 서비스를 이용할 수 있습니다.

개인적인 기술

  • IoT 콤포넌트 장비에 관심이 많습니다.
  • 홈 자동화 시스템을 취미로 개발 하기도 했고 스마트 미러를 개발하기도 했습니다.
  • 영어능력
    • 기술문서를 읽고 해석할 수 있습니다.
      • 애플 WWDC, Google I/O등의 컨퍼런스 동영상을 자막없이 들을 수 있습니다.
      • 다수의 해외 출장 & 여행 경험이 있고 기초적인 커뮤니케이션이 가능하고 기술적 커뮤니케이션 역시 가능합니다.

스타트업을 위한 소프트웨어를 개발 합니다

스타트업을 위한 기술 컨설팅과 소프트웨어를 개발 하고 있습니다.

오랫동안 많은 스타트업과 함께 일한 경험을 기반으로 경험이 적은 스타트업에서 일어 날 수 있는 많은 시행 착오를 줄이고 가장 효율적이고 적은 비용으로 목표를 달성 할 수 있는 방법을 제시 합니다. 서비스 플랫폼, 개발도구, 업무의 효율성을 높일 수 있는 다양한 도구와 개발팀 구성, 리크루팅 까지 테크 비즈니스 전반에 걸쳐 함께 협의 하고 목표를 달성하게 위해 협력 합니다.

더 자세한 문의는 rtlink.park@gmail.com 로 해주세요