1. Dart 문법 실습

박은서's avatar
Apr 29, 2026
1. Dart 문법 실습
Contents
0. 실습 들어가기 전에…📁 이번 실습에서 다룬 파일🎯 먼저 기억할 핵심1. 실행과 프로그램 시작점1) 실습2) 개념3) 사용법4) Java와 비교2. 변수와 기본 타입1) 실습2) 개념3) 사용법4) 실습에서 확인한 것5) Java와 비교3. 타입 추론: var, dynamic, final1) 실습2) 종류3) Java와 비교4) 공부 포인트4. 함수, 익명 함수, 람다, 메서드1) 실습2) 개념3) 사용법4) 실습에서 확인한 것5) Java와 비교5. 클래스와 객체1) 실습2) 개념3) 실습에서 확인한 것4) Java와 비교6. 생성자1) 실습2) 개념3) 사용법※ 이름 있는 생성자(named constructor)2) 필요한 이유3) Java와 비교4) 언제 유용한가5) 정리7. 선택적 매개변수와 named parameter1) 실습2) 개념3) 왜 좋은가4) 기본값5) Java와 비교8. cascade 연산자 ..1) 실습2) 개념3) 예시4) 장점5) Java와 비교9. null safety: Dart에서 가장 중요한 문법 중 하나1) 기본 null safety2) null 체크와 안전 호출: ?.3) null 병합 연산자: ??4) null assert: !5) late6) 비전공자용 이해7) Java와 비교8) 실무 팁10. 상속, super, final 필드 초기화1) 상속 extends2) super3) 이니셜라이저와 final4) Java와 비교11. mixin: Dart다운 재사용 문법1) 실습2) 개념3) 장점4) Java와 비교5) 공부 포인트12. 추상 클래스와 implements1) 실습2) 개념3) 실습에서 확인한 것4) Java와 비교13. 컬렉션: List, Map, Set1) 실습2) 개념3) 실습에서 확인한 것4) Java와 비교14. 반복문과 컬렉션 함수 map, where1) 실습2) 개념3) 왜 중요한가4) Java와 비교15. spread 연산자와 컬렉션 다루기1) 실습2) 개념3) 어디에 쓰나4) 실습에서 확인한 것5) Java와 비교16. final과 const1) 실습2) 종류3) Java와 비교4) Flutter에서 특히 중요함17. Java와 비교했을 때 꼭 익숙해져야 할 Dart 포인트비슷해서 빠르게 넘어가도 되는 것Dart에서 특히 중요하거나 Java와 다른 것18. 실습 외에 추가로 꼭 알아둘 문법1) required named parameter2) 비동기 처리 Future, async, await3) getter / setter4) enum5) extension6) record / pattern matching7) 라이브러리와 private 규칙19. 비전공자를 위한 공부 순서 추천1단계2단계3단계4단계

0. 실습 들어가기 전에…

📁 이번 실습에서 다룬 파일

  • hello_world.dart : 실행과 main()
  • test01_variable.dart : 변수와 기본 타입
  • test02_type_inference.dart : var, dynamic, final
  • test03_function.dart : 함수, 익명 함수, 람다, 메서드
  • test04_class.dart : 클래스와 객체
  • test05_constructor.dart : 생성자
  • test06_optional_parameter.dart : named parameter, 기본값
  • test07_cascade.dart : cascade 연산자 ..
  • test08_dart_null_safety.dart : null safety
  • test09_null_check.dart : ?., ??
  • test10_null_assert.dart : !
  • test11_late.dart : late
  • test12_extends.dart : 상속
  • test13_super.dart : super
  • test14_final.dart : final 필드와 이니셜라이저
  • test15_mixin.dart : mixin
  • test16_abstract_class.dart : 추상 클래스와 implements
  • test17_collection.dart : List, Map, Set
  • test18_for.dart : for, map, where
  • test19_spread.dart : spread 연산자
  • test20_final_const.dart : finalconst

🎯 먼저 기억할 핵심

  • Dart는 문법이 Java와 비슷하지만, Flutter에서 자주 쓰는 현대적인 문법이 많음
  • 특히 null-safety, named parameter, cascade, mixin, spread, const는 Java보다 Dart 색깔이 강함
  • Flutter 코드를 읽을 때는 "객체를 만들고, named parameter로 값을 넣고, cascade로 연속 설정하고, null-safe하게 처리한다"는 흐름이 반복

