logosvg한 입 크기로 잘라먹는 리액트
Search

8. 함수

 
자바스크립트 코드를 작성하다 보면 유사하게 동작하는 코드를 작성할 때가 있습니다. 그러나 동일하거나 유사한 코드를 필요하다고 매번 만들게 되면 불필요한 중복 코드가 생깁니다. 자바스크립트에서는 공통으로 사용하는 유사 코드를 하나로 묶어 ‘함수’라는 이름으로 사용할 수 있습니다.
 

함수가 필요한 이유

함수의 사용법을 본격적으로 알아보기 전에 함수는 어떨 때 사용하는 게 유용한지 사례를 통해 살펴보겠습니다. 다음은 주어진 높이와 너비를 이용해 직사각형의 면적을 출력하는 간단한 예입니다.
코드를 불러오는 중 입니다 ...
직사각형의 넓이를 한 개가 아닌 두 개 구해야 한다면 다음과 같이 작성합니다.
 
코드를 불러오는 중 입니다 ...
직사각형을 구하는 방법은 첫 번째나 두 번째나 다 똑같습니다. 두 직사각형의 넓이 변수area1과 area2는 이름과 값만 다를 뿐, 높이와 너비를 곱해 넓이를 구하는 방법은 동일합니다. 같은 방식으로 10개가 넘는 직사각형의 넓이를 구한다면 어떻게 될까요? 이런 식으로 유사하게 동작하는 코드를 중복해 작성하면, 코드는 길어지고 가독성도 현저히 떨어집니다.
함수를 사용하면 유사하게 동작하는 중복 코드를 하나의 블록 단위로 묶을 수 있습니다. 그리고 이 블록에 이름을 붙여 원할 때마다 호출해 사용할 수 있습니다. 한마디로 더 간결하고 구조적인 프로그래밍이 가능하게 됩니다.
 

함수 선언

함수는 ‘이름이 붙은 명령들의 모음’이라고 말할 수 있습니다. 예를 들어 직사각형의 넓이를 구하는 함수를 만든다고 하면, 높이와 너비를 곱해 넓이를 구하는 명령만을 모아 하나의 함수로 구성할 수 있습니다.
자바스크립트에서는 기본적으로 다음과 같이 함수를 만듭니다.
코드를 불러오는 중 입니다 ...
자바스크립트에서는 function이라는 키워드를 사용해 함수를 만듭니다. function 키워드 바로 다음에는 함수의 이름, 그 다음에는 매개변수가 오며, 마지막으로 중괄호로 감싼 곳에 함수가 수행할 명령을 작성합니다. 매개변수는 함수에 값을 전달하는 일종의 매개체입니다. 매개변수의 설명과 사용법은 다음 단원에서 자세히 다룹니다.
만약 환영 인사를 하는 기능을 함수로 만든다고 하면 다음과 같이 작성할 수 있습니다.
코드를 불러오는 중 입니다 ...
이렇게 만든 함수는 greeting이라는 이름으로 안녕하세요!라는 문자열을 콘솔에 출력하는 기능을 갖게 됩니다.
이와 같이 함수를 정의하는 작업을 ‘함수 선언’이라고 합니다.
 

함수 호출

