본문 바로가기

선택적 매개변수와 기본 매개변수

생략 가능한 인자와 기본값이 있는 인자를 구분하고 매개변수 순서 규칙을 지켜 유연하면서 예측 가능한 함수를 설계합니다.

이번에는 함수를 더욱 유연하게 만들면서도 타입 안전성을 유지할 수 있도록 돕는 두 가지 중요한 개념, 바로 선택적 매개변수(Optional Parameters)와 기본 매개변수(Default Parameters)에 대해 깊이 있게 다루겠습니다.

앞 절의 기본 문법을 바탕으로 어느 인수 자리를 비우는지와 기본값이 언제 발동하는지를 계산합니다. 이 절의 선택적 매개변수는 strictNullChecks를 켠 검사에서 읽습니다. 타입상 허용되는 값과 함수가 누락으로 취급하는 값은 따로 정합니다.

optional은 본문에서 undefined 가능성을 남깁니다. default는 undefined만 대체하고 null·빈 문자열·0·false는 보존합니다. 기본값 앞에 필수 인수가 있으면 순서를 지켜 호출합니다.

TYPE / RUNTIME / CONTRACT

기본값은 undefined일 때만 적용됩니다

생략·undefined·null·falsy는 서로 다른 입력입니다. 아래는 strictNullChecks를 켠 타입 검사와 JavaScript 기본값 동작을 함께 비교한 것입니다.

OPTIONAL

생략해도 초기값이 생기지는 않습니다

email?: string의 값은 string | undefined입니다. summarizeUser의 if (email)은 빈 문자열도 제외합니다.

DEFAULT

생략 또는 명시적 undefined

logWithPrefix(message)와 두 번째 인수에 undefined를 전달한 호출은 모두 [INFO]를 사용합니다.

NULL / FALSY

허용 타입과 기본값 동작은 별개

string 매개변수에 null을 전달하려면 허용 타입이 필요합니다. null과 빈 문자열은 기본값으로 바뀌지 않습니다. 0·false도 각각 타입이 허용할 때 그대로 유지됩니다.

ORDER

뒤의 필수 인수는 계속 필요합니다

createGreeting(undefined, "Have a great day!")는 Hello, Unknown!으로 시작합니다. 선택 매개변수 뒤 필수 매개변수는 오류지만 기본값 뒤 필수 매개변수는 가능합니다.

선택 인수가 많다면 options 객체를 검토할 수 있습니다. 기본값 자체가 입력 검증을 수행하지는 않습니다.


선택적 매개변수 기초 문법

때때로 함수를 호출할 때 모든 매개변수가 항상 필요한 것은 아닐 수 있습니다.

특정 매개변수가 존재할 수도 있고, 없을 수도 있는 상황에서 사용되는 것이 바로 선택적 매개변수입니다.

타입스크립트에서는 매개변수 이름 뒤에 물음표(?)를 붙여 해당 매개변수가 선택적임을 나타냅니다.

// 사용자 정보를 요약하는 함수
function summarizeUser(name: string, email?: string, phone?: string): string {
  let summary = `이름: ${name}`;
  if (email) {
    summary += `, 이메일: ${email}`;
  }
  if (phone) {
    summary += `, 전화번호: ${phone}`;
  }
  return summary;
}

// 다양한 방식으로 함수 호출
console.log(summarizeUser("홍길동"));
// 출력: 이름: 홍길동

console.log(summarizeUser("김철수", "[email protected]"));
// 출력: 이름: 김철수, 이메일: [email protected]

console.log(summarizeUser("이영희", "[email protected]", "010-1234-5678"));
// 출력: 이름: 이영희, 이메일: [email protected], 전화번호: 010-1234-5678

// 오류: 필수 매개변수를 누락할 수 없습니다.
// summarizeUser(); // Error: Expected 1-3 arguments, but got 0.

위 예시에서 email과 phone 매개변수는 ?가 붙어 있어 선택적입니다.

이 예제의 if (email)과 if (phone)은 undefined뿐 아니라 빈 문자열도 제외합니다. 생략 여부만 구별하려면 !== undefined처럼 검사해야 하며, 어떤 값을 누락으로 취급할지는 함수 계약으로 정합니다. 전화번호만 전달할 때는 summarizeUser("윤지", undefined, "010-0000-0000")처럼 이메일 자리를 undefined로 유지합니다. 두 번째 인수에 전화번호를 바로 쓰면 그 값은 email로 전달됩니다.

중요한 규칙: 타입스크립트에서 선택적 매개변수는 항상 필수 매개변수 뒤에 위치해야 합니다.

만약 필수 매개변수 앞에 선택적 매개변수를 배치하려고 하면 컴파일 오류가 발생합니다.

// function invalidOrder(first?: string, second: string): void { // Error: Required parameter cannot follow an optional parameter.
//   // ...
// }

이 규칙은 함수 호출 시 매개변수들의 의미를 명확하게 하고, 타입스크립트 컴파일러가 인자들을 올바르게 매핑할 수 있도록 돕습니다.