1. 실행과 프로그램 시작점

1) 실습

  • 실습 파일: ex01/hello_world.dart
void main() { print("HelloWorld!"); }

2) 개념

  • main()은 프로그램이 시작되는 입구
  • Dart 파일을 실행하면 가장 먼저 main() 호출

3) 사용법

  • 콘솔 앱은 dart 파일명.dart로 실행할 수 있음
  • Flutter 앱도 결국 진입점은 main()

4) Java와 비교

  • Java도 시작점은 public static void main(String[] args)으로 비슷한 개념
  • 차이는 Dart는 훨씬 짧고 간단함

2. 변수와 기본 타입

1) 실습

  • 실습 파일: test01_variable.dart
int n1 = 1; double n2 = 10.1; bool b1 = true; String s1 = "홍길동"; String s3 = "나는 ${s1}이다";

2) 개념

  • 변수 : 값을 담는 상자
  • Dart도 Java처럼 타입 존재
  • 기본적으로 많이 쓰는 타입
    • int : 정수
    • double : 실수
    • bool : 참/거짓
    • String : 문자열

3) 사용법

  • 문자열 안에 ${변수}를 넣으면 문자열 보간 가능
    • ➡️ 문자열과 값을 자연스럽게 섞을 때 매우 자주 사용
String name = "홍길동"; print("내 이름은 ${name}입니다");

4) 실습에서 확인한 것

  • 큰따옴표와 작은따옴표 모두 문자열에 사용 가능
  • runtimeType으로 실제 타입을 확인
  • JSON처럼 보이는 문자열도 그냥 String으로 저장할 수 있음

5) Java와 비교

  • Java와 거의 비슷함
  • 다만 Java에서 문자열 결합을 "이름: " + name처럼 많이 썼다면, Dart에서는 ${}가 더 자연스러움

3. 타입 추론: var, dynamic, final

💡
이 부분은 Java 사용자도 헷갈리기 쉽다.
겉보기에는 다 비슷해 보여도 역할이 다르다.

1) 실습

  • 실습 파일: test02_type_inference.dart
var d1 = 1; dynamic d2 = 1; d2 = true; final d4 = 1;

2) 종류

var

  • var : "타입을 내가 직접 안 쓸게, 컴파일러가 보고 정해줘"
  • 한 번 타입이 정해지면 그 뒤에는 바뀌지 않음
var num = 10; // int로 추론 num = "문자열"; // 🚨에러

dynamic

  • dynamic : 타입 검사를 느슨하게 함
  • 컴파일 시점에 강한 타입 보호를 덜 받음
  • 초보자에게는 편해 보이지만, 실수도 늘어남
dynamic value = 10; value = "문자열"; value = true;

final

  • final은 한 번 값을 넣으면 다시 바꿀 수 없음
  • 한 번만 대입 가능
final name = "ssar"; // name = "cos"; // 에러

3) Java와 비교

  • var는 Java의 지역 변수 타입 추론 var와 비슷함
  • dynamic은 Java의 Object보다 더 느슨함
    • Java의 Object : 메서드 호출 전에 캐스팅이 필요
    • dynamic : 컴파일러가 타입 검사를 강하게 하지 않음
  • final은 Java의 final과 비슷함

4) 공부 포인트

  • 실무에서는 dynamic 남용을 피하는 편이 좋음
  • Flutter에서는 var와 명시 타입, final을 많이 사용됨

4. 함수, 익명 함수, 람다, 메서드

1) 실습

  • 실습 파일: test03_function.dart
int add(int n1, int n2) { return n1 + n2; } final add2 = (n1, n2) { return n1 + n2; }; final add3 = (n1, n2) => n1 + n2;

2) 개념

  • 함수 : 독립된 작업 단위
  • 익명 함수 : 이름 없이 바로 만든 함수
  • 람다 : 한 줄로 짧게 표현한 함수
  • 메서드 : 클래스 안에 들어 있는 함수

