점프 테이블을 실제로 연습해보기
12/1/2024, 11:16:59 PM
-
🔖 태그:
- JS
점프테이블을 실제로 연습해보면서 느낀점을 써보자
점프테이블을 연습해보자
- 두서
- 첫번째 예시
- 두번째 예시
- 마치며
두서
점프 테이블이라는 글에서 작성했듯이 점프 테이블에 대해 알아봤으니 연습을 해보는게 좋겠습니다.
아주 기본적인 형태부터, 조금 개량시킨 형태등을 알아보겠습니다.
state machine을 구현한다는 느낌으로 작성해보겠습니다.
첫번째 예시
const states = {
add1: n => {
n += 1;
return 'add2';
},
add2: n => {
n += 2;
return null;
}
}
const runner = (init, ctx) => {
let state = init, passedCtx;
while(state) {
state = states[state]?.(ctx);
}
}
위의 형태가 아마 가장 단순한 형태일 것입니다.
물론 이렇게 생각하실 수 있습니다.
const add1add2 = n => [1, 2].reduce((acc,cur) => acc + cur, n)
위에서 만든 상태 머신에 비해 훨씬 짧고 간단하며, 이미 검증 되었고 등등… 이렇게 만드는 것도 매우 훌륭합니다.
사실 이 점프머신과 함수형 프로그래밍은 저에게 매우 비슷하다는 느낌을 줍니다.
원하는 함수등을 지정해놓고, 순서에 따라 파이프에 물을 흘려 보내듯이 순서대로 흘려보내는 것이 닮아 있습니다.
여기서 점프 테이블의 강점은 명시적인 상태 관리라고 생각합니다. 각 상태를 각 함수가 관리하고, 상태에 따라 다른 상태로 넘기는 것이 명시적으로 드러나게 됩니다.
const state = {
a: (ctx) => ctx > 5 ? null : 'b',
b: (ctx) => ctx > 7 ? null : 'c',
// ...
}
이렇게 명시적으로 상태를 지정하는 것이 가능합니다.
만약 상태 a에서 ctx > 5
라는 조건을 만족한다면 바로 상태머신은 종료됩니다.
이 글을 쓰면서도 단점이 보여지긴 합니다. 만약 위처럼 a, b, c 등으로 시퀀스를 갖는 이름으로 상태를 관리하는 경우 유지보수 기간 중 a와 b 사이의 어떤 상태가 추가될 때, 이름을 끼워넣기 난해할 수 있다는 점입니다.
함수형 코드가 반환값을 주니 점프 테이블도 반환값을 받을 수 있게 약간 손을 보겠습니다.
두번째 예시
const states = {
add1:(n)=>{
n += 1;
return ['add2', n];
},
add2:(n) => {
n += 2;
return ['done', n];
},
done: (n) => [null, n]
};
const runner = (init, ctx) => {
let state = init, passedCtx;
while(state) {
[state, passedCtx] = states[state]?.(passedCtx || ctx);
}
return [state, passedCtx];
}
const result = runner('add1', 1);
각 상태는 이제 다음 이동 할 state
와 해당 함수의 반환값을 튜플에 담아 반환합니다.
[state, return value]
이런식으로 말입니다.
while
문 내에서 passedCtx
는 이전 상태에게 전달받은 값의 포인터 혹은 원시값이 저장되며 해당 값을 다음 state 함수에 전달합니다. 만약 값이 없다면 처음 받은 값을 전달합니다.
여기서 계속 발전시킬 수 있습니다. 예를 들어 처음 받은 ctx
와 passedCtx
를 항시 전달하게 한다거나, 받은 인자들을 spread
연산자를 사용하여 계속 전달 한다거나 등등… 다양한 방법이 있겠습니다.
단, 단순하게 if-else를 나열하는 것보다는 낫다고 생각합니다.
마치며
위에서 함수형과 점프 테이블에 대한 비교를 했습니다. 비교는 비교일 뿐 서로 더 나은 점이 있고 보완할 점이 있습니다.
전 이럴 때, 둘을 섞어 쓰는게 더 좋다고 생각합니다.
큰 흐름은 점프 테이블로 관리하고 점프 테이블의 각 함수는 함수형으로 관리를 하는 것입니다.
비슷한 느낌으로 객체지향에 함수형을 섞는 등의 방법도 있습니다.