SwiftUI Tabar/NavigationView (탭바/네비게이션뷰)

최근 Flutter가 좀 지루해져서 – 지루해진 이유는 다음에 쓰기로 하고 – iOS 네이티브 개발을 다시 해보고 싶다는 충동(?)에 SwiftUI 스터디를 시작했다. iOS 개발은 Obj-C 부터 거의 10여년을 하고 있지만 아직 SwiftUI를 써보지 못해서 아래 링크의 튜토리얼을 따라해보고 대략의 감을 잡을 수 있었다.

아래 링크를 따라가면 SwiftUI의 기본적인 Interface에 대한 이해를 얻을 수 있다.

https://developer.apple.com/tutorials/swiftui/creating-and-combining-views

각설하고… 아래 코드는 iOS의 대표적인 UI인 탭바네비게이션 셈플코드이다. Xib 파일도 없고 폼디자이너도 없다. 이렇게 심플하게 코드를 만들 수 있는데 그동안 왜 그렇게 했는지 이해 할 수 없지만… 매우 만족 스럽다. Group, VStack, HStack 등을 이용해서 뷰 상세를 꾸미다보면 CSS에서 본것 같기도 하고 Flutter 에서 본것 같기도한데 각종UI 프레임워크의 좋은 점을 잘 가져와서 만들었다는 생각이 들었다.

//
//  ContentView.swift
//  study1
//
//  Created by Park Billy on 2021/04/20.
//

import SwiftUI

struct View1: View {
    var body: some View {
        
        // 네이게이션뷰로 만들어 줘야 BarTitle을 만들며 상세뷰로 이동 할 수 있다.
        NavigationView {
            // DetailView로 이동
            NavigationLink(destination: DetailView()){
                Text("Go Detail View")
            }
            .navigationBarTitle("첫번째뷰")
        }
        .tabItem { // 탭바 타이틀과 아이콘
            Text("View1")
            Image(systemName: "tray.full")
        }
    }
}

struct View2: View {
    var body: some View {
        NavigationView {
            Text("Hello View2")
                .navigationBarTitle("두번째뷰")
            
        }
        .tabItem {
            Text("View2")
            Image(systemName: "tray")
        }
    }
}

struct DetailView: View {
    var body: some View {
        Text("Hello Detail View")
            .navigationBarTitle("상세뷰")
    }
}

struct ContentView: View {
    var body: some View {
        // 탭바를 만든다 ... 이렇게 간단히?
        TabView {
            View1()
            View2()
        }
    }
}

아래는 실행 결과 – 첫번째뷰에서 [Go Detail View]를 누르면 상세뷰로 이동한다. 상세뷰는 상단에 네비게이션 타이틀이 뷰 스크롤되면 자동으로 상단으로 붙어올라가는 기능이 있다. 그리고 빌드하지 않아도 Xcode에서 프리뷰를 볼 수도 있다.

오랜만에 네이티브로 스토어에 앱을 하나 올려야겠다고 생각했다.

코로나 집콕 프로젝트 #3

