점프 테이블을 실제로 연습해보기

12/1/2024, 11:16:59 PM




점프테이블을 실제로 연습해보면서 느낀점을 써보자

점프테이블을 연습해보자

  • 두서
  • 첫번째 예시
  • 두번째 예시
  • 마치며

두서

점프 테이블이라는 글에서 작성했듯이 점프 테이블에 대해 알아봤으니 연습을 해보는게 좋겠습니다.

아주 기본적인 형태부터, 조금 개량시킨 형태등을 알아보겠습니다.

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 함수에 전달합니다. 만약 값이 없다면 처음 받은 값을 전달합니다.

여기서 계속 발전시킬 수 있습니다. 예를 들어 처음 받은 ctxpassedCtx를 항시 전달하게 한다거나, 받은 인자들을 spread 연산자를 사용하여 계속 전달 한다거나 등등… 다양한 방법이 있겠습니다.

단, 단순하게 if-else를 나열하는 것보다는 낫다고 생각합니다.

마치며

위에서 함수형과 점프 테이블에 대한 비교를 했습니다. 비교는 비교일 뿐 서로 더 나은 점이 있고 보완할 점이 있습니다.

전 이럴 때, 둘을 섞어 쓰는게 더 좋다고 생각합니다.

큰 흐름은 점프 테이블로 관리하고 점프 테이블의 각 함수는 함수형으로 관리를 하는 것입니다.

비슷한 느낌으로 객체지향에 함수형을 섞는 등의 방법도 있습니다.