Dart 튜토리얼 24편: 멀티플랫폼 & 환경 설정(Flutter·-D·fromEnvironment)
요약
핵심 요지
- 문제 정의: 같은 앱이라도 디버그/프로덕션, 무료/유료 같은 “버전(플레이버)”이 생기면 코드 분기가 필요해지고, 기준이 없으면 배포 실수가 늘어난다.
- 핵심 주장: 멀티플랫폼 앱은 Flutter 프레임워크를 권장하는 흐름이 제시되고, 빌드/실행 시점에
-D/--define으로 환경 선언을 주입한 뒤fromEnvironment로 읽는 방식이 제시된다. - 주요 근거:
dart run --define=DEBUG=true -DFLAVOR=free1,const bool.fromEnvironment2,const bool.hasEnvironment3 예시가 제시된다. - 실무 기준: 설정은 “런타임 환경 변수”가 아니라 “컴파일 환경 선언”으로 고정하고, 기본값(
defaultValue)을 항상 지정한다.
문서가 설명하는 범위
- 멀티플랫폼 앱에서 Flutter를 권장하는 이유(플랫폼/컴파일러/개발 사이클)
- 컴파일 환경 선언(environment declarations)의 개념과
-D/--define지정 방법 fromEnvironment/hasEnvironment를 이용한 접근과, 도구별 설정 방식(IDE/Flutter)
읽는 시간: 14분 | 난이도: 초급
참고 자료
문제 상황
앱이 커지면 환경이 늘어납니다.
예를 들어 디버그에서만 로그를 찍거나, 특정 빌드에서만 기능을 켜는 경우가 생깁니다.
이때 설정이 코드 여기저기에 흩어지면 “어느 빌드에서 무엇이 켜지는지”가 불명확해지고, 배포 실수가 늘어납니다.
그래서 이 글은 설정값을 넣고 읽는 표준 흐름을 고정합니다.
해결 방법
단계 1: 멀티플랫폼 앱은 Flutter 기반으로 접근한다
Why
NOTE여러 OS/디바이스를 동시에 지원하려면 UI/빌드/패키징까지 포함한 프레임워크가 필요합니다.
그래서 멀티플랫폼 네이티브 앱 개발에는 Flutter 프레임워크를 권장하는 흐름이 제시됩니다.
What
NOTE멀티플랫폼 앱 페이지는 Flutter가 Dart 플랫폼 위에서 동작하며, 핫 리로드 개발 사이클과 AOT/JS 컴파일러를 통해 여러 플랫폼에 빠르게 배포할 수 있다고 설명합니다.
How
TIP멀티플랫폼 목표가 명확하다면, “UI/런타임/빌드”가 함께 묶인 Flutter 기반으로 프로젝트 방향을 잡는 것이 기준입니다.
이 글의 나머지 내용(환경 선언)은 Flutter 포함 모든 Dart 앱에서 유용하게 적용할 수 있습니다.
Watch out
WARNING플랫폼마다 “파일 시스템/네트워크/브라우저 API”처럼 사용할 수 있는 라이브러리가 다릅니다.
따라서 멀티플랫폼에서는 “어떤 플랫폼에서 무엇이 가능한지”를 기준으로 의존성을 선택해야 합니다.
결론: 멀티플랫폼 앱은 Flutter 기반으로 방향을 잡고, 설정은 컴파일 단계에서 고정합니다.
단계 2: -D/--define으로 컴파일 환경 선언을 주입한다
Why
NOTE배포 실수의 원인은 종종 “설정값이 다르게 들어간 것”입니다.
설정값이 빌드 단계에서 명시적으로 보이면, 재현성과 검증이 좋아집니다.
What
NOTE컴파일 환경 선언은 키-값 쌍으로 구성된 설정이며, 컴파일 시점에 평가됩니다.
예시로--define또는-D옵션을 사용해 주입하는 방식이 제시됩니다.
How
TIP다음처럼 실행 시점에 선언을 전달할 수 있습니다.
Terminal window $ dart run --define=DEBUG=true -DFLAVOR=free
Watch out
WARNING용어 주의: 여기서 말하는
environment는 OS 환경 변수 의미가 아니라 “Dart 컴파일 환경”을 뜻한다.
즉,PUB_CACHE같은 OS 환경 변수와는 다른 층위입니다.
결론: 설정값은 -D/--define으로 주입해 “빌드/실행 절차”로 고정합니다.
단계 3: 코드에서는 fromEnvironment로 값을 읽고, 기본값을 명시한다
Why
NOTE설정이 없을 때의 동작이 모호하면, 환경에 따라 앱이 다르게 동작할 수 있습니다.
그래서 기본값을 함께 지정하는 습관이 필요합니다.
What
NOTE환경 선언 값은
const컨텍스트에서fromEnvironment생성자를 통해 접근하는 방식이 제시됩니다.
예시로bool.fromEnvironment,int.fromEnvironment,String.fromEnvironment가 소개됩니다.
How
TIP디버그 로그를 켜고 끄는 예시는 다음과 같습니다.
코드 블록 주석은 한글로 맞췄습니다.void log(String message) {// 환경 선언 'DEBUG'가 `true`일 때만 로그를 남긴다.// 값이 없으면 로그를 남기지 않는다.if (const bool.fromEnvironment('DEBUG', defaultValue: false)) {print('Debug: $message');}}
Watch out
WARNING
fromEnvironment계열 생성자는const로 호출될 때만 동작이 보장된다는 설명이 함께 제시됩니다.
즉, “컴파일 시점에 평가되어야 한다”는 전제를 깨면 기대한 최적화(도달 불가능 코드 제거)가 되지 않을 수 있습니다.
결론: 환경 값은 const ...fromEnvironment로 읽고, defaultValue로 기본 동작을 고정합니다.
단계 4: “설정이 존재하는지”는 hasEnvironment로 분리해서 판단한다
Why
NOTE값이
false인 것과, 값이 “아예 지정되지 않은 것”은 의미가 다를 수 있습니다.
예를 들어 “설정을 켜지 않았다”와 “설정 자체를 모르고 빌드했다”를 구분하고 싶을 수 있습니다.
What
NOTE환경 선언이 지정되었는지 확인하려면
bool.hasEnvironment를 사용하라는 예시가 제시됩니다.
How
TIP다음 코드는
DEBUG설정이 존재하는지 확인합니다.if (const bool.hasEnvironment('DEBUG')) {print('Debug behavior was configured!');}
Watch out
WARNING도구별로
-D처리 방식이 일관되지 않을 수 있다는 경고가 포함되어 있습니다.
특히 콤마로 여러 값을 전달하는 방식은 도구/컴파일러에 따라 다를 수 있다는 제약이 제시됩니다.
결론: 값 자체와 “설정 존재 여부”를 분리하면, 설정 누락을 더 빨리 감지할 수 있습니다.
Footnotes
공유
이 글이 도움이 되었다면 다른 사람과 공유해주세요!