3) 사용법

  • Dart에서는 함수도 값처럼 다룰 수 있음
    • ➡️ 함수를 변수에 담거나 다른 함수에 전달할 수 있음
      ⚠️ 이 점은 Flutter에서 매우 중요! 버튼 클릭 시 실행할 코드를 함수로 넘기는 일이 많기 때문

4) 실습에서 확인한 것

  • add()는 일반 함수
  • add2는 익명 함수를 변수에 담은 형태
  • add3는 화살표 문법 =>를 사용한 람다
  • Car.run()은 메서드로, 객체 상태 x를 변경

5) Java와 비교

  • Java도 람다가 있지만, Dart는 더 자연스럽고 자주 사용
    • 특히 Flutter에서는 onPressed: () {} 같은 코드가 매우 흔함
      ➡️ Dart에서는 익명 함수와 람다를 "특수 문법"이 아니라 "일상 문법"으로 받아들이는 것이 좋다.

5. 클래스와 객체

1) 실습

  • 실습 파일: test04_class.dart
class Dog { String name = "Toto"; int thirsty = 100; void drinkWater(Water w) { w.drink(); thirsty -= 50; } }

2) 개념

  • 클래스 : 설계도
  • 객체
    • 설계도로 만든 실제 대상
    • 객체는 상태와 동작을 함께 가짐
      • 상태: name, thirsty
      • 동작: drinkWater()

3) 실습에서 확인한 것

  • Dog 객체가 Water 객체를 받아서 같이 동작
    • ➡️ 객체지향은 "혼자 일하는 객체"보다 "서로 메시지를 주고받는 객체"로 이해하면 쉽다.

4) Java와 비교

  • Java의 클래스와 거의 같다.
  • 다만 Dart는 new를 생략할 수 있어 Java보다 코드가 조금 더 간결함
Dog d1 = Dog();

6. 생성자

1) 실습

  • 실습 파일: test05_constructor.dart
class Dog { String name; int age; String color; int thirsty; Dog(this.name, this.age, this.color, this.thirsty) {} }

2) 개념

  • 생성자
    • 객체가 만들어질 때 처음 실행되는 특별한 메서드
    • 객체의 초기값을 세팅하는 역할

3) 사용법

  • Dart는 this.name처럼 쓰면 "매개변수를 바로 필드에 넣어라"라는 축약 문법을 제공
  • 초보자 기준으로는 아래 두 코드가 같은 의미라고 보면 된다.
Dog(this.name, this.age);
Dog(String name, int age) { this.name = name; this.age = age; }

※ 이름 있는 생성자(named constructor)

1) 개념

  • 실습 파일에는 직접 나오지 않았지만, Dart 생성자를 공부할 때 꼭 같이 알아야 하는 문법
  • 이름 있는 생성자는 같은 클래스 안에서 목적이 다른 생성자를 여러 개 만들고 싶을 때 사용
class User { String name; int age; User(this.name, this.age); User.guest() : name = "guest", age = 0; User.fromMap(Map<String, dynamic> data) : name = data["name"], age = data["age"]; }

2) 필요한 이유

  • 기본 생성자 외에 여러 생성 방식을 만들 수 있음
  • 코드만 봐도 객체가 어떻게 만들어지는지 의미 알 수 있음
  • JSON, Map, 서버 응답을 객체로 바꿀 때 자주 사용
    • User.guest() : 손님 사용자 생성
    • User.fromMap(...) : 데이터에서 사용자 생성이라는 뜻

3) Java와 비교

  • Java에서는 보통 생성자 오버로딩으로 해결
User(String name, int age) { ... } User() { ... }
  • 하지만 Dart의 이름 있는 생성자는 User.guest(), User.fromMap()처럼 이름 자체에 의도를 담을 수 있어서 더 읽기 쉬움
  • 비전공자 입장에서는 "생성자에 이름표를 붙인다"고 이해하면 쉬움

4) 언제 유용한가

  • 로그인 전 임시 사용자 만들기
  • Map이나 JSON 데이터를 객체로 변환하기
  • 테스트용 객체를 빠르게 만들기
  • 기본값이 있는 객체를 의미 있게 생성하기

5) 정리

  • Java보다 생성자 문법이 짧음
  • 필드가 많아질수록 Dart의 축약 문법이 편함
  • 이름 있는 생성자는 Java의 오버로딩보다 의도가 더 잘 드러난다는 장점도 있다.

