티스토리 뷰

Today I Learned

함수형 프로그래밍이란?

심재철 2020. 3. 25. 20:49

그동안 어렴풋하게만 알고 있던 함수형 프로그래밍이란 무엇인지 정리하기 위해 남깁니다.

 

함수형 프로그래밍의 컨셉

1. 사이드 이펙트(side effect)를 없애라.

사이드 이펙트라는건 부작용이라는 뜻인데, 우리가 함수를 호출 하는 이유는 인풋에 따른 결과값을 얻어내기 위해서 입니다. 근데 함수가 함수 외부의 어떤것을 변경하게 되면 우리가 의도치 않은 동작을 하는 것입니다. 이런 현상을 함수형 프로그래밍에선 사이드 이펙트 라고 합니다. 프로젝트에 사이드 이펙트를 가진 함수가 많아지면 디버깅 하기 굉장히 어려워지게 됩니다. (각 함수 내부를 뒤져서 이게 어디에 영향을 주는지 일일이 파악해야함) 간단한 예시를 하나 살펴 보겠습니다.

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

현재 프로그램의 정보를 가져오는 간단한 함수가 있습니다. 이 함수는 사이드 이펙트가 존재합니다. 바로 new Date(); 부분입니다. 이 함수는 현재시간 이라는 함수 외부 환경에 영향을 받고 있습니다. 이 함수를 순수함수로 만들기 위해서 다음과 같이 new Date();를 인자로 받아야 합니다.

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

여기서 중요한게 있습니다. 이 함수를 자세히 살펴보면

 

getProgramAt(TVGuide guide, int channel, Date when)

 

이런식으로 선언되어 있습니다. guide, channel, when이라는 인풋과 getProgram이라는 함수의 이름을 통해서 이 함수가 어떤 인풋을 받아서 어떤 아웃풋을 내는지 전부 보여주고 있습니다. 순수함수에서는 이렇게 모든 인풋과 아웃풋이 함수의 선언부에 드러나있어야합니다.

 

이제 이 함수는 같은 인풋에 대해 같은 아웃풋을 낼 것이며, 함수 외부에 영향을 주지도 받지도 않는 깨끗한 순수함수가 되었습니다. 인풋에 따른 아웃풋이 명확해 졌기 때문에 함수 내부를 살펴보지 않아도 이 함수가 무슨일을 하는지 이름만 보아도 짐작할 수 있습니다. 순수함수는 이렇게 숨겨진 입력(함수가 외부에 영향을 받음)이나 숨겨진 출력(함수가 외부에 영향을 줌)이 없어야 합니다.

2. 같은 인풋에서는 같은 아웃풋이 나와야 한다.

우리는 고등학교때 함수라는게 y=f(x) 라는걸 배웠습니다. x가 뭐가 됬든 함수를 거치고 나면 결과값이 나오는데 그 결과값은 항상 일정하다는것을요. 프로그래밍에서의 함수도 수학에서의 함수와 비슷합니다. 인풋이 들어가면 아웃풋이 나오죠. 근데, 프로그래밍을 하다보면 함수 내부값에 의해서 인풋이 항상 일정한 결과를 내지 않을 수 도 있습니다. 그런걸 방지해서 항상 같은 x가 같은 y가 되게 하자는게 함수형 프로그래밍의 컨셉입니다.

3. 함수는 순수함수(pure functions)여야 한다.

사이드 이펙트가 없으며 같은 인풋에 같은 아웃풋을 내는 함수를 순수함수라고 합니다. 함수형 프로그래밍에서의 순수함수는 위 두가지 조건을 만족시켜야 합니다.

3. 모든 것은 객체다. 심지어 함수도 객체다.

함수형 프로그래밍에서는 모든것을 객체로 취급합니다. 특히 함수는 1급 객체로 취급되는데, 이게 뭐냐면 객체가 값으로 취급돼서 변수나, 매개변수, 리턴값에 할당 될 수 있다는 얘기입니다. 

 

