⚒️

Appendix. React App 단축키 구현

Created
2020/12/26 05:48
Tags
블로그의 UX를 개선해보자는 심산으로 단축키를 구현해 보았다. 처음에는 Component에 종속된 Event Listener를 생성해 등록된 키를 입력하면 특정 업무를 수행하도록 해 놓았는데, 하는 김에 조금 더 일반적인 - 전체 앱에서 사용할 수 있고, 현재 mount 되어 있는 component에 따라 단축키가 역동적으로 변하는 - 단축키 기능을 구현해 보았다.
전체적인 아이디어는 다음과 같다:
단축키는 특수한 키(cmd, ctrl 등)와 다른 키의 조합으로 이루어져 있음을 상정한다.
react-redux를 통해 각 컴포넌트가 마운트될 때 해당 컴포넌트에 대한 단축키를 목록에 등록하고, 언마운트될 때 목록에서 삭제한다.
전체 앱에서 미리 정해 둔 특수한 키(cmd, ctrl 등)를 누른 상태에서 다른 키를 누르면, 단축키 목록에서 해당 키를 조회하고 실행하도록 한다.

Redux를 이용한 단축키 관리

먼저 다음과 같이 key(등록할 단축키)와 func(실행할 함수)를 받아 뿌려주는 action을 등록한다.
// actions.js const ENROLL_SHORTCUT = "ENROLL_SHORTCUT"; export const enroll_shortcut = (key, func) => { return ({ type: ENROLL_SHORTCUT, payload: { key, func }, }) }
JavaScript
복사
그리고 다음과 같이 reducer를 만들어준다. shortcutReducer는 key로 반응할 단축키 값을, value로 실행할 함수를 담는 registered 오브젝트를 state로 가진다.
// reducers.js const shortcutReducer = (state = {registered: {}}, action) => { switch (action.type) { case ENROLL_SHORTCUT: return ({ registered: { ...state.registered, [action.payload.key]: action.payload.func } }) default: return state } }
JavaScript
복사

AddEventListener

이제 App.js 부분에 다음과 같은 코드를 추가해준다. 키가 눌리는 event를 listen하고, 눌린 키가 원하는 키(cmd 혹은 ctrl 등)이면 다음 키를 기다렸다가, 등록되어 있는 키가 입력되면 해당하는 함수를 실행해준다.
// App.js // 키를 누르고 뗄 때마다 관련 함수를 실행시킨다. componentDidMount() { window.addEventListener('keydown', this.onMetaDown); window.addEventListener('keyup', this.onMetaUp); } // 키를 누를 때마다 실행되는 함수. // 눌린 키가 cmd 키이면, 키보드 입력을 기다리는 다른 리스너를 추가한다. onMetaDown = event => { if (event.key === "Meta") { window.addEventListener('keydown', this.onKeyDown); } } // cmd키를 떼면, 키보드 입력을 기다리는 리스너를 제거한다. onMetaUp = event => { if (event.key === "Meta") { window.removeEventListener('keydown', this.onKeyDown); } } // cmd 키가 눌린 상태에서 다른 키를 누르면 실행되는 함수 // 눌린 키가 shortcut으로 등록된 키이면, 해당하는 함수를 실행시킨다. onKeyDown = event => { if (this.props.shortcut.registered[event.key]) { event.preventDefault(); this.props.shortcut.registered[event.key](); } }
JavaScript
복사
이제 적절한 단축키를 적절한 컴포넌트에서 등록해주기만 하면 컴포넌트별로 단축키를 사용할 수 있다. 다음과 같이 등록한다.
// 원하는 키와 함수를 redux store에 등록 this.props.dispatch(enroll_shortcut("key", this.function_to_register));
JavaScript
복사
이제 특정 페이지에서만 사용하고 싶은 단축키는 해당 컴퍼넌트에서 등록 및 삭제하고, 앱 전체에서 사용하고 싶은 단축키는 App.js 등에 등록하면 된다. 나름 만족스러운 결과이다!
E.O.D.