Flutter + Dart/Flutter + Dart TIP

Dart(및 Flutter) 언어에서 사용되는 주요 키워드/수식어(modifier)/식별자(reserved identifiers)

GREEN나무 2025. 5. 16. 11:34
728x90

아래 표는 Dart(및 Flutter) 언어에서 사용되는 주요 키워드·수식어(modifier)·식별자(reserved identifiers)를 분류별로 정리한 것입니다. 각 항목별 간단한 설명과 예시 코드도 함께 제공합니다.


1. 선언·수정자(Declaration Modifiers)

키워드 설명 예시 코드
abstract 추상 클래스/메서드 선언 abstract class Animal { void speak(); }
const 컴파일 타임 상수 static const pi = 3.14;
final 런타임 상수 (한 번 할당 후 변경 불가) final name = 'Flutter';
late 지연 초기화 (나중에 한 번만 할당) late String description;
external 구현부가 네이티브 라이브러리 등 외부에 있음을 표시 external void nativeFunction();
factory 팩토리 생성자 선언 class A { factory A() => A._(); A._(); }
static 클래스 레벨(정적) 멤버 선언 static const version = '1.0';
typedef 함수 또는 제네릭 타입 별칭 선언 typedef Callback = void Function(int);
var 타입 추론 변수 선언 var count = 3;
dynamic 런타임 타입 검사 변수 dynamic anything = 'text';
void 반환값이 없음을 표시 void runApp() { /*...*/ }
required named parameter를 필수로 표시 void fn({required int id}) {}
covariant 파라미터를 하위 타입 허용 void set value(covariant num v) {}

 


2. 클래스·믹스인·인터페이스 관련

키워드 설명 예시 코드
class 클래스 선언 class Person { String name; }
extends 상속 class Student extends Person { int grade; }
implements 인터페이스(다중) 구현 class Dog implements Animal { void speak() {} }
with 믹스인 사용 class Bird with Flyable {}
mixin 믹스인 선언 mixin Flyable { void fly() {} }
enum 열거형 타입 선언 enum Color { red, green, blue }
extension 기존 타입에 메서드 추가 extension StrUtils on String { bool get isEmpty_ => this.isEmpty; }

 


3. 라이브러리·모듈 관리

키워드 설명  예시 코드
import 다른 라이브러리 가져오기 import 'package:flutter/material.dart';
export 다른 라이브러리를 재노출 export 'src/utils.dart';
library 라이브러리 파일 그룹 정의 library my_library;
part 라이브러리의 파트 파일 포함 part 'src/part_a.dart';
part of 해당 파트가 소속된 라이브러리 지정 part of my_library;
show import/ export 시 특정 멤버만 노출 import 'dart:math' show pi, sqrt;
hide import/ export 시 특정 멤버만 숨김 import 'dart:math' hide Random;
deferred 지연 로딩(import) import 'package:heavy.dart' deferred as heavy;

 


4. 흐름 제어(Control Flow)

 

키워드 설명 예시 코드
if / else 조건 분기 if (x>0) print('양수'); else print('음수');
switch 다중 분기 switch(c){ case 1: break; default:}
case / default switch 내 분기 switch(color) { case Color.red: break; }
for 반복문 for(var i=0;i<3;i++) print(i);
while   while (!done) { /*...*/ }
do...while 후조건 반복 do { work(); } while(!done);
break 루프 또는 switch 탈출  
continue 루프의 다음 반복으로 이동  
return 함수/메서드 반환 int sum() => 0;
try / catch / finally 예외 처리 try { risky(); } catch(e) {} finally {}
throw 예외 발생  throw Exception(); 
rethrow 캐치된 예외 재발생 catch(e) { rethrow; }
assert 디버그 모드 검증 assert(value!=null);

 


5. 비동기·생성기(Async & Generator)

키워드 설명 예시 코드
async 비동기 함수 선언 Future fetch() async { await api(); }
await Future 완료 대기  
async* 비동기 생성기 Stream<int> gen() async* { yield 1; }
sync* 동기 생성기 Iterable<int> gen2() sync* { yield* [2,4]; }
yield 생성기 단일 값 방출  
yield* 다른 Iterable/Stream 전체 방출  

6. 기타 식별자·연산자 관련

키워드 설명 예시 코드
as 타입 캐스트 / 네임스페이스 별칭 value as String; import 'a.dart' as a;
is 타입 검사 if(obj is Person){}
in for-in 루프 for(var ch in 'abc'.split('')){}
operator 연산자 오버로딩 A operator +(A o)=>this;
get / set 게터/세터 선언 int get x=>_x; set x(int v){_x=v;}
new 객체 생성 (선택적) var o=new Object();
this 인스턴스 자신 참조 print(this.name);
super 부모 클래스 참조 super.toString();
on 믹스인 제약 or 이벤트 핸들러 메서드 지정 extension E on String{}
covariant 하위 타입 허용 파라미터 표시 void set value(covariant num v) {}
required null-safety에서 필수 named parameter 표시 void fn({required int id}) {}
never 결코 반환하지 않는 함수의 반환 타입(Never) Never throwError() { throw Error(); }

7. 리터럴·상수 값