이글은 앞선글(http://practical.kr/?p=239)에 연결된다. 작업을 진행 할때마다 페이스북에 올린 짧은글들과 이미지들을 묶어서 정리했다

2021년 2월 20일

수분습도 센서라고 팔고 있는것들은 다 삿다. 왼쪽에 케이블 달려 있는 놈이 전에 말한 불량품이다. 이틀간 맞다가 일주일째에 데이터가 틀려지는 기이한 놈. 왼쪽 두번째가 3주간 테스트 결과를 통과(?)한 놈. 나머지는 이제 테스트 해야할 놈.오늘은 구입한 방수박스에 넣어서 조립을 시작할 예정.

이번주에 알리에서 배송된 여러가지(?) 중에 부루투스 비콘. 이걸 왜 삿냐면 두어주 전에 타임라인에서 누가 Esp32 와 비콘으로 집안에서 고양이 위치 추적을 만든 사람이 있었는데 나름 재미있다고 생각했음. 그리고 최근 Flutter에서 블루투스 기능을 구현 했는데 잘되네… 이후 뭔지 알수없는 이끌림(?)에 구입함. 일단 서랍속으로… ^^;두번째는 쿠팡! 리튬배터리 충전모듈보통 이런건 알리에서 사거나 좀 급하면 디바이스마트에서 사는데 디바이스 마트에서 1300원 하는걸 쿠팡에서 350원에 팔고 있음. 거의 알리수준. 게다가 다음날 배송까지. 알리는 빨라야 2주다. 쓸데는 없지만 10개를 안살수가 없지 않은가… 미안하게 달랑 한개 살수는 없고 ^^;

2021년 2월 21일

방수케이스를 사긴 했는데 전원입력부분의 사이즈를 고려하지 못한 실수로 왼쪽 케이블 홀에 방수 커넥터를 붙이지 못하고 조립완료. 코드 수정하듯이 할수 있으면 좋겠지만 하드웨어는 그러게 쉬운건 아닌듯… 10개쯤 만들면 좀 모양이 나오지 않을까?납땜 실력이 너무 허접해서 뒷면을 보여 드릴 수가 없다요. ㅠㅠ 일단 데이터는 잘 들어오는데 두어주 정도 돌려볼 생각. 앱에 노티피케이션도 추가 해야하는데… 자꾸 다른 아이디어가 따올라서 진행이 잘 안되고 있음. OLED 달아야지 등등… ^^;

2021년 2월 22일

원래 이 고양이는 뒷면에 LED가 있어서 은은하게 발광(?)하는 고양이였는데 내장을 드러내고 최근 작업중이던 ESP32의 mini 타입과 배터리 충전기를 넣고 온습도계를 달아서 온도계를 만들었다.그리고 얼굴에 창(?)을 내고 OLED display를 달아서 현재 온습도를 보여준다. 앱에서 기존에 설치된 토양습도계 아래쪽에 채널을 하나 더 설정해서 데이터를 수집, 조회 할 수 있다.어제 토양습도계를 조립해 놓고 보니 앱을 켜지 않으면 센서에서 데이터를 알 수가 없어서 일단 실내용으로 하나 만들어 봤다.폰트가 너무 작아서 잘인보이는 문제가 좀 있다.

2021년 2월 28일

태양광 패널 2개를 달아서 충전실험시작오늘 날씨가 흐리긴 하지만 Led가 켜지고 충전이 되는듯 보임. 전류가 낮아 안될수도… ESP32를 구동하기위한 충분한 패널의 갯수를 알고 싶어 시작한 실험… 며칠 돌려 보면 알겠지. ESP32는 한시간에 한번씩 전압을 측정해서 전송하고 딥슬립으로 들어가고 한시간 후에 자동으로 깨어나 다시 전압을 서버로 전송하고 또 잠든다.

2021년 3월 5일

오전에 해가 쨍! 해서 장비를 배란다 밖에 내어 놓았더니 지난 일주일간 최고의 충전전압을 보여줬다. 센서를 추가로 달아도 혼자 충방전 해가며 운영 할수 있을것 같기도 하다 ^^

2021년 3월 8일

2월 28일부터 측정을 시작한 태양광 패널 전압은 3월1일부터 날씨가 흐려서 전압이 다소 떨어졌지만 배터리가 ESP32를 구동할만큼 버텨줬고 3일부터 맑은날씨가 계속되면서 3일 하루만에 만충전 상태가 되었고 이후로 오늘까지 디바이스의 측정과 데이터 전송에 무리없이 작동되고 있다. 참고로 이 디바이스는 매시간 딥슬립상태에서 깨어나서 전압을 측정해서 서버에 MQTT로 데이터를 전송하고 슬립상태로 대기한다.오늘부터 추가로 온습도 센서를 붙여서 실험예정

코로나 집콕 프로젝트 #2

이글은 앞선글(http://practical.kr/?p=183)에 연결된다. 작업을 진행 할때마다 페이스북에 올린 짧은글들과 이미지들을 묶어서 정리했다

2021년 1월 15일

https://www.facebook.com/rtlink.park/posts/4243516198997718

ESP32의 문제는 디스플레이가 없어서(당연한거지만… ) 디버깅이 힘들다. USB로 컴퓨터에 물려놓고 로그를 찍어가며 실행을 확인해 볼 수 밖에 없다. 근데 이게 그러라고 만든 기계가 아니니 전원만 넣으면 혼자 돌아가야 한다.며칠전에 데이터가 잘 들어오다가 새벽부터 데이터가 안들오고 다운이 되었는데 원인을 알수가 없었다 – 물론 원인은 내 발코딩이다 당연하지! – 그래도 뭘 잘못했는지는 알아야 해서 MQTT로 로그를 서버에 전송하는 기능을 넣고 앱에서 조회 할 수 있도록 만들었다. 정확한 에러의 원인은 알 수 없지만 최소한 로그를 많이 남기면 그전에 뭘 하고 있었는지는 알 수 있다. 그 다음이 문제였겠지… 결국 그 버그는 잡았지만 버그라는게 그것 뿐일리가 없다.그리고 적당한 타이밍에 알리에서 Pan & Tilt Servo 셋트를 보내 주셨다. 카메라를 원격에서 조정하면 좋겠다고 생각하고 주문했는데 일단 조립만 하고 OTA 다 하면 붙여봐야지!

2021년 1월 16일

https://www.facebook.com/rtlink.park/posts/4246916305324374

간밤에 ESP32의 OTA를 다 만들었다. 이제는 SW 업그레이드를 위해 설치한 장비를 떼러 가지 않아도 된다. 그래서 좀 더 형태를 갖춘 온도 측정기를 만들었다.ESP32-BME680 기반으로 온도, 습도, 압력, VOC를 측정기를 하나 더 만듬. 빵판에 올려 놓으니 그래도 조금은 깔끔해짐. 이건 식당에 설치할 예정.앱 인터페이스가 좀 더 예뻐져야 하는데… 공돌이에겐 진짜 어려운일..^^;

2021년 1월 24일

https://www.facebook.com/rtlink.park/posts/4270100223005982

기존의 일체형 토양수분 측정기의 문제는 화분에 물을 준다던가 실외에 둘때 비가 온다거나 하면 통신모듈(esp32)이 침수된다. 그래서 독립형 센서를 연결했다. 데이터는 대충 맞췄고, 방수박스까지 사놓긴 했는데…왠일인지 동백화분은 시들시들하다. 모든 식물을 다 죽이고 마는 똥손이 이런걸 만들고 있다니… 아이러니 라고..

2021년 1월 28일

https://www.facebook.com/rtlink.park/posts/4282926348390036

ESP32 보드 수집이 취미가 될것 같음. 오늘 도착한 보드는 10개 묶어서 35달러짜리 미니 보드와 아두이노 타입의 조금 큰 보드지난번에 사놓은 케이스에 토양수분 센서까지 붙여서 넣어봤는데 보드만 있는것보다는 뭔가 있어보임. 그동안 여러가지 센서를 테스트 삼아 붙여 봤는데 토양수분, 온습도만 측정하는 전용박스로 프로젝트를 마무리 하는게… 누가 뭐라하는 사람이 없으니 끝이 안나서.. ^^;근데 토양수분센서는 캘리브레이션이 제일 문제… 제로/스팬 환경을 만들기가 너무 어려움

2021년 1월 31일

https://www.facebook.com/rtlink.park/posts/4290248040991200

ESP32에 토양습도 센서를 붙여서 데이터의 거동을 보다가 – 화분에 물을 주면 처음엔 100% 수준에서 쭉 떨어지다가 어느 시점이 되면 약간 증가하는 현상을 보이고 또 떨어지다가 어느 시점에서 약간 증가한 후에 다시 떨어지는 모양의 그래프가 나타난다.처음 데이터가 올라갈땐 이럴리가 없을텐데.. 캘리브레이션 과정에서 제로/스팬이 잘못된게 아닌가 하고 여러 방법으로 코드를 바꿔 봤지만 동일한 결과가 나타났고 좀 더 지켜보니 그런 패턴이 반복된다. 자료를 좀 찾아보니 토질에 따라 다르고 그 결과도 흡수와 배출을 반복하는게 아닌가(? 확실치 않다..) 하는 생각에 이르게 되었다. 뭘 알겠는가… 코딩만 하는 공돌이가.. ^^;엇쨋든 결론은 앱에서 그래프를 축소 확대 할 수 있는 기능이 필요하다는데 이르렀다. 결론이 이상하네.. ^^;

2021년 2월 2일

https://www.facebook.com/rtlink.park/posts/4295899163759421

세상에는 이해할 수 없는 일이 많기도 하지만 가끔은 그런일이 내 거실에서 일어 나기도 한다. 이전 포스팅에서 화분에 꽂아둔 수분센서가 측정한 토양 수분 데이터가 오르고 내리기를 반복하면서 점점 내려간다고 올렸는데 중간에 위치를 바꾸느라 전원이 끊어져 리부트된 이후에 계속해서 올라만 가고 있다.내가 안보는 사이에 누군가 물을 조금씩 붇고 있나? 알수없는 일이다.결국 처음부터 다시 할 수 밖에… 이러면 센서의 정확성을 의심하지 않을 수 없다. 이러니 중국산 센서를 어떻게 믿나… 까지 가고 만다.

2021년 2월 4일

https://www.facebook.com/rtlink.park/posts/4301045793244758

며칠전 올린 포스트에서 중국산 토양수분센서의 데이터가 시간에 따라 상승하는 결과가 나타나서 믿을 수 없다는 생각을 하고 또 다른 중국산(?) 센서를 동시에 같은 화분에 설치해서 약 24시간 측정했다.두 센서의 캘리브레이션이 달라서 절대 수치는 다르지만 대략 데이터의 움직임은 비슷하게 나타났다. 이것들이 같은 중국산이라고.. 서로 짯나? ㅋ 엇쨋든 보이지 않는곳에서 일어나는 변화는 나의 예측과 맞지 않는다. 일단 하루 더 지켜보는 걸로.. 하여간 IOT 측정 네트웍을 만들려던 프로젝트는 센서의 정확도를 확인하는 프로젝트로 변해가고 있는데… 나도 어디로 갈지 잘모르겠다.

2021년 2월 6일

https://www.facebook.com/rtlink.park/posts/4307357982613539

2틀이나 들여서 토양수분, 온도, 습도 챠트를 통합했지만 토양수분 데이터의 변화폭이 너무 적어서 상호관계를 한눈에 알기가 쉽지않다.청색이 온도 챠트인데 환기를 할때마다 고꾸라지는 특성이 있다. ㅋㅋ

2021년 2월 7일

https://www.facebook.com/rtlink.park/posts/4310002775682393

화분1, 2는 동일한 화분에 다른 토양수분센서가 설치되어 있고 화분1은 센서의 성능이 의심되고 있던 센서이다. 일주일만에 이놈이 불량스러운 아웃풋을 내고 있다는 사실을 확인했다. 처음엔 비슷하게 떨어지다가 며칠지나서 토양수분이 다시 서서히 올라감… 아직 원인 파악은 못함.. 그냥 센서 자체가 문제인듯… 여러개 구입했는데 다 똑같음하여간 축적된 데이터는 중요하다 이말씀.. 이힛!

2021년 2월 17일

https://www.facebook.com/rtlink.park/posts/4337140246301979

3주간의 데이터 측정결과 – 이전 포스팅에서 중국산 센서의 정확성을 믿을 수가 없어서 믿을만한(?) 다른 중국산 토양 수분센서를 구해서 측정을 시작한지 대략 3주가 지났다. 센서는 문외한이지만 데이터를 가지고 판단해 본다면 화분1의 센서가 문제가 있다고 판단해도 되지 않을까 싶은데… 이런건 돈받고 팔고 있다니.. 나쁜 사람들 같으니라고… 그동안 투자한 내 시간은 어디서 보장받나 싶지만… 난 한가한 사람이니 참기로 한다. 앱의 UI를 바꿨는데 좀 예뻐진건지… 그게 그거 같기도 하고..

코로나 집콕 프로젝트 #1

의도

2020년은 코로나의 해였다. 년초에 시작한 코로나는 년말을 지나도록 잡히지 않았고 나는 하반기 내내 외부 프로젝트를 줄이고 집에 박혀서 더 많은 삽질을 했다. 이유없는 삽질에 결론을 만들기는 어렵긴 하지만 무언가 결과가 있어야겠다고 생각한게 12월이니… 오래도 결렸다.

하반기에 주로 많이한 일들이 IoT 디바이스를 가지고 놀아본거였고 거기에 Flutter를 이용해서 앱을 두어개 만들어 스토어에 업로드 해본 경험으로 IoT Network을 만들 수 있지 않을까? 하는 생각을 했고 순수하게 우리집안에 온습도 정도를 측정해보자는 생각으로 12월초에 프로젝트를 시도 했다.

12월 16일

페이스북에 뭔가 하고 있다고 공유를 시작했는데… 대략 아래와 같은 기술 스택으로 프로토 타입을 만들어 봤다. 그림에 보이는 보드는 5~6달러 정도의 ESP32 호환 보드로 여기에 MicroPython을 올려서 DHT11 온습도 센서를 연결하고 받은 데이터를 Wifi – MQTT 프로토콜을 이용해서 AWS EC2 서버에 Python & FASTApi 기반으로 개발된 서버에 전송한다.

서버에서 MQTT로 수신한 데이터는 MariaDB에 저장하고 FASTApi는 모바일앱에서 데이터를 요청하면 REST 기반으로 데이터를 보내준다.

앱은 Flutter & Dart 로 개발되었고 iOS & Android를 지원한다. 서버에 측정 데이터를 요청하고 받은 측정 데이터를 보여준다. 대략의 기술 스택은 아래와 같다.

ESP32, Raspberry PI + DHT11 + MicroPython + MQTT + AWS EC2 + MariaDB + Flutter

https://www.facebook.com/rtlink.park/posts/4162860857063253

위에 보이는 라즈베리파이 Zero에도 ESP32와 똑같은 기능의 Python 코드를 별도로 만들어 서버로 전송하고 앱에서 데이터를 조회 할 수 있다. 그렇게 3개의 온습도 측정기를 거실과 베란다에 설치하고 측정을 시작했다.

저렴한 ESP32보드(5달러짜리임..)를 사용한 탓인지 중국산 건전지 탓인지 아니면 둘다의 문제인지 3일이 못가서 건전지가 다 소모 되었고 결국 5V 아답터로 교체했다. ESP32는 하루 한번 정도 다운이 되었는데 코드 버그인지 보드 문제인지 알수가 없었다 – 나중에 알게 되었지만 코드에도 문제가 있었다. ^^;

12월 21일

https://www.facebook.com/rtlink.park/posts/4176739459008726

원래 온습도를 측정하기 시작한 이유는 코로나 시즌이니 가족들의 건강을 위하여 실내환경을 좀더 쾌적하게 유지해 보려는 의도였는데 데이터를 앱으로만 보고 있으니 접근성이 좋지 않았다. 그리고 앱을 계속 디버깅하고 있으니 가족들에게 앱을 설치해주는 일도 쉽지 않았다.

그래서 온습도 전용 디스플레이를 만들어야겠다고 생각하고 아래의 모니터링 장비를 만들었다. 이 모니터는 라즈베이파이4와 전용 디스플레이로 구성되어 있으며 라즈비안OS가 설치되어 있는데 개발은 Vue.js + Nuxt.js로 개발 하였고 웹브라우저를 Full Screen으로 오픈하는 방식으로 화면을 채우고 주기적으로 서버에 REST를 통해 데이터를 요청하고 디스플레이한다.

앱에는 설정된 온습도 범위에 따라 데이터 컬러가 변하는 정도의 알람(?)과 그래프가 추가 되어서 시간별 데이터를 조회 할 수 있게 되었다.

12월 28일

크리스마스에도 달렸다. 코딩말고 뭘 더할게 있겠는가? ㅋ

https://www.facebook.com/rtlink.park/posts/4194455677237104

알리익스프레스에서 거의 1달만에 도착한 토양수분측정기를 동백나무 화분에 설치했다. 이것 역시 ESP32기반의 모듈이라 온습도 측정을 위해 만든 모듈에 토양수분 측정 기능만 추가 했는데 토양 수분 모듈은 기기별로 데이터의 캘리브레이션이 필요한데 일단 이건 나중에 하기로 하고 일반적인 수식을 적용 했더니 데이터가 정확히 맞지는 않는듯 했지만 시간이 지날수록 수분이 줄어들고 있다는것을 확인 할 수 있었다.

앱은 한눈에 모든 기기의 현재 데이터를 확인 할 수 있도록 바꾸었고 불루투스를 이용해서 디바이스의 초기 데이터(디바이스 코드, Wifi SSID)를 셋팅 하기 위하여 Flutter에서 블루투스 전송 작업을 시작했고, 디바이스를 더 붙여 보려는 욕심에 인벤토리를 뒤져서 먼지측정 센서를 찾아냈다. 하지만…

12월 31일

올해 마지막날이라고 해서 들뜬 분위기로 하루를 보낼수는 없다!

알리에서 주문한 새 ESP32 디바이스가 6개 그리고 와이파이 안테나가 한뭉치 왔다. 안테나를 붙이니 보드에 붙어있던 안테나에 비해 도달거리가 늘어났고 그래서 세탁실에도 온습도 측정기를 하나 더 달았다. 그리고 작업중이던 미세먼지 측정기도 연결하기 위해 배선 작업을 했지만 측정기에 문제가 있었는지 아니면 배선을 잘못했는지 아니면 코딩을 잘못했는지… (원인이 너무 많아 디버깅불가) 하여간 데이터가 들어 오지 않았다.

미세먼지 측정기는 가진게 하나밖에 없어서 두번째 시도를 못하고 그냥 두고 있다.

2021년 1월 3일

https://www.facebook.com/rtlink.park/posts/4210535365629135

홈 IoT의 꽃은 리모트 컨트롤이다. 앱에 버튼을 눌러 전등을 끄고 켜거나.. 끄고 켜거나.. 끄고 켜거나… 그거말고 뭘하지?… 하여간 기왕에 하는거 이걸 안하면 안될것 같아서 리모트 컨트롤 기능을 추가했다.

서버에서로 MQTT를 이벤트 방식으로 수신하기 때문에 당연히 같은 방법으로 ESP32에서도 수신 할 수 있을거라고 생각했지만 ESP32에서는 이벤트 방식으로 되지 않았다. 쓰레드 루프를 만들고 계속 확인을 하면서 리모트 컨트롤 데이터를 수신해야 했다.

앱에서는 리모트 컨트롤 인터페이스를 기존의 측정기 화면과 동일한 화면을 쓰게 만들긴 했는데… 나중에 별도의 화면으로 만들어야 될것 같다.

2021년 1월 8일

https://www.facebook.com/rtlink.park/posts/4224526074230064

하다보면 욕심이 생긴다. 데이터만 볼게 아니고 화면도 볼 수 있을까? 인벤토리를 뒤져보니 ESP32-Cam이 나왔다. 이건 언제 삿지? 하여간 붙여야지…

그래서 온습도를 측정중인 동백꽃을 동영상으로 볼 수 있도록 기능을 추가 했는데 MicroPython으로 ESP32-CAM을 연동하는 셈플이 많지않아서 C코드 기반의 MJPEG 스트리밍을 송신하고 앱에서는 웹뷰로 스트리밍을 수신하도록 구성했다. 로컬 Wifi IP로 라우팅되고 있어서 외부에 나가서는 볼 수가 없어서 일단은 공유기에서 포트포워딩을 하도록 만들었다.

아래 링크를 보면 ngrok를 쓸수 있다는 내용이 있는데… 나중에 해봐야겠다.

삽질은 2021년에도 계속 된다…

스캐니(Scanny) – 아이폰용 스캐너앱

저는 개인적으로 개발언어를 스터디 하는 방법으로 마켓 릴리즈를 목표로 제품을 하나 만들어가며 스터디하는 것을 좋아합니다. 목적이 분명하면 생각보다 빠르게 프레임워크의 구조와 내용을 파악할 수 있습니다. 플러터(Flutter)를 스터디하기 시작하면서 벌써 세번째 앱을 앱스토어 릴리즈 했는데요. 앞의 두개는 이것을 만들면서 앱스토어에서 플러터가 어떻게 업로드 되고 돌아가는지를 확인하기 위해 짬짬이 만든것 이었습니다.

스캐니(Scanny)는 폰카메라를 이용해 문서를 촬영해서 자동으로 문서를 인식하고 사진내에서 문서만 추출해서 노이즈를 제거하는 등의 전처리를 거치고 최종적으로 OCR을 위한 깨끗한 문서를 만들어 문자인식(OCR)을 하거나 PDF로 변환하는 기능을 가진 앱입니다.

책을 단위별로 스캔하기위하여 폴더 시스템의 UI를 만들어 책단위 혹은 챕터 단위로 스캔을 할수도 있습니다. PDF 출력을 위하여 리스트에서 전체를 선택하거나 일부 그리고 드랙 & 드롭으로 순서를 바꾸어 PDF를 만들 수도 있습니다.

촬영한 문서는 OCR 문자인식 기능을 이용하여 한글/영문을 자동인식하여 텍스트로 변환하여 저장하고 공유할 수 있습니다. 향후 더 많은 언어를 지원할 계획입니다.

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

앱은 무료 아닙니다. 4,900원입니다. 광고 없습니다. 현재 목표는 앞으로 10년간은 업그레이드를 하려고 생각하고 있습니다. 아래 링크에서 확인하세요.


둘째가 만들어준 아이콘

이 앱은 플러터를 이용해 개발되었기 때문에 당연히 안드로이드를 지원합니다. 플레이스토어에 런칭도 할 수 있습니다. 앞의 테스트 앱에서 테스트 해봤습니다. 하지만 앱의 기능상 카메라에서 문서 인식 기능이 매우 중요한데 안드로이드에서 약간 불안정한 상황이 발생하고 있어서 좀더 보완을 거친후에 업로드 하려고 생각중입니다.

위의 글은 스토어 런칭 광고성 글입니다. 여기서부터는 개발자 입장입니다. 플러터(Flutter)는 모바일 개발을 위한 다할나위없이 훌륭한 도구입니다. 기본적으로 아이폰과 안드로이드를 동시에 지원하는 멀티 플랫폼 개발툴이구요. 참! 최근에는 베타상태 이긴 하지만 웹과 윈도우도 지원하기 시작했습니다. 그리고 프레임워크가 수년째 접어들면서 패키지 라이브러리와 개발자 생태계도 아주 훌륭해 졌습니다.

개인적으로는 지난 수년간 React & Vue 들을 통하여 상태(State)와 그 상태의 변경이 익숙해져 있었기 때문에 여럽지 않게 적응 했을 수도 있지 않았을까 싶지만 네이티브만 개발하던 개발자라면 Provider와 State 에대한 개념이 약간(?)은 걸림돌이 되지 않을까 싶기도 합니다만 매우 좋은 도구이고 충분히 투자 할만한 가치가 있다고 생각합니다.

Change Log

2020-11-13 : V1.0 Initial Release
2020-11-19 : V1.1.0
컬러문서 스캔 기능 추가

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