핵심 요약
Dart는 정적 타입 언어이며 var는 타입을 없애는 문법이 아니라 초기값에서 타입을 추론하는 문법입니다.
검수 범위
Dart의 현재 타입 추론, 불변 선언, null safety 용어를 공식 언어 문서 기준으로 다시 확인했습니다.
Flutter를 시작하면 가장 먼저 마주치는 것이 Dart 문법이고, 그중에서도 “변수 선언”과 “타입”을 제대로 이해해두면 이후 위젯, 상태관리, 비동기까지 훨씬 수월해집니다. 이 글에서는 Dart에서 변수를 선언하는 방법, 타입 시스템의 핵심, 그리고 실무에서 자주 겪는 실수 포인트까지 한 번에 정리합니다.
변수
변수(variable)는 값을 담아두는 이름표입니다. 프로그램은 실행 중에 숫자, 문자열, 참/거짓 같은 값을 계속 다루는데, 그 값을 재사용하기 위해 변수에 저장합니다.
Dart에서는 변수를 선언할 때 “타입을 명시”할 수도 있고, “자동으로 추론”하게 할 수도 있습니다. 또한 “값이 바뀔 수 있는가(가변/불변)”에 따라 var / final / const를 구분해서 씁니다.
var, final, const 차이
var: 일반 변수(가변)
var는 값을 바꿀 수 있는 변수입니다. 처음 값을 대입하면 Dart가 타입을 추론합니다.
-
초기값을 넣으면 타입이 고정됩니다.
-
이후 다른 타입 값을 넣으려 하면 오류가 납니다.
예: 처음에 정수로 시작하면 계속 정수로 유지됩니다.
final: 한 번만 대입(런타임 상수 느낌)
final은 “한 번만 값이 결정되는 변수”입니다.
-
실행 중에 값이 정해질 수 있습니다. (예: API 결과, 현재시간 등)
-
단, 한 번 값이 들어가면 변경 불가입니다.
const: 컴파일 타임 상수(진짜 상수)
const는 “컴파일 시점에 값이 확정되는 상수”입니다.
-
빌드(컴파일) 단계에서 이미 값이 확정되어 있어야 합니다.
-
완전히 고정된 리터럴/상수 표현식만 가능.
실무 감각으로는 이렇게 정리하면 편합니다.
-
값이 바뀔 가능성이 있으면
var -
값은 안 바뀌는데 실행 중에 결정될 수 있으면
final -
앱 코드상 완전히 고정된 값이면
const
Flutter(Dart) 코드 작성 기본: var / final / const로 변수 선언
타입(Type) 시스템의 핵심: 정적 타입 + 타입 추론
Dart는 정적 타입 언어입니다. 즉, 변수의 타입이 명확해야 하고, 컴파일 단계에서 타입 오류를 잡아줍니다. 다만 개발 편의를 위해 타입을 생략하면 Dart가 타입을 추론해줍니다.
-
타입을 직접 쓰는 방식: 코드 명확성 ↑
-
타입을 생략하고 추론: 코드 간결성 ↑
Flutter 실무에서는 “위젯 트리/콜백 타입”이 복잡해질수록 명시 타입이 디버깅에 유리해지는 경우가 많습니다.
기본 타입(Primitive/코어 타입)
Dart에서 가장 많이 쓰는 대표 타입은 아래와 같습니다.
int (정수)
정수 값에 사용합니다. 예: 0, 1, -10
double (실수)
소수점이 있는 수에 사용합니다. 예: 3.14, 0.5
num (숫자 상위 타입)
int와 double을 모두 포함하는 타입입니다. 숫자 처리를 통합하고 싶을 때 사용합니다.
String (문자열)
텍스트를 저장합니다. Dart는 문자열 보간(interpolation)이 강력합니다.
-
${변수}또는$변수형태로 문자열 안에 값을 삽입할 수 있습니다.
bool (불리언)
true / false 두 값만 가집니다. 조건문, 토글 상태 등에서 사용합니다.
dynamic, Object, 그리고 타입 안정성
Dart에는 “타입을 유연하게” 쓰는 방법이 몇 가지 있습니다. 하지만 Flutter 프로젝트에서는 무분별하게 쓰면 런타임 에러가 늘어나는 원인이 됩니다.
Object
Dart의 거의 모든 값이 Object로 표현될 수 있습니다.
-
다만
Object로 받으면 “그 값이 무엇인지” 확실치 않기 때문에 사용 시 캐스팅/검사가 필요합니다.
dynamic
dynamic은 타입 체크를 느슨하게 만들어, 컴파일 단계에서 잡아야 할 오류가 런타임으로 넘어갈 수 있습니다.
-
빠르게 테스트할 때는 편하지만, 운영 코드에서는 최소화하는 편이 좋습니다.
정리하면:
-
가능한 한 정적 타입 유지
-
정말 필요할 때만
Object또는dynamic사용 -
외부 데이터(JSON 등)를 다룰 때는 파싱/모델링으로 안정성 확보
Null Safety(널 안정성): 타입 뒤의 ? 의미
Dart(2.12+)는 Null Safety가 기본입니다. 즉, 기본적으로 변수는 null을 가질 수 없습니다.
-
String name;은 null 불가 -
String? name;은 null 가능
?는 “Nullable(널 가능)”을 의미합니다. Flutter에서 특히 API 응답, 선택 입력값, 조건부 위젯 등에서 매우 자주 쓰입니다.
널 가능 타입을 쓸 때는 다음 케이스를 신경 써야 합니다.
-
값이 null일 수 있는지
-
null일 때 대체값을 줄지
-
null이 아니라고 확신할 근거가 있는지
컬렉션 타입: List, Map, Set
UI/데이터 처리에서 가장 많이 쓰는 구조입니다.
List<T>
순서가 있는 배열입니다.
-
예:
List<String>은 문자열 목록
Map<K, V>
키-값 구조입니다.
-
예:
Map<String, int>는 문자열 키로 정수 값을 저장
Set<T>
중복을 허용하지 않는 집합입니다.
-
태그 목록, 선택 항목 중복 제거 등에 사용
Dart는 제네릭(Generic)으로 내부 타입을 명확히 지정할 수 있어서, 컬렉션에서도 타입 안정성을 확보할 수 있습니다.
late 키워드: “나중에 초기화” 선언
late는 “지금은 값이 없지만, 사용하기 전에 반드시 넣겠다”는 약속입니다.
-
생성자 이후에 초기화되거나
-
특정 흐름에서만 초기화되는 값에 사용됩니다.
주의할 점은, 실제로 값을 넣기 전에 접근하면 런타임 에러가 납니다. 즉 late는 편하지만, 책임도 함께 커집니다.
타입 변환(캐스팅/파싱) 기본 감각
앱 개발에서는 문자열로 들어온 값을 숫자로 바꾸거나(JSON, 입력값), 숫자를 문자열로 바꾸는 일이 흔합니다.
-
문자열 → 숫자: 파싱(parse)
-
숫자 → 문자열: 변환(toString)
또한 as 캐스팅은 타입이 확실할 때만 사용해야 하며, 불확실하면 타입 체크(is)가 안전합니다.
실무에서 가장 추천하는 변수/타입 습관
Flutter/Dart로 앱을 만들 때 실수를 줄이는 습관은 아래 3가지입니다.
-
가능하면
final을 기본값으로 두고, 정말 필요할 때만var로 바꾸기 -
dynamic은 최소화하고, JSON은 모델 클래스로 파싱해서 타입을 고정하기 -
Nullable(
?)는 “정말 null일 수 있는가”를 기준으로 설계하고, null 처리 흐름을 코드에 명확히 드러내기
결론
Dart의 변수와 타입은 Flutter 개발 전반의 안정성과 생산성을 좌우하는 핵심 기초입니다. var, final, const로 “값 변경 가능성”을 명확히 구분하고, int/double/String/bool 같은 기본 타입과 List/Map/Set 같은 컬렉션 타입을 제네릭으로 정확히 선언하면 타입 오류를 초기에 차단할 수 있습니다. 또한 Null Safety에서 ?의 의미를 분명히 이해하고, dynamic 사용을 최소화하며, 외부 데이터(JSON)는 모델링과 파싱으로 타입을 고정하는 습관을 들이면 런타임 오류를 크게 줄일 수 있습니다. 결국 “가능하면 타입을 명확히, 값은 불변으로, null은 설계로 관리”하는 방향이 Dart 초보에서 실무 단계로 넘어가는 가장 빠른 길입니다.
검증 기준과 참고 자료
이 글은 2026-09-08에 아래 공식 문서와 공개 기술 문서를 기준으로 내용과 용어를 다시 검수했습니다. 제품 버전과 기기 제조사에 따라 화면 이름은 달라질 수 있으므로 실제 화면과 공식 문서를 함께 확인하세요.