# 매개변수 전달 방식

Dart에서 함수와 메소드의 매개변수 전달 방식은 다양한 형태로 지원되며, 각 방식에 따라 함수의 동작 방식이 달라진다. 이 섹션에서는 Dart에서 제공하는 매개변수 전달 방식과 그 활용법을 자세히 살펴보자.

#### 1. 기본 매개변수 전달

기본 매개변수 전달 방식은 함수를 정의할 때 매개변수를 함수의 인자로 지정하여 전달하는 방식이다. 함수가 호출될 때 인자 값이 순서대로 전달된다. Dart에서는 기본적으로 **값에 의한 전달(pass by value)** 방식이 사용된다. 이는 전달된 값의 복사본이 함수로 전달된다는 것을 의미한다.

**예제:**

```dart
void increment(int number) {
  number++;
}

void main() {
  int value = 10;
  increment(value);
  print(value); // 출력 결과는 여전히 10
}
```

위 코드에서 `increment` 함수는 `number` 값을 증가시키지만, `main` 함수에서 선언된 `value`에는 영향이 없다. 이는 **값에 의한 전달**로 인해 함수 내에서 변경된 값이 호출된 함수 외부에 반영되지 않기 때문이다.

#### 2. 선택적 매개변수

Dart는 함수의 매개변수를 선택적으로 정의할 수 있는 방법을 제공한다. 선택적 매개변수는 크게 두 가지로 나뉜다: **위치 선택적 매개변수**와 **이름 선택적 매개변수**이다.

**위치 선택적 매개변수 (Positional Optional Parameters)**

위치 선택적 매개변수는 **대괄호**(`[]`)를 사용하여 선언한다. 이 매개변수들은 선택적으로 전달할 수 있으며, 전달되지 않을 경우 `null` 값 또는 기본값이 사용된다.

**예제:**

```dart
void greet(String name, [String? message]) {
  print('Hello, $name!${message ?? ''}');
}

void main() {
  greet('Alice'); // Hello, Alice!
  greet('Bob', 'Good to see you!'); // Hello, Bob! Good to see you!
}
```

위 코드에서 `greet` 함수는 두 번째 매개변수인 `message`를 선택적으로 받을 수 있으며, 전달되지 않을 경우 `null`로 처리된다. `??` 연산자를 사용하여 `null`일 때 빈 문자열을 출력하게 설정하였다.

**이름 선택적 매개변수 (Named Optional Parameters)**

이름 선택적 매개변수는 **중괄호**(`{}`)를 사용하여 선언하며, 함수 호출 시 매개변수 이름을 명시하여 값을 전달한다. 이 방식은 매개변수의 순서에 상관없이 호출할 수 있어 더욱 유연하게 사용할 수 있다.

**예제:**

```dart
void greet({required String name, String? message}) {
  print('Hello, $name!${message ?? ''}');
}

void main() {
  greet(name: 'Alice'); // Hello, Alice!
  greet(name: 'Bob', message: 'Good to see you!'); // Hello, Bob! Good to see you!
}
```

이름 선택적 매개변수에서 `required` 키워드를 사용하여 반드시 값을 전달해야 하는 매개변수를 지정할 수 있다. 위 코드에서 `name` 매개변수는 필수이지만, `message`는 선택적이다.

#### 3. 기본값 지정

매개변수에 기본값을 지정할 수 있는 기능도 Dart에서 제공하는 매우 유용한 특징 중 하나이다. 기본값은 선택적 매개변수에서 사용되며, 함수가 호출될 때 해당 매개변수에 값이 전달되지 않으면 기본값이 사용된다.

**예제:**

```dart
void greet(String name, {String message = 'How are you?'}) {
  print('Hello, $name!$message');
}

void main() {
  greet('Alice'); // Hello, Alice! How are you?
  greet('Bob', message: 'Good to see you!'); // Hello, Bob! Good to see you!
}
```

위 코드에서 `message` 매개변수는 기본값으로 `'How are you?'`를 갖는다. 따라서 함수가 호출될 때 `message` 매개변수를 전달하지 않으면 기본값이 사용된다.

#### 4. 값에 의한 전달 (Pass by Value)

Dart에서 매개변수는 **값에 의한 전달** 방식으로 처리된다. 이는 함수로 전달된 인자의 **복사본**이 함수 내에서 사용된다는 의미이다. 전달된 인자의 값이 함수 내부에서 변경되더라도, 함수 외부의 값에는 영향을 미치지 않는다.

**예제:**

```dart
void updateValue(int value) {
  value = 20;
}

void main() {
  int x = 10;
  updateValue(x);
  print(x); // 출력: 10
}
```

이 경우 `x` 값이 함수 내에서 변경되더라도, 함수 외부에서는 여전히 `10`의 값을 유지하게 된다. 이는 값을 복사하여 함수에 전달하기 때문에 발생하는 현상이다.

#### 5. 참조에 의한 전달을 흉내내기 (Mimicking Pass by Reference)

Dart는 기본적으로 **값에 의한 전달**을 사용하지만, 참조 타입(예: 객체나 리스트)을 이용하여 \*\*참조에 의한 전달(pass by reference)\*\*를 흉내낼 수 있다. 참조 타입은 객체의 주소값을 전달하므로, 함수 내부에서 객체를 수정하면 외부에도 영향을 미치게 된다.

**예제:**

```dart
void updateList(List<int> numbers) {
  numbers[0] = 100;
}

void main() {
  List<int> myList = [1, 2, 3];
  updateList(myList);
  print(myList); // 출력: [100, 2, 3]
}
```

이 예제에서 리스트 `myList`는 참조 타입이므로 함수에서 리스트의 첫 번째 값을 변경하면, 함수 외부에서도 그 변경 사항이 반영된다. 이는 참조를 전달하는 방식이기 때문에 발생하는 현상이다.

#### 6. 매개변수로 함수 전달

Dart에서는 함수를 매개변수로 전달할 수 있다. 이를 통해 고차 함수(higher-order function)를 작성할 수 있으며, 함수 내에서 다른 함수를 호출하거나 처리할 수 있게 된다.

**예제:**

```dart
void executeFunction(Function func, String value) {
  func(value);
}

void printMessage(String message) {
  print(message);
}

void main() {
  executeFunction(printMessage, 'Hello, Dart!'); // 출력: Hello, Dart!
}
```

위 코드에서 `executeFunction` 함수는 함수와 문자열을 인자로 받아 해당 함수를 호출한다. 이처럼 함수를 매개변수로 전달함으로써 유연한 코드 작성을 할 수 있다.

#### 7. 콜백 함수 사용

콜백 함수는 특정 작업이 완료된 후 호출되는 함수이다. Dart에서는 비동기 작업이나 이벤트 처리 중에 콜백 함수를 자주 사용한다.

**예제:**

```dart
void fetchData(Function callback) {
  // 데이터 처리 후 콜백 함수 호출
  callback('Data fetched successfully!');
}

void main() {
  fetchData((message) {
    print(message); // 출력: Data fetched successfully!
  });
}
```

위 코드에서 `fetchData` 함수는 콜백 함수를 인자로 받아 비동기적으로 데이터 처리 후 해당 콜백을 호출한다. 콜백 함수는 주로 비동기 프로그래밍에서 중요한 역할을 한다.
