Dart: 구문과 기본 개념

이 포괄적인 가이드를 통해 Dart 프로그래밍의 기초 개념을 탐구하세요. 구문, 변수 유형, 함수, 루프, 제어 흐름과 같은 필수적인 주제를 다루며, Dart 기초에 대한 심도 있는 이해를 제공합니다. 초보자에게 이상적이며, 간단한 데이터 유형부터 복잡한 함수에 이르기까지 Dart를 마스터하는 데 필요한 견고한 기반을 마련해줍니다.

Dec 28, 2023

소개

Dart의 세계에 오신 것을 환영합니다. Dart는 사용 편의성과 높은 성능을 위해 설계된 현대적인 언어입니다. Flutter로 모바일 앱을 개발하려는 경우든 웹 및 서버 측 개발을 탐색하려는 경우든, Dart 학습은 여러분의 첫 번째 단계입니다. 이 글에서는 Dart의 기본 구문과 기본 개념을 살펴보고, 코딩 여정을 위한 강력한 기초를 설정할 것입니다.
 

기본 구문

Dart에서의 Hello World
모든 프로그래밍 여정은 종종 'Hello World' 프로그램으로 시작합니다. Dart에서는 다음과 같습니다:
void main() { print('Hello, World!'); }
이 프로그램은 모든 Dart 애플리케이션의 진입점인 main 함수를 정의합니다. print 함수는 문자열 'Hello, World!'를 콘솔에 출력합니다.
변수와 데이터 타입
  1. 기본 선언 및 초기화
    1. Dart에서는 명시적인 타입 주석을 사용하거나 타입 추론을 위한 var 키워드를 사용하여 변수를 선언할 수 있습니다.
      • 타입 주석:
        • String name = 'Alice'; int age = 30;
      • var를 이용한 타입 추론:
        • var city = 'New York'; // String으로 추론됨 var distance = 100; // int로 추론됨
  1. Final, Const, 그리고 Late
    1. Dart는 특별한 변수 선언을 위해 final, const, late 키워드를 제공합니다.
      • final: 한 번 설정되면 변경할 수 없는 값에 사용됩니다.
        • final String greeting = 'Hello';
      • const: 컴파일 시점의 상수를 선언합니다.
        • const double pi = 3.14159;
      • late: 지연 초기화를 나타냅니다.
        • late String description; // 재할당할 수 있음 late final int calculatedValue; // 한 번 설정된 값 late String? nullOrStringValue; // null 또는 String 값이어야 함
      • 동적 타입: dynamic vs var
        • Dart는 dynamicvar 두 가지 동적 타입을 제공합니다. 차이점은 타입 체크에서 있습니다:
        • dynamic: 정적 타입 체크를 명시적으로 비활성화합니다. 시간이 지남에 따라 타입이 변경될 수 있습니다.
          • dynamic variable = 'Hello'; variable = 100; // 허용됨
        • var: 정적 타입 체크를 유지합니다. 한 번 설정되면 타입을 변경할 수 없습니다.
          • var variable = 'Hello'; // variable = 100; // 오류: 'int' 타입을 'String'에 할당할 수 없음
  1. Dart의 데이터 타입
      • 숫자:
        • int: 정수를 나타냅니다.
          • int population = 150000;
        • double: 부동 소수점 숫자를 처리합니다.
          • double price = 99.99;
      • 문자열:
        Dart에서 문자열은 UTF-16 코드 단위의 시퀀스입니다.
        • String fullName = 'John Doe'; String multiline = ''' 이것은 여러 줄 문자열입니다. ''';
          문자열 보간법:
          String greeting = "Hello, $fullName!"; String greeting = "Hello, ${getFullName()}"; String getFullName() => "YourName";
      • 불리언:bool 타입은 참(true) 또는 거짓(false) 값을 나타냅니다.
        • bool isVisible = false; bool isEligible = age > 18;
      • 리스트, 맵, 그리고 세트:
        • List: 순서가 있는 객체의 컬렉션입니다. Dart는 명시적으로 선언되지 않은 경우 리스트의 타입을 추론합니다.
          • List<String> languages = ['Dart', 'JavaScript', 'Python']; var numbers = [1, 2, 3, 4, 5]; // List<int>로 추론됨
        • Map: 키-값 쌍의 컬렉션입니다.
          • Map<String, String> capitals = { 'USA': 'Washington D.C.', 'Japan': 'Tokyo', };
        • Set: 순서가 없고 고유한 객체의 컬렉션입니다.
          • Set<int> numbers = {1, 2, 3, 4, 5}; var numbers2 = {1, 2, 3, 4, 5}; // Set<int>로 추론됨
      • 룬과 심볼:
        • Runes: Dart에서 유니코드 문자를 나타냅니다.
          • Runes input = new Runes('\u{1F605}'); print(new String.fromCharCodes(input)); // 😅
        • Symbols: Dart의 리플렉션 기능에서 사용되는 연산자 또는 식별자를 나타냅니다.
      • 널 안전성:
        Dart 2.12는 기본적으로 모든 변수를 널이 아닌(non-nullable) 것으로 만들어 널 안전성을 도입했습니다.
        • ?를 사용한 널 가능 타입:
        • int? nullableAge;
        • 널 인식 연산자(?., ??, ??=):
        • int? age; print(age?.isEven); // 안전한 접근을 위해 ?. 사용 // 같은 의미 if(age != null) { print(age.isEven) // 불리언 값 출력 } else { print(age) // 널 출력 } print(age ?? 0); // 널인 경우 기본값 0 // 같은 의미 if(age != null) { print(age); // age 값 출력 } else { print(0); } age ??= 10; // 널인 경우 값 할당 // 같은 의미 if(age != null) {} else { age = 10; }

