카테고리 보관물: iOS

[iOS] 애플 시뮬레이터 명령어로 실행하는 방법

애플 기기에서 도는 앱을 실험해보기 위해서는 (1) 실장비가 있어야 하거나 (2) 시뮬레이터를 쓰는 방법이 있습니다. 후자 시뮬레이터는 일종의 가상머신으로 애플에서 발표한 실장비의 제품과 운영체제를 실험해볼 수 있는 도구로, 모바일 앱을 실장비 없이 테스트해볼 수 있게 해주는 방법을 제공합니다. Xcode의 일부이지만, xcrun simctl 명령어를 쓰면 명령행에서 제어가 가능합니다.

시뮬레이터를 잘 쓰면 아래와 같은 기능이 가능합니다.

(1) 시뮬레이터를 만들고, 부팅하고, 셧다운하고 지우기
(2) 사진과 영상을 시뮬레이터에 옮기기
(3) 모바일 앱을 설치하고, 삭제하고, 실행하고, 종료하기
(4) 스크린샷을 캡처하고 비디오를 레코딩
(5) 시뮬레이터 로그 확인
(6) 그외

xcrun simctl 명령어는 안드로이드로 치자면 adb가 하는 일을 하는 애플 시뮬레이터 전용 명령어입니다. 위치는 /Applications/Xcode.app/Contents/Developer/usr/bin/simctl 이구요.

명령행을 띄워 일련의 명령어를 흐름대로 입력하면 사용이 가능합니다.

기본 명령어 형식은

이고

라고 입력하면 가능한 subcommand가 나옵니다.

라고 입력하면 Device Types, Runtimes, Devices, Device Pairs 가 나옵니다. 이들 중에서 Device Types와 Runtimes를 조합해서 새로운 시뮬레이터를 셋업하고 부팅해서 실행해볼 수 있습니다.

그러면 문자와 숫자로 이루어진 코드가 출력됩니다. 제 경우 86AA2714-FE27-4FBB-B1B8-A54A3FB2A6A0 였습니다.

이라고 입력하면 방금 만든 시뮬레이터가 부팅이 됩니다.

이라고 입력하면 만들고 부팅한 시뮬레이터가 실행됩니다.

셧다운하고 지우려면 아래 명령어를 입력합니다.

그외에도 맨위에 나열한 작업도 되는데 일단 생략합니다. 앱을 심으려면 일단 앱 파일을 빌드하고

라고 입력하면 설치가 됩니다.

이라고 입력하면 됩니다. com.mycompany.myapp 부분은 앱제작시 설정한대로 입력합니다.

앱을 종료하려면

시뮬레이터에서 앱을 지우려면

이라고 하면 됩니다.

[안드로이드] 안드로이드 앱 용량 줄이기 2

https://shutterpress.info/pc/2023/02/17/%ec%95%88%eb%93%9c%eb%a1%9c%ec%9d%b4%eb%93%9c-%ec%95%b1-%ec%9a%a9%eb%9f%89-%ec%a4%84%ec%9d%b4%ea%b8%b0/

전에 작성했던 글에서 해설하지 않은 부분을 보충합니다.

우선 플러터 작업시 프로젝트 페인에서 android → app → build.gradle 에 아래 라인을 추가합니다. (안드로이드 스튜디오의 경우)

build.gradle의 android { } 블락안에

이 라인을 추가합니다. 제가 참고한 네이버 개발자의 말에 의하면 위 구문을 추가시 앱이 크래시 잘된다고 하는데 아마도 구형 기기라서 그런 것 같네요. 크래시 잘 안되는게 일반 같아서 위 라인을 추가해도 되는 것 같습니다. 위 라인 추가후 Run 메뉴에서 Flutter run ‘main.dart’ in Release Mode 로 빌드하면 각각의 아키텍처에 맞는 APK 파일이 생성됩니다. 타깃이 되는 장비에 맞추어 생성이 되는데 이 경우 위 구문의 효력과, 릴리즈 모드 빌드의 효력이 겹쳐서 앱 파일 크기 조정이 더 잘 됩니다.

또한 APK Analyzer를 쓰면 APK 구성 요소 중에서 APK 파일 크기를 차지하는 파일들과 디렉토리 등을 볼 수 있습니다.

https://developer.android.com/studio/build/apk-analyzer?hl=ko

이 도구를 쓰면 크기를 차지하는 구성 요소들을 잘 선별해낼 수 있어서 최적화에 도움됩니다. 사진을 더 압축한다든지 해서 용량 줄이는데 정보를 주기도 하고, 여러 기능이 지윈되니 써볼만합니다. 실행방법은 위 페이지 링크로 가면 나옵니다.

