Search

[Pattern] 데이터 / 계산 / 액션

1. 세션 요약 - 빈칸 채우기

(기본 원칙) 개발할 때 _______, _______, _______을 구분해서, _______과 _______의 범위는 늘리고 _______의 범위는 줄여야 한다.
(데이터 / 계산 / 액션 전문가 6단계)
1. 요구사항에 따라 작업할 부분에 대한 전체적인 흐름을 파악한다.
2. 최종적으로 해야 하는 _______을 정의하고, 그 액션에 필요한 _______ 형태를 확인한다.
3. 데이터가 들어오는 _______ 이후부터, _______ 직전까지의 구간을 _______ 구간으로 정의한다.
4. '계산' 구간을 몇 개의 _______로 나누어 처리할지 정의하고, 각 계산에 필요한 _______을 알아낸다.
5. 코드가 최초 _______과 _______ 되도록 번갈아 읽으며 점검하고, _______ 한다.
6. 모든 작업을 완료한 뒤 정상 동작을 확인한다.

2. 세션 목표

개발을 하다보면 다음과 같은 어려움을 빈번히 겪게 됩니다
함수 안에 너무 많은 것들이 엮여 있어서 읽거나 건드리기 힘들다
거대한 함수에 대해 변경을 가했을 때 결과가 잘 예측되지 않아 불안하다
복잡하게 얽혀 있는 코드를 어떤 기준으로 분리하거나 구분해야 할지 모르겠다
이번 세션에서 다루는 내용을 잘 이해하면,
코드의 순수하고 신뢰할 수 있는 영역(데이터, 계산)과, 불확실한 영역(액션)의 경계선을 그어 바라볼 수 있게 됩니다.
신뢰할 수 있는 영역인 데이터, 계산의 범위는 늘리고, 불확실한 영역인 액션의 영역은 축소하는 방법을 익히게 됩니다.

3. 인접 개념

관심사의 분리 (SRP, Single Responsibility Principle)
순수 함수 (Pure Function) / 부수 효과 (Side Effect)
멱등성 (Idempotency)
의존성 역전 (IoC, Inversion of Control)

4. 멘탈 모델 & 시각화 자료

// 데이터: 외부에서 온 것들(네트워크, DOM, URL, 스토리지) raw = readData() // 계산(순수): raw → 결과. 같은 입력이면 항상 같은 출력. result = compute(raw) // 액션: 화면/네트워크/스토리지/라우터 같은 경계와 상호작용. doEffect(result)
TypeScript
복사
before: 데이터 / 계산 / 액션이 하나의 함수에서 뒤섞여 있음
after: 액션과 데이터 / 계산이 분리되어 있음

5. ‘데이터 / 계산 / 액션’ 패턴이란?

신뢰할 수 있는 '데이터 / 계산'의 영역을 최대한 넓히고, 예측 불가능한 '액션'의 영역을 최대한 작고 고립된 경계 밖으로 몰아내는 것.
‘액션 → 계산 → 데이터’ 순으로,
외부 요소에 대한 ‘얽힘(Entanglement)’ 정도가 줄어든다. 이는 외부 요소에 대한 의존으로도 바꾸어 말할 수 있다.
고려해야 하는 외부 요소가 줄어들기 때문에 인지 부하가 낮아지며, 단순하여 신뢰할 수 있는 코드가 된다.
데이터 (Data)
변하지 않는 사실 그 자체입니다. 숫자, 문자열, 일반 객체 등 값과 정보를 나타냅니다.
데이터는 거짓말을 하지 않으므로 100% 신뢰할 수 있습니다.
계산 (Calculation)
데이터를 입력받아 새로운 데이터를 출력하는 '순수한 공장'입니다. 같은 재료를 넣으면 언제나 같은 제품이 나옵니다.
외부 세계에 어떤 영향도 주지 않으므로(부수효과 없음), 계산 역시 100% 신뢰할 수 있습니다. (a, b) => a + b 와 같은 순수 함수가 여기에 해당합니다.
액션 (Action)
외부 세계와 소통하며 '변화'를 일으키는 모든 것입니다.
API를 호출하거나, 데이터베이스에 저장하거나, console.log를 찍거나, 심지어 new Date()Math.random()처럼 실행할 때마다 결과가 달라지는 코드도 모두 액션입니다.
액션은 외부 환경에 의존하기에, 본질적으로 예측 불가능하며 우리가 의심하고 신중하게 다뤄야 할 대상입니다.

6. 예제 풀이

const name = "김토스" // ? console.log(name) // ? const upper = name.toUpperCase() // ? localStorage.getItem('user') // ? const sum = a + b // ? new Date() // ? [1,2,3] // ? Math.random() // ?
TypeScript
복사

