식(Expressions)

식(Expressions)

PHP를 처음 배우다 보면, 코드를 짜다 보면 자연스럽게 만나는 개념이 바로 **식(expression)**이에요. PHP에서 식은 가장 중요한 구성 블록인데, 사실 여러분이 이미 아주 자주 쓰고 있답니다. PHP에서는 여러분이 작성하는 거의 모든 것이 식이거든요. 식을 가장 간단하면서도 정확하게 정의하자면 "값을 가지는 무엇이든"이라고 할 수 있어요.

출처: php.net/manual/en/language.expressions.php (Language Reference · Expressions)

본문

식이란 무엇일까요?

가장 기본적인 형태의 식은 **상수(constant)**와 **변수(variable)**예요. 여러분이 $a = 5라고 입력하면, 5$a에 넣는 것이죠. 5는 당연히 값 5를 가지니까, 다시 말해 5는 값이 5인 식이에요(이 경우 5는 정수 상수입니다).

할당이 끝나고 나면 $a의 값도 5가 될 거예요. 그래서 $b = $a라고 쓰면, 마치 $b = 5라고 쓴 것과 똑같이 동작할 거라고 기대하게 되죠. 다시 말해 $a도 값이 5인 식인 셈이에요. 모든 게 제대로 동작한다면, 정확히 그렇게 될 거예요.

함수도 식이에요

식의 조금 더 복잡한 예로는 **함수(function)**가 있어요. 예를 들어 이런 함수를 생각해 볼게요.

<?php
function foo ()
{
    return 5;
}
?>

함수의 개념을 알고 있다면, $c = foo()라고 입력하는 건 본질적으로 $c = 5라고 쓰는 것과 같을 거라고 짐작할 수 있어요. 맞아요, 정확히 그렇습니다. 함수는 반환값(return value)을 값으로 가지는 식이에요. foo()는 5를 반환하니까, 식 foo()의 값은 5인 거죠. 물론 함수가 항상 정적인 값을 반환하는 건 아니고, 보통 뭔가를 계산해서 반환해요.

값의 종류

당연히 PHP의 값이 항상 정수일 필요는 없고, 실제로도 그렇지 않은 경우가 많아요. PHP는 네 가지 스칼라(scalar) 값 타입을 지원해요: int 값, 부동소수점 값(float), string 값, 그리고 bool 값이 그것이에요. (스칼라 값이란, 예를 들어 배열과 달리 더 작은 조각으로 "쪼갤 수 없는" 값이에요.) PHP는 또한 두 가지 복합(비-스칼라) 타입, 즉 배열(array)과 객체(object)도 지원해요. 이 각각의 값 타입은 변수에 할당되거나 함수에서 반환될 수 있어요.

PHP는 식 중심 언어예요

PHP는 다른 많은 언어와 같은 방식으로 식을 훨씬 더 확장해서 다루는데요, 이렇게 말하면 거의 모든 것이 식이라는 의미에서 PHP는 식 중심(expression-oriented) 언어예요. 아까 다룬 $a = 5라는 예를 다시 볼까요? 여기에는 두 가지 값이 관련되어 있다는 걸 쉽게 알 수 있어요. 정수 상수 5의 값, 그리고 5로 갱신되는 $a의 값이죠. 그런데 사실 여기에는 값이 하나 더 숨어 있어요, 바로 할당 자체의 값입니다. 할당은 그 자체로 할당된 값을 평가값으로 가집니다. 여기서는 5가 되겠죠. 실제로 이건 $a = 5가, 그것이 하는 일과는 무관하게, 값이 5인 식이라는 뜻이에요. 그래서 $b = ($a = 5)라고 쓰는 건 $a = 5; $b = 5;라고 쓰는 것과 같아요. (세미콜론은 구문statement의 끝을 표시합니다.) 할당은 오른쪽에서 왼쪽으로 파싱되기 때문에, $b = $a = 5라고 쓸 수도 있어요.

전위/후위 증감 연산자

식 중심 성격을 보여주는 또 다른 좋은 예는 전위·후위 **증가(increment)**와 **감소(decrement)**예요. PHP와 다른 여러 언어를 쓰는 분들이라면 variable++variable--라는 표기법에 익숙할 거예요. 이들은 증가·감소 연산자입니다. PHP에는 C에서처럼 두 종류의 증가 연산이 있는데, 바로 **전위 증가(pre-increment)**와 **후위 증가(post-increment)**예요. 둘 다 본질적으로 변수를 증가시키고, 변수에 미치는 효과는 동일합니다. 차이는 증가 식이 가지는 에서 나와요. 전위 증가는 ++$variable이라고 쓰는데, 증가된 값을 평가값으로 가집니다(PHP가 값을 읽기 전에 변수를 증가시키기 때문에 'pre-increment'라는 이름이 붙었어요). 후위 증가는 $variable++라고 쓰는데, 증가되기 전의 $variable의 원래 값을 평가값으로 가져요(PHP가 값을 읽은 뒤에 변수를 증가시키니까 'post-increment'라는 이름이 붙은 거예요).

비교 식

아주 흔한 종류의 식으로는 **비교 식(comparison expression)**이 있어요. 이 식들은 false 또는 true로 평가됩니다. PHP는 >(크다), >=(크거나 같다), ==(같다), !=(같지 않다), <(작다), <=(작거나 같다)를 지원해요. 또한 엄격한 동등 연산자 집합도 지원하는데, ===(같고 타입도 같다)와 !==(같지 않거나 타입이 같지 않다)가 그것이에요. 이 식들은 if 문 같은 조건부 실행 안에서 가장 흔히 사용됩니다.