7. 선택적 매개변수와 named parameter

1) 실습

  • 실습 파일: test06_optional_parameter.dart
class Person { String? name; int money; Person({this.name, this.money = 0}); } Person p1 = Person(name: "홍길동"); Person p2 = Person(name: "임꺽정", money: 10000);

2) 개념

  • 매개변수 이름을 직접 써서 전달할 수 있고, 일부는 생략할 수도 있음
  • Dart의 핵심 장점 중 하나

3) 왜 좋은가

  • 함수 호출만 봐도 의미 알 수 있음
  • 숫자만 여러 개 들어가는 생성자보다 훨씬 읽기 쉬움
Person(name: "홍길동", money: 10000)

4) 기본값

  • money = 0처럼 값을 미리 정해두면, 호출할 때 생략 가능하다.

5) Java와 비교

  • Java에는 이 문법이 없음
    • 생성자 오버로딩, setter 사용, Builder 패턴 사용 등으로 해결
  • Dart의 named parameter는 Java보다 훨씬 읽기 쉽고 실수도 줄여줌
  • Flutter 위젯 코드가 읽히는 이유도 대부분 이 문법 덕분

8. cascade 연산자 ..

1) 실습

  • 실습 파일: test07_cascade.dart
Chef c1 = Chef("홍길동")..cook();

2) 개념

  • 같은 객체에 대해 여러 작업을 연속으로 할 때 쓰는 문법
  • 객체를 다시 이름으로 꺼내지 않고 바로 이어서 작업할 수 있음

3) 예시

final person = Person(name: "ssar") ..money = 1000 ..toString();

4) 장점

  • 코드가 짧아짐
  • 같은 객체를 연속 설정할 때 읽기 편함
  • Flutter 위젯 설정 코드에서 자주 보임

5) Java와 비교

  • Java에는 직접 대응되는 문법이 거의 없음
    • 가장 비슷한 것은 Builder 패턴이나 메서드 체이닝
    • 하지만 cascade는 메서드가 this를 반환하지 않아도 같은 객체에 계속 접근할 수 있다는 점이 다름
  • 이 문법은 Dart 초보자가 처음엔 낯설지만, 익숙해지면 생산성이 높음

9. null safety: Dart에서 가장 중요한 문법 중 하나

  • 실습 파일
    • test08_dart_null_safety.dart
    • test09_null_check.dart
    • test10_null_assert.dart
    • test11_late.dart

1) 기본 null safety

String name = "John"; String? nullableName;

① 개념

  • Dart에서는 null을 가질 수 있는 변수와 없는 변수를 구분
    • String name : null 불가
    • String? name : null 가능
➡️ null 때문에 앱이 죽는 문제를 미리 줄일 수 있다.

② Java와 비교

  • Java는 대부분 참조형이 null을 가질 수 있음
    • 그래서 실행 중 NullPointerException이 자주 발생
  • Dart는 타입 단계에서부터 null 가능성을 표시하게 강제

2) null 체크와 안전 호출: ?.

String? maybeName; int length = maybeName?.length ?? 0;
  • ?.는 값이 null이 아니면 뒤를 실행하고, null이면 그냥 null을 반환

3) null 병합 연산자: ??

String displayName = name ?? "Unknown";
  • 왼쪽 값이 null이면 오른쪽 기본값을 사용한다.

4) null assert: !

String? name = "John"; String nameNotNullable = name!;
  • !는 "내가 책임질게, 지금 이 값은 null 아님"이라고 컴파일러에게 말하는 것
⚠️ 실제로 null이면 런타임 에러 발생

5) late

class MyClass { late String name; MyClass() { name = "홍길동"; } }
  • late는 "지금 바로는 아니지만, 나중에 반드시 값을 넣을게"라는 뜻
  • 초기화 시점이 늦어질 때 사용

6) 비전공자용 이해

  • ? : 비어 있을 수도 있음
  • ?. : 비어 있지 않을 때만 실행
  • ?? : 비어 있으면 기본값 사용
  • ! : 비어 있지 않다고 강하게 주장
  • late : 지금은 비어 있지만 나중에 채울 예정

