[Enact] Enact 프레임워크 기본 개념 및 예시
새 프로젝트 진행에 앞서 내가 보려고 만드는 Enact 프레임워크 정리
저희 팀은 현재 2024년 신규 프로젝트로 enact
framework를 채택했습니다.
생소하기도 했지만, React.js
의 framework 이고,
현재 저희 팀이 가장 잘 익숙하게 잘 다룰 수 있는 React
기반의 framework라고 하니 거부감보다는 신선함과, 흥미로움이 더욱 생기게 되었습니다.
현재 스터디 중이므로 정확하지 않을 수 있습니다.
Enact 란?
Enact
란, 웹 어플리케이션을 구축하기 위한 Javascript
의 프레임워크입니다.
React.js
기반으로 구축되었기에 편의 상 React.js
의 프레임워크라고도 할 수 있습니다.
Enact
는 주로 TV와 같은 대형화면을 가진 디바이스에서의 사용을 염두에 두고 설계되었고,
굉장히 유연한 설계 방식을 제공하면서도, 요즘 front-end
에서는 기본 소양이라고도 할 수 있는 React
를 기반으로 하여 구축되었기에
개발자들이 쉽게 접근이 가능하다는 장점이 있습니다.
내가 느낀 Enact
의 장점
우선 Enact
는 앞서 말한 것과 같이 TV와 같은 대형 화면의 디바이스에서의 사용을 위해 설계되었기에,
4방향 포커싱
에 대해 기능을 쉽게 구현할 수 있도록 지원이 되어있습니다.
단순 React
환경이라면, 키보드의 4방향과 관련된 로직을 따로 작성해주어야 하는데,
Enact
에서는 그럴 필요가 없으니, 코드가 굉장히 간결해지고 깔끔해지는 이점이 있는 것 같습니다.
이 부분에서
Enact
를 채택하게 되었습니다.
뿐만 아니라, Enact
는 접근성을 굉장히 중요하게 생각하기에, 웹 콘텐츠의 접근성 지침을 준수하는 어플리케이션을 구축할 수 있도록 다양한 도구와 컴포넌트를 지원하고있습니다.
실제 예시를 통해 Enact
가 얼마나 편리한지 설명이 가능합니다.
React
에서의 4방향 포커싱 처리
React
에서는 따로 4방향 포커싱 처리에 관한 기능이 제공되어있지 않으므로, 개발자가 직접 키보드 이벤트에 관한 처리를 직접 해주어야합니다.
쉬운 예로 다음 인덱스번호의 컴포넌트로 포커싱을 이동하는 효과를 구현해보겠습니다.
interface FocusableButtonProps {
children: React.ReactNode;
onFocused: () => void;
}
const FocusableButton = ({children, onFocused}: FocusableButtonProps) => {
<button tabIndex={-1} onFocus={onFocused}>{children}</button>
}
export default function Component() {
const [focusedIndex, setFocusedIndex] = useState(0)
const handleKeyDown = useCallback((event: KeyboardEvent) => {
const {keyCode} = event;
const focusableElements = Array.from(document.querySelectorAll('button'));
const currentIndex = focusableElements.indexOf(document.activeElement as HTMLButtonElement);
let nextIndex = currentIndex;
switch (keyCode) {
case 37:
case 38:
nextIndex = Math.max(0, currentIndex - 1);
break;
case 39:
case 40:
nextIndex = Math.min(focusableElements.length - 1, currentIndex + 1)
break;
default:
return;
}
setFocusedIndex(nextIndex)
focusableElements[nextIndex].focus();
event.preventDefault();
}, [])
useEffect(() => {
window.addEventListener('keydown', handleKeyDown)
return () => {
window.removeEventListener('keydown', handleKeyDown)
}
}, [handleKeyDown])
useEffect(() => {
const focusableElements = Array.from(document.querySelectorAll('button'))
if (focusableElements.length > 0) {
focusableElements[focusedIndex].focus();
}
}, [focusedIndex])
return (
<>
<FocusableButton onFocused={() => setFocusedIndex(0)}>Button 1</FocusableButton>
<FocusableButton onFocused={() => setFocusedIndex(1)}>Button 2</FocusableButton>
<FocusableButton onFocused={() => setFocusedIndex(2)}>Button 3</FocusableButton>
<>
)
}
위 코드는 3개의 버튼 내에서 키보드 방향키를 이용한 포커싱 이동을 구현한 것입니다.
사실 크게 복잡하지는 않은 로직이지만, 단순 포커싱만을 처리하기에는 너무 많은 내용을 담고 있습니다.
물론 이러한 것들은 따로 util
폴더를 통해 포커싱에 관련된 함수를 만들어 재사용성을 높여 사용할 수는 있지만,
Enact
를 사용하게 되면 이러한 작업마저도 불필요해집니다.
Enact
에서의 4방향 포커싱 처리
import { SpotlightContainerDecorator } from "@enact/spotlight/SpotlightContainerDecorator";
import { Spottable } from "@enact/spotlight/Spottable";
const Container = SpotlightContainerDecorator("div");
const SpottableButton = Spottable("button");
export default function Component() {
return (
<Container>
<SpottableButton>Button 1</SpottableButton>
<SpottableButton>Button 2</SpottableButton>
<SpottableButton>Button 3</SpottableButton>
</Container>
);
}
딱 봐도 어마어마한 양의 코드가 줄었고, 훨씬 보기 편하게 깔끔해졌습니다.
React
내에서는 따로 구현을 해야만 했던 4방향 포커싱
기능을 Enact
에서는 Enact
에서 제공해주는 Spotlight
기능만 사용하면 편리하게 구현이 가능합니다.
물론 현재 이 코드만 봐서는 SpotlightContainerDecorator
가 무엇인지, Spottable
이 무엇인지 알 수 없지만,
해당 내용은 다음 포스팅에서 설명하기로 하고, 우선 코드의 간결함에 대해서 집중해보도록 하겠습니다.
이처럼 Enact
에는 자체적으로 포커싱에 대한 처리가 지원이 되어, 코드를 좀 더 편하게 작성할 수 있어
기능적인 로직 구현에만 온전히 집중할 수 있도록 도움을 주고있습니다.
그럼 Enact
의 단점은 ?
Enact
의 편의성이 실로 대단하지만, Enact
는 사실 TV 같은 키보드 포커싱 처리가 굳이 필요없다면 사용하지 않아도 될 framework 입니다.
또한, 이건 실제로 개발 초기 셋팅을 진행하면서 느꼈던 부분인데
공식문서를 보면 알겠지만, 각각의 기능에 대해서 설명이 굉장히 부족합니다.
때문에 개발 초기셋팅을 진행하면서 라이브러리와 버전 호환 등의 이슈로 라이브러리 교체를 몇 번이나 진행한 이력이 있습니다.
근데 이는 사실 내가 진행할 프로젝트가 webOS 지원 버전이
Chrome 38
부터 지원해야하므로,webOS
버전 자체의 이슈도 있습니다.
실제로 webOS 3.0
버전부터 지원을 하려면 Chrome 38
버전에서 작동이 가능해야하는데,
너무 옛날 버전이다보니 enact/cli
의 버전이 최신 버전이라면 현재 사용이 불가능합니다.
또한, ES6
문법을 지원하지 않아서, babel
로 하나하나 설정을 해줘야하는 번거로움이 있었으며,
그 마저도 *"원인을 파악하지 못한 이슈"*가 여러 부분 발생했었습니다.
프로젝트를 진행하며 상태 관리를 위해 Redux-toolkit
을 채택했는데
무슨 이유에선지 build
를 하고 실제 webOS 3.0
TV에 앱을 실행시켜보니 흰 화면만 노출되었습니다.
찾아보니, redux-toolkit
라이브러리 내의 optional-chaining
이 문제였는데,
바벨 설정을 통해 이를 수정해보아도 전혀 해결되지 않았습니다.
그래서 전통적인 방식의 redux
를 사용하니 잘 되었습니다.
오랜만에 전통적인 방식의 redux
를 사용하니 뭔가 감회가 색다르긴 했습니다.
같은 이유로 webOS 3.0
과 같은 낮은 버전에서는 typescript
사용이
불가능합니다.
나에게 있어 이 부분이 가장 큰 문제라고 생각합니다.
규모가 꽤 있는 프로젝트를 진행하고 있는데, typescript
사용이 불가능하니 유지보수 측면에서도 난관에 봉착할 미래가 훤히 보였습니다.
그래서 저희 팀은 React
의 prop-types
를 사용해서 어느 정도 문제를 해결하려고 하고 있는데
사실 컴파일 단계에서 오류를 잡아주는 부분이 아니라 근본적인 문제 해결을 할 수는 없을 것 같습니다.
❌ 구글링을 해도 정보가 거의 없습니다.
현재까지는 공식문서를 열심히 참고하며, 개발 가이드를 익히고 있지만, 설명이 조금 부족한 내용에 대해 참고할 만한 reference
가 별로 없는 것이 문제입니다.
마치며..
다행히 아직까지는 개발을 진행함에 있어 큰 이슈가 나지 않았고, 해결 방법이 있어 초기 셋팅에 있어서는 아직까지는 문제가 없습니다.
아쉬운 부분도 다소 있지만, 4방향 포커싱
에 관해서 아주 대단한 기능을 제공해주다보니, 위의 단점들은 어느정도 상쇄가 되는 것 같습니다.
처음에 "이게 돼?" 하며 걱정도 했지만, 새로운 기술을 접하다보니 나름 재미도 있고 생각보다 어렵지 않았습니다.
focusing
에 관련해서 다양한 가이드를 제공하고 있는데, 이 부분에 관해서도 스터디를 진행하며 포스팅할 예정입니다.