함수를 선언했다고 해서 함수를 바로 실행할 수 있는 것은 아닙니다. 함수는 이름을 불러 주어야 실행되는데, 이를 ‘함수 호출’이라고 합니다.
코드를 불러오는 중 입니다 ...
함수를 호출하면 미리 선언해 두었던 함수를 실행합니다.
정확히는 호출하면 함수를 선언할 때 중괄호에 작성했던 명령을 실행합니다. 결국 함수 선언은 호출하면 바로 실행할 수 있도록 준비하는 작업이라고 생각할 수 있습니다.
지금까지 작성했던 자바스크립트 코드는 실행하면, 위에서부터 아래로 순서대로 한 줄씩 수행됩니다. 그런데 함수를 호출하면 코드의 실행 흐름이 바뀝니다. 다음 예에서 코드의 실행 순서를 눈 여겨 보길 바랍니다.
코드를 불러오는 중 입니다 ...
함수를 선언합니다.  함수 시작 전이라는 문자열을 콘솔에 출력합니다  함수 greeting을 호출합니다. 기존에 순서대로 진행되던 코드의 흐름은 여기서 멈추고, 호출된 함수를 수행하기 위해 선언한 곳으로 흐름이 이동합니다. 함수가 실행되면서 콘솔에 안녕하세요!를 출력합니다.  호출된 함수가 동작을 모두 종료하면 코드의 흐름은 다시 원래대로 돌아오며 이후의 코드를 수 행합니다. 콘솔에 함수 종료를 출력합니다.
함수가 어떻게 동작하는지 알아보았습니다. 다음에는 함수를 이용해 직사각형의 넓이를 구하는 코드를 작성하겠습니다.
코드를 불러오는 중 입니다 ...
getArea라는 이름의 함수는 너비와 높이를 곱해 넓이를 구한 다음 콘솔에 출력합니다. 자주 사용하는 코드를 함수로 만들어 두면, 매번 작성하지 않아도 필요할 때 호출해 직사각형의 넓이를 쉽게 구할 수 있습니다.
다음은 함수 getArea를 호출하는 예제입니다.
코드를 불러오는 중 입니다 ...
 

함수의 인수와 매개변수

앞서 작성한 직사각형을 구하는 함수 getArea는 부족한 면이 있습니다. 언제나 똑같은 넓이만 반환하기 때문입니다. 이 함수에는 너비와 높이의 값이 언제나 고정적으로 제공됩니다. 이 문제를 해결하기 위해서는 함수 getArea를 호출할 때, 구하려는 직사각형의 너비와 높이의 값을 함수에 전달하면 됩니다. 그러면 함수 getArea는 전달받은 높이와 너비를 계산해 새 넓이의 값을 반환합니다.
자바스크립트에서는 ‘인수’와 ‘매개변수’라는 기능을 이용해 함수를 호출 하면서 값을 주고받습니다. 다음은 함수 getArea에 높이와 너비의 값을 전달하는 예입니다.
코드를 불러오는 중 입니다 ...
함수를 호출하면서 이번에는 소괄호에 두 개의 값을 콤마로 구분하여 작성합니다. 작성한 값은 호출한 함수로 전달되는데, 이 값을 ‘인수(argument)’라고 합니다.  함수를 선언할 때, 함수의 선언부에는 인수로 전달된 값을 저장할 변수 이름을 소괄호에 작성합니다. 이렇듯 인수로 전달된 값을 함수에서 사용할 수 있게 저장하는 변수를 ‘매개변수(parameter)’ 라고 합니다. 코드에서 width는 10, height는 20이라는 값을 받게 됩니다.
인수와 매개변수는 자주 혼동되는 단어입니다. 인수는 함수를 호출 하면서 넘겨주는 값이고, 매개변수는 함수에서 넘겨받은 인수를 저장하는 변수입니다. 즉 인수는 ‘값’, 매개변수는 그 값을 저장할 ‘변수’로 생각하면 이해하기 쉽습니다.
 

함수 반환

보통 누군가를 부르면 돌아오는 대답이 있기 마련입니다. 자바스크립트의 함수 또한 호출에 대한 답으로 값을 반환할 수 있습니다. 함수에서 값을 반환 하려면 return문을 사용합니다.
코드를 불러오는 중 입니다 ...
함수 내에 return 문을 사용하면, return 문에 있는 값을 ‘반환’합니다. 참고로 함수가 돌려주는 값을 ‘반환값’이라고 합니다.  ② ①에서 반환한 값을 변수 result에 저장합니다. 반환값은 함수 호출의 결괏값이기도 합니다.
함수는 return 문으로 수행한 결과를 반환합니다. 한 가지 주의할 점은 함수에서 더 동작할 코드가 남았더라도 return 문을 만나면 함수는 종료된다는 사실입니다.
코드를 불러오는 중 입니다 ...
함수 getArea는 return 문을 만나면 값을 반환하고 바로 종료합니다.  ② ①에서 값을 반환함과 동시에 함수가 종료되기 때문에 이 명령은 수행되지 않습니다.
 

