액션과 계산, 데이터의 차이를 알기
프로그래밍에서는 모든 코드가 액션(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
액션을 계산으로 바꾸는 구체적인 방법은 다음 챕터에서 배우게 됩니다.
정리하기
- 데이터: 이벤트에 대한 사실을 표현 (불변성, 직렬화, 비교 가능)
- 계산: 입력 → 출력 (순수 함수, 조합 용이, 테스트 쉬움)
- 액션: 외부 세계와 상호작용 (실행 시점/횟수 의존)
- 내부에 계산과 데이터가 있고 가장 바깥쪽에 액션이 있는 구조가 이상적입니다.