본문 바로가기

끄적끄적

V-Gesture 제작기 - 2. Gesture , Plugin, GestureManager

조금 대충그리긴 했지만... 일단 전체적인 플로우

 

 

Gesture.

당연하지만 VGesture 모듈이 Gesture을 인식함에 있어서 필요한 정보들을 리스트업 하되, 제스처, 그 자체에 동작과 연관성이 떨어지는 속성들은 최대한 배제하고, 배제된 요소들은 Plugin 레이어로 올리는 방향으로 방향성을 잡았다. 

 

애당초 Gesture 클래스를 구현해야하는 임의의 개발자 입장에서 안 그래도 Plugin 클래스 까지 구현해야 비로소 완성이되는데, 코어인 Gesture 클래스가 너무 난잡하거나 요구하는 구현 스펙이 너무 많다면 개발자 입장에서 상당히 부담스러울거라 생각했다.

 

따라서 정리하여 크게 6가지 속성으로 정리했다.

 

  • name : 해당 Gesture의 고유 이름. 다른 Gesture와 구분하기 위한 식별자
  • eventName: 해당 Gesture가 감지 될 시, 발생할 이벤트 이름
  • determinant: 인풋 값들에 대해, 현재 인풋값이 해당 제스처인지 확인하는 판별 함수
  • handler: %eventName%이 감지될 시, 실행되는 이벤트 콜백 함수
  • usedHand: 제스처를 감지할 손의 방향. (왼손이냐 오른손이냐)
  • operationsRequest: gestureManager에 연산을 캐시하거나 캐시된 연산을 가져올 수 있게하는 속성 

 

Plugin.

 

플러그인의 경우, 지금 당장은 직접적으로 필요는 없지만 후에 breaking change가 발생할 시, 유연하게 대처하기 위한 레이어의 역할이 처음 설계 당시 목적이었으나, Gesture 의 생명주기 관리 혹은 메타 데이터를 담기 위한 레이어로 정의하였다.

 

따라서 현재(2024.06.07) 기준으로 3가지 속성을 제시하였다.

 

  • gesture : 제스처 instance
  • register : gesture 셋업 함수. 기본적으로 제공하는 함수는 eventListener 달아주는 함수이다.
  • unregister : gesture 제거 함수. 기본적으로 제공하는 함수는 eventListener 제거해주는 함수이다.

 

 

GestureManager.

gestureManager의 경우, 말 그대로 Gesture들을 관리하고 VGesture과 각 Gesture간의 연결을 중개하는 역할을 하는 클래스이다.

기본적으로 각 제스처들과 직접적으로 참조하고 있고, gesture들이 요청하는 연산(operationsRequest)들을 저장하여, 각 gesture들이 연산을 요청 시, 연산을 캐시 혹은 로드해준다.

 

gestureManager가 VGesture모듈에 있어서 굉장히 코어 로직들을 담고 있고, 또 자칫 잘못 변형시켰다간 굉장한 메모리 누수를 일으킬 수 있기에 해당 부분에 대한 방어책을 제시할 필요성을 느꼈다.

 

물론 그냥 만들고 배포한 후 사용하다가 개발자가 실수로 변형해서 심각하게 메모리 누수를 일으키면 그 개발자 탓이지만, 결국 사용하는 유저가 불편함을 감수해야하고 또 어쩌다가 내 모듈이 욕먹긴 싫어서... proxy 객체와 symbol을 조합해 프로그래밍적으로 절대 변형 불가능하게 했다. (혹시 뚫리면 알려주세요...)

 

여담이지만 개인적으로 symbol과 proxy조합이 참 잘 어올려서 애용한다.

 

export const protect = (obj: object, $setterAccessKey: Symbol, deep = false) => {
  const trap = {
    get: (target: typeof obj, key: keyof typeof obj, receiver: any): unknown => {
      if (deep && typeof target[key] === 'object' && target[key] !== null) {
        return new Proxy(target[key], trap)
      }
      return Reflect.get(target, key, receiver);
    },
    set: (target: typeof obj, key: keyof typeof obj, envelop: { accessKey: Symbol, value: any } | any) => {
      // protected property
      if (key[0] === '_') {
        if (envelop.accessKey === $setterAccessKey) {
          (target as any)[key as any] = envelop.value;
          return true;
        } else {
          return false
        }
      }
      (target as any)[key as any] = envelop;
      return true
    }
  }

  return new Proxy(obj, trap);
}

export function createMutationEnvelop<T>($setterKey: Symbol, value: T): T {
  const envelop = {
    accessKey: $setterKey,
    value
  };
  return envelop as T
}

 

 

 

 

 

OperationsRequest.

이쯤되면 OperationRequest의 배경에 대해 궁금해할것 같아서 적어본다.

 

먼저 이전 글에서 서술했듯, VGesture 모듈은 굉장히 많은 리소스를 잡아 먹는다.

 

여기서 당연하지만 제스처를 추가할수록 연산량은 선형적으로 증가한다.

 

"연산 끽 해봐야 얼마나 하겠어~" 라고 생각할 수 있는데, 해당 연산들외에 내부적으로 수행하는 작업들이 굉장히 많다.

 

16.7ms 안에 다음을 수행해야한다.

  1. handDetector의 손 위치 정보 탐지
  2. K-d 트리 인스턴스 생성
  3. 가장 인접한 노드 검색
  4. gestureManager 업데이트
  5. canvas에 손가락 위치 업데이트 및 렌더링
  6. 제스처 별로 연산 수행 및 판단

 

러프하게 생각해보면 일반적으로 자바스크립트의 선형시간 동안 연산의 한계선이 10^6 정도니(버벅x), 주어진 시간 상, 10^4 정도의 연산량이어야 유저가 불편함이 없을 것이다.

 

10^4수준의 연산량이면, 일상에서 생각보다 쉽게 용량을 채우기에, 연산 최적화는 필요한 작업이었다.

 

연산을 대체 어떻게 최적화할까 고민하다가 다음과 같은 스텝으로 결론을 내렸다.

  1. 제스처를 판단하기 위해선 손가락의 정점(vertice) 데이터가 요구된다.
  2. 제스처는 결국 물리량이다.
  3. 손가락 정점 데이터는 21개이고 해당 데이터를 조합하여 수행할 연산의 종류에는 한계가 있다.
  4. 그러면 연산을 종류별로 캐시하여 만약 중복되는 연산이 존재할 경우, 해당 연산을 캐시하자.

 

여기서 어떻게 gesture가 GestureManager에게 캐시할 연산을 알려줄까 고민을 하다가 rpc 호출할때, 메서드 명을 인자로 삼는게 떠올라서 해당 방식을 오마쥬했다.

 

func::get2FingerDistance-indexTip-thumbTip

 

 

  • :: = 연산 지칭자
  • - = 파라미터 구분자

(요청하는 연산의 타입)(연산 지칭자)(연산의 이름)...[(파라미터 구분자)(손가락 정점 이름)]

 

손가락 정점의 이름은 다음을 참고하면 된다.

https://github.com/dovigod/V-Gesture/tree/main?tab=readme-ov-file#requestable-operations--variables

 

GitHub - dovigod/V-Gesture

Contribute to dovigod/V-Gesture development by creating an account on GitHub.

github.com

 

'끄적끄적' 카테고리의 다른 글

V-Gesture 제작기 - 4. 번들링  (1) 2024.06.07
V-Gesture 제작기 - 3. VGesture  (1) 2024.06.07
V-Gesture 제작기 - 1. intro ~ prototyping  (1) 2024.06.06