Dart 문법 기초 — 변수, 타입, 함수, null safety

Flutter를 배우려면 Dart부터 알아야 합니다. Java나 JavaScript를 해봤다면 익숙한 부분이 많지만, null safety는 Dart만의 중요한 특징이니 꼭 짚고 넘어가야 합니다.


변수 선언

DART
// var: 타입 추론 (첫 할당 시 타입 결정)
var name = '심정훈';  // String으로 추론
// name = 123;        // 에러! 이미 String으로 결정됨

// 명시적 타입 선언
String greeting = '안녕하세요';
int age = 25;
double height = 175.5;
bool isStudent = true;

// dynamic: 타입 변경 가능 (가급적 사용 자제)
dynamic anything = '문자열';
anything = 123;  // 가능하지만 타입 안전성을 잃음

// final: 런타임에 한 번만 할당
final DateTime now = DateTime.now();

// const: 컴파일 타임 상수
const double pi = 3.14159;

final vs const 차이

면접에서 정말 자주 물어봅니다.

구분finalconst
할당 시점런타임컴파일 타임
예시final now = DateTime.now()const pi = 3.14
객체참조만 불변객체 자체가 불변

기본 타입

DART
// 숫자
int count = 42;
double price = 9.99;
num value = 100;  // int와 double의 상위 타입

// 문자열
String name = 'Flutter';
String interpolation = '이름: $name, 길이: ${name.length}';

// 불리언
bool isActive = true;

// 리스트
List<int> numbers = [1, 2, 3];
var fruits = ['사과', '바나나', '포도'];

// 맵
Map<String, int> scores = {'국어': 90, '수학': 85};

// Set (중복 불가)
Set<String> tags = {'Flutter', 'Dart', 'Mobile'};

함수

DART
// 기본 함수 선언
int add(int a, int b) {
  return a + b;
}

// 화살표 함수 (한 줄일 때)
int multiply(int a, int b) => a * b;

// 선택적 위치 매개변수
String greet(String name, [String? title]) {
  if (title != null) {
    return '$title $name님 안녕하세요';
  }
  return '$name님 안녕하세요';
}

// 이름 있는 매개변수 (Flutter 위젯에서 자주 사용)
void createUser({
  required String name,
  required int age,
  String role = 'user',  // 기본값 지정
}) {
  print('$name ($age) - $role');
}

// 호출
createUser(name: '심정훈', age: 25);

Flutter 위젯의 생성자가 거의 대부분 이름 있는 매개변수를 사용합니다. required 키워드와 기본값 패턴은 꼭 익혀두세요.


Null Safety

Dart 3부터 null safety는 필수입니다. 변수가 null이 될 수 있는지 타입 시스템에서 명확히 구분합니다.

DART
// null 불가 (기본)
String name = '심정훈';
// name = null;  // 컴파일 에러!

// null 허용 (? 붙이기)
String? nickname;  // null로 초기화됨
nickname = '정훈';
nickname = null;   // OK

// null 체크 방법들
void printLength(String? text) {
  // 1. if 문으로 체크
  if (text != null) {
    print(text.length);  // null이 아님이 보장됨
  }

  // 2. ?. (null-aware 접근)
  print(text?.length);  // null이면 null 반환

  // 3. ?? (기본값 지정)
  print(text ?? '기본값');

  // 4. ! (강제 언래핑 - 확실할 때만!)
  // print(text!.length);  // null이면 런타임 에러
}

late 키워드

DART
// 나중에 초기화하겠다는 선언
late String description;

void init() {
  description = '나중에 할당';  // 사용 전에 반드시 할당해야 함
}

// lazy 초기화에도 활용
late final int heavyValue = _computeHeavyValue();
// heavyValue에 처음 접근할 때 _computeHeavyValue() 실행

컬렉션 관련 유용한 문법

DART
final numbers = [1, 2, 3, 4, 5];

// spread 연산자
final moreNumbers = [0, ...numbers, 6];  // [0, 1, 2, 3, 4, 5, 6]

// collection if
final items = [
  '항상 포함',
  if (true) '조건부 포함',
];

// collection for
final doubled = [
  for (var n in numbers) n * 2,
];  // [2, 4, 6, 8, 10]

// where, map, fold 등 함수형 메서드
final evens = numbers.where((n) => n % 2 == 0).toList();
final strings = numbers.map((n) => '$n번').toList();
final sum = numbers.fold<int>(0, (prev, n) => prev + n);

제어문

DART
// switch expression (Dart 3+)
String describe(int number) => switch (number) {
  0 => '영',
  1 => '일',
  _ => '기타',  // default
};

// 패턴 매칭 (Dart 3+)
final json = {'name': '심정훈', 'age': 25};
if (json case {'name': String name, 'age': int age}) {
  print('$name은 $age살');
}

정리

  • var는 타입 추론, dynamic은 타입 변경 가능 (지양)
  • final = 런타임 불변, const = 컴파일타임 불변
  • Null safety: ?로 nullable 선언, ?., ??, !로 처리
  • 이름 있는 매개변수 + required는 Flutter에서 매일 씁니다
  • Dart 3의 패턴 매칭과 switch expression도 알아두면 좋습니다
댓글 로딩 중...