중첩 함수

자바스크립트는 함수 내에 또 다른 함수를 선언할 수 있습니다. 특정 함수 내부에서 선언된 함수를 ‘중첩 함수(Nested Function)’라고 합니다.
코드를 불러오는 중 입니다 ...
함수 greeting 안에서 greetingWithName이라는 함수를 선언합니다. 이 함수는 중첩함수 입니다. 이름을 전달받아 템플릿 리터럴을 이용해 인사말을 출력합니다.  함수 greeting 내에서 선언한 함수 greetingWithName을 호출하면서 인수로 ‘이정환’이라는 값을 담은 변수 name을 전달합니다.
중첩 함수를 많이 두면 가독성을 헤치는 단점이 있으나, 적절히 활용하면 함수 내에서 서로 역할을 분담할 수 있어 중복 코드를 방지하는 데 도움이 됩니다.
 

함수와 호이스팅

호이스팅(hoisting)이란 프로그램에서 변수나 함수를 호출하거나 접근하는 코드가 함수 선언 코드보다 위에 있음에도 불구하고, 마치 선언 코드가 위에 있는 것처럼 동작하는 자바스크립트만의 독특한 기능입니다. 다음 예제를 보면 쉽게 이해할 수 있습니다.
코드를 불러오는 중 입니다 ...
이 코드에서는 함수 func을 선언도 하기 전에 호출하지만 오류가 발생하지 않습니다. 즉, 함수 func에 대한 선언이 호출 코드보다 아래에 있지만, 마치 호출보다 먼저 함수를 선언한 것처럼 자연스럽게 동작합니다.
자바스크립트에서 함수는 선언하기 전에도 호출할 수 있는데, 이런 기능을 ‘호이스팅’이라고 합니다. 이런 현상이 일어나는 이유는 자바스크립트의 내부 알고리즘 때문입니다. 자바스크립트는 코드를 실행하기 전에 준비 단계를 거칩니다. 준비 단계에서 중첩 함수가 아닌 함수들은 모두 찾아 미리 생성해 둡니다. 자바스크립트 코드는 이런 준비 단계를 거친 다음에 실행됩니다. 따라서 함수 선언 코드를 호출보다 늦게 작성해도 자연스럽게 호출할 수 있습니다.
자바스크립트의 독특한 특징의 하나인 호이스팅은 코드 내에서 함수 선언의 위치를 강제하지 않기 때문에 더 유연한 프로그래밍을 작성하는 데 도움을 줍니다.
 

함수 표현식

자바스크립트는 함수 선언 말고도 함수를 만드는 또 다른 방법이 있습니다. 바로 ‘함수 표현식’을 이용하는 방법입니다. 함수 표현식이란 함수를 생성하고 변수에 값으로 저장하는 방법입니다.
코드를 불러오는 중 입니다 ...
자바스크립트에서는 함수를 숫자나 문자열처럼 값으로 취급합니다. 그래서 변수에 함수를 저장할 수 있습니다. 변수에 함수를 저장하면 변수 이름으로 호출할 수있습니다. 이렇게 함수를 변수의 값으로 저장해 생성하는 방법을 ‘함수 표현식’이라고 합니다.
이 코드에서는 함수를 만들 때 이름을 생략했습니다. 이 함수는 변수의 이름인 greeting으로 호출하기 때문에 굳이 함수에 이름을 달지 않았습니다. 이렇듯 이름을 정의하지 않은 함수를 ‘익명 함수’라고 합니다.
다음은 선언한 함수를 변수에 저장해 사용하는 예입니다.
코드를 불러오는 중 입니다 ...
변수 greeting에 함수 greetFunc를 저장합니다. 한 가지 주의할 점은 함수를 변수에 저장할 때에는 함수 호출과 달리 소괄호를 명시하지 않습니다.
함수 표현식으로 만든 함수는 함수 선언으로 만든 함수와는 달리 호이스팅되지 않습니다.
코드를 불러오는 중 입니다 ...
funcA는 함수 선언으로 만들었기 때문에 호이스팅의 대상입니다. 따라서 함수 선언 전에도 호출할 수 있지만, funcB에 저장한 함수는 호이스팅되지 않습니다. 함수표현식을 사용하여 저장한 함수는 선언이 아닌 ‘값’으로 취급하기 때문에 호이스팅을 하지 못합니다.