이 글 1편에서 해설한 것과 이 글에서 설명한 것을 다 적용하니 앱이 150MB에서 15.8MB로 줄었네요 ^^ 안드로이드의 경우 그렇습니다.

참고: 위 본문에 언급한 abi “구문의 효력과, 릴리즈 모드 빌드의 효력이 겹쳐서”라는 말의 의미는 각각 효력이 있어서 동시에 적용하면 결국 파일이 더 작아진다는 것을 말하려고 한 언급입니다. 두 방법이 겹치는 특별한 원리가 있는지는 미상인데 일단 각각 효력이 있는 것이 사실이고 둘다 적용하면 APK 파일 크기가 더 작아집니다. 두 방법 중에 하나를 안적용해도 다른 하나는 잘 작동합니다. 둘다 적용하면 더 좋구요. 위에 언급한 표현으로는 두가지 방법이 긴밀한 연관성이 있게 적용된다는 의미가 되는데, 이게 확인은 안되었습니다. 그냥 두가지 방법을 둘다 적용하면 전에 쓴 글에서 소개한 것만 적용한 것에 비해 APK 파일 크기가 더 줄어든다는 의미입니다. 그냥 설명을 하다보니 표현이 애매해져서 참고 사항으로 보충합니다.

플러터에서 앱 화면 구동까지 딜레이 주기 (카운트 다운)

플러터로 가위바위보 게임을 만들고 있습니다. 우선 가위, 바위, 보 중에서 하나를 누르면 선택지가 입력되어 게임이 진행되는 구조인데요. 채점하는 동안 선택지를 더 못고르게 DateTime() 함수로 2초 동안 못고르게 만들었습니다. 그런데 구조적인 문제로 인해 화면이 로딩되고나서 무심코 유저들이 가위, 바위, 보를 탭하다보면 2초간 못고르게 된게 화면 로드할때부터 효력이 있어서 이것저것 누르다보면 UI에 대한 신뢰감이 저하됩니다.

그래서 화면 로드 후 첫로드일때만 3초간 딜레이를 주고 있습니다. 3초부터 0초까지 카운트 다운 합니다.

우선 아래와 같은 코드면 됩니다.

코드에서 중요한 것은 _timer 변수를 Timer? 타입으로 지정하고 Timer.periodic(duration) 객체를 담아 1초 간격으로 tick해서 적절한 처리를 하는 원리입니다. _timer 변수는 Timer 객체를 담고, 인자로 주어지는 timer로 tick을 조사합니다. tick은 0부터 시작해서 이 함수에서는 1초 간격으로 늘어나는데, 이를 조건문으로 검사해서 setState() 로 갱신해줍니다.

이렇게 실행하면 UI에서

처럼 해둔 위젯에 표시가 갱신됩니다.

이렇게 만든 initCountDown()을 initState() 함수에 기재합니다.

이 위치 이외에 build() 함수 등에 두면 갱신시마다 initCountDown() 이 실행되어 $counter 부분이 점멸하니 반드시 initState()에서 실행하여 화면 갱신되어도 두번 다시 실행되지 않게 합니다.

플러터 ListTile 위젯에 이미지를 제목 위에 추가하는 방법

플러터로 텍스트를 목록으로 표시하고 탭하면 지정한 작동을 하도록 하는 위젯이 꽤 됩니다. 그중에서 간편하게 쓸 수 있는 것이 ListTile 입니다. ListTile은 해시맵과 같은 유형으로 읽어들인 구조적인 데이터의 구조를 입력받아 각 타일을 채워넣는 것이 자동화됩니다. 아래처럼 할 수 있습니다.

이렇게 저장된 데이터를 리스트로 만들어 저장하고 이 값을 map() 으로 받아와서 처리할 수 있습니다. 이 경우 Row()나 Column()의 children: [ ] 속성에 기재하면 여러개의 ListTile이 자동으로 만들어집니다.