기본 매개변수 활용 패턴

ES2015(ES6)부터 자바스크립트에서는 함수 매개변수에 기본값(Default Value)을 직접 할당하는 문법이 도입되었습니다.

타입스크립트도 이 문법을 타입 검사와 함께 처리합니다.

기본값 매개변수 뒤에 필수 매개변수가 없다면 호출 인수를 생략할 수 있습니다. 기본값은 실제 인자가 undefined일 때 적용되며 null이나 빈 문자열에는 적용되지 않습니다.

함수 호출 시 해당 인자를 제공하지 않으면, 지정된 기본값이 사용됩니다.

// 메시지를 출력하는 함수 (기본 접두사 지정)
function logWithPrefix(message: string, prefix: string = "[INFO]"): void {
  console.log(`${prefix} ${message}`);
}

// 기본값 사용
logWithPrefix("애플리케이션이 시작되었습니다.");
// 출력: [INFO] 애플리케이션이 시작되었습니다.

// 기본값 재정의
logWithPrefix("데이터베이스 연결 실패!", "[ERROR]");
// 출력: [ERROR] 데이터베이스 연결 실패!

// 다른 예시: 숫자의 거듭제곱 계산
function power(base: number, exponent: number = 2): number {
  return base ** exponent;
}
기본 매개변수의 장점
  • 코드 간결성: 함수 내부에서 if (arg === undefined)와 같은 기본값 할당 로직을 작성할 필요가 없어 코드가 더 간결해집니다.
  • 가독성: 함수 서명만으로 어떤 매개변수가 선택적이며 어떤 기본값을 가지는지 명확하게 알 수 있습니다.
  • 런타임 안전성: undefined 값이 의도치 않게 사용되는 것을 줄여줍니다.

선택적 매개변수와 기본 매개변수의 순서

선택적 매개변수와 마찬가지로, 기본 매개변수 역시 필수 매개변수 뒤에 배치하는 것이 일반적입니다.

하지만, 기본 매개변수는 선택적 매개변수와 달리 필수 매개변수 중간에도 위치할 수 있습니다.

단, 이 경우 해당 기본 매개변수를 생략하려면 undefined를 명시적으로 전달해야 합니다.

// 기본 매개변수 뒤에 필수 매개변수가 오는 경우 (가능은 하지만 권장되지 않음)
function createGreeting(
  name: string = "Unknown",
  message: string, // 필수 매개변수
  salutation: string = "Hello"
): string {
  return `${salutation}, ${name}! ${message}`;
}

// console.log(createGreeting("World")); // Error: 'message' 매개 변수에 대한 인수가 없습니다.
// 필수 매개변수 `message`를 생략할 수 없습니다.

// 기본 매개변수를 생략하려면 undefined를 전달해야 합니다.
console.log(createGreeting(undefined, "Have a great day!"));
// 출력: Hello, Unknown! Have a great day!

console.log(createGreeting("Alice", "Nice to meet you!", "Hi"));
// 출력: Hi, Alice! Nice to meet you!

이러한 혼합된 순서는 코드의 가독성을 해칠 수 있으므로, 일반적으로 모든 필수 매개변수를 먼저 배치하고 그 뒤에 선택적/기본 매개변수를 배치하는 것이 좋은 습관입니다.


선택적 매개변수와 기본 매개변수는 함수 호출 규칙을 유연하게 만들면서 타입 검사를 유지하는 기능입니다.

기본값과 실제 값 계산하기

원 power를 사용하여 power(3), power(3, undefined), power(3, 0)의 값을 예측하고 각각 실행합니다. 첫 두 호출은 지수 2로 9를 반환하지만, 셋째는 지수 0을 그대로 사용해 1을 반환합니다. 0은 undefined가 아니므로 기본값 2로 바뀌지 않습니다. power(3, null)은 이 엄격한 number 계약에서 타입 오류이며, null이 기본값을 선택하는 약속은 아닙니다.

혼자 호출을 구성하기

summarizeUser에 이름 윤지와 전화번호 010-0000-0000만 주는 호출을 작성하고 출력 문자열을 적어 보세요. createGreeting에는 이름 기본값을 유지하면서 message는 좋은 하루, salutation은 안녕을 전달합니다. 마지막으로 name에 빈 문자열을 명시하면 Unknown으로 바뀌는지 판단합니다.

빈 자리와 기본값 해설

summarizeUser("윤지", undefined, "010-0000-0000")은 이름: 윤지, 전화번호: 010-0000-0000입니다. 전화번호를 세 번째 자리에 놓기 위해 두 번째 자리를 유지했습니다. createGreeting(undefined, "좋은 하루", "안녕")은 안녕, Unknown! 좋은 하루입니다. name에 빈 문자열을 주면 그대로 사용하므로 안녕, ! 좋은 하루가 됩니다. 기본값은 빈 문자열을 자동으로 정상 이름으로 바꾸는 입력 검증 기능이 아닙니다.