결합 대입(operator-assignment) 식

여기서 다룰 식의 마지막 예는 결합 연산자-대입(combined operator-assignment) 식이에요. $a를 1만큼 증가시키고 싶다면 $a++++$a라고 쓰면 된다는 걸 이미 아실 거예요. 그런데 1보다 더 많이, 예를 들어 3만큼 더하고 싶다면 어떻게 할까요? $a++를 여러 번 쓸 수도 있지만, 그건 분명히 효율적이거나 편한 방법이 아니에요. 훨씬 흔한 방법은 $a = $a + 3이라고 쓰는 거예요. $a + 3$a의 값에 3을 더한 값으로 평가되고, 다시 $a에 할당되면서 $a를 3만큼 증가시키는 결과를 내지요. PHP에는 C 같은 다른 여러 언어에서처럼 이걸 더 짧게 쓰는 방법이 있는데, 오래 쓰다 보면 더 명확하고 빨리 이해할 수 있게 되는 방법이에요. $a의 현재 값에 3을 더하는 걸 $a += 3이라고 쓸 수 있어요. 이건 정확히 "$a의 값을 가져와서, 3을 더하고, 다시 $a에 할당한다"는 뜻입니다. 더 짧고 명확한 것에 더해, 이 방식은 실행도 더 빨라요. $a += 3의 값은 일반적인 할당처럼 할당된 값이에요. 주의할 점은, 이 값이 3이 아니라 $a에 3을 더한 결합 값이라는 거예요(그게 $a에 할당되는 값이니까요). 두 자리(two-place) 연산자는 모두 이 연산자-대입 방식으로 쓸 수 있어요. 예를 들어 $a -= 5($a의 값에서 5를 뺀다), $b *= 7($b의 값에 7을 곱한다) 같은 식이죠.

삼항 조건 연산자

다른 언어에서 본 적이 없다면 다소 낯설게 느껴질 수 있는 식이 하나 더 있어요, 바로 **삼항 조건 연산자(ternary conditional operator)**입니다.

<?php
$first ? $second : $third
?>

첫 번째 하위식의 값이 true(0이 아니면)라면 두 번째 하위식이 평가되고, 그것이 조건식의 결과가 됩니다. 그렇지 않으면 세 번째 하위식이 평가되고, 그 값이 결과가 돼요.

실제 예제로 확인하기

다음 예제는 전위·후위 증가와 식 전반을 더 잘 이해하는 데 도움이 될 거예요.

<?php
function double($i)
{
    return $i * 2;
}

$b = $a = 5;        /* assign the value five into the variable $a and $b */
$c = $a++;          /* post-increment, assign original value of $a 
                       (5) to $c */
print "a = {$a}; b = {$b}; c = {$c}" . PHP_EOL;

$e = $d = ++$b;     /* pre-increment, assign the incremented value of 
                       $b (6) to $d and $e */
print "b = {$b}; d = {$d}; e = {$e}" . PHP_EOL;

/* at this point, both $d and $e are equal to 6 */

$f = double($d++);  /* assign twice the value of $d before
                       the increment, 2*6 = 12 to $f */
print "d = {$d}; f = {$f}" . PHP_EOL;

$g = double(++$e);  /* assign twice the value of $e after
                       the increment, 2*7 = 14 to $g */
print "e = {$e}; g = {$g}" . PHP_EOL;

$h = $g += 10;      /* first, $g is incremented by 10 and ends with the 
                       value of 24. the value of the assignment (24) is 
                       then assigned into $h, and $h ends with the value 
                       of 24 as well. */
print "g = {$g}; h = {$h}" . PHP_EOL;
?>

식을 구문으로 쓰기

어떤 식은 **구문(statement)**으로 간주될 수 있어요. 이 경우 구문은 'expr ;' 형태, 즉 표현식 뒤에 세미콜론이 따라오는 형태를 가집니다. $b = $a = 5;에서 $a = 5는 유효한 식이지만 그 자체로는 구문이 아니에요. 그러나 $b = $a = 5;는 유효한 구문입니다.

식의 참·거짓 값

마지막으로 언급할 만한 것은 식의 **참·거짓 값(truth value)**이에요. 많은 경우, 특히 조건부 실행과 루프 안에서는 식의 구체적인 값보다 그 식이 true를 뜻하는지 false를 뜻하는지만 관심이 있게 돼요. 상수 truefalse(대소문자 구분 없음)는 두 가지 불(boolean) 값이에요. 필요할 때 식은 자동으로 불(boolean)로 변환됩니다. 어떻게 변환되는지에 대한 자세한 내용은 타입 캐스팅(Type Casting) 섹션을 참고해 주세요.

PHP는 식을 완전하고 강력하게 구현하고 있어서, 그걸 전부 이 매뉴얼에 담는 것은 범위를 벗어나요. 위의 예제들은 식이 무엇이고, 어떻게 유용한 식을 구성할 수 있는지에 대한 좋은 감을 잡는 데 충분할 거예요. 매뉴얼의 나머지 부분에서는 어떤 유효한 PHP 식이든 나타낼 때 expr이라고 쓸 거예요.

더 알아보기