🛠️ 처음부터 만드는 Signal — 값이 바뀌면 자동으로 반응하기
문제
변수 A가 바뀌면 A를 참조하는 B도 자동으로 업데이트되어야 합니다.
스프레드시트의 셀처럼요. `price`가 바뀌면 `tax`도, `total`도 알아서 다시 계산되는 것.
수동으로 업데이트 함수를 호출하면 빠뜨리기 쉽고, 의존 관계가 복잡해질수록 관리가 불가능해집니다.
Signal은 이 문제를 해결하는 반응형 프리미티브입니다. Angular, Solid.js, Preact가 모두 채택했고, TC39에서 JavaScript 표준으로 제안 중입니다.
---
코드 — 50줄로 만드는 Signal 시스템
```typescript
// signal.ts — 복사해서 바로 실행 가능
let currentEffect: (() => void) | null = null;
// 1. Signal: 값을 담는 반응형 컨테이너
function createSignal
let value = initialValue;
const subscribers = new Set<() => void>();
function get(): T {
// 읽는 순간, 현재 실행 중인 effect를 구독자로 등록
if (currentEffect) {
subscribers.add(currentEffect);
}
return value;
}
function set(newValue: T) {
if (Object.is(value, newValue)) return; // 같은 값이면 무시
value = newValue;
// 값이 바뀌면 모든 구독자에게 알림
for (const fn of subscribers) {
fn();
}
}
return { get, set };
}
// 2. Effect: Signal을 읽는 함수 → 자동으로 의존성 추적
function createEffect(fn: () => void) {
const execute = () => {
currentEffect = execute; // "지금 나를 추적해" 표시
try {
fn(); // fn 안에서 signal.get() 호출 → 자동 구독
} finally {
currentEffect = null; // 추적 종료
}
};
execute(); // 최초 1회 실행하여 의존성 수집
}
// 3. Computed: 다른 Signal로부터 파생되는 읽기 전용 Signal
function createComputed
const computed = createSignal
createEffect(() => {
computed.set(fn());
});
return { get: computed.get }; // set 노출하지 않음
}
```
---
사용 예제
```typescript
// 스프레드시트처럼 동작하는 계산
const price = createSignal(10000);
const quantity = createSignal(3);
const taxRate = createSignal(0.1);
const subtotal = createComputed(() => price.get() * quantity.get());
const tax = createComputed(() => subtotal.get() * taxRate.get());
const total = createComputed(() => subtotal.get() + tax.get());
// effect: 값이 바뀔 때마다 자동 실행
createEffect(() => {
console.log(`합계: ${total.get().toLocaleString()}원`);
});
// → "합계: 33,000원"
price.set(20000);
// → "합계: 66,000원" (자동!)
quantity.set(5);
// → "합계: 110,000원" (자동!)
```
---
핵심 원리 3줄 요약
| 개념 | 역할 |
|------|------|
| Signal | 값을 저장하고, 읽는 쪽을 자동 추적 |
| Effect | Signal을 읽는 함수. 의존하는 Signal이 바뀌면 재실행 |
| Computed | 다른 Signal에서 파생된 읽기 전용 Signal |
비밀은 `currentEffect`라는 전역 변수입니다. `effect` 실행 중에 `signal.get()`이 호출되면, 그 signal은 "아, 이 effect가 나를 읽고 있구나"라고 자동으로 기억합니다. 이것을 자동 의존성 추적(auto-tracking)이라고 합니다.
---
실전에서는?
이 50줄 구현은 학습용입니다. 프로덕션에서는 다이아몬드 의존성, 글리치 프리(glitch-free) 업데이트, 메모리 누수 방지 등을 추가로 처리해야 합니다.
실전 라이브러리 추천:
---
Comments (0)
💬
No comments yet.
Be the first to comment!