내가 개발에 사용한 플러터 패키지

플러터 (Flutter)를 이용해서 앱을 개발하는데 패키지는 필수불가결한 요소입니다. 물론 온전히 기본제공하는 위젯(Widget)과 기능만으로 목적하는 기능을 구현할 수도 있겠지만 기본으로 지원하지 않거나 특별한 디자인과 기능을 원하는 요구사항을 만족시키기는 기본 패키지만으로는 매우 어렵습니다. 하지만 공개된 패키지를 잘 사용하면 쉽고 빠르게 목표물에 도달 할 수도 있습니다.

이 글에서는 내가 스캐니(Scanny – http://practical.kr/?p=71) 를 개발하면서 사용한 패키지들을 용도 위주로 정리했습니다. 여러 패키지들을 테스트해서 검토하고 실제 사용해서 릴리즈까지 해봤으니 개발자들에 도움이 되길 바랍니다.

패키지 검색 & 설치

플러터 패키지 검색은 https://pub.dev 에서 키워드를 입력하면 됩니다. 검색 결과에서 Popularity 숫자가 높은것을 선택하면 비교적 안심하고 쓸 수 있습니다. 하지만 자신에게 맞는것을 확인 하려면 결국 설치 해보고 테스트 해보는것이 최선입니다. 일반적으로 github 리파지터리에 셈플 프로젝트가 있으므로 다운 받아서 실행해보고 자신의 프로젝트에 적용하는 것이 좋습니다.

설치는 검색 결과에서 Installing 탭에 있는 dependencies아래에 있는 패키지명과 버전을 복사해서 자신의 프로젝xm 안에 pubspec.yaml 파일에 붙여넣고 터미널에서 아래와 같이 입력하면 설치됩니다.

> flutter pub get

그리고 실제 사용할 코드에서 아래와 같이 Import 해서 사용합니다.

import 'package:url_launcher/url_launcher.dart';

pub.dev 에는 패키지가 굉장히 많습니다. 기존에 iOS/Android를 지원하던 많은 오픈소스 패키지를 Flutter에 맞도록 포팅했기 때문에 거의 필요한건 웬만하면 다 있다고 생각하면 될것 같습니다.

개발에 사용한 패키지 목록

아래는 최근 릴리즈한 스캐니(Scanny)를 개발하며 사용 피키지 목록과 개략적인 설명

Provider - https://pub.dev/packages/provider

상태관리에 거의 필수적으로 쓰는 패키지
image_picker - https://pub.dev/packages/image_picker

사진촬영 과 사용자 앨범에서 이미지를 가지고 올때 쓴다. 파라메카 옵션을 카메라와 앨범을 선택 할 수 있고 해상도 조정도 가능합니다
http - https://pub.dev/packages/http

http 통신을 위해 사용합니다. Rest Api- GET, POST들을 이것으로 했습니다. 또한가지 많이 사용하는 패키지가 Dio(https://pub.dev/packages/dio)가 있는데 장단점이 있고 내가 보기엔 Dio가 조금 더 좋아보이지만 http를 먼저 사용하기 시작해서 그냥 이걸로 쓰고있습니다. 다음엔 Dio를 고려해볼 생각입니다.
photo_view - https://pub.dev/packages/photo_view

이미지 조회용 - 여러장의 이미지를 좌우 스와이프로 조회 할 수 있습니다. 이미지 앨범을 만들때 유용합니다.
modal_progress_hud - https://pub.dev/packages/modal_progress_hud

통신중이거나 처리중에 모달로 대기화면을 만들때 사용했습니다. 이런류의 프로그래스 컨트롤은 워낙 많지만 단순한게 제일 좋다고 생각합니다.
event_bus - https://pub.dev/packages/event_bus

컨트롤러 사이에 데이터를 주고 받을때 쉽게 사용할 수 있는 데이터버스. 사용상에 주의할 점은 싱글톤으로 개발해야 한다는 점입니다. 이벤트버스 클래스를 별도로 만들고 한번만 생성되도록 만들어야 데이터를 주고 받을 수 있습니다. 
toast - https://pub.dev/packages/toast

제목 그대로 토스트 - 간단한 메세지를 뿌립니다. 역시 심플한게 최고죠
path_provider - https://pub.dev/packages/path_provider

폴더명을 얻어올때 사용했습니다. 파일 읽기, 저장할때. pub.dev에 보면 Favorite아이콘이 붙어 있는 패키지가 있는데 이것도 그렇습니다. 좋은거라는 말이겠죠? ^^;
image_crop - https://pub.dev/packages/image_crop

말그대로 이미지 잘라내는 용도
flutter_cache_manager - https://pub.dev/packages/flutter_cache_manager

캐시된 파일을 읽어서 앨범에 저장하거나 공유하는 용도로 사용했습니다.
공유(Share)는 과거 버전에서는 소셜별로 기능별로 구현해야 했지만 최근 프레임워크가 통합관리되어 개발은 편해졌지만 커스터마이즈가 어려워진건 불만요소. 하지만 개발은 편합니다. 사용자 인터페이스도 일관성이 있고.. 아래 두가지 패키지가 미묘하게 기능이 달라서 두개를 한꺼번에 쓰게 되었습니다. 여기도 중국 개발자들이 많네요 중국어 코맨트... 영어로 좀 쓰지 말입니다. 번역기 좋은데 ㅋ

share_extend - https://pub.dev/packages/share_extend
esys_flutter_share - https://pub.dev/packages/esys_flutter_share
keyboard_attachable - https://pub.dev/packages/keyboard_attachable

UI 만들면서 좀 어려웠던것이 키보드와 뷰의 연동이었는데 앱의 키보드가 올라오면 하단의 버튼바가 같이 올라와야 하는데 기존에 디자인과 충돌이 있어서 이걸 사용했는데 구현방법에 차이가 있어서 디자인에 일관성이 나오지 않아 좀 애를 먹었지만 해결은 했습니다.  
easy_localization - https://pub.dev/packages/easy_localization

다국어 지원 - 다국어용 패키지가 많은데 이게 비교적 사용하기 쉽습니다. 언어별로 json 파일을 만들면 됩니다. 이말은 다른건 그보다 복잡하다는 말입니다. 스캐니는 일단 영어, 한글만 지원했습니다. 
url_launcher - https://pub.dev/packages/url_launcher

주어진 URL Schemes에 따라 브라우저를 띄우거나 이메일 클라이언트를 자동으로 호출해 줍니다. 매우 편해요.
package_info - https://pub.dev/packages/package_info

프로젝트 정보 - 버전, 패키지 이름, 빌드번호 등을 자져올 수 있습니다.

플러터 패키지는 잘 쓰면 매우 유용합니다. 하지만 너무 많고 옥석을 골라내기가 힘들기 때문에 꽤 많은 시간을 투자해서 나만의 패키지들을 구성하는게 중요한것 같습니다. 위에 사용한 패키지들의 실제 동작은 아래 링크의 앱 – 스캐니(Scanny) – 에서 확인 할 수 있습니다.

https://apps.apple.com/kr/app/id1529856835

박병일

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