7) Java와 비교

  • Java에는 이 조합이 없음
    • 보통 if (name != null)을 계속 쓰거나, Optional을 일부 상황에서만 사용
  • Dart는 언어 차원에서 null-safety를 강하게 지원

8) 실무 팁

  • 가능하면 !는 적게 쓰는 것이 좋음
  • ??, ?., 기본값, 방어적 코드를 먼저 고려하는 편이 안전함
  • late는 편리하지만, 실제 초기화가 누락되면 런타임 에러가 날 수 있음

10. 상속, super, final 필드 초기화

  • 실습 파일
    • test12_extends.dart
    • test13_super.dart
    • test14_final.dart

1) 상속 extends

class Burger {} class CheeseBurger extends Burger {}
  • 자식 클래스가 부모 클래스의 특징을 물려받음
  • Java와 거의 같은 개념

2) super

class CheeseBurger extends Burger { CheeseBurger(String name) { super.name = name; } }
  • super는 부모 쪽 속성이나 생성자에 접근할 때 사용

3) 이니셜라이저와 final

class Burger { final String name; Burger(this.name); } class CheeseBurger extends Burger { CheeseBurger(String name) : super(name) {} }
  • final 필드는 한 번만 초기화할 수 있음
    • ➡️ 생성 시점에 값을 꼭 넣어야 한다.
  • 이때 : super(name) 같은 이니셜라이저 문법이 자주 등장

4) Java와 비교

  • 상속 자체는 Java와 비슷
  • 하지만 Dart에서는 생성자 앞뒤 문법과 이니셜라이저 리스트가 처음에는 조금 낯설 수 있음
    • 그래도 "부모 생성자를 먼저 호출해서 final 값을 채운다"고 이해하면 됨

11. mixin: Dart다운 재사용 문법

1) 실습

  • 실습 파일: test15_mixin.dart
mixin Engine { int power = 5000; } mixin Wheel { String wheelName = "4륜 구동 바퀴"; } class BMW with Engine, Wheel {}

2) 개념

  • mixin : 여러 기능 조각을 클래스에 섞어 넣는 문법
  • 상속과 비슷해 보이지만 목적이 다름
    • 상속 : 부모-자식 관계 중심
    • mixin : 기능 재사용 중심

3) 장점

  • BMW는 하나의 부모만 상속 받는 대신, 여러 mixin의 기능을 함께 가질 수 있음

4) Java와 비교

  • Java는 클래스 다중 상속 불가능
  • 인터페이스와 default method로 일부 흉내는 낼 수 있지만, Dart의 mixin은 훨씬 직접적
  • Dart에서 여러 공통 기능을 재사용할 때 매우 유용

5) 공부 포인트

  • Flutter에서도 animation, lifecycle 보조 기능, 공통 유틸 로직을 mixin으로 분리하는 경우가 있음
  • Java 감각으로만 보면 낯설지만, Dart에서는 중요한 문법

12. 추상 클래스와 implements

1) 실습

  • 실습 파일: test16_abstract_class.dart
abstract class Animal { void sound(); } class Dog implements Animal { void sound() { print("멍멍 배고파"); } }

2) 개념

  • 추상 클래스 : 공통 규칙만 정하고, 실제 내용은 자식이 구현하게 하는 클래스

3) 실습에서 확인한 것

  • start(Animal a) 함수는 Dog, Cat, Fish를 모두 받을 수 있음
➡️ 이것이 다형성

4) Java와 비교

  • 개념은 Java와 비슷함
  • 다만 Dart의 implements는 인터페이스처럼 동작하며, 약속된 멤버를 직접 구현해야 함
➡️ 공통 규격을 맞추는 데 좋음

13. 컬렉션: List, Map, Set

1) 실습

  • 실습 파일: test17_collection.dart
List<int> nums = [1, 2, 3, 4]; Map<String, dynamic> user = {"id": 1, "username": "cos"}; Set<int> lotto = {};

2) 개념

  • List : 순서 있는 묶음
  • Map : key-value 묶음
  • Set : 중복 없는 묶음

3) 실습에서 확인한 것

  • List는 인덱스로 접근
  • Map은 key로 값을 꺼냄
  • Set은 로또 번호처럼 중복 제거가 필요할 때 유용함
  • toList()sort()도 사용