키워드 설명 예시 코드
true 불리언 상수 true bool ok = true;
false 불리언 상수 false bool ng = false;
null null 값 String? s = null;

 

 

1. 선언 키워드별 차이와 활용

  • var vs final vs const vs dynamic
    • var x = 3; → int로 추론, 재할당 가능
    • final x = 3; → 런타임에 한 번만 초기화, 재할당 불가
    • const x = 3; → 컴파일 타임 상수, 인스턴스 공유
    • dynamic x = 3; → 타입 검사 런타임 수행, 유연하지만 안정성 ↓
  • 언제 타입 명시?
    1. 공개 API의 파라미터/리턴
    2. 제네릭·복잡 타입
    3. 가독성 위해

2. final String label;, final VoidCallback onTap; 설명

  • 위젯 프로퍼티로, 생성자 초기화 후 불변
  • VoidCallback = void Function() 타입 별칭
  • 예시
    class MyButton extends StatelessWidget {
      final String label;
      final VoidCallback onTap;
      const MyButton({required this.label, required this.onTap, Key? key}): super(key:key);
      @override Widget build(BuildContext c) => GestureDetector(onTap:onTap,child:Text(label));
    }

3. final String todo = 'do something'; 에 키워드가 두 개 들어간 이유

  • final = 수정자(modifier), 런타임 상수
  • String = 타입 지정(key type)
  • 타입 생략 시: final todo = 'do something'; → String으로 추론

4. const 위젯 vs final 프로퍼티

  • const 생성자
    • 컴파일 타임에 완전 불변이라는 것을 Dart가 보장
    • 위젯 트리에서 동일한 인스턴스를 재사용해 메모리·성능 최적화
    • 조건
      1. 모든 필드가 final이어야 하고,
      2. 생성자 인자로 전달되는 값도 const여야 함
    • 언제 사용하나?
      • UI가 전혀 변하지 않을 때 (예: 아이콘, 단순 텍스트 위젯)
      • 반복해서 그리는 작은 위젯(리스트 아이템, 버튼 등)의 부모에 const를 붙이면 하위 전체를 재빌드하지 않음
  • final 프로퍼티
    • 런타임에 한 번만 할당하고 이후 변경 불가
    • 인자값이 런타임에 결정될 때(네트워크 응답, 사용자 입력 등)
    • 언제 사용하나?
      • 생성자에 required this.value 형태로 넣되, 값이 const가 아닐 때
      • StatefulWidget에서 initState 내에서 초기화해야 할 때
// const 쓰기 좋은 예
class StaticLabel extends StatelessWidget {
  const StaticLabel({Key? key}) : super(key: key);
  @override Widget build(_) => const Text('앱 이름');
}

// final 써야 하는 예
class UserBadge extends StatelessWidget {
  final String userName;
  const UserBadge({required this.userName, Key? key}): super(key: key);
  @override Widget build(_) => Text(userName);
}

5. 타입 명시 컨벤션

  • 로컬 변수 생략 (타입 추론)
    • var count = 0; → int로 추론
    • 읽기 쉽고 코드 양 감소
    • 적합할 때:
      • 복잡하지 않은 숫자·문자열·컬렉션
      • 테스트 코드·샘플 코드처럼 가독성을 우선할 때
  • 공개 API만 명시
    • void fetchData(List<String> ids) 처럼 외부 사용자가 보는 함수 시그니처에 타입을 명시
    • 장점: 문서화 효과, 동적 리팩토링 시 안정성
  • 추천 가이드라인
    1. 프로젝트/팀 스타일 가이드 채택
    2. public API: 항상 타입 명시
    3. private·로컬: 간단한 경우 var/추론, 복잡·제네릭이면 명시

6. late 초기화 이슈 경험과 대처

  • 주요 오류:
    • LateInitializationError: Field 'xxx' has not been initialized.
    • 순서상 initState 전에 접근했거나, 초기화 조건문 내에서만 할당해 호출 시점에 누락
  • 원인 분석
    1. StatefulWidget의 build에서 곧바로 참조
    2. 비동기 로직 완료 전 접근
  • 해결책
    • nullable 타입로 변경 후 null 체크
    • late String? data; if (data != null) Text(data!);
    • 초기화 보장 패턴
      • 생성자 초기화 리스트
      • initState에서 초기화 후 setState로 알림
    • 커스텀 Getter로 지연 초기화
    • String get config => _config ??= loadConfig(); String? _config;

 

핵심 요약

  • 변수 선언:
    • var → 재할당 가능, 타입 추론
    • final → 런타임에 한 번만 초기화
    • const → 컴파일 타임 상수, 인스턴스 공유
    • dynamic → 런타임 타입 검사, 유연하지만 안정성↓
  • 타입 명시:
    • 공개 API(파라미터·리턴) → 항상 명시
    • 로컬·단순 변수 → var/추론, 복잡할 땐 명시
  • 위젯 불변성:
    • const 생성자 → 모든 필드 final, 인자도 const일 때
    • final 프로퍼티 → 런타임 값 필요 시
  • late 초기화:
    • 주의: 초기화 전 접근 시 LateInitializationError
    • 해결: nullable+체크, 생성자·initState 초기화, 커스텀 Getter 활용