반응형

.gitignore ?

github, gitlab 등으로 소스 관리 및 배포가 대세입니다. 하지만 개발하는 OS, 플랫폼, IDE 등 사용환경에 따라 각자 관리하는, 배포에 상관없는 파일이나 디렉토리가 생깁니다. 이 파일들을 제외하기 위해서 .gitignore 파일이 사용됩니다.

파일 생성

git init

사용 방법

// flutter 프로젝트 기준으로 정리합니다.

// 지정된 파일 제외
.metadata

// 특정 패턴 파일들 제외
*.lock // lock 확장자 파일 제외
.*    // . 으로 시작하는 파일 제외

// 특정 디렉토리만 삭제. 맨앞에 / 붙여야 합니다.
/android/

// 디렉토리 이하 특정 파일 제외
/android/*.lock   // android/ 이하 lock 확장자 파일 들 제외
반응형
블로그 이미지

센스쟁이 프로그래머 비트센스

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

FlutterFire는 Flutter 앱으로 Firebase를 연동하는 Flutter 플러그인 세트 입니다. 기본은 macos 개발을 위한 정보 확인 중에 찾은 자료라서 플랫폼 별로 모두 설정 확인을 하도록 해보겠습니다.

주의) 1주일 가까이 firebase와 씨름을 한 거 같습니다. 상황이 m1 맥미니를 구입한지 얼마 안되었고, flutter 2.0에 깜짝 발표된 뒤라, 먼가 정리되지 않은 상태에서 버전 이슈라고만 생각을 했었는데... ㅠ,.ㅠ

더보기

기본 시스템 환경

Mac Mini 2020 M1 (8core CPU, 8core GPU, 8GB Ram), macOS Big Sur 11.2.2

Flutter 2.0.2 / Dart 2.12.12 / CocoaPods 1.10.1
Android Studio 4.1.2
Xcode 12.4

설치

firebase 사이트는 iOS, android, Web 앱 설정만 있습니다. 저는 Flutter로 데스크탑 앱을 만들고 있는 중이라, 저의 개인적인 요구에 따라서 macOS 연동을 목표로 정리를 합니다. 하지만 iOS와 설정이 거의 동일하기 때문에 되도록 같이 설명을 하겠습니다.

로컬 머신에서 flutter 프로젝트를 생성하고, Firebase Console에 프로젝트 생성 혹은 기존 프로젝트에서 앱 추가를 합니다.

Cloud Firestore 앱 추가

iOS 앱 추가 - macos 와 공통으로 사용해야할 앱

iOS 번들 ID 확인 (혹시 이미 만들어 놓은 프로젝트에서 번들 ID를 모르신다면 참조하세요)

os(macos)/Runner.xcworkspace 프로젝트를 Xcode로 열고, 최상단 Runner 선택 후 General 탭 > Identity 영역 > Bundle Identifier 항목 확인.

Android Studio 에서 프로젝트 생성을 할때, Project Name을 입력한 다음 페이지에 Package name이 번들 ID 입니다. flutter create [project]로 직접 생성했다면, com.example.project가 기본 번들ID로 생성됩니다.

iOS/macOS 설정 및 소스 일부 변경 (Xcode 활용)

구성 파일 다운로드

GoogleService-Info.plist 파일 다운로드 및 Xcode에 추가

Runner 선택 및 오른쪽 버튼 클릭 > Add Files to "Runner" 클릭 > (Copy items if needed 옵션 선택) > GoogleService-Info.plist 선택 추 (* Runner 폴더 밑으로 추가를 해주셔야 합니다)

Firebase Emulator Suite 사용 설정

Firebase Emulator Suite는 빠르고 복잡하지 않은 설정을 지원하기 위해서 암호화 되지 않은 네트워킹 연결을 사용합니다. macOS는 기본으로 암호회된 네트워킹 연결을 요구합니다. 로컬 머신에서 개발하는 동안 Firebase Emulator Suite를 사용하려면, 작업 중인 macOS 앱에 보안이 되지 않는 로컬 네트워크 서비스에 연결하도록 허용해야 합니다.

ios(macos)/Runnder/Info.plist 에 아래 설정을 추가합니다.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

Deployment Target 변경

iOS 9.0 > 10.0, macOS 10.11 > 10.12

# macos/Podfile
platform :osx, '10.12'

# ios/Podfile
platform :ios, '10.0'

AppDelegate.swift

# 추가 코드
import Firebase

FirebaseApp.configure()
    
# 적용 예
import Cocoa
import FlutterMacOS
import Firebase

@NSApplicationMain
class AppDelegate: FlutterAppDelegate {
  override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    FirebaseApp.configure()
    return true
  }
}

iOS/ macOS 빌드 시간 개선 (Podfile 변경)

현재 Firebase iOS SDK는 Xcode로 빌드시 5분 이상 걸릴 수 있는 약 500k 줄 짜리 c++ 코드에 의존하고 있습니다. 빌드 시간을 크게 단축하기 위해서, ios/Podfile에 1줄을 추가해 프리컴파일된 버전을 사용하도록 합니다.

# ios(macos) /Podfile 추가
pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.26.0'

// 추가 위치
# ...
target 'Runner' do
  pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => $FirebaseSDKVersion
# ...
end

FirebaseSDKVersion 변수는 아래 Native SDK 버전 정의를 참조하세요.

추가로 cocoapods를 1.9.1 이나 그 이상 버전으로 업그레이드 힙니다. gem install cocoapods
(참조 : https://github.com/FirebaseExtended/flutterfire/issues/2751)

저의 경우에는 2021-03-13 현재, 1.10.1로 업그레이드가 되었습니다.

Native SDK 버전 재정의

최상단 platform 정의 바로 밑에 추가해주세요.

# ios(macos)/Podfile

# Override Firebase SDK Version
$FirebaseSDKVersion = '6.33.0'

pod install 실행

실행 테스트

오류 팁

 % flutter run -d macos
Changing current working directory to: /Volumes/Data/Study/flutter/nativeappmaker
Launching lib/main.dart on macOS in debug mode...
Running pod install...                                           1,775ms
In file included from /Users/websniper/Development/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.16.0+1/macos/Classes/FLTFirebaseFirestorePlugin.m:9:
/Users/websniper/Development/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.16.0+1/macos/Classes/Private/FLTFirebaseFirestoreUtils.h:42:4: error: expected a type
+ (FIRFirestoreSource)FIRFirestoreSourceFromArguments:(NSDictionary *_Nonnull)arguments;
   ^                                                                    

FirebaseSDKVersion = '7.4.0'

참조 사이트 : firebase.flutter.dev/docs/overview/

 

 

 

반응형
블로그 이미지

센스쟁이 프로그래머 비트센스

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

하나의 StatefulWidget에서 상태 값을 관리하는 방법은 setState()를 사용하는 것입니다. setState() 없이 상태 값을 관리할 수도 있는데, ValueNotifier를 사용하는 것입니다. ValueNotifier가 좋은 것은 다른 위젯에서 변경한 상태값을 적용할 수 있습니다.

setState() 없이 상태값을 변경하는 예제

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ValueNotifier<int> _counter = ValueNotifier<int>(0); // ValueNotifier 변수 선언
  final Widget goodJob = const Text('Good job!');
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title)
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            ValueListenableBuilder(
              valueListenable: _counter, // 사용할 변수를 지정. _counter가 변경 되면 자동 호출
              builder: (BuildContext context, int value, Widget? child) {
                // value = _counter 로 적용
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Text('$value'),
                    child!, // child는 아래 지정된 위젯으로 치환됨
                  ],
                );
              },
              child: goodJob,
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.plus_one),
        onPressed: () => _counter.value += 1, // _counter.value 값이 수정되면 자동 호출
      ),
    );
  }
}

ValueNotifier로 수정한 값을 다른 위젯에서도 사용하고 싶을때

ValueNotifier가 영향을 미치는 범위는 ValueListenableBuilder() 내 입니다. 전체 위젯에 값을 적용하기 위해서는 setState()를 사용해야 하나 그럴 경우 오류가 발생합니다. build가 완료되기 전에 setState()를 호출하게 되면 빨간 화면을 마주하게 됩니다.

이 오류를 피하면서 setState()를 사용하는 방법은 WidgetsBinding.instance.addPostFrameCallback() 입니다.

addPostFrameCallback()는 페이지 빌드 후에 비동기로 콜백함수를 호출하기 때문에 빨간 화면을 피할 수 없습니다.

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ValueNotifier<int> _counter = ValueNotifier<int>(0); // ValueNotifier 변수 선언
  final Widget goodJob = const Text('Good job!');
  
  int _count = 0;
  
  void setCount(int counter) {
    setState(() {
      _count = counter + 1;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title)
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            ValueListenableBuilder(
              valueListenable: _counter, // 사용할 변수를 지정. _counter가 변경 되면 자동 호출
              builder: (BuildContext context, int value, Widget? child) {
                // setState() 가 있는 함수를 호출
                WidgetsBinding.instance.addPostFrameCallback((_) {
                  setCount(value);
                });
                
                // value = _counter 로 적용
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Text('$value'),
                    child!, // child는 아래 지정된 위젯으로 치환됨
                  ],
                );
              },
              child: goodJob,
            ),
            Container(
              child: Text('$_count')
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.plus_one),
        onPressed: () => _counter.value += 1, // _counter.value 값이 수정되면 자동 호출
      ),
    );
  }
}
반응형
블로그 이미지

센스쟁이 프로그래머 비트센스

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

맥 M1에서 지원하는 PHP 기본 버전은 8.0.3 입니다. 터미널 사용 버전을 다운그레이드 하는 것은 쉬운데, 웹은 여전히 8.0이 사용되고 있었습니다. 웹서버는 valet을 사용하고 있었는데, 생각보다 버전 변경하는 것이 쉽네요. 매뉴얼을 대충 보면 안됩니다. ^^

다운그레이드 설정 전 phpinfo() 상태

※ 아래 내용은 모두 로제타로 실행한 터미널에서 실행해야 합니다. 현재 m1에서는 php 8.0 이상만 지원하는 것으로 보입니다.

% php -v   
PHP 8.0.3 (cli) (built: Mar  4 2021 20:45:17) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.3, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.3, Copyright (c), by Zend Technologies
    
// php 7.3 버전 설치
% brew install php@7.3

// composer 설치
% php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
% php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
% php composer-setup.php
% php -r "unlink('composer-setup.php');"
% mv composer.phar /usr/local/bin/composer

// laravel & valet 설치
% composer global require laravel/installer
% composer global require laravel/valet
% valet install

// valet 사용 버전 변경
% valet use php@7.3

// 터미널 버전도 다운그레이드를 하고 싶다면
% brew unlink php
% brew link php@7.3
% php -v
PHP 7.3.27 (cli) (built: Feb 27 2021 18:04:51) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.27, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.27, Copyright (c) 1999-2018, by Zend Technologies

다운그레이드 후 phpinfo 상태

반응형
블로그 이미지

센스쟁이 프로그래머 비트센스

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

php, laravel, vuejs, vuetify 설치

brew install php@7.3

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
mv composer.phar /usr/local/bin/composer

composer global require laravel/installer
composer global require laravel/valet

valet install

laravel new blog

cd blog

valet park
valet link
valet paths

composer require laravel/ui --dev
php artisan ui vue --auth

npm install & npm run dev
npm install -g @vue/cli

vue add vuetify

npm install @mdi/font -D
npm install moment vuex vue-router

프론트 페이지 추가

resources/views/vue.blade.php 추가

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
</div>
</body>
</html>

resources/js/views/App.vue 추가

<template>
<div>
    <h1>VUE Single page</h1>
</div>
</template>

<script>
export default {
name: "App"
}
</script>

<style scoped>

</style>

resources/js/app.js 수정

import Vue from 'vue';
import App from './views/App';

new Vue({
    render: h => h(App)
}).$mount('#app');

routes/web.php 소스 추가

Route::get('/vue', function () {
    return view('vue');
});

http://blog.test/vue 확인

반응형
블로그 이미지

센스쟁이 프로그래머 비트센스

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요