Skip to content

Commit

Permalink
Create ch01.md (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
deepbig authored Jul 21, 2024
1 parent 470faa9 commit 5a57204
Showing 1 changed file with 363 additions and 0 deletions.
363 changes: 363 additions & 0 deletions hong/flutter/코드팩도리의 플러터 프로그래밍/ch01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
# 코드팩토리의 플러터 프로그래밍

## 설치

macOS 개발 환경 구축하기

https://docs.flutter.dev/get-started/install/macos/mobile-ios

### 1. Development tools 설치

- [Xcode](https://developer.apple.com/xcode/) : debug와 compile을 하기 위해 필요. flutter app을 iOS용으로 빌드하려면 반드시 필요.
- [CocoaPods](https://cocoapods.org/) : Flutter plugin을 통해 컴파일하기 위해 필요.
- CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. It has over 100 thousand libraries and is used in over 3 million apps. CocoaPods can help you scale your projects elegantly.

### 2. editor 선정 및 flutter plugin 설치

> **Recommended**
>
>
> The Flutter team recommends installing [Visual Studio Code](https://code.visualstudio.com/docs/setup/mac) 1.77 or later and the [Flutter extension for VS Code](https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter). This combination simplifies installing the Flutter SDK.
>
### 3. Flutter SDK 설치

- `flutter_macos_arm64_3.22.2-stable.zip` 파일 다운로드
- unzip하고 path 설정하면 끝.

> macOS는 기본적으로 2가지 종류의 셀을 사용하는데 아래 명령어를 실행해서 어떤 셀을 사용하는지 확인 가능.
>
```kotlin
echo $SHELL
// bash를 사용하는 경우, 아래 두개 중에 택 1
vi ~/.bash_profile
vi ~/.bashrc
// Z shell 을 사용하는 경우
vi ~/.zshrc

// 위 파일에서 아래 라인 추가 (설치 경로임)
export PATH=$HOME/Documents/programs/flutter/bin:$PATH
```

- bash_profile:
- 시스템에 로그인할 때마다 로드됨 (Login Shell에서 실행)
- 대부분 개별 사용자에 대한 설정에 대한 코드들이 들어감.
- bashrc:
- 이미 로그인 한 상태에서 새 터미널 창을 열 때마다 로드됨 (Non-Login Shell에서 실행)

### 4. Configure iOS development

- Xcode 설치가 완료되면 설치한 Xcode 버전을 시스템에서 사용할 Xcode 버전으로 설정해야 함.

```kotlin
sudo sh -c 'xcode-select -s /Applications/Xcode.app/Contents/Developer && xcodebuild -runFirstLaunch'
```

### 5. Configure your target iOS device

Xcode와 함께라면 Flutter app도 iOS device와 simulator를 통해 실행할 수 있음.

- 해당 설정은 개발하면서 차차 진행할 예정..

### 6. 설치 문제 확인

- 설치 과정에서 빠진 환경 설정이나 문제를 확인하기 위한 툴을 실행한다.
- 구글에서 환경 설정의 어려움을 최소화할 `flutter doctor` 를 제공함.
- 문제 확인과 해결 방법을 개발자에게 알려주는 도구.

```kotlin
flutter doctor
```

<img width="789" alt="Screenshot 2024-07-13 at 1 23 41 PM" src="https://github.com/user-attachments/assets/d8ecc098-83ff-4b79-8e8d-9a1f54d127e6">

# 1. 다트 언어 마스터하기

1장에서 기초 문법, 2장에서 객체 지향 프로그래밍, 3장에서 비동기 프로그래밍, 4장에서 다트 3.0 신규 문법 학습.

## 1.1. 다트 소개

- 구글에서 개발, 2011년 10월 공개
- 구글은 크롬에 다트 가상 머신을 심어 자바스크립트를 대체하려 했으나 웹 개발에 혼란을 가져온다는 문제를 극복하지 못하고 결국 다트 언어를 자바스크립트로 완전 컴파일 가능하게 만드는 데 그침.
- 비록 웹에서 자바스크립트를 대체하겠다는 목적은 달성하지 못했지만, 플러터의 인기에 힘입어 모바일 영역에서 다트 언어가 큰 각광을 받고 있음.

다트의 장점

- 다트 언어는 UI를 제작하는 데 최적화되어 있음.
- 완전한 비동기 언어이며 이벤트 기반으로 동작.
- isolate를 이용한 동시성 기능도 제공.
- Null Safty, Spread Operator, Collection If 문 등 효율적으로 UI를 코딩할 수 있는 기능을 제공.
- 효율적인 개발 환경을 제공. 핫 리로드를 통해 코드의 변경 사항을 즉시 화면에 반영해볼 수 있음.
- 멀티 플랫폼에서 로깅 및 디버깅을 하고 실행할 수 있음.
- AOT 컴파일이 가능하기 때문에 어떤 플랫폼에서든 빠른 속도를 제공.
- Ahead Of Time(AOT) 컴파일:
- 목표 시스템의 기계어와 무관하게 중간 언어형태로 배포된 후, 목표 시스템에서 인터프리터나 JIT 컴파일 . 등기계어 번역을 통해 실행되는 중간 언어를 미리 목표 시스템에 맞는 기계어로 번역하는 방식을 뜻함.
- 소스 코드를 미리 컴파일 하는 방식 / 설치 시점에 기계어로 변역
- 미리 컴파일을 해놓기 때문에 속도가 상대적으로 빠르다.
- Just In TIme(JIT) 컴파일:
- 브라우저에서 파일들을 다운로드 한 뒤에 한번 컴파일해서 브라우저 엔진이 실행할 수 있는 저수준 언어로 바꿔준 후, 화면을 렌더링 하는 방식.
- 실행 시점에서 bytecode를 기계어로 번역
- 소스코드가 서버에서 컴파일 되는 것이 아닌 사용자의 브라우저에서 컴파일 되는 방식. 실행 속도가 상대적으로 느리다.
- 자바스크립트로의 완전한 컴파일을 지원.
- 백엔드 프로그래밍을 지원.

다트 언어의 컴파일 플랫폼

- 다트는 모바일이나 데스크톱 기기를 targeting하는 `native platform`과 웹을 targeting하는 `web platform`으로 컴파일 가능.
- 네이티브(x64/ARM): JIT + VM (개발 시), AOT + runtime (배포 시)
- 웹 자바스크립트: dartdevc (개발 시), dart2js (배포 시)
- 소프트웨어를 효율적으로 개발하려면 코드의 변경된 사항을 화면에 반영해보고 수정하는 반복적인 과정이 빠른 사이클로 진행돼야 함. JIT 컴파일 방식은 다트 가상 머신에서 제공하는 기능으로 코드의 변경된 사항을 처음부터 다시 컴파일할 필요 없이 즉시 화면에 반영할 수 있는 핫 리로드 기능, 실시간으로 매트릭스를 확인할 수 있는 기능, 디버깅 기능을 제공 함.

## 1.2. 문법 공부 환경

- https://dartpad.dev/
- 또는 flutter project의 `lib/main.dart` 파일의 main 함수 안에서 코드 추가 후 `dart lib/main.dart`로 실행

## 1.3. 기초 문법

**var**

- 변수는 `var 변수명 = 값` 형식으로 선언
- 하지만 변수에 값이 들어가면 자동으로 타입을 추론하는 타입 추론 기능을 제공하기 때문에 명시적으로 타입을 선언하지 않아도 됨 (실제 코드가 컴파일될 때는 추론된 타입으로 `var` 이 치환됨.
- var 타입은 변수의 값을 사용해서 변수의 타입을 유추하는 키워드. 타입을 한번 유추하면 추론된 타입이 고정됨.
- 따라서, 고정된 변수 타입과 다른 변수 타입의 값을 같은 변수에 다시 저장하려고 하면 에러가 남.

**dynamic**

- 하지만, dynamic 키워드를 사용하면 변수의 타입이 고정되지 않아서 다른 타입의 값을 저장할 수 있음.

```kotlin
void main() {
dunamic name = '';
name = 1;
}
```

**final / const**

- final과 const 키워드는 변수의 값을 처음 선언 후 변경할 수 없음.

```kotlin
final String name = 'roo';
name = 'loo'; // runtime error.

const String name2 = 'roo';
name2 = 'loo'; // build time error
```

- finaldms 런타임, const는 빌드 타임 상수.
- 예: 현재 시간을 가져오는 DateTiome.now() 함수는 `DataTime.now()` 함수가 실행되는 순간의 날짜 및 시간을 제공해준다. 다시 말해서 런타임, 즉 실행을 해봐야 값을 알 수 있음.

```kotlin
final DateTime now = DateTime.now();
print(now);
```

- final 키워드를 사용했으니 now 값이 한 번 저장되면 추후 변경할 수 없음.
- 반면에 const를 사용하면 `에러`가 남. const 로 저장한 변수는 빌드 타임에 값을 알수 있어야 하는데 DateTime.now() 함수는 런타임에 반환되는 값을 알 수 있기 때문

```kotlin
// 에러 발생
const DateTime now = DateTime.now();
```

**정리: 코드를 실행하지 않은 상태에서 값이 확정되면 const, 실행될 때 확정되면 final 사용!**

**변수 타입**

- 모든 변수는 고유의 변수 타입을 갖고 있음.
- var 키워드를 사용하면 자동으로 변수 타입을 유추할 수 있지만 직접적으로 변수 타입을 명시해주면 코드가 더욱 직관적이어서 유지보수가 편해짐.

```dart
String name = 'roo';
int num = 10;
double d = 2.5;
bool isTrue = true;
```

### 1.4 Collection

- 컬렉션은 여러 값을 하나의 변수에 저장할 수 있는 타입.
- List: 여러 값을 순서대로 저장
- Map: 특정 키 값을 기반으로 빠르게 값을 검색
- Set: 중복된 데이터를 제거할 때 사용
- 컬렉션 타입은 서로의 타입으로 자유롭게 형변환이 가능.

List

```dart
List<String> abcList = ['a', 'b', 'c'];
```

- List 타입의 기본 제공 함수
- add():
- List에 값 추가
- where():
- List의 값들을 순서대로 순회하면서 특정 조건에 맞는 값만 필터링
- 순회가 끝나면 유지된 값들을 기반으로 iterable이 반환됨.

```dart
final newList = abcList.where((name) => name == 'a'' || name == 'b').toList();
```
- map():
- List의 값들을 순서대로 순회하면서 값을 변경
- 반환하는 값이 현재의 값을 대체하며 순회가 끝나면 iterable이 반환됨.
```dart
final newList = abcList.map((name) => 'a $name').toList();
```
- reduce():
- List의 값들을 순서대로 순회하면서 매개변수에 입력된 함수를 실행.
- reduce() 함수는 순회할 때마다 값을 쌓아감.
- reduce()는 iterable이 아닌 List 멤버 타입과 같은 타입을 반환.
- 매개변수로 함수를 입력받고 해당 함수는 매개변수 2개를 입력받음.
- 순회가 처음 시작될 때 첫 번째 매개변수(value)는 리스트의 첫 번째 값을 받고, 두 번째 매개변수(element)는 두 번째 값을 받음.
- 이후 첩 번째 매개변수에 기존 순회에서 반환한 값이 들어가는 방식.
```dart
final abc = abcList.reduce((value, element) => value + ', ' + element);
```
- fold()
- fold() 함수는 reduce() 함수의 특수한 형태.
- reduce() 함수는 함수가 실행되는 리스트 요소들의 타입이 같아야 하지만, fold() 함수는 어떠한 타입이든 변환할 수 있음.
- 첫 번째 매개변수에 시작할 값을 지정하고, 두 번째 매개변수에 reduce() 함수와 똑같이 작동하는 함수를 입력함.
- 다만 첫 번째 순회 때 리스트의 첫 번째 값이 아닌 fold() 함수의 첫 번째 매개변수에 입력된 값이 초깃값으로 사용됨.
```dart
final count = abcList.fold<int>(0, (value, element) => value + element.length);
```
Map
- Map은 키를 이용해서 원하는 값을 빠르게 찾는데 중점을 둠.
```dart
Map<String, String dictionary = {
'a': 1,
'b': 2,
'c': 3,
};
print(dictionary.keys); // (a, b, c)
print(dictionary.values); //.(1, 2, 3)
```

Set

- 중복 없는 값들의 집함

```dart
Set<String> members = {'a', 'a', 'a'}
print(members.contains('a')) // true
List<String> memberList = ['a', 'a', 'a'];
print(Set.from(memberList)); // {'a'}
```

enum

- enum은 한 변수의 값을 몇 가지 옵션으로 제한하는 기능.
- 선택지가 제한적일 때 사용.
- String으로 완전 대체할 수 있지만 enum은 기본적으로 자동 완성이 지원되고 정확히 어떤 선택지가 존재하는지 정의해둘 수 있기 때문에 유용.

```dart
enum Status {
approved,
pending,
rejected,
}
void main() {
Status status = Status.approved;
print(status); // Status.approved
}
```

### 1.5. 연산자

연산자로는 수치 연산자, null 값 입력 관련 연산자, 값 비교 연산자, 타입 비교 연산자, 논리 연산자가 있음.

기본 수치 연산자

```dart
double number = 2;
print(number + 2); // 4
print(number - 2); // 0
print(number * 2); // 4
print(number / 2); // 1
print(number % 2); // 0
// 단항 연산도 가능
numeber++;
number--;
number += 2;
number -= 2;
number *= 2;
number /= 2;
```

null 관련 연산자

- null은 아무 값도 없음을 뜻하고, 0과는 다름.
- 다트 언어에서는 변수 타입이 null 값을 가지는지 여부를 직접 지정해줘야 함.
- 타입 키워드를 그대로 사용하면 기본적으로 null 값이 지정될 수 없음.
- 타입 뒤에 `?`를 추가해줘야 null 값이 지정될 수 있음.
- null을 가질 . 수있는 변수에 새로운 값을 추가할 때 `??` 를 사용하면 기존에 null 일 때만 값이 저장되도록 할 수도 있음.

```dart
double? number1 = null;
// 에러 발생
double number2 = null;
// 자동으로 null 값 지정
double? number;
// ??를 사용하면 기존 값이 null일 때만 지정됨.
number ??= 3;
print(number); // 3
// number가 null이 아니므로 3이 유지됨.
number ??= 4;
print(number) // 3
```

값 비교 연산자

```dart
int number1 = 1;
int number2 = 2;
print(number1 > number2); // false
print(number1 < number2); // true
print(number1 >= number2); // false
print(number1 <= number2); // true
print(number1 == number2); // false
print(number1 != number2); // true
```

타입 비교 연산자

```dart
int number1 = 1;
print(number1 is int); // true
print(number1 is String); // false
print(number1 is! int); // false
print(number1 is! String); // true
```

논리 연산자

```dart
bool result = 12 > 10 && 1 > 0; // true
bool result2 = 12 > 13 || 1 > 0; // true
```

###

0 comments on commit 5a57204

Please sign in to comment.