위와 같이 하면 map((e) => ListTile() 이 가능해집니다. 여기에 주어진 e 변수는 연관 배열처럼 쓸 수 있습니다. 목록이 자동으로 완성됩니다.

그런데 가끔 목록에 이미지를 추가하고 싶어질 때가 있습니다. 이미지를 추가하려고 하면 ListTile의 경우 leading: 이나 trailing: 속성에 둡니다. 그런데 이 속성에 이미지를 배치하면 좌측이나 우측에 배치되고 위로는 안되서 방법을 찾는데 잘 안찾아지네요. 스택오버플로우처럼 경험 많고 상세하게 답변이 오가는 사이트에서도 뾰족한 답변을 안해줍니다.

구글 공식 API 문서를 살펴보니, ListTile의 title: 속성과 subtitle: 속성은 Widget을 넘겨받는 속성이라, Text외에도 Image.asset()을 넘겨도 되겠다는 생각이 들었습니다. 아니나 다를까, 해보니 됩니다. 위 예제 구조를 그대로 받는다면, title: 에 이미지를 배치하고 subtitle: 에 글의 메타데이터를 배치하는 방법이 가능해집니다.

구체적으로 아래처럼 하면 됩니다.

웹검색만으로는 방법이 잘 안찾아지는데 실력이 늘으니 구글 공식 API 문서 읽다가 힌트를 얻네요.

참고로 thumbnail() 함수는 Image.asset을 포함하는 위젯 모음을 리턴하구요. metainfo() 함수는 제목과 카테고리를 처리하는 Column() 위젯에 Text() 위젯을 집어넣어 리턴합니다. 한마디로 말해 title: 속성에 Image.asset()을 포함하는 처리를 할 수 있다는 것입니다.

위의 코드는 dataList1에 map() => ListTile을 달아 쓰기에 ListTile 안에서만 작동하게 해야 e 변수를 쓸 수 있습니다. 그래서 뭔가 신박한 코드구조를 개발할 수 있을지 모르지만, ListTile이 제공하는 속성을 최대한 이용해야 합니다. 달리 말해 특정 위젯 구조를 무조건 써야할때, 어느 속성에 어느 위젯을 배치할지, 살펴보려면 구글 공식 API 문서를 잘 보면 힌트가 얻어집니다. 위의 예에서는 Text 대신에 Image.asset을 배치하는 힌트를 얻으려고 찾아보았구요. 타위젯도 흡사한게 가능한지는 구글 공식 API 문서에서 찾아보면 됩니다. 각 API 클래스 해설 페이지에서 Properties를 잘 보면 됩니다. Properties를 잘 보면 가능한 속성과 어떤 타입인지 잘 나옵니다.

[플러터] 플러터 쓰다가 생각난 이런 저런 상념

(1) build 함수에 위젯 주렁주렁 달기
build 함수에 return 문에 위젯을 배치해서 처리하는 것이 플러터의 특징이다. UI 구성을 하다보면 위젯 개수가 많아지고 속성도 많아져서 매우 길게 늘어진다. 이렇게 되면 코드가 가독성도 없고, 무거운 앱인 경우 오버헤드가 있다고 한다. 그래서 고안된 추천 사항은 children: [] 속성 설정이 가능한 위젯을 두고 달아둘 위젯을 클래스나 함수로 분리해서 배치하라는 기법이다. 함수보다는 클래스가 더 오버헤드가 적댄다. 빌드할때 반복빌드하는지의 여부 같다. 난 내 코드가 이렇게 반드시 해야 할줄 알았는데 깃헙을 둘러보다보니 유려한 앱을 만든 타개발자들도 나처럼 return 문에 위젯을 주렁주렁 달아서 쓰더라. 우선 이래도 되는 이유도 만만찮다. 나열해보면

(i) 코드가 분산되면 스크롤을 여러번 해야 해서 불편하다
(ii) PC 하드웨어 발달로 인해 램 크기가 커져서 빌드시 지장이 없는 한도가 있다
(iii) 안드로이드 스튜디오에서 heap에 2GB, VM에 1GB 정도 할당되어 있는데 이 설정이 빌드와 실행에 관여한다면 왠만하면 스택오버플로우 안난다
(iv) 태블릿과 모바일도 사양이 좋아져서 지장없는 한도가 있다
(v) 지금 만드는 앱의 처리가 매우 가볍다. 글은 텍스트로 된 커봤자 10KB도 안되는 길이의 글을 처리하는 앱이고 게임도 3D 리소스가 없다

일단 지금 지식 범위 내에서 테스트안해보고 게워낸 체험담인데 UI 배치 구문은 주렁주렁 달아도 괜찮은 것 같다. 다만, UI 외적인 처리가 보일러 플레이트처럼 안되려면 간결한 코드로 해결하는 프로젝트를 구해서 잘 살펴보는 것은 여전히 필요하다. 오늘 만든 게임 처리 코드도 작동은 하되, 구문이 지저분해보이기도 하는데 이것도 기우인가? 일단 쉬운 리팩토링으로 해야 할게 if 문을 switch 문으로 바꾸는 코드 정도. 나머지는 타개발자들도 그냥 나처럼 하는 게 확인이 되었다.

(2) 어떤 문제인지는 미확인인데 오래된 소스코드를 받아와서 컴파일하다보면 다트와 코틀린, JDK, 의존성 라이브러리들의 버전이 문제가 되는 경우가 많다. IDE가 정확하게 짚어주는 편이라, 링크된 문서를 보면서 하다보면 컴파일이 되는데, 때로는 플러터 코드뿐아닌 안드로이드나 iOS 코드도 직접 수정해야 할때가 있다. 일단 IDE가 짚어준대로 할 수 있는 논리적 범위내에서 잘 작동하는 프로젝트와 흡사한 설정인 경우, 문제가 된 버전을 잘 작동하는 프로젝트의 것을 빌려와서 컴파일하면 잘 되기도 하는데 이게 안되기도 한다. 이런 경우, lib, assets, pubspec.yaml 정도만 복사해두고 프로젝트를 다 밀어버린 후, 플러터 프로젝트를 새로 만들어서 거기에 복사해둔 파일을 덮어씌우고 하면 잘 될때가 많다.

플러터 프로젝트 생성시 안드로이드나 iOS 소스 베이스도 함께 생성하던데, 위에 언급한 다트, 코틀린, JDK, 의존성 라이브러리들의 버전 문제도 있을수 있고, 그레이들 캐시 문제거나 그레이들 설정, 저장소 문제 등등이 겹쳐서 문제가 있을 때 위 방법대로 하면 해결이 되는 경우가 많다. 일단 이 방법 쓰기전에 IDE가 짚어준 문서는 읽어보고 적용해보는게 좋을 수는 있다.

(3) 대충 의식 흐름대로 쓴 글이라 표현이 독자들의 판단 의지보다 내 생각을 표시하는데 주력한 글이 되는데, 여튼 이런 저런 상념을 하고 있다. 플러터는 배운지 두달 정도라 더 다루어보고, 더 다루다가 의자가 발동되면 플러터 API 소스코드도 들여다봐야겠다. GlobalKey 관련해서 조금 해봤는데 늘 하는게 옳다. 특히 컴파일 오류 나면 예외 발생인 경우 실행 순서대로 오류 과정 추적하게 IDE가 배려를 해주는데 다 읽어봐야겠다. 지금까지는 코드 구문 바꿔가면서 했고 그래도 버그는 잡히는데 코드 구문 바꾸기전에 API 소스코드도 좀 봐야하겠다.

(4) 안드로이드 스튜디오에 플러터 플러그인을 설치해서 운용하면 안드로이드 API로 개발할때와 같은 사용성으로 플러터도 개발이 가능해진다. 플러터 프로젝트를 생성할때 멀티플랫폼으로 안드로이드, iOS, 리눅스, 웹, 윈도우 소스코드 베이스도 같이 생성한다. 안드로이드의 경우 그레이들을 빌드용으로 쓰는데 정확한 확인은 안했으나 실행 순서를 생각해보면, 그레이들 설정을 기본값으로 되돌릴때 세심한 주의가 필요한 것 같기도 하다.

안드로이드 스튜디오를 설치할때 그레이들도 설치한다. 그레이들이 설치되고 써봤다든지 하면, 프로젝트 루트에 생성된 android 디렉토리 아래 .gradle 디렉토리가 생성되어 필요한 파일을 캐시해두기도 하고 빌드할때 필요한 설정들이 일반적인 방법으로는 고치기가 어려운 파일들이 생성된다. 그런데 빌드 문제가 겹쳐서 그레이들 설정이 의심되는 경우, 이 디렉토리와, 운영체제 사용자 홈디렉토리 아래에도 생성되는 .gradle 디렉토리를 아예 그냥 확 밀어버리면 문제가 있게 되는 것 같기도 하다.

저 두 히든 디렉토리를 지워버리면 그레이들 재설치시, 의존성 라이브러리가 사용자가 지정도 안한 종류가 추가되는 것 같기도 하고, 내가 추가한 패키지가 참조해서 그런지는 미확인인데, 저 두 디렉토리 지우고 그레이들을 다시 설치한 이후부터 앱 컴파일된 apk 파일 크기가 5배가 늘었다.

그냥 강제로 지웠다면 안드로이드 스튜디오를 언인스톨하고 관련 디렉토리를 전부다 지우고 다시 설치하지 않으면 그레이들 설정을 복구하는게 어렵지 않나 싶다.

일단 그레이들은 gradlew.bat 파일에 옵션줘서 조치를 하는 방법이 있을 것 같은데, 디렉토리를 함부로 지우지 말고 저 명령어로 처리하는게 좋을 것 같다. 물론 옵션이 필요한게 제공되면.

이런 저런 상념인데 일단 말은 맞는 것 같다.

[플러터] 플러터로 앱 제작시 같은 자리에 오는 위젯을 조건에 따라 달리 표시하는 방법

플러터의 장점은 UI 배치가 매우 쉬운 배려가 되어 있는 언어라는 점입니다. 위젯 형태로 제공되는 기본 UI 구성 요소가 많이 제공되고, 각각의 위젯 내부에 배치할 수 있는 속성에 위젯 클래스를 배치하기만 하면 UI 구성이 잘 됩니다. 이 장점으로 인해 저도 아주 훌륭한 혜택을 받고 있습니다. 다트와 플러터에서 제공되는 제작사가 만든 UI 위젯뿐아니라, 사용자 생태계에서 제공되는 패키지도 쓰면 아주 쉽게 UI 배치가 되서 좋습니다.

플러터는 화면을 채우는 위젯에 하위 위젯을 배치하면서 UI 구성을 설계해갑니다. main() 함수에서 runApp()으로 호출되는 최상위 위젯 아래에 return 문을 확장해가면서 코딩을 할 수 있습니다.

이 파일을 실행하면 화면에 Hello, world!가 뜰 것입니다. 다른 언어처럼 실행 첫진입 지점을 포함한 파일이 읽히게 되고, 이 파일에 정의된 main() 함수에서 runApp() 함수가 실행됩니다. 위 예제에서는 다른 클래스를 return하지 않고 즉시 Center() 위젯을 불러와서 그 안에 텍스트를 표시하는 Text() 위젯을 배치해서 코딩이 되었습니다.

주목할 것은 Center() 함수 안에 child: 라고 표시된 부분입니다. 플러터에서 제공하는 위젯들은 계층구조를 가지고 배치가 되는데, 배치하는 위치에는 십중팔구 타위젯을 배치할 수 있게 설계된 속성이 옵니다. 위의 경우 child: 라고 표시된 부분이 그러한데요. Center() 위젯이 설계될 당시에 child: 속성을 써서 타위젯을 배치하게 되게 해둔 것입니다. 여기에 올 수 있는 위젯이라면 다 올 수 있습니다. (플러터 API doc에 나옴) 예제에서는 화면 중앙에 배치하기 위해 Center() 위젯을 최상위 위젯으로 두었고 그 안에 Text() 위젯을 써서 문자열을 표시하게 해두었습니다.

때로는 MaterialApp()과 Scaffold() 같은 위젯을 return 해서 보다 더 규모있는 앱을 만들기도 하죠.

이 경우 유의할 것은 child: 와 흡사하면서 여러개의 위젯을 병렬해서 배치가 가능한 위젯들이 있다는 것입니다. Column() 이나 Row()가 그 예로, child: 대신 children: [ ] 과 같은 속성이 제공되면, [ ] 안에 여러 위젯을 쉼표로 구분하면서 배치할 수 있게 해서 레이아웃 구성에 효율이 있게 될때가 많습니다.

이 경우 특히 좋은 것은 전역변수로 지정한 변수에 상태값을 대응시켜서 같은 자리에 내용만 바꿔 위젯 표시를 하고 싶을때 가능해게 해준다는 것입니다.

위에 예에서처럼 children: [ ] 내부에 특별한 방법으로 채워주면 실행이 가능한 기능이 있습니다. setState() 함수로 _conditional 값을 조정하면 _conditional 값에 따라 같은 위치에 Text() 값만 바뀌어 표시할 수 있습니다. 조정된 _conditional 이 충족되는 값일때 : 로 구분한 영역의 코드만 재실행되는 것입니다. 이렇게 하면 안내 메시지 표시할때 route 기능 없이도 같은 위치에 다른 표시를 할 수 있게 됩니다.

예를 들면 GestureDectector() 와 같이 onTap: 속성이 제공되는 위젯에서 사용자가 탭한 것을 받아서 setState() 함수로 _conditional 값을 바꿔주면 실행이 됩니다.

이 경우 _conditional 변수가 전역변수여야 하고, setState() 함수가 실행가능해야 합니다. (setState() 실행 가능한 한 조건은 createState() 함수로 State 클래스가 작성되어 있어야 합니다)

설명을 잘한지 모르는데, 일단 흐름은 이해가 될 것입니다. setState() 함수를 실행하는 코드 예시는 아래 링크에서 힌트를 얻어보세요.

https://docs.flutter.dev/development/ui/interactive

참고가 되셨을 것 입니다.

플러터와 macOS로 iOS 앱 빌드하기에 따른 사양 문제

제가 쓰는 맥 머신은 맥 미니 M2 8GB 256GB SSD 깡통 제품입니다. 플러터로 앱 개발을 할때 iOS 앱 빌드는 맥 머신에서만 되는 체제라 구했는데 다들 램 크기에 대한 갑론을박을 하네요. 일단 램이 크면 빌드시 큰 규모의 빌드에 강합니다. 맥 미니는 macOS Ventura 부팅시 첫부팅에는 4GB 이하의 램이 남는데, 이를 생각하면 램을 크게 커스텀해서 주문하는게 좋다고 합니다. 그런데 이런 조건도 생각해보면 깡통으로 돌려도 괜찮은 경우가 있습니다.

(1) 앱스토어에서 찾아보면 램상주하면서 특정 시간 동안 안쓰는 램을 비워주는 앱이 있습니다. 이 앱을 이용해서 수동으로 필요할때마다 비워주고 자동으로 비우는 옵션을 켜면 5GB까지도 램이 남네요.

(2) 안드로이드 스튜디오는 살펴보면 IDE에서 쓰는 heap에 2GB, VM에 1GB를 할당하던데 시스템마다 달라지겠으나 램이 5GB 남은 상태에서 빌드시 빌드할 프로젝트 규모에 따라 한도가 정해질 것 같습니다.

(3) vscode 같은 규모가 작지만 플러터도 지원하는 강력한 IDE를 쓰면 규모가 큰 IDE보다 램 활용 여유가 남습니다.

(4) 애플 태블릿이나 아이폰이 있으면 시뮬레이터 안써도 되서 램이 더 남습니다. (안드로이드는 에뮬레이터라고 하고 애플은 시뮬레이터라고 하는데 둘다 가상머신에서 실장비를 흉내내는 경우로, 이역시도 멀티태스킹으로 IDE와 웹브라우저, 가상머신을 동시에 띄우고 작업하는 것을 말하는 것입니다)

(5) 이 경우 vscode로 작업후 빌드하고 vscode를 종료한후, xcrun simctl 명령어로 시뮬레이터에 빌드한 앱을 심고 동작시키면 실장비 없이 램을 더 잘 활용가능해집니다.

(6) 프로그래밍 작업시에도 웹문서를 참조할때 여러개의 탭을 웹브라우저에 띄우고 쓰는데 이 경우에도 최대한 램을 덜 차지하는 웹브라우저를 쓰면 됩니다.

(7) 동시에 띄워야 할 프로그램도 다시 띄우는데 큰 속도저하가 없네요. 특별한 조건만 아니라면, SSD에서 로드해서 실행하는 것이라, 불편이 안큽니다.

(8) 그리고 플러터앱이 아주 무거운 3D 게임이 아니라면 (예: 수십킬로바이트 텍스트에 작은 크기의 그림파일을 쓰는 정보제공앱) 시뮬레이터에서 작업시 큰 무리가 없죠.

(9) 타개발자들 의견도 갈리는데 (a) 램은 우선 크면 좋다. (b) 그러나 8GB 깡통 사양도 나쁘다는 말이 아니다. (c) 질문자의 조건을 완전하게 모를때 답변하면 안전빵으로 16GB로 가라고 하는데 이 경우에도 불편이 없는 경우에는 쓰는게 지장이 없는 방법이 있다. (d) 느려진다는 보고는 일차적으로 존중해야 하는데 실재로 써보면 아닌 경우가 있다 = 하드웨어와 소프트웨어 조합에 의하면 포괄적인 조건이라고 기술된 바가 커버하지 못하는 경우가 있다. (e) 그럼에도 개발자가 제시하면 그게 어떤 경우 안통하면 개발자가 속이는 것과 같아서 16GB 램을 추천한다. (f) 8GB도 크게 안나쁜 조건을 잘 생각하면 비용 많이 안들여도 된다.

(10) 포토샵이나 애프터이펙트 등의 CG처리 프로그램은 무조건 16GB 이상 램이 좋은데, 규모 작은 앱 개발할 것이면 괜찮다. 집에 이들 작업을 커버할 PC가 있다면, 맥 머신은 깡통으로 해도 무리가 없다.

이러한 것을 실재로 해보면 확신이 되는데 다들 구입전에는 확인을 못하고, 애플 스토어가도 이런 테스트를 못하는 것도 겹쳐서 갑론을박 되는데, 제일 포괄적인 답변은 (i) 우선 비용이 충분하면 램을 16GB 이상 달아라 (ii) 세부를 조정할 아이디어가 있으면 깡통으로 해도 되는 경우가 있다. 이것이 결론입니다.

[안드로이드] 안드로이드 앱 용량 줄이기

본래 28MB 정도 크기로 설치되던 앱이 모종의 이유로 159MB까지 늘어났습니다. 그 이유는 의존성 라이브러리의 비대화, 리소스 파일이 너무 큰 경우 등등의 원인이 있습니다. 이를 해결할때 참조할만한 방법을 소개합니다.

우선 플러터로 안드로이드 스튜디오에서 작업할때를 기준으로 소개합니다.

Project 패널에서 아래 파일을 엽니다.

Project→android→app→build.gradle

그리고 아래 라인을 입력합니다. 우선 defaultConfig 블락 안에

이 라인을 추가하면 현재 시장에서 널리 쓰이는 CPU로 된 장비에 특화되게 빌드를 해서 앱 용량이 작아지는 효과가 있습니다. 더 정확하게 말하자면 시장에서 널리 안쓰이게 된 아키텍처를 빌드에서 제외하는 것입니다.

이 방법과 유사한 방법으로 apk파일을 위 아키텍처에 따라 각각 생성하고 업로드하게 하는 방법이 있는데 개별 apk 파일 크기는 더 줄어들어도 개발자에 의하면 크래시가 잘 되어 위 방법을 추천한댑니다.

그리고 같은 파일에 아래 라인을 입력합니다. buildTypes 안의 release 블락에

를 추가합니다. 이렇게 하면 불필요한 코드를 정리해줍니다. 대략 이런 모양새입니다.

그리고 안드로이드 스튜디오 상단 메뉴에서 Refactor→Remove unused resources 를 선택하여 리팩토링하면 안쓰는 리소스를 정리해줍니다.

그리고 앱 빌드시 상단 메뉴에서 Run→Flutter Run ‘main.dart’ in Release Mode 로 빌드해서 기기에 심어도 디버깅 모드로 할때보다 앱이 2분의 1 더 줄어듭니다.

때로는 플러터 프로젝트 디렉토리에서 android 디렉토리에 들어가서 .\gradlew app:dependencies 명령어로 의존성 라이브러리 검사를 해서 IDE 메뉴에서 삭제하기도 하면 좋다지만 이 단계는 생략하고 위에 방법들만 써도 앱 크기가 3분의 1에서 5분의 1까지 줄어들었습니다.

그래도 변화가 없으면 기기에서 앱을 수동으로 지우고 위에 방법을 모두 실행해보세요. 변화가 있습니다.

[플러터] 안드로이드 앱 실행시 런처 아이콘 표시 화면 안띄우기

플러터로 안드로이드 앱을 만들때 런처 아이콘이 화면에 표시되고 그 다음 메인 화면으로 넘어갑니다. 이 경우 스플래시 화면을 XML 독립적으로 만들었다면 시각적으로 방해가 됩니다. 예를 들면 main.dart에서 splash_screen.dart의 SplashScreen 클래스를 호출해서 스플래시를 표시하는 체제일때, 안드로이드에서 실행시 런처 아이콘이 SplashScreen 클래스보다 우선 표시되어 시각적인 방해가 되죠.

이 경우 안드로이드에서 실행한다면 해당 플러터 프로젝트에서 생성된 android 디렉토리로 가서 리소스 파일로 생성된 style.xml 파일 두개를 수정해야 합니다.

경로는 Project 패널에서 android→app→src→main→res→values→style.xml
경로는 Project 패널에서 android→app→src→main→res→values-night→style.xml

두 파일이고 대충 아래와 같아야 합니다.

res/values/style.xml

res/values-night/style.xml

여기서 중요한 대목은 첫번째 style 지정인 LaunchTheme 엘리먼트 하위 엘리먼트로

를 추가하는 것입니다.

이렇게 해두고 플러터 프로젝트를 빌드하고 실행하면 런처 아이콘이 안뜨고 앱이 실행이 됩니다.

M2 맥 미니 신청해두었습니다

플러터로 멀티플랫폼 모바일 앱 개발을 하는데 iOS용 빌드는 맥에서만 가능합니다. 본래 가격이 좀 쎈 편인 기기들이라 안드로이드 앱을 우선 출시하고 돈벌어 구하려다가 비용 사정이 나아져서 맥 미니 M2 버전을 신청해두었네요. 8GB 모델이고 M2도 8코어 CPU에 10코어 GPU 라는데 우선 플러터 개발을 위한 머신으로 신청했고, 어느 정도 성능이 나온다면 캡처 장치를 연결할 목적으로도 쓰고 싶은데요. 선더볼트 4 포트가 2개 있어서 연결하면 되는데, SSD가 256GB 이고 따로 다른 SSD가 안달려 있어서 ProRes 캡처가 필요할때 SSD 성능이 어떨련지 궁금하네요. 캡처 장치가 선더볼트 3에 무압축 코덱을 지원하는데 무압축으로 캡처받으면 SSD가 macOS 설치된 SSD라, 분리된 SSD가 아니라서 어떻게 될지 미상입니다. 왠만하면 잘 되겠죠.

대략적인 사양은 아래와 같습니다.

M2 프로세서가 좋다고 하는데 일단 제가 신청한 제품 CPU는 M2 Pro 가 아닌 M2 이구요. Xcode를 주로 돌릴 생각인데 빌드가 잘 될지 미상입니다. 규모가 안큰 프로젝트들이 될 것 같고 macOS은 어떤지 모르지만 부팅하고나서 6GB 이상만 여분이 있으면 컴파일할때도 크게 지장이 없을 것 같습니다. 전에 들은바로는 컴파일시 램이 8GB 밖에 안되면 안된다는 의견도 있던데요. 스택과 VM에 램을 최대한 할당해볼 생각입니다. 여의치 않으면 램 증설하거나요.

그런데 업글이 가능한지는 직접 봐야 하는데 일단 구입하고나면 업글이 불가능하다는 말이 있네요. 아무래도 밀폐된 케이스라서 그런 듯한데 아마존에서 구해서 할부 한달 지불 비용을 낮출 수 있었으나 램은 기본탑재 크기인 8GB 그대로입니다. 구입후에도 업글이 되면 좋겠습니다. 케이스를 여는게 가능하다면요. 램말고 보조기억장치도 SSD를 하나 더 달거나 램을 직접 더 달거나 등등의 작업이 안되면 어떡할까요. 그래도 초기 세팅된 하드웨어로도 가능할 것 같긴 한데요.

일단 Xcode 잘 돌아가면 됩니다. 하지만 캡처 기능의 경우 SSD 하나 더 못달면 OS를 설치한 SSD로 캡처도 처리해야 하는데 잘 될지 확인해봐야 하겠습니다. SSD니, 과부하가 늦게 올테지만 코덱에 따라서는 문제가 있을 것 같기도 합니다.

여튼 주목적이 플러터로 iOS 앱 개발도 하는 것이라 앱 테스트 용도로 앞으로 비용 추이봐서 아이폰이나 아이패드도 구해야 하는데 비용이 넘칠 수도 있습니다. 비용이 넘치면 iOS 실행 테스트는 에뮬레이터로 버텨야 할 것 같습니다. 이번달에서도 비용이 거의 커버할 것 같으나 일단 살펴봐야 합니다.

M2 맥 미니 머신을 구하면 좋은 점은

(1) iOS 앱 개발 가능
(2) M1 맥 미니 제품에 비해 100불 저렴함
(3) ProRes 캡처 가능

입니다.

이정도로 대략 생각을 표현해봅니다.

잘써야죠.

https://macmini.inf-news.com/

아무래도 M2가 SoC인 것 같습니다. 해체하는 영상이 있는데 로직보드가 굉장히 작네요. ARM 계열입니다. CPU의 기능들을 담당하는 컴포넌트와 GPU, Neural Processor, WiFi 등이 한칩에 들어간 것 같습니다. 확인해보면 이중에 몇개는 아닐 수 있더라도 SoC의 정의가 그러하네요. 그래서 작은 크기로도 성능이 나오는 것 같습니다.


아마존 캐나다에서는 애플 캐나다에서보다 더 낮은 한달 비용으로 할부를 더 세부적으로 고르는게 되는 것 같습니다. 물론 할부 기간을 늘리고 한달 비용을 낮추면 이자가 붙기도 하네요. 일단 구입적으로 메리트가 있는게 아마존 캐나다에서 애플 스토어 채널을 이용하는 것 같습니다.


참고로 애플 캐나다와 아마존 캐나다에서 형성된 가격이 M2 기종이 M1 기종 동급 라인업보다 100불이 저렴하네요. 새로 나온 제품인데…