Dart에서의 반복문

For 반복문
  • 표준 For 반복문: 정해진 횟수만큼 반복합니다.
    • for (int i = 0; i < 10; i++) { print('반복 $i'); // 0부터 9까지 출력 }
  • For-In 반복문: 컬렉션의 요소를 순회합니다.
    • var numbers = [1, 2, 3, 4, 5]; // List<int>로 추론됨 for (var number in numbers) { print('숫자: $number'); }
While 반복문
  • 조건이 참인 동안 실행됩니다.
    • int count = 0; while (count < 5) { print('카운트는 $count'); count++; } // 0부터 4까지 출력
Do-While 반복문
  • 조건을 확인하기 전에 블록을 한 번 실행합니다.
    • int counter = 0; do { print('카운터는 $counter'); counter++; } while (counter < 5);
Break와 Continue
  • Break: 즉시 반복문을 종료합니다.
    • for (int i = 0; i < 10; i++) { if (i == 5) break; // i가 5일 때 반복문을 종료 print(i); }
  • Continue: 현재 반복의 나머지 부분을 건너뜁니다.
    • for (int i = 0; i < 10; i++) { if (i % 2 == 0) continue; // 짝수는 건너뜀 print('홀수: $i'); }

논리 블록

간단한 If 문
  • 조건이 참일 때 코드 블록을 실행합니다.
    • int age = 20; if (age >= 18) { print('성인'); }
If-Else 문
  • If 조건이 거짓일 경우 대체 경로를 제공합니다.
    • if (age >= 18) { print('성인'); } else { print('미성년자'); }
If-Else-If 사다리
  • 여러 조건을 순차적으로 확인합니다.
    • if (age >= 18) { print('성인'); } else if (age >= 13) { print('청소년'); } else { print('어린이'); }
중첩된 If 문
  • 다른 if 문 내부의 if 문입니다.
    • bool hasDrivingLicense = true; if (age >= 18) { if (hasDrivingLicense) { print('운전할 수 있음'); } else { print('면허 없이는 운전할 수 없음'); } }
조건부(삼항) 연산자
  • 간단한 if-else 문을 간결하게 작성하는 방법입니다.
    • String type = age >= 18 ? '성인' : '미성년자';
Switch Case
  • 실행할 여러 코드 블록 중 하나를 선택합니다.
    • String grade = 'A'; switch (grade) { case 'A': print('우수함'); break; case 'B': print('좋음'); break; default: print('유효하지 않은 성적'); }

함수 정의하기

기본 함수 구문
  • 간단한 함수 선언은 반환 타입, 함수 이름, 매개변수, 그리고 본문을 포함합니다.
    • void greet(String name) { print('안녕, $name!'); }
반환 타입
  • 함수는 값을 반환할 수 있습니다. 반환 타입은 함수 이름 앞에 지정됩니다.
    • int add(int a, int b) { return a + b; }
  • 함수가 값을 반환하지 않으면 반환 타입은 void입니다.
선택적 매개변수
  • Dart는 선택적 위치 매개변수와 명명된 매개변수를 지원합니다.
    • 위치: 대괄호 [] 안에 포함됩니다.
      • void sayMessage(String message, [String? author]) { print('$message 작성자: ${author ?? '익명'}'); }
    • 명명된: 중괄호 {} 안에 포함되며 종종 기본값과 함께 사용됩니다.
      • void setSettings({bool bold = false, bool hidden = false}) { // 함수 본문 }
화살표 함수
  • 단일 표현식 함수에 적합합니다.
    • void greet(String name) => print('안녕, $name!');
익명 함수
  • 컬렉션에서나 고차 함수의 인자로 자주 사용됩니다.
    • var numbers = [1, 2, 3]; numbers.forEach((number) { print(number); });

고급 함수 개념

고차 함수
  • 다른 함수를 매개변수로 받거나 함수를 반환할 수 있는 함수입니다.
    • void executeFunction(Function callback) { callback(); }
함수를 일급 객체로 사용하기
  • 함수를 변수에 할당하거나 매개변수로 전달할 수 있습니다.
    • var multiply = (int a, int b) => a * b; int result = multiply(10, 2);
클로저
  • 자신의 렉시컬 스코프에서 변수에 접근하고 수정할 수 있는 함수입니다.
    • Function makeAdder(int addBy) { return (int i) => addBy + i; } var adder = makeAdder(5); print(adder(3)); // 8 출력
제너레이터
  • yieldyield*를 사용해 값의 시퀀스를 생성하는 함수입니다.
    • Iterable<int> count(int max) sync* { for (int i = 0; i < max; i++) { yield i; } }
비동기 함수
  • 비동기 작업을 처리하며 Future 또는 Stream을 반환하는 함수입니다.
    • Future<void> fetchData() async { // 비동기 작업 }
확장 메서드
  • 기존 클래스에 새로운 기능을 추가할 수 있습니다.
    • extension StringExtension on String { bool get isCapitalized => this.length > 0 && this[0].toUpperCase() == this[0]; }
함수 매개변수와 기본값
  • 위치 및 명명된 매개변수에 대한 기본값 설정.
    • void printMessage(String message, {int times = 1}) { for (int i = 0; i < times; i++) { print(message); } }
필수 명명된 매개변수
  • required 키워드를 사용하여 명명된 매개변수를 필수로 만듭니다.
    • void setAddress({required String street, String? city}) { // 함수 본문 }