PHP · 심층 가이드
PHP 함수 완전 정리
기본값과 가변 인자부터 화살표 함수, Generator, first class callable까지 PHP에서 함수를 값으로 다루는 방법을 정리하고 재사용 가능한 파이프라인을 만듭니다.
PHP에서 함수는 오랫동안 온전한 값이 아니었습니다. 콜백은 함수 이름 문자열이나 [$obj, 'method'] 형태의 배열로 넘겼고, 그 흔적이 지금도 표준 라이브러리 시그니처에 callable이라는 이름으로 남아 있습니다. 이후 Closure, 화살표 함수, 그리고 strlen(...) 같은 first class callable 문법이 차례로 들어오면서 함수를 변수에 담고 조립하는 일이 자연스러워졌습니다. 이 계보를 알면 왜 같은 목적에 네 가지 표기법이 공존하는지 납득이 됩니다.
앞부분의 기본값 파라미터와 가변 인자 받기는 호출 규약을 다루고, 이름 있는 인자로 함수 호출과 함께 보면 인자가 많은 함수를 어떻게 정리하는지 감이 옵니다. 중반의 화살표 함수 사용과 클로저 팩토리는 상태를 품은 함수를 만드는 두 방식이고, 여기서 만든 조각을 함수형 파이프라인 헬퍼와 부분 적용 함수 만들기가 이어 붙입니다. 메모리를 아껴야 하는 순회는 Generator 로 범위 만들기에서 시작해 yield from 위임으로 중첩 소스를 평탄하게 합치는 순서로 읽으면 좋습니다.
클로저의 캡처 방식은 두 문법이 정반대입니다. 화살표 함수 fn() 은 바깥 변수를 자동으로, 값으로 캡처하지만 본문이 표현식 하나로 제한되고, function() use ($x) 는 명시적으로 적어야 하며 use (&$x) 로 참조 캡처가 가능합니다. 반복문 안에서 클로저를 모을 때 이 차이가 결과를 갈라 놓습니다. Generator도 함정이 있는데, 한 번 소비하면 되감을 수 없어 두 번째 foreach에서 예외가 나고, return으로 돌려준 값은 getReturn()으로만 꺼낼 수 있습니다.
01반환 타입이 있는 함수
입력 타입과 반환 타입을 함께 선언하는 가장 기본적인 함수 예제입니다.
PHP code
<?php
function add(int $a, int $b): int {
return $a + $b;
}
echo add(3, 4);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
02기본값 파라미터
자주 생략되는 인자에 기본값을 부여하는 함수 선언 예제입니다.
PHP code
<?php
function greet(string $name = 'guest'): string {
return "hello {$name}";
}
echo greet();함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
03가변 인자 받기
가변 길이 인자를 받아 합계를 구하는 variadic 함수 예제입니다.
PHP code
<?php
function total(int ...$numbers): int {
return array_sum($numbers);
}
echo total(1, 2, 3, 4);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
04참조 인자로 값 바꾸기
참조 인자를 통해 호출자 변수 자체를 수정하는 예제입니다.
PHP code
<?php
function increment(int &$value): void {
$value++;
}
$count = 0;
increment($count);
echo $count;함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
참조 전달은 데이터 흐름을 감추기 쉬우므로 반환값으로 바꿀 수 있는지 먼저 고민하는 편이 좋습니다.
05callable 전략 주입
callable 타입으로 동작을 주입받는 함수형 스타일의 기본 예제입니다.
PHP code
<?php
function runFormatter(string $value, callable $formatter): string {
return $formatter($value);
}
echo runFormatter('php', 'strtoupper');함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
06재귀 팩토리얼
재귀 호출 구조를 가장 단순하게 익히는 팩토리얼 함수 예제입니다.
PHP code
<?php
function factorial(int $n): int {
return $n <= 1 ? 1 : $n * factorial($n - 1);
}
echo factorial(5);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
07배열을 합치는 reduce 함수
array_reduce를 함수 내부에서 감싸 더 읽기 쉬운 도메인 함수로 만드는 예제입니다.
PHP code
<?php
function joinWords(array $words): string {
return array_reduce($words, function (string $carry, string $word): string {
return $carry === '' ? $word : $carry . '-' . $word;
}, '');
}
echo joinWords(['php', 'api', 'server']);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
08클로저 팩토리
함수가 함수를 반환하는 클로저 팩토리 예제입니다.
PHP code
<?php
function makeMultiplier(int $factor): Closure {
return function (int $value) use ($factor): int {
return $value * $factor;
};
}
$double = makeMultiplier(2);
echo $double(10);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
09화살표 함수 사용
짧은 변환 로직을 fn 화살표 함수로 표현하는 예제입니다.
PHP code
<?php
$numbers = [1, 2, 3];
$doubled = array_map(fn (int $n): int => $n * 2, $numbers);
print_r($doubled);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
10Generator 로 범위 만들기
yield를 이용해 메모리를 아끼며 값을 순차 생성하는 generator 예제입니다.
PHP code
<?php
function rangeGen(int $start, int $end): Generator {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
}
foreach (rangeGen(3, 5) as $n) {
echo $n . PHP_EOL;
}함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
11yield from 위임
다른 iterable의 값을 그대로 위임하는 yield from 예제입니다.
PHP code
<?php
function chunks(): Generator {
yield from ['php', 'go'];
yield from ['python'];
}
foreach (chunks() as $item) {
echo $item . PHP_EOL;
}함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
12함수 내부 static 변수
호출 사이에 상태를 유지하는 static 지역 변수 사용 예제입니다.
PHP code
<?php
function nextId(): int {
static $id = 0;
return ++$id;
}
echo nextId() . ' / ' . nextId();함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
13이름 있는 인자로 함수 호출
호출부 가독성을 높이는 이름 있는 인자 사용 예제입니다.
PHP code
<?php
function buildUrl(string $host, string $path, bool $https = true): string {
$scheme = $https ? 'https' : 'http';
return "{$scheme}://{$host}/{$path}";
}
echo buildUrl(path: 'docs', host: 'example.com');함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
14nullable 반환 타입
찾지 못한 경우 null을 반환하는 함수의 타입 설계를 보여주는 예제입니다.
PHP code
<?php
function findUser(array $users, int $id): ?array {
foreach ($users as $user) {
if ($user['id'] === $id) {
return $user;
}
}
return null;
}
var_dump(findUser([['id' => 1]], 2));함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
15union 반환 타입
성공 값과 실패 값을 union 타입으로 표현하는 예제입니다.
PHP code
<?php
function parsePort(string $value): int|false {
$port = filter_var($value, FILTER_VALIDATE_INT);
return $port === false ? false : (int) $port;
}
var_dump(parsePort('8080'));함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
16Closure::fromCallable 사용
메서드를 Closure 인스턴스로 변환해 콜백 API에 넘기는 예제입니다.
PHP code
<?php
class Slugger {
public function slug(string $text): string {
return strtolower(str_replace(' ', '-', trim($text)));
}
}
$closure = Closure::fromCallable([new Slugger(), 'slug']);
echo $closure('Hello PHP');함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
17first class callable 문법
PHP 8.1 first class callable 문법으로 함수를 값처럼 전달하는 예제입니다.
PHP code
<?php
function normalize(string $value): string {
return trim(strtolower($value));
}
$callable = normalize(...);
echo $callable(' PHP ');함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
18function_exists 폴리필
폴리필을 안전하게 선언하기 위해 function_exists를 감싸는 예제입니다.
PHP code
<?php
if (!function_exists('str_contains_all')) {
function str_contains_all(string $text, array $needles): bool {
foreach ($needles as $needle) {
if (!str_contains($text, $needle)) {
return false;
}
}
return true;
}
}
var_dump(str_contains_all('php api server', ['php', 'api']));함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
19스프레드로 인자 풀기
배열에 담긴 값을 함수 인자로 펼치는 스프레드 호출 예제입니다.
PHP code
<?php
function connect(string $host, int $port, string $db): string {
return "{$host}:{$port}/{$db}";
}
$params = ['localhost', 3306, 'app'];
echo connect(...$params);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
20정렬용 comparator 콜백
usort에 비교 함수를 주입해 도메인 규칙으로 정렬하는 예제입니다.
PHP code
<?php
$users = [
['name' => 'Lee', 'score' => 90],
['name' => 'Kim', 'score' => 98],
];
usort($users, function (array $a, array $b): int {
return $b['score'] <=> $a['score'];
});
print_r($users);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
21함수형 파이프라인 헬퍼
값을 단계적으로 변환하는 간단한 pipe 헬퍼 함수 예제입니다.
PHP code
<?php
function pipe(mixed $value, callable ...$steps): mixed {
foreach ($steps as $step) {
$value = $step($value);
}
return $value;
}
$result = pipe(' PHP ', 'trim', 'strtolower', fn (string $v) => $v . '-api');
echo $result;함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
22메모이제이션 함수
재귀 함수에 static 캐시를 붙여 메모이제이션하는 예제입니다.
PHP code
<?php
function fib(int $n): int {
static $cache = [0 => 0, 1 => 1];
if (!array_key_exists($n, $cache)) {
$cache[$n] = fib($n - 1) + fib($n - 2);
}
return $cache[$n];
}
echo fib(10);함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
23부분 적용 함수 만들기
일부 인자를 미리 고정해 새 함수를 만드는 부분 적용 예제입니다.
PHP code
<?php
function partial(callable $fn, mixed ...$fixed): Closure {
return function (mixed ...$rest) use ($fn, $fixed): mixed {
return $fn(...array_merge($fixed, $rest));
};
}
$startsWith = partial('str_starts_with', 'php-framework');
var_dump($startsWith('php'));함수 예제는 인자 타입, 반환 타입, 호출 방식 세 가지를 같이 확인하면 이해가 빠릅니다.
인자 순서와 기본값, 참조 전달 여부를 혼동하면 함수 호출이 쉽게 꼬입니다.
정리하며
- 표현식 하나로 끝나는 콜백은 fn(), 여러 문장이 필요하면 use 절 클로저를 씁니다.
- 콜백을 넘길 때는 문자열 대신
foo(...)문법으로 오타를 즉시 드러냅니다. - 큰 목록은 배열을 만들어 반환하지 말고 Generator로 흘려보내 메모리를 고정합니다.
- 제너레이터는 일회성이므로 재사용이 필요하면 팩토리 함수로 매번 새로 만듭니다.
더 깊이 들어가고 싶다면 PHP 학습 라이브러리에서 다른 주제 가이드를 이어서 보거나, 언어 비교에서 같은 개념이 다른 언어에서 어떻게 표현되는지 확인해 보세요.