그래서 "함수형 프로그래밍"이 뭔데요?

"함수형 프로그래밍"을 한마디로 얘기해보라고 하면 저는 이렇게 대답할 것 같습니다.

 

최대한 많은 함수가 순수함수로 작성 되어 함수 외부에 영향을 주지도 받지도 않아서 애플리케이션이 유지보수 하기 쉬운 상태가 되는것

 

물론 개발을 하다보면 모든 함수를 사이드 이펙트가 없게 만들 수가 없습니다. 다만 최대한 많은 함수가 순수함수일수록 코드가 읽기 쉬워지고 유지보수하기 좋아집니다. 왜냐면 인풋에 따라 아웃풋이 일정하고 외부에 영향을 주지도 받지도 않으니까 딱 그 함수만 보면 되기 때문입니다.

 

자바스크립트는 "함수형 프로그래밍 언어" 인가요?

모든 언어에서 함수를 "순수함수"로 작성할 수 있습니다. 그냥 함수내에 숨겨진 인풋과 아웃풋을 함수 선언부로 끌어 올리면 순수함수로 변경 시킬 수 있습니다. 그럼 모든 언어가 전부다 "함수형 프로그래밍 언어"냐고 물어보면 그건 아닙니다. 

 

"함수형 프로그래밍 언어"란 함수를 순수함수로 작성할 수 있도록 장려하는 언어입니다.

 

사이드 이펙트가 있는 함수는 프로그램을 복잡하게 만들어서 유지보수하기 힘들게 만듭니다. 함수형 프로그래밍 언어에서는 개발자가 이런 사이드 이펙트를 최대한 발생시키지 않도록 장려합니다.

 

결론부터 얘기하면, 자바스크립트는 함수형 프로그래밍 언어가 아닙니다. 

this 바인딩

자바스크립트를 처음 배울때 this가 가리키는게 상황에 따라 달라져서 애를 먹었던 기억이 납니다. 이 this 자체가 사이드 이펙트를 유발합니다.

 

this가 이벤트 핸들러내에서 사용될 경우 이벤트 대상을 가리킵니다.

this가 메소드로 호출된 경우엔 그 메소드를 호출한 객체를 가리킵니다.

 

이렇게 상황에 따라 this가 가리키는게 달라집니다. 그렇단 얘기는, 함수내에서 this가 사용되면 this가 가리키는 대상에 따라 그 함수가 같은 인풋에 다른 결과를 낼 가능성이 생기고, this 자체가 함수 외부에 영향을 받기도 주기도 하기 때문입니다. this는 순수 함수의 두가지 조건을 모두 불만족 시킵니다.

 

그럼 자바는 "함수형 프로그래밍 언어" 인가요?

자바는 "함수형 프로그래밍 언어"와 완전 정반대에 있습니다. 자바로 코드를 작성해본 사람들은 알겠지만, 보통 객체 내에 멤버 변수를 선언하고 메서드를 정의합니다. 그리고 메서드에서는 같은 객체 내에 있는 여러 로컬 변수와 메서드를 사용해서 아웃풋을 내죠..

 

우리가 위에서 얘기했던 순수함수와 완전 거리가 멉니다. 객체의 메소드는 로컬 멤버 변수의 값을 참조하기 때문에 같은 인풋에 따라 아웃풋을 내지도 않을 뿐더러, 함수 외부에 영향을 받고 영향을 줍니다. (멤버 변수를 가져와서 사용하고 멤버 변수를 조작하기도함)

 

어떻게 보면 자바뿐만아니라 객체 지향 언어함수형 언어의 차이입니다. 객체 지향 언어에서는 사이드 이펙트를 객체 내부로 국소화 시킨것이고 함수형 언어는 사이드 이펙트 자체를 적대시한다는 차이가 있는것입니다.

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함