4) Java와 비교

  • Java의 List, Map, Set과 개념은 같음
  • 하지만 Dart는 리터럴 문법이 훨씬 간단함
[1, 2, 3] {"id": 1} {1, 2, 3}
➡️이 간결함은 Flutter UI 코드에서 큰 장점이 됨

14. 반복문과 컬렉션 함수 map, where

1) 실습

  • 실습 파일: test18_for.dart
for (int i = 0; i < list.length; i++) { print(list[i]); } var chobabChange = chobab.map((i) => "간장_" + i); var chobabChange2 = chobab.where((i) => i != "광어초밥");

2) 개념

Dart는 전통적인 for문도 쓰고, 함수형 스타일도 많이 사용
  • map() : 각 요소를 변환
  • where() : 조건에 맞는 요소만 필터링

3) 왜 중요한가

  • Flutter에서는 위젯 목록을 만들 때 map()을 매우 많이 사용
  • 예를 들어, 데이터 리스트를 화면 카드 리스트로 바꾸는 식이다.

4) Java와 비교

  • Java의 Stream API와 비슷함
  • 하지만 Dart는 문법이 짧아서 더 자주 사용
➡️ Dart에서 map, where는 특별한 고급 문법이 아니라 기본 습관에 가까움

15. spread 연산자와 컬렉션 다루기

1) 실습

  • 실습 파일: test19_spread.dart
var newList = list.map((i) => {...i}).toList(); var newList2 = [...list2, 4];

2) 개념

  • spread 연산자 ...는 컬렉션 안의 요소를 펼쳐 넣는 문법

3) 어디에 쓰나

  • 기존 리스트 복사
  • 기존 데이터에 새 항목 추가
  • Map 복사 및 일부 값 변경
  • 불변 스타일 코드 작성

4) 실습에서 확인한 것

  • Map 깊은 복사 비슷한 처리
    • var newList = list.map((i) => {...i}).toList();
      ➡️ 리스트 안에 있는 각 Map을 새 Map으로 복사해서, 원본과 새 리스트가 서로 덜 얽히게 만듦
  • 리스트에 값 추가
    • var newList2 = [...list2, 4];
      ➡️ 기존 리스트를 유지하면서 새 리스트를 만들었다.
  • 특정 데이터만 바꾸기
    • var newUser = users .map((user) => user["id"] == 2 ? {...user, "username": "love"} : user) .toList();
    • 원본은 유지하고, 조건에 맞는 데이터만 바꾼 새 목록 만들기
    • Flutter 상태 관리에서 매우 자주 쓰이는 패턴

5) Java와 비교

  • Java에서는 보통 새 컬렉션을 만들고 복사하고 수정하는 코드가 더 길어짐
  • Dart는 spread와 컬렉션 리터럴 덕분에 매우 짧고 읽기 쉽게 쓸 수 있음

16. finalconst

1) 실습

  • 실습 파일: test20_final_const.dart
class Animal { final String name; const Animal(this.name); } Animal a1 = const Animal("사자"); Animal a2 = const Animal("사자");

2) 종류

둘 다 "바꾸지 않는 값"과 관련이 있지만 완전히 같지는 않다.

final

  • 한 번 값이 정해지면 다시 바꿀 수 없음
  • 실행 중에 값이 결정돼도 됨
  • 로그인한 사용자 이름처럼 실행 시점에 한 번 정해지는 값에 적합

const

  • 컴파일 시점에 값이 확정되어야 함
  • 완전한 상수 객체를 만들 수 있음
  • 같은 상수 값이면 재사용될 수 있음
  • 실습에서 const Animal("사자") 두 개의 hashCode를 비교한 이유
    • 상수 객체가 재사용될 수 있음을 보기 위해서

3) Java와 비교

  • Java의 final은 Dart의 final과 비슷
  • 하지만 Dart의 const는 Java에서 체감상 대응되는 문법이 거의 없음
  • static final 상수와 비슷해 보일 수는 있지만
    • Dart의 const는 객체 자체를 컴파일 타임 상수로 다루는 점이 더 강력