콜백 함수

앞서 함수 표현식에서 자바스크립트는 함수를 값으로 취급해 변수에 저장할 수 있음을 알았습니다. 따라서 함수는 다른 함수의 인수(인수=값)로도 전달할 수 있는데, 이를 ‘콜백 함수(Callback Function)’라고 합니다.
다음은 간단한 콜백 함수의 예입니다.
코드를 불러오는 중 입니다 ...
함수 선언으로 2개의 함수 parentFunc와 childFunc을 만들었습니다. 그리고 에서 함수 parentFunc을 호출하면서 인수로 함수 childFunc을 전달합니다. 따라서 함수 parentFunc의 매개변수 callback에는 함수childFunc이 저장됩니다. 
함수 parentFunc을 호출하면 먼저 parentFunc은 parent를 콘솔에 출력합니다. 그런 다음 매개변수 callback에 저장된 함수를 호출합니다.
매개변수 callback에는 에서 인수로 전달된 함수 childFunc이 저장되어 있습니다. 따라서 함수 callback 을 호출하면 함수 childFunc이 실행되어 ‘child’를 콘솔에 출력합니다.
참고로 콜백 함수를 인수로 받는 함수를 고차 함수(Higher-Order Function, HOF)라고 합니다.
 

콜백 함수가 필요한 이유

그렇다면 콜백 함수는 왜 필요할까요? 콜백 함수가 어떤 상황에서 필요한지 살펴보기 위해 0부터 전달받은 숫자만큼 반복하는 함수를 하나 만들겠습니다.
코드를 불러오는 중 입니다 ...
함수 repeat는 매개변수 count만큼 반복하면서 현재의 반복이 몇 번째인지 콘솔에 출력합니다.
만일 함수 repeat와 동일한 구조로 반복하는 반복문이지만 다른 기능이 추가적으로 필요하다면 어떻게 하는 게 좋을까요? 일반적으로 다음과 같이 새 함수를 만들겁니다.
코드를 불러오는 중 입니다 ...
함수 repeatDouble은 repeat처럼 전달된 숫자만큼 반복하는 작업은 동일하지만, 반복문에서 수행하는 명령이 조금 다릅니다.
함수가 동일한 기능을 갖더라도 특정 부분이 달라 새 함수를 만들게 되면 중복코드가 발생합니다. 콜백 함수를 사용하면 이러한 문제를 효과적으로 해결할 수 있습니다.
코드를 불러오는 중 입니다 ...
매개변수를 콘솔에 출력하는 함수 origin을 만듭니다.  함수 repeat를 호출하고 인수로 5와 함수 origin을 전달합니다.  함수 repeat가 호출되면 매개변수 count에는 숫자 5를 저장하고, callback에는 함수 origin을 저장합니다.  0부터 4까지 총 5회 반복할 때마다 매개변수 callback에 저장한 함수 origin을 호출하고 idx + 1을 인수로 전달합니다. 따라서 함수 origin은 함수 repeat의 반복문에서 총 5회 호출되면서 숫 자 1부터 5까지 콘솔에 출력합니다.
만일 함수 repeat에서 반복문의 동작을 변경하고 싶다면, 새 함수를 만들어 repeat 의 인수로 전달하면 됩니다.
코드를 불러오는 중 입니다 ...
매개변수에 2를 곱해 콘솔에 출력하는 함수 double을 만듭니다.  함수 repeat의 인수로 함수 double을 전달합니다. 이제 함수 repeat의 매개변수 callback에는 함수 double이 저장됩니다.  함수 repeat의 반복문에서 반복할 때마다 매개변수 callback에 저장된 함수 double을 호출하고 인수로 idx + 1을 전달합니다. 따라서 2 4 6 8 10이 콘솔에 출력됩니다.
만일 함수 repeat 내에서 또 다른 일을 하고 싶다면, 새 함수를 만들고 인수로 전달해 콜백 함수를 교체하면 됩니다. 콜백 함수를 이용하면 상황에 맞게 하나의 함수가 여러 동작을 수행하도록 만들 수 있습니다.
 

함수 표현식을 이용한 콜백 함수

콜백 함수는 함수 표현식으로도 만들 수 있습니다. 다음은 함수 표현식을 이용한 콜백 함수의 예입니다.
코드를 불러오는 중 입니다 ...
받은 인수에 2를 곱해 콘솔에 출력하는 익명 함수를 만들어 double에 저장합니다.  변수 double에 저장된 함수를 repeat의 인수로 전달해 콜백 함수로 사용합니다.
변수 double에 저장한 익명 함수를 다시 사용할 필요가 없는 상황이라면, 다음과 같이 익명 함수를 직접 인수 형태로 전달해도 됩니다. 그럼 코드를 더 줄일 수 있습니다.
 
코드를 불러오는 중 입니다 ...
함수 repeat를 호출하며 첫 번째 인수로는 숫자 5, 두 번째 인수로는 콜백 함수로 활용할 익명 함수를 직접 생성해 전달합니다. 그럼 익명 함수는 함수 repeat의 매개변수 callback에 저장되어 repeat 내에서 호출할 수 있게 됩니다.
함수 호출과 함께 익명 함수를 인수로 전달하여 콜백 함수를 사용하는 예는 다른언어에서 찾아보기 힘든 문법이므로 처음에는 어색하게 느껴질 수 있습니다. 그러나 앞으로 자바스크립트 프로그래밍을 진행하다 보면, 이런 예제를 무수히 만나므로 금방 익숙해집니다.
 

화살표 함수

화살표 함수는 익명 함수를 매우 간결하게 작성할 때 사용하는 함수 표현식의 단축 문법입니다. 화살표 함수는 다음과 같은 형식으로 사용합니다.
코드를 불러오는 중 입니다 ...
화살표 함수 funcA는 다음 함수와 동일합니다.
코드를 불러오는 중 입니다 ...
다음은 이름을 전달받아 탬플릿 리터럴 형식으로 인사말을 반환하는 간단한 화살표 함수를 만드는 예입니다.
코드를 불러오는 중 입니다 ...
만약 화살표 함수 본문이 여러 줄이면 다음과 같이 중괄호를 사용하면 됩니다.
코드를 불러오는 중 입니다 ...
다만 화살표 함수 본문에 중괄호를 사용하면, 함수 선언 때처럼 값을 반환할 때 return문을 써주어야 합니다.
콜백 함수로 사용할 함수 또한 다음과 같이 화살표 함수로 작성할 수 있습니다
코드를 불러오는 중 입니다 ...
함수 confirm의 첫 번째 인수로 콘솔에 ‘승인’을 출력하는 화살표 함수를 전달합니다. 이 함수는 매개변수 onYes에 저장됩니다.  함수 confirm의 두 번째 인수로 콘솔에 ‘거부’를 출력하는 화살표 함수를 전달합니다. 이 함수는 매개변수 onNo에 저장됩니다.
화살표 함수는 함수를 간결하게 쓸 수 있다는 장점 외에도 다른 특징이 많지만, 지금 다루기에는 너무 어려우므로 그 내용에 대해서는 차차 설명하겠습니다.
 
PREV7. 반복문
NEXT9. 스코프