본문 바로가기

Javascript

[함수형 코딩] 입출력 개념 이해하기

입출력 개념 이해

입력과 출력의 개념을 설명을 하면 다음과 같다.

 

입력 : 입력은 함수나 프로그램이 외부로부터 받는 데이터를 의미하며, 이를 기반으로 작업을 수행

출력 :  함수나 프로그램이 작업을 수행한 후 외부로 내보내는 결과를 의미

 

밑에서 설명할 암묵적 입출력은 함수를 만들 때 생기는 부작용이 생기는 경우를 말하는데, 다음과 같다.

 

암묵적 입출력

암묵적 입력

시스템이 외부 환경이나 사용자의 행동을 관찰하여 간접적으로 얻는 데이터를 말한다. 함수의 입력값으로 명시적으로 전달되지 않는 파라미터를 말함. 즉, 인자 외 다른 입력을 말하며, 함수가 반환하는 값 이외에 함수를 실행하는 동안에 외부에 영향을 주는 행위를 말한다.

 

예시

  • 쿠키나 로컬스토리지나 DOM 값에서 값을 가져오는 경우
  • 함수 안에서 API, 파일, DB등에서 값을 가져오는 경우
  • 암묵적인 입력은 함수인자가 아닌 형태로 사용되는 데이터나 함수내부에서 선언한 데이터 등을 의미함

암묵적 출력

기본적으로 함수는 리턴을 가지는 경우가 있고, 없으면 void를 반환해서 아무것도 반환을 안 하는 경우가 있다. 리턴 값 외 다른 출력

암묵적인 출력은 함수의 반환값이 아닌 외부세상에 변화를 주는 것(DOM, console, 전역변수에 대입)을 의미함.

 

예제

순수 함수가 아닌 예제 1)

function multiply() {
  globalValue = globalValue * 2;
}

// main
let globalValue = 10;

multiply(); // globalValue : 20

위에서 언급했듯이, 전역 변수를 바꾸는 행위는 암묵적 입출력의 행위이다. 이로 인해 순수함수가 안된다.

 

순수 함수가 아닌 예제 2)

function f1 () {
  const local = getLocalStrorage();
  return local;
}

function f2() {
  const date = new Date();
  return date;
}

함수의 인자는 없는데 함수 내부에서 로컬스토리지에서 값을 가져와서 (암묵적 입력)에 대한 특정 결과를 반환한다. 이 또한 순수함수가 아니며, 함수의 내부 안에서 date를 선언하는 것 또한 순수 함수가 아닌 예제이다.

순수 함수가 아닌 예제 3)

let a = 10;

function wrongFunction1 () {
  console.log(a);
}

위의 함수도 예측 불가능성이 있다. 함수 결과는 언제 어디서 a의 값이 변경되었는지에 따라 달라질 수가 있어서 언제나 같은 결과를 반환하지 못해서 매번 console.log를 확인할 때 마다 a의 값이 달라질수가 있다.

 

결론

암묵적 입출력 인자와 반환값에 따라 다음은 부작용이 생기는 경우

  • 인자값이 없는데 반환값이 있는 경우
  • 인자값이 있는데 반환값이 없는 경우
  • 인자값과 반환값 둘 다 없는 경우

 

순수함수가 아닌 경우 쉽게 판별해 보기

암묵적 입력과 출력들의 경우를 보면 대부분 비동기 함수이다.  즉, async 가 필요한 경우 이 함수들은 예외없이 모두 부작용 함수이다. 정리하면, 부작용이 있는 함수인지 판별하는 방법은 다음과 같다.

  • 인자값과 반환값 둘 중 하나라도 존재하지 않음
  • async가 있음.

이러한 이유로 인해 부작용 없는 함수로 변환하는 작업이 필요하다. 이를 순수함수라고 부르는데, 순수 함수를 만들기 위해서는 명시적 입/출력이 필요하다

 

명시적 입출력

함수나 프로그램이 입력으로 받는 데이터(매개변수)와 결과로 반환하는 데이터(반환값)를 코드 상에서 명확하게 지정하는 방식을 말한다. 명시적 입출력은 쉽게 말해 함수 호출 시 인자로 직접 전달되고, 리턴 값이 있는 경우를 말한다.

명시적 입력

  • 인자
  • 함수의 인자를 의미

명시적 출력

  • 리턴 값
  • 함수의 반환값을 의미합니다
  • 암묵적 출력을 리턴값으로 바꿀 수 있음

 

순수함수 예제

// before
function wrong (value) {
  a = a * 2;
}

let a = 10;
wrong(); // 20

// after
function best (value) {
  return value * 2;
}

const bestValue = best(2); // 4

 

마지막으로 순수함수로 만들어야 하는 이유?

일단 먼저, 동일 입력 → 동일 출력으로 인해 버그가 감소한다. 또한 외부 상태 변경 안 하기에 병렬 처리에 안전하며, 디버깅 용이하다.

입력만으로 작동하기에 테스트 용이성 극대화, 캐싱도 가능하다.