4) Flutter에서 특히 중요함

  • Flutter에서는 const Text("안녕")처럼 위젯 앞에 const를 붙여 불필요한 재생성을 줄이는 최적화에 자주 사용

17. Java와 비교했을 때 꼭 익숙해져야 할 Dart 포인트

비슷해서 빠르게 넘어가도 되는 것

  • 기본 타입
  • 클래스와 객체
  • 생성자 기본 개념
  • 상속
  • 추상 클래스
  • 컬렉션의 큰 개념

Dart에서 특히 중요하거나 Java와 다른 것

  • vardynamic의 차이
  • named parameter
  • cascade ..
  • null-safety (?, ?., ??, !, late)
  • spread ...
  • const 객체
  • mixin
이 항목들은 Flutter를 하면서 계속 마주치므로, 문법만 외우기보다 "왜 있는지"를 같이 이해하는 게 좋다.

18. 실습 외에 추가로 꼭 알아둘 문법

실습에 없지만 Flutter와 Dart 공부를 계속하려면 아래 문법도 중요하다.

1) required named parameter

① 개념

class User { final String name; final int age; User({required this.name, required this.age}); }
  • named parameter의 장점은 살리면서, 꼭 넣어야 하는 값은 강제할 수 있음
  • Flutter 위젯 생성자에서 매우 자주 사용

② Java와 비교

  • Java에는 직접 대응 문법이 없음
  • Builder 패턴보다 간결함

2) 비동기 처리 Future, async, await

① 개념

Future<String> getData() async { return "data"; }
  • 서버 통신, 파일 읽기, DB 작업에서 필수
  • Flutter 앱은 네트워크 요청이 많기 때문에 반드시 배워야 함

② Java와 비교

  • Java의 CompletableFuture보다 문법이 단순하고 읽기 쉬움

3) getter / setter

class Person { String _name = ""; String get name => _name; set name(String value) { _name = value; } }
  • Dart는 필드처럼 접근하지만 내부적으로 getter/setter가 동작할 수 있음

4) enum

enum Status { ready, loading, done }
  • 상태값을 안전하게 표현할 때 좋음
  • 문자열보다 실수를 줄임

5) extension

extension NumberParsing on String { int toInt() => int.parse(this); }
  • 기존 클래스에 새 기능을 덧붙이는 문법
  • 유틸 함수 정리에 좋음
extension StringException on String { int whatTime() { return 50; } } void main() { String username = "ssar"; print(username.whatTime()); }
ex01\test_teacher07.dart

6) record / pattern matching

  • Dart 3에서 중요해진 문법
  • 여러 값을 묶어 반환하거나, 값을 구조적으로 꺼낼 때 유용함
  • Flutter와 서버 코드 모두에서 점점 중요해지고 있음
// 레코드 void main() { final user = ("코스", 10); print(user.$1); // 코스 print(user.$2); // 10 print("===================="); // print(user.runtimeType); // (String, int) (String, int) user2 = ("메타", 20); // int 자리에 "20" 넣으면 터짐! print(user2.$1); print(user2.$2); print("===================="); // 강사님 추천! ({String name, int age}) user3 = (name: "쌀", age: 30); print(user3.name); print(user3.age); print("===================="); var user4 = (name: "러브", age: 25); print(user4.name); print(user4.age); print("===================="); }
ex01\test_teacher05.dart
({int id, String title}) download() { // 1과 "안녕"을 응답해야 할 경우 return (id: 1, title: "안녕"); } void main() { var data = download(); print(data); print(data.id); print(data.title); }
ex01\test_teacher06.dart

7) 라이브러리와 private 규칙

  • Dart는 파일 단위 라이브러리 개념이 강함
  • 이름 앞에 _를 붙이면 같은 라이브러리 밖에서는 접근하기 어려운 private 의미가 됨
  • Java처럼 private, public, protected를 세세하게 나누는 방식과는 감각이 다름

19. 비전공자를 위한 공부 순서 추천

1단계

  • main()
  • 변수와 타입
  • 함수
  • 클래스와 객체

2단계

  • 생성자
  • named parameter
  • 컬렉션
  • for, map, where

3단계

  • null-safety
  • late
  • finalconst
  • spread

4단계

  • 상속
  • 추상 클래스
  • mixin
  • 비동기 처리 async/await
Share article