댄이 만든 useState
프로토타입은 가능성의 문을 열었지만, 동시에 더 큰 난관을 드러냈다. 하나의 컴포넌트가 여러 상태를 가져야 할 때, 그의 단순한 전역 변수 모델은 속수무책이었다.
그날 오후, 댄은 자신의 실험 결과를 세바스티안에게 보여주었다. 세바스티안은 댄의 코드를 조용히 훑어보더니, 예상했다는 듯 희미한 미소를 지었다.
“첫걸음으로는 훌륭하군요. 이제 진짜 문제를 풀 시간입니다.”
세바스티안은 자신의 컴퓨터에서 오래된 연구 논문과 프로그래밍 언어 명세서를 몇 개 찾아 띄웠다. 화면에는 낯선 단어들이 가득했다. ‘Effect Handlers’, ‘Continuations’, 그리고 ‘Algebraic Effects’.
“오래전부터 고민해 온 아이디어가 있습니다.”
세바스티안은 ‘대수적 효과(Algebraic Effects)’라는 개념에 대해 설명하기 시작했다. 그것은 주류 프로그래밍 세계에서는 거의 논의되지 않는, 학술적인 영역에 머물러 있는 난해한 개념이었다.
쉽게 비유하자면, 자바스크립트의 try...catch
구문과 비슷했다. try
블록 안에서 에러가 throw
되면, 함수의 실행은 그 자리에서 즉시 멈추고 가장 가까운 catch
블록으로 제어권이 넘어간다.
대수적 효과는 이 개념을 한 단계 더 발전시킨 것이었다.
“만약 throw
처럼 함수를 멈추는 특별한 명령어가 있는데, 그게 꼭 에러일 필요는 없다면 어떨까요?”
세바스티안이 가상의 코드를 그렸다.
function calculate() {
const a = perform 'get_number'; // 여기서 실행이 '일시 정지'된다.
const b = perform 'get_number'; // 여기서도.
return a + b;
}
perform
이라는 키워드가 바로 대수적 효과를 발생시키는 명령어였다. calculate
함수는 perform 'get_number'
를 만나는 순간, 실행을 ‘일시 정지’하고 자신을 호출한 외부의 ‘핸들러(Handler)’에게 제어권을 넘긴다.
핸들러는 'get_number'
라는 요청을 받고, 사용자에게 숫자를 입력받는 등의 어떤 작업을 수행한 뒤, 멈춰있던 calculate
함수에게 결과값(예: 5)을 돌려준다. 그러면 calculate
함수는 멈췄던 바로 그 지점부터 실행을 ‘재개’하여, 5라는 값을 a
변수에 할당한다.
“이게 의미하는 바가 보이나요?”
세바스티안의 눈이 빛났다.
“함수 calculate
는 자신이 어떻게 숫자를 얻어오는지는 전혀 신경 쓰지 않습니다. 그저 ‘숫자가 필요하다’는 요청만 보낼 뿐이죠. 실제 로직은 외부의 핸들러가 책임집니다. 테스트 환경에서는 핸들러가 고정된 숫자를 돌려주게 할 수도 있고, 실제 앱에서는 사용자 입력을 받게 할 수도 있겠죠. 함수의 핵심 로직과 부수 효과를 완벽하게 분리할 수 있게 되는 겁니다.”
댄은 숨을 죽이고 그의 설명을 들었다.
머릿속이 번개에 맞은 듯한 충격에 휩싸였다.
이것이 바로 자신이 useState
로 어설프게 흉내 내려고 했던 것의 완전한 형태였다.
리액트의 함수형 컴포넌트가 바로 저 calculate
함수였다.
useState
는 perform 'get_state'
와 같은 요청을 보내는 것이었다.
그리고 리액트 코어는 외부의 핸들러가 되어, 컴포넌트의 요청을 받아 상태 값을 제공하고, 실행을 다시 재개시켜주는 역할을 하는 것이다.
이 모델을 사용하면, 컴포넌트는 자신이 몇 번째 상태를 요청하는지만 알면 되었다.
function UserProfile() {
const name = perform 'get_state'; // 첫 번째 상태 요청
const age = perform 'get_state'; // 두 번째 상태 요청
// ...
}
리액트라는 핸들러는 이 요청들을 순서대로 받아 처리하고, 내부적으로 [name의_상태값, age의_상태값]
과 같은 배열에 저장해두면 되었다. 컴포넌트가 리렌더링되어 다시 상태를 요청할 때도, 똑같은 순서로 요청이 들어올 것이므로, 배열에서 순서에 맞는 값을 꺼내주기만 하면 되는 것이다.
댄은 자리에서 벌떡 일어났다.
전역 변수 같은 꼼수가 아니었다. 이것은 컴퓨터 과학의 깊은 이론에 뿌리를 둔, 우아하고도 견고한 해답이었다.
문제는 단 하나였다.
자바스크립트에는 대수적 효과라는 기능이 존재하지 않았다.
세바스티안도 그 사실을 알고 있었다.
“물론, 우리는 이 기능을 자바스크립트로 직접 구현할 수 없습니다. 하지만 이 ‘모델’을 흉내 낼 수는 있습니다. 컴포넌트의 렌더링 과정 자체를 하나의 거대한 핸들러로 보고, 함수 호출의 ‘순서’를 이용해 상태를 구분하는 거죠.”
세바스티안이 제시한 것은 단순한 코딩 기술이 아니었다.
그것은 리액트의 패러다임을 바꿀 수 있는, 강력한 멘탈 모델이었다.
댄은 새로운 영감에 휩싸여 다시 자신의 자리로 돌아갔다. 그는 방금 얻은 깨달음을 바탕으로, 허점투성이였던 첫 번째 프로토타입을 폐기하고 새로운 도전을 시작할 준비가 되어 있었다.