Skip to content

액션과 계산, 데이터의 차이를 알기 ​

프로그래밍에서는 모든 코드가 액션(Action), 계산(Calculation), 데이터(Data) 중 하나로 분류됩니다. 이 셋을 구분하면 코드의 성격을 더 명확히 이해할 수 있고, 테스트와 재사용성도 좋아집니다.

스터디 회차: 2회차 (2025년 8월 14일)

데이터 (Data) ​

  • 데이터는 이벤트에 대한 사실을 표현한 것입니다.
  • 개발자가 처리과정에서 필요한 데이터를 만들기도 합니다.
  • 예: 사용자 이메일, 추천 횟수, 쿠폰 정보

데이터의 불변성 ​

  • Copy-on-write: 변경 시 복사본을 만듭니다. → 불필요한 복사를 줄여 성능 이점이 있습니다.
  • 방어적 복사: 외부 변경으로부터 안전하게 하기 위해 복사본을 만듭니다.

데이터의 장점 ​

  • 직렬화 가능 (저장/전송 용이)
  • 동일성 비교 가능 (두 데이터가 같은지 쉽게 판단)
  • 자유로운 해석 가능 (다양한 방식으로 재활용 가능)

계산 (Calculation) ​

  • 계산은 입력을 받아 출력을 만드는 과정입니다.
  • 즉, 순수 함수처럼 참조 투명성을 가진 연산입니다.

계산의 장점 ​

  • 테스트하기 쉽습니다.
  • 기계적으로 분석하기 쉽습니다.
  • 다른 계산과 조합하기 좋습니다.

액션과 달리 신경쓰지 않아도 되는 것 ​

  • 실행 순서
  • 실행 횟수
  • 과거·미래 실행 여부

액션 (Action) ​

  • 액션은 외부 세계와 상호작용하는 코드입니다.
  • 코드 안쪽에 액션을 실행하는 코드는 프로그램 전체를 액션으로 만듭니다.
  • 즉, 실행 시점이나 횟수에 따라 결과가 달라질 수 있습니다.

액션의 예 ​

  • 함수/메서드 호출
  • 객체 생성
  • 변수/속성 참조 및 할당
  • 상태 변경

액션을 잘 다루는 방법 ​

  • 가능한 적게 사용합니다.
  • 가능한 작게 만듭니다.
  • 내부는 계산과 데이터, 가장 바깥쪽에 액션이 위치하는 구조가 이상적입니다.
  • 호출 시점·횟수에 의존하지 않도록 만듭니다.

액션은 코드 전체로 퍼집니다 ​

1단계: sendPayout -> figurePayout ​

ts
function figurePayout(affiliate) {
  var owed = affiliate.sales * affiliate.commission;
  if (owed > 100) sendPayout(affiliate.bank_code, owed); // 액션
}

function affiliatePayout(affiliates) {
  for (var a = 0; a < affiliates.length; a++) {
    figurePayout(affiliates[a]);
  }
}

function main(affiliates) {
  affiliatePayout(affiliates);
}
  • 액션은 sendPayout으로 시작합니다.
  • 돈을 송금하는 코드로, 호출 시점이나 횟수가 중요하기 때문에 액션입니다.

2단계: figurePayout -> affiliatePayout ​

ts
function figurePayout(affiliate) { // 액션
  var owed = affiliate.sales * affiliate.commission;
  if (owed > 100) sendPayout(affiliate.bank_code, owed);
}

function affiliatePayout(affiliates) {
  for (var a = 0; a < affiliates.length; a++) {
    figurePayout(affiliates[a]); // 액션
  }
}

function main(affiliates) {
  affiliatePayout(affiliates);
}
  • sendPayout가 포함된 figurePayout도 액션을 호출하고 있기 때문에 함수 전체가 액션입니다.
  • figurePayout 함수도 역시 내부에서 sendPayout를 호출하고 있기 때문에 호출 시점과 횟수에 의존하게 되고 액션입니다.

3단계: affiliatePayout -> main ​

ts
function figurePayout(affiliate) { // 액션
  var owed = affiliate.sales * affiliate.commission;
  if (owed > 100) sendPayout(affiliate.bank_code, owed);
}

function affiliatePayout(affiliates) { // 액션
  for (var a = 0; a < affiliates.length; a++) {
    figurePayout(affiliates[a]);
  }
}

function main(affiliates) {
  affiliatePayout(affiliates); // 액션
}
  • 마찬가지로 figurePayout를 포함하고 있는 affiliatePayout도 액션이고 전체 프로그램이 액션이 됩니다.

실습으로 알아보기 ​

예제: 추천 사용자에게 쿠폰 제공하기 ​

  • 이메일 데이터 베이스에는 이메일과 추천수가 저장되어있습니다.
  • 쿠폰 데이터 베이스에는 쿠폰이름과 랭크가 저장되어있습니다.
  • 쿠폰 랭크는 bad, good, best 세가지로 나누어집니다.
  • 사용자에게 good 쿠폰을 제공하고, 10명이상 추천한 사용자에게는 best쿠폰을 제공합니다.

나의 수도 코드 ​

전체 사용자 이메일 리스트 가져오기
쿠폰에서 good 가져오기
모든 사용자에게 good 전송하기

10명이상 추천한 사용자 이메일 가져오기
쿠폰에서 best 가져오기
10명이상 추천한 사람에게 전송하기
  • 위 코드를 기반으로, good과 best를 입력받는 함수를 선언하고 두번 실행하도록 구성했습니다.

나의 실습 코드 ​

ts
const 쿠폰_제공_함수 = (type: "good" | "best") => {
  const 이메일_리스트 = 이메일_리스트_가져오기(type); // 액션
  const 쿠폰 = 쿠폰_가져오기(type); // 액션
  이메일_전송하기(이메일_리스트, 쿠폰); // 액션
};

쿠폰_제공_함수("good"); // 액션
쿠폰_제공_함수("best"); // 액션
  • 함수 안에서 모든 작업을 처리 → 액션이 전파되어 모든 코드가 액션이 되었습니다.

책의 코드 (액션과 계산을 최대한 분리) ​

ts
const 쿠폰 = 전체쿠폰_가져오기(); // 액션
const good_쿠폰 = 쿠폰_선별하기(쿠폰, "good"); // 계산
const best_쿠폰 = 쿠폰_선별하기(쿠폰, "best"); // 계산
const 사용자_리스트 = 사용자_가져오기(); // 액션
const 이메일_내용 = 이메일_구성하기(사용자_리스트, good_쿠폰, best_쿠폰); // 계산
이메일_전송하기(이메일_내용); // 액션
  • 쿠폰 선별, 이메일 구성은 계산으로 처리합니다.
  • 외부 의존적인 부분(쿠폰/사용자 가져오기, 이메일 전송)만 액션으로 처리합니다.
  • 따라서 액션이 바깥쪽에만 존재하고, 내부는 계산으로 채워져 있어 재사용과 테스트가 용이합니다.

TIP

액션을 계산으로 바꾸는 구체적인 방법은 다음 챕터에서 배우게 됩니다.

정리하기 ​

  • 데이터: 이벤트에 대한 사실을 표현 (불변성, 직렬화, 비교 가능)
  • 계산: 입력 → 출력 (순수 함수, 조합 용이, 테스트 쉬움)
  • 액션: 외부 세계와 상호작용 (실행 시점/횟수 의존)
  • 내부에 계산과 데이터가 있고 가장 바깥쪽에 액션이 있는 구조가 이상적입니다.