Dart 튜토리얼 3편: 함수의 구조를 잡는 법
요약
핵심 요지
문서가 설명하는 범위
- 함수 정의와
파라미터규칙을 다룬다. function type과typedef사용법을 설명한다.callable object와dot shorthand6 문법을 소개한다.
읽는 시간: 14분 | 난이도: 초급
참고 자료
- Functions - 함수 정의와 파라미터
- Callable objects -
call()로 호출 가능한 객체 - Typedefs - 함수 타입 별칭
- Dot shorthands - 간결한 호출 표기
문제 상황
JavaScript 같은 동적 언어에서는 함수 호출 시 어떤 파라미터가 필수인지 선택인지 구분하기 어렵습니다.
실행해봐야만 누락된 파라미터를 알 수 있어서 디버깅이 어렵습니다.
기존 방식의 한계
// JavaScript 예시function createUser(name, age, email) { console.log(name, age, email);}
createUser("Alice"); // Alice undefined undefined 출력 - 오류 없음createUser("Bob", 25); // Bob 25 undefined 출력 - 오류 없음문제는 다음과 같습니다.
- 어떤
파라미터가 필수인지 함수시그니처만 봐서는 알 수 없다. - 선택적
파라미터와 필수파라미터구분이 없다. - 실행해봐야만 누락된 값을 발견할 수 있다.
해결 방법
Dart는 함수 파라미터 규칙을 문법으로 명확히 구분하고, 함수 타입을 타입 시스템에 통합했습니다.
단계 1: 함수 시그니처와 선택적 파라미터
Why
NOTE함수를 호출할 때 실수가 가장 많이 나는 지점은 “값을 빼먹는 것”과 “순서를 헷갈리는 것”입니다.
그래서 호출 실수를 줄이려면, 선언부에서부터 호출 규칙이 드러나야 합니다.void setSize(int width, int height) {}// setSize(10); // 컴파일 오류: 필요한 인자가 부족하다.
What
NOTE
signature는 “이 함수는 어떤파라미터를 받는가”를 나타내는 선언부 규칙입니다.
How
TIPDart는
required positional parameter7,named parameter8,optional positional parameter9를 제공합니다.
함수의signature에파라미터형태가 드러납니다.void enableFlags({bool bold = false, bool hidden = false}) {}// 호출: 이름을 명시해서 전달enableFlags(bold: true, hidden: false);필수
named parameterconst Scrollbar({super.key, required Widget child});// child를 빼먹으면 컴파일 오류
Watch out
WARNING
named parameter는 기본적으로 선택입니다.
“반드시 받아야 하는 값”이라면required로 강제해야, 누락이 컴파일 단계에서 잡힙니다.void log({String? tag}) {print(tag);}log(); // OK: tag는 선택이고, 전달하지 않으면 null이다.
결론: 파라미터 형태가 선언부에 명확히 보이고, 컴파일러가 누락을 잡아냅니다.
단계 2: 함수 타입과 typedef
Why
NOTE함수를 “값처럼” 넘기기 시작하면, 어느 순간부터는 “이 함수가 어떤 입력/출력을 가지는지”를 타입으로 고정해야 합니다.
그렇지 않으면 잘못된 함수를 넘겨도 늦게 발견될 수 있습니다.int plus(int a, int b) => a + b;int minus(int a, int b) => a - b;// 어떤 함수를 넘기는지 명확히 하고 싶다.
What
NOTE
function type은 함수가 받는 인자와 반환 타입을 타입으로 표현한 것입니다.
How
TIPDart는 함수도 객체라서 변수에 할당하거나 다른 함수의 인자로 전달할 수 있습니다.
function type은 함수의 입력과 반환 형태를 나타내는 타입입니다.void greet(String name, {String greeting = 'Hello'}) =>print('$greeting $name!');// 함수 타입 선언void Function(String, {String greeting}) g = greet;g('Dash', greeting: 'Howdy');
typedef를 사용하면 긴 타입을 짧은 이름으로 표현할 수 있습니다.typedef IntList = List<int>;IntList il = [1, 2, 3];typedef Compare<T> = int Function(T a, T b);int sort(int a, int b) => a - b;assert(sort is Compare<int>); // true
Watch out
WARNING
function type은 “모양(시그니처)”이 정확히 맞아야 합니다.
즉, 인자 개수/순서/이름이 다르면 같은 함수처럼 보이더라도 타입이 맞지 않아 할당할 수 없습니다.void greet(String name, {String greeting = 'Hello'}) {}// void Function(String) g = greet; // 컴파일 오류: named parameter가 포함된 시그니처다.
결론: 긴 타입을 짧은 이름으로 표현하고, 함수 타입을 재사용할 수 있습니다.
단계 3: callable object
Why
NOTE함수 하나로는 부족하고 “상태를 가진 동작”이 필요할 때가 있습니다.
이때 객체를 함수처럼 호출할 수 있으면, API가 더 단순해집니다.class Counter {int value = 0;}
What
NOTE
call()메서드를 구현하면, 클래스 인스턴스를 함수 호출 문법으로 부를 수 있습니다.
How
TIP클래스 인스턴스를 함수처럼 호출하려면
call()메서드를 구현합니다.
call()메서드는 일반 함수와 동일하게파라미터와 반환 타입을 가질 수 있습니다.class WannabeFunction {String call(String a, String b, String c) => '$a $b $c!';}var wf = WannabeFunction();var out = wf('Hi', 'there,', 'gang');print(out); // Hi there, gang!설계 의도는 다음과 같습니다.
- 클래스 인스턴스에 함수 호출 형태를 부여한다.
파라미터와 반환 타입은 일반 함수와 동일하다.- 함수처럼 동작하지만 상태를 가질 수 있다.
결론: 함수처럼 호출 가능하면서도 클래스의 상태와 메서드를 활용할 수 있습니다.
Watch out
WARNING
call()은 “함수”가 아니라 “메서드 호출 문법을 제공하는 객체”입니다.
즉, 인스턴스 자체의 타입은 클래스이며, 필요한 경우에는call()의 시그니처를 기준으로 타입을 맞춰야 합니다.var wf = WannabeFunction();print(wf is WannabeFunction); // true: wf는 클래스 인스턴스다.print(wf('Hi', 'there,', 'gang')); // call()이 실행된다.
한계
dot shorthand는 다음 제약을 가집니다.
- Dart 버전 3.10 이상이 필요하다.
context type10이 분명해야 한다.- 표현식 문장은
.로 시작할 수 없다.
// 가능: 타입 문맥이 명확함int port = .parse('8080'); // int.parse('8080')
// 불가능: 표현식 문장은 .으로 시작 불가class Logger { static void log(String message) => print(message);}
void main() { // .log('Hello'); // 컴파일 오류 Logger.log('Hello'); // 명시적으로 작성}Footnotes
-
parameter(파라미터): 함수가 받는 입력값을 정의하는 변수다. ↩
-
function type(함수 타입): 함수의 입력과 반환 형태를 나타내는 타입이다. ↩
-
typedef(타입 별칭): 긴 타입 이름을 짧게 부르는 별칭이다. ↩
-
callable object(호출 가능한 객체):
call()메서드를 구현해 함수처럼 호출할 수 있는 객체다. ↩ -
signature(시그니처): 함수의 이름, 파라미터, 반환 타입으로 구성된 선언부다. ↩
-
dot shorthand(점 표기 축약): 점으로 시작하는 간결한 호출 표현식이다. ↩
-
required positional parameter(필수 위치 파라미터): 호출 시 순서대로 반드시 전달해야 하는 파라미터다. ↩
-
named parameter(이름 있는 파라미터): 중괄호로 감싸 이름을 붙여 전달하는 파라미터다. ↩
-
optional positional parameter(선택적 위치 파라미터): 대괄호로 감싸 선택적으로 전달하는 파라미터다. ↩
-
context type(문맥 타입): 표현식이 놓인 위치에서 기대되는 타입을 뜻한다. ↩
공유
이 글이 도움이 되었다면 다른 사람과 공유해주세요!