7. 전문가들의 ‘데이터 / 계산 / 액션’ 패턴

7-1. 미니 과제 - Before

7-2. 전문가 영상

전문가들은 ‘데이터 / 계산 / 액션’을 나눌 때 아래와 같은 단계를 거친다.
1.
요구사항에 따라 작업할 부분에 대한 전체적인 흐름을 파악한다.
ex1. “서버에서 데이터를 컴포넌트에 가지고 온 다음 그룹핑을 해서 화면에 뿌려야 해.”
ex2. “Form을 Submit 하는 함수가 복잡해서 확실한 영역과 불확실한 영역을 분리해야겠어.”
2.
최종적으로 해야 하는 액션을 정의하고, 그 액션에 필요한 데이터 형태를 확인한다.
ex1. “결국 컴포넌트로 렌더링할 때 필요한 데이터 형태는 B구나.”
ex2. “결국 form.submit() 함수에 넘겨줄 데이터 형태는 B구나.”
3.
데이터가 들어오는 input 이후부터, 액션 직전까지의 구간을 ‘계산’ 구간으로 정의한다.
ex1. “서버에서 가져온 데이터 형태는 A이고, 컴포넌트로 렌더링할 때는 B라는 형태로 넘겨줘야 해.“
ex2. “form으로 받은 input의 데이터 형태는 A이고, submit 함수에 B라는 형태로 넘겨줘야 해.”
4.
‘계산’ 구간을 몇 개의 덩어리로 나누어 처리할지 정의하고, 각 계산에 필요한 입출력을 알아낸다. 즉, 각 계산이 어떤 input / output으로 맞물리게 할지 결정한다.
ex1. “서버에서 가져온 A를 B로 만드는 동안, 1-1) 정렬 1-2) 그룹핑 1-3) UI 형태에 맞게 포매팅이 되어야 해. UI 형태에 포매팅 하는 부분은 다시 2-1) 금액 쉼표 처리 2-2) 타입별 색상 매핑 등의 작업이 있지만 이 부분은 이쪽 계산에서 처리하지 않고 컴포넌트에 인라인 할래.“
ex2. “form으로 받은 데이터 A를 B로 만드는 동안, 1) 각 필드에 대한 유효성 검사를 한 뒤 2) 특정 필드의 포매팅해야 해. 유효성 검사는 zod schema에서 예외를 던지게 해 catch에서 잡아서 처리하고, 포매팅의 경우 계산 함수에서 책임지도록 할거야.”
주의 사항
‘데이터 → 계산 1 / 2 / 3 / … → 액션’ 형태로 맞물리게 한다.
계산 함수를 작성할 때, 반드시 함수의 이름과 인터페이스로부터 동작과 리턴 값이 예측 가능하도록 한다. 이를 위해 함수의 인터페이스를 세부 구현보다 먼저 작성한다.
한번에 여러가지 역할과 책임을 처리하는 몬스터 함수를 피한다. 이 경우 더 작은 함수로 쪼개어 다시 input / output이 맞물리도록 한다.
5.
코드가 최초 요구사항과 1:1 매칭 되도록 번갈아 읽으며 점검하고, 재조정 한다.
함수의 이름, 인터페이스, 추상화 단위가 적절한지 점검한다
요구사항과 코드가 매칭되어 위에서 아래로 글처럼 읽히는지
함수의 이름과 인터페이스만으로 동작을 예측할 수 없어 시점 이동이 일어나지 않는지
formatDate(date)formatDate(date, "YYYY-MM-DD")
함수의 책임이 아닌 것을 외부로 위임하기 위해 IoC(ex. callback을 인자로 받기)를 고려한다 https://evan-moon.github.io/2023/01/15/what-is-abstract
6.
모든 작업을 완료한 뒤 정상 동작을 확인한다.

7-3. 미니 과제 - After

8. Wrap-up

(기본 원칙) 개발할 때 데이터, 계산, 액션 구분해서, 데이터와 계산의 범위는 늘리고 액션의 범위는 줄여야 한다.
(데이터 / 계산 / 액션 전문가 6단계)
1. 요구사항에 따라 작업할 부분에 대한 전체적인 흐름을 파악한다.
2. 최종적으로 해야 하는 액션을 정의하고, 그 액션에 필요한 데이터 형태를 확인한다.
3. 데이터가 들어오는 입력 이후부터, 액션 직전까지의 구간을 계산 구간으로 정의한다.
4. '계산' 구간을 몇 개의 덩어리로 나누어 처리할지 정의하고, 각 계산에 필요한 입출력을 알아낸다.
5. 코드가 최초 요구사항1:1 매칭 되도록 번갈아 읽으며 점검하고, 재조정 한다.
6. 모든 작업을 완료한 뒤 정상 동작을 확인한다.