한마디로 표현하자면 스트레스의 연속이었다. 기회가 된다면 좀 더 진득하게 프론트엔드 프레임워크에 대해 알아볼 수 있다면 좋을 것 같다. 단순한 1화면 1UI 프론트엔드이기 때문에 프레임워크를 사용하는 것은 불필요한 복잡도 및 꼭 필요 하지 않은 기능들을 덧붙이게 되는 Overkill이라고 생각하였고 내가 필요한 Javscript + HTML + CSS만 이용하여 '최대한 단순하고 깔끔하게 만들자'를 목표로 시작하였다.
HTML + CSS
단순 할 수록 사용하기 편하다! 라는 아이디어를 실현 시키기 위해 (사실 복잡해지면 개발하기도 복잡한 것 같다..), 위와 같은 구성으로 SPA, 정말 SPA를 구현해 보았다. CSS의 grid display를 이용하면 윈도우를 커다란 엑셀시트처럼 사용할 수 있었다. 가로 세로로 원하는 크기로 칸을 만들고 각각 의 선마다 이름을 지정하여 쓸 수 있는 매우매우 편리한 도구 였다.
TMI) 처음에는 flex박스를 사용하려고 했지만 윈도우 크기에 따라, 또는 박스의 크기에 따라 UI가 전혀 의도치 않은 방식으로 재조정되는 것을 보고 바로 CSS파일을 전부 엎어버렸다.
TODO
- 터치 버튼!
- GUI 사이즈가 현재 하드코딩 되어있음. 디스플레이 상태(윈도우 크기, 모바일 vs 데스크탑)에 맞게 재조정하도록 env 관리 클래스를 만들기
Javascript
컴포넌트 별로 .js 파일을 따로 만들었고 자바스크립트를 객체지향적으로 사용 하기 위해서 선택 한 방식은 IIFE를 이용해 오브젝트를
생성 -> 해당 객체의 메써드를 return 하여 외부에서 사용 할 수 있도록 하였다.
Javascript 잘 활용하기!
의도는 그저 객체를 리턴받아 밖에서 쓰고 싶었던 거였지만... 자바스크립트에 대해 정보를 찾아보다가, 프로젝트에서 사용한 함수 선언 방식이 closure를 활용한 자바스크립트의 encapsulation 방식 이라는 것을 찾았다!..
- websocket: 웹소켓 연결 및 웹소켓 메세지 핸들링
- rtc: RTCPeerConnection 객체를 통해 ICE Candidate 찾기, SDP Offer 및 Answer 생성 및 저장, MediaStream(비디오 오디오 스트림) 관리
- controller: 키보드입력 이벤트 핸들러 및 Libretro를 위한 keyMap 정의
- input: 컨트롤러 상태에 대한 polling, 여러 종류의 입력을 LibretroAPI 에 맞도록 bitmap으로 인코딩 (현재는 키보드 뿐이지만, 조이패드, 터치패드 등 여러가지 입력 디바이스 추가 확장을 위해서 컨트롤러와 분리 되어있다.)
컴포넌트 사이의 커뮤니케이션은 간이 PubSub 클래스를 이용 하여 개발했다.
컨트롤러를 예로...
// controller.js
// KEY_PRESSED 이벤트에 등록되어 있는 콜백 함수
// PubSub에 의해 Key_PRESSED가 어딘가에서 publish 될때마다 실행된다!
const onKeyPress = (data) => {
input.setKeyState(data.key, true);
}
// KEY_PRESSED 이벤트에 onKeyPress 함수를 PubSub에 등록
PubSub.subscribe(KEY_PRESSED, onKeyPress);
const Keyboard = (() => {
...
const onKeyChange = (code, callback) => {
if (code in keyMap) {
const key = keyMap[code]
// key => PubSub.publish(KEY_PRESSED, {key: key}) 함수가 실행되며
// KEY_PRESSED 이벤트 발생
callback(key);
}
};
const init = () => {
// 브라우저 키보드 이벤트 핸들러 등록
document.body.addEventListener('keydown',
event => onKeyChange(event.code,
key => PubSub.publish(KEY_PRESSED, {key: key})
)
);
document.body.addEventListener('keyup',
event => onKeyChange(event.code,
key => PubSub.publish(KEY_RELEASED, {key: key})
)
);
....
console.log('[input] keyboard init');
}
return {
init,
}
}()
Keyboard.init()
개발 할때는 subscribe와 publish를 한쌍으로 언제나 유지하도록 노력하여 중간에 실수가 일어나는 일은 거의 없었으나 이벤트 기반으로 개발을 하다보니 subscribe와 publish가 코드 여기지거에 흩뿌려져 있어 확실히 가독성이 떨어지는 것을 볼 수 있었다. 이벤트를 가독성있게 구조화하려면 어떻게 해야할지는 좀 더 고민해봐야겠다...
완성품 공개! (사실 이거 자랑하려고..)
to be continued...
코드 설명도 하고 싶지만... 아직 자바스크립트가 무르익지 않았다.. 조만간 코드도 정리하고 깔끔하게 올려보도록 하자..!
'remote-craft' 카테고리의 다른 글
RemoteCraft 11 - 브라우저 실험 결과 + 힘들었던 점 + 해야 할것 (0) | 2021.07.30 |
---|---|
RemoteCraft 10 - 호스팅 + 후기 (0) | 2021.07.30 |
RemoteCraft 08 - Worker (0) | 2021.07.27 |
RemoteCraft 07 - Websocket (feat. Lobby) (0) | 2021.07.25 |
RemoteCraft 05 - WebRTC Pion! (0) | 2021.07.23 |