[강의록] Dart 시작하기_노마드코더
https://nomadcoders.co/dart-for-beginners
Dart 시작하기 – 노마드 코더 Nomad Coders
Flutter 앱 개발을 위한 Dart 배우기
nomadcoders.co
INTRODUCTION
#0.1 Why Dart
1. 두 개의 컴파일러 제공 (JIT : for dev, AOT : for run)
2. 모두 Google에서 만듦 -> flutter를 위해 dart 수정이 가능
1. AOT 컴파일러
네이티브(arm, x86, x64), 웹(js)
시스템에 맞게 최적화된 바이너리를 생성하므로 컴파일에 많은 시간이 걸린다.
최종 배포시 사용.
2. JIT 컴파일러
dart VM 사용
코드의 결과를 바로 보여준다.
가상머신에서 동작중이라 조금 느리지만 많은 디버깅 옵션도 지원.
개발중에만 사용하며 배포에는 사용하지 않음.
3. null safety 특성을 가진다.(안전한 프로그램 빌드)
c나 java에서 null 참조하면 오류 발생. dart는 null safety라는 도입하여 안전한 프로그래밍 가능.
4. flutter, dart 둘 다 google 에서 개발 한 것이다 즉 flutter 의 성능 향상을 위해 dart 를 변경 하는 것도 가능하다.
(flutter 가 처음 나왔을 때 AOT 컴파일러 는 없었다. flutter 팀의 요청에 의해 dart 팀에서 개발 한 것.)
#0.2 How To Learn
dart의 모든 것을 배우는 것이 아니고 flutter에서 필요한 기본기만 익히는 것이 목적
1. VSCode 학습
- dart-sdk 설치
- brew install dart-sdk
- vscode의 익스텐션인 flutter 설치
2. dartpad.dev라는 웹 IDE에서 학습
VARIABLES
#1.0 Hello World
1. main 메서드:
- Dart 프로그램의 진입점은 main 함수입니다. 모든 Dart 애플리케이션은 main 함수 내에서 실행되어야 합니다.
- main 함수는 반환 값이 없는 void 타입이어야 하며, 매개변수를 가질 수도 있고 가지지 않을 수도 있습니다.
void main() {
// 여기에 코드 작성
print('Hello, Dart!');
}
2. 세미콜론:
- 세미콜론(;)은 문장의 끝을 나타내는 데 사용됩니다. 각 문장이 끝날 때마다 세미콜론을 반드시 사용해야 합니다.
- 세미콜론을 사용하지 않으면 구문 오류가 발생합니다. (캐스케이드 연산자 기능으로 인해)
void main() {
print('hello world');
}
2-1. Cascade Operator
Dart의 캐스케이드 연산자(..)는 객체의 메서드나 속성을 간결하게 호출할 수 있게 해줍니다. 이를 통해 객체를 생성하고 나서 여러 번 해당 객체에 접근해야 할 때 유용합니다. 캐스케이드 연산자를 사용하면 코드가 더 간결해지고 가독성이 향상됩니다.
캐스케이드 연산자를 사용하지 않은 예제:
void main() {
var sb = StringBuffer();
sb.write('Hello, ');
sb.write('world!');
sb.write(' How are you?');
print(sb.toString());
}
캐스케이드 연산자를 사용한 예제:
void main() {
var sb = StringBuffer()
..write('Hello, ')
..write('world!')
..write(' How are you?');
print(sb.toString());
}
#1.1 The Var Keyword
변수의 타입이 한 번 정해지면 바뀔 수 없습니다.
void main() {
var name = 'John';
String greeting = 'Hello, Dart!';
// name과 greeting은 스트링 타입이므로 이후에 다른 타입으로 바꿀 수 없다.
// name = 2; 불가능
// greeting = 2; 불가능
}
#1.2 Dynamic Type
dart의 dynamic은 매우 유연한 타입으로, 다양한 유형의 값을 저장할 수 있도록 허용한다.
dart의 모든 객체를 포함할 수 있으며, javaScript의 var와 유사하다.
잘못된 타입을 사용하는 경우 런타임 에러가 발생할 수 있으므로 dynamic 타입 사용 시 주의가 필요하다.
1. 동적 타입 지정: dynamic 타입 변수는 초기화할 때 타입을 명시하지 않아도 됩니다. 변수에 할당된 값에 따라 런타임에 타입이 결정됩니다.
// var로 선언만 하는 경우
voide main() {
var name;
}
// dynamic 타입으로 지정하는 경우
void main() {
dynamic variable = 'Hello';
print(variable); // Output: Hello
variable = 42;
print(variable); // Output: 42
variable = true;
print(variable); // Output: true
}
2. 타입 검사가 없음: 컴파일 타임에 타입 검사가 이루어지지 않으므로, 잘못된 타입 사용으로 인한 오류가 런타임에 발생할 수 있습니다.
void main() {
dynamic variable = 'Hello';
// The following line will compile, but will cause a runtime error
// because a string cannot be multiplied by a number.
print(variable * 2); // Runtime error
}
3. 정적 타입과의 차이: Dart에는 var와 dynamic 모두 변수를 선언할 때 사용될 수 있지만, var는 초기화 시 타입이 결정되고 이후 변경될 수 없다는 점에서 다릅니다.
void main() {
var name = 'Alice'; // name is inferred as String
// name = 42; // This will cause a compile-time error
dynamic age = 30;
age = 'thirty'; // This is allowed and will not cause a compile-time error
}
4. Object 타입과의 비교: dynamic 타입은 Object 타입과도 다릅니다. Object는 Dart의 모든 클래스의 최상위 타입이며, 컴파일 타임에 타입 검사가 이루어집니다.
void main() {
Object name = 'Alice';
print(name.length); // 컴파일 타임 에러를 발생시킵니다.
// `name`이 Object 타입으로 처리되며 String 메서드를 가지지 않기 때문입니다.
dynamic nameDynamic = 'Alice';
print(nameDynamic.length); // 이 코드는 동작하지만, 문자열이 아니기에 런타임 에러가 발생합니다.
}
#1.3 Nullable Variables
1. Non-nullable 타입: 기본적으로 모든 변수는 non-nullable입니다. 즉, null 값을 가질 수 없습니다.
2. Nullable 타입: 타입 뒤에 ?를 붙여 nullable로 만들 수 있습니다. 이 경우 해당 변수는 null 값을 가질 수 있습니다.
3. null-aware 연산자: ?., ??, ??=, ! 등을 사용하여 null 안전하게 코드를 작성할 수 있습니다.
void main() {
String? name = "John"; // name은 null일 수 있습니다.
name = null; // 허용됨
// null safe 접근
int? length = name?.length; // name이 null이면 length는 null, 그렇지 않으면 name의 길이
print(length); // null
}
null-aware 연산자:
• ?. : null이 아닐 때만 접근합니다.
• ?? : 앞의 값이 null이면 뒤의 값을 사용합니다.
• ??= : 앞의 값이 null이면 뒤의 값을 할당합니다.
• ! : null이 아님을 단언합니다.
JavaScript의 옵셔널 체이닝
옵셔널 체이닝 연산자(?.)는 객체의 프로퍼티에 접근할 때 해당 프로퍼티가 존재하지 않으면 undefined를 반환합니다. 이는 여러 단계의 중첩된 객체 구조에서 안전하게 프로퍼티에 접근할 수 있도록 도와줍니다.
JavaScript의 옵셔널 체이닝과 Dart의 null safety는 비슷한 목표를 가지고 있지만, JavaScript는 런타임에서 null을 안전하게 처리하고, Dart는 컴파일 타임에서 null 안전성을 보장합니다. Dart의 null safety는 더 엄격한 타입 시스템을 제공하여 null로 인한 오류를 더 확실하게 방지할 수 있습니다.
#1.4 Final Variables
final 변수는 한 번만 설정될 수 있으며, 설정된 후에는 변경할 수 없습니다.
즉, final 키워드를 사용하여 선언된 변수는 초기화된 후에는 값을 재할당할 수 없습니다.
void main() {
final int a = 10; // 정수형 final 변수 선언 및 초기화
// a = 20; // 오류: final 변수는 재할당할 수 없음
final String name = 'Alice'; // 문자열형 final 변수 선언 및 초기화
// name = 'Bob'; // 오류: final 변수는 재할당할 수 없음
print(a); // 출력: 10
print(name); // 출력: Alice
}
final vs const
final
• 런타임 상수: final 변수는 런타임에 초기화될 수 있습니다. 프로그램이 실행되는 동안 값이 결정될 수 있습니다.
const
• 컴파일 타임 상수: const로 선언된 변수는 컴파일 타임에 값이 결정되어야 합니다. 즉, 프로그램이 컴파일될 때 이미 값이 정해져 있어야 합니다.
void main() {
final DateTime now = DateTime.now(); // 런타임에 현재 시간 할당
print(now); // 현재 시간 출력
const DateTime now = DateTime.now(); // 오류: const 변수는 컴파일 타임에 값을 알아야 함
}
#1.4 Late Variables
Dart에서 late 키워드는 변수를 선언할 때 초기값을 나중에 할당할 수 있도록 하는 기능입니다. late 키워드는 특히 다음과 같은 상황에서 유용합니다: