[FE] 함수

seunghee.Rho·2025년 2월 4일

FE

목록 보기
18/26
post-thumbnail

1. 함수란 무엇인가?

함수란 작업을 수행하거나 값을 계산하는 등의 과정을 표현하고, 이를 하나의 블록으로 감싸서 실행 단위로 만들어 놓은 것을 의미한다.

리액트에서 컴포넌트를 만드는 함수도 이러한 기초적인 형태를 따르는 것을 알 수 있다.

function Component(props) {
	return <div>{props.hello}</div>
}

Component라고 하는 함수를 선언하고, 매개변수로는 Props라고 부르는 단일 객체를 받으며 return문으로 JSX를 반환한다.

2. 함수를 정의하는 4가지 방법

2-1. 함수 선언문

함수를 선언할 때 가장 일반적으로 사용하는 방식

function add(a, b) {
	return a + b
}

함수 선언문은 표현식이 아닌 일반 문(statement)으로 분류된다.
앞선 함수의 선언으로는 어떠한 값도 표현되지 않았으므로 표현식이 아닌 문으로 분류되는 것이다.

2-2. 함수 표현식

함수는 다른 함수의 매개변수가 될 수도 있고, 반환 값이 될 수도 있으며, 앞에서 본 것처럼 할당도 가능하므로 일급 객체가 되기 위한 조건을 모두 갖추고 있다. 앞서 함수가 일급 객체라고 했으니, 함수를 변수에 할당하는 것은 당연히 가능하다.

const sum = function (a, b) {
	return a + b
}

sum(10, 24) // 34

함수 표현식에서는 할당하려는 함수의 이름을 생략하는 것이 일반적이다.
그 이유는 코드를 봤을 때 혼란을 방지하지 위함이다.

const sum = function add(a, b) {
	...
}

sum(10, 24)
add(10, 24) // TypeError

위 함수 표현식 예제를 살펴보면 실제로 함수를 호출하기 위해서 사용된 것은 sum임을 알 수 있다. add는 실제 함수 내부에서만 유효한 식별자일 뿐, 함수를 외부에서 호출하는 데에는 사용할 수 없는 식별자다. 따라서 함수 표현식에서 함수에 이름을 주는 것은 함수 호출에 도움이 전혀 안 되는, 코드를 읽는 데 방해가 될 수 있는 요소다.

🌟 함수 표현식과 선언 식의 차이

이 두가지 방식의 가장 큰 차이는 호이스팅(hoisting) 여부다.
함수의 호이스팅이라 함은, 함수 선언문이 마치 코드 맨 앞단에 작성된 것처럼 작동하는 자바스크립트의 특징을 의미한다.

함수 선언문의 호이스팅(hoisting)

함수의 호이스팅은 함수에 대한 선언을 실행 전에 미리 메모리에 등록하는 작업을 의미한다.

hello()

function hello() {
	console.log('hello')
}

hello()

hello 함수가 코드 중간에 있음에도 불구하고 맨 앞에서 호출한 hello는 정상적으로 실행된다. 함수의 호이스팅 덕분에 함수 선언문이 미리 메모리에 등록됐고, 코드의 순서에 상관없이 정상적으로 함수가 호출된 것이다.

함수 표현식의 호이스팅(hoisting)

반면 함수 표현식은 함수를 변수에 할당했다. 변수도 마찬가지로 호이스팅이 발생한다. 그러나 함수의 호이스팅과는 다르게 호이스팅되는 시점에서 var의 경우에는 undefined로 초기화한다는 차이가 있다.

hello() // TypeError

var hello = function() {
	console.log('hello')
}

hello()

맨 앞에서 호출된 hello는 함수 선언문과 다르게 정상적으로 호출되지 않고 undefined로 남아있는 것을 알 수 있다. 함수와 다르게 변수는 런타임 이전에 undefined로 초기화되고, 할당문이 실행되는 시점, 즉 런타임 시점에 함수가 할당되어 작동한다는 것을 알 수 있다.

2-3. Function 생성자

const add = new Function('a', 'b', 'return a + b')

Function 생성자 함수를 사용해서 만든 모습은 썩 좋아보이지 않는다.
코드 작성 관점에서만 보더라도 모두 문자열로 작성해야 한다.
이는 메모장에서 코드를 작성하는 것만큼이나 어렵고, 혼란스러운 방법이다.
그리고 이렇게 생성자 방식으로 함수를 만들게 되면 함수의 클로저 또한 생성되지 않는다.
실제 코딩에서 거의 사용되지 않는 방법이라고 볼 수 있다.

2-4. 화살표 함수

function이라는 키워드 대신 => 라는 화살표를 사용해서 함수는 만든다.

const add = (a, b) => {
	return a + b
} 

화살표 함수는 앞에서 언급한 함수 생성 방식과 몇가지 차이점이 있다.
1. constructor을 사용할 수 없다.
2. arguments가 존재하지 않는다.
3. this 바인딩
this는 자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 값이다. 이 this는 함수가 어떻게 호출되느냐에 따라 동적으로 결정된다.
그러나 화살표 함수는 함수 자체의 바인딩을 갖지 않는다. 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 따르게 된다.

📌 화살표 함수는 this가 선언되는 시점에 이미 상위 스코프로 결정돼 있어 미리 _this를 받아서 사용하는 모습과 다르게, 일반함수는 호출하는 런타임 시점에 결정되는 this를 그대로 따른다.

3. 함수를 만들 때 주의사항

3-1. 함수의 부수 효과를 최대한 억제하라

함수의 부수 효과(side-effect)란 함수 내의 작동으로 인해 함수가 아닌 함수 외부에 영향을 끼치는 것을 의미한다. 부수 효과가 없는 함수를 순수 함수라 하고, 부수 효과가 존재하는 함수를 비순수 함수라고 한다.

순수함수는 외부에 어떤 영향을 미치지도 않고, 언제 실행되든 항상 결과가 동일하기 때문에 예측 가능하며 안정적이라는 장점이 있다.

부수 효과를 만드는 것은 애플리케이션을 만들면서 피할 수 없는 요소이지만 이러한 부수 효과를 최대한 억제할 수 있는 방향으로 함수를 설계해야 한다.

따라서 자바스크립트 함수에서는 가능한 한 부수 효과를 최소화하고, 함수의 실행과 결과를 최대한 예측 가능하도록 설계해야 한다. 예측 가능한 단위의 부수 효과가 작은 함수를 설계하면 개발자와 이를 유지보수하는 또 다른 개발자에게 많은 도움을 준다.

3-2. 가능한 한 함수를 작게 만들어라

함수당 코드의 길이가 길어질수록 코드냄새가 날 확률이 커지고, 내부에서 무슨 일이 일어나는지 추적하기 어려워진다. 하나의 함수에서 너무나 많은 일을 하면 문제를 일으킬 여지가 커진다는 것이다.

유닉스의 선구자인 더글러스 매킬로가 말한 것처럼, 함수는 하나의 일을, 그 하나만 잘하면 된다. 그것이 함수의 원래 목적인 재사용성을 높일 수 있는 방법이다.

3-3. 누구나 이해할 수 있는 이름을 붙여라

클린 코드나 리팩토링 등에서도 많이 언급되는 문제지만, 가능한 한 함수 이름은 간결하고 이해하기 쉽게 붙이는 것이 좋다. 코드를 유심히 살펴보지 않더라도 어떤 일을 하는지, 또 어떻게 작동하는지를 단번에 알아채는데 도움이 될 것이다.

profile
Web Developer

0개의 댓글