Cabin Fever 코딩: Node.js 백엔드 튜토리얼
게시 됨: 2022-03-11COVID-19 잠금으로 인해 우리 중 많은 사람들이 집에 갇혀 있게 되었으며, 아마도 객실 발열이 우리가 경험할 최악의 발열이기를 바랐을 것입니다. 우리 중 많은 사람들이 그 어느 때보다 더 많은 비디오 콘텐츠를 소비하고 있습니다. 지금은 운동이 특히 중요하지만 때때로 노트북이 손이 닿지 않는 곳에 있으면 좋은 구식 리모콘의 사치품에 대한 향수가 있습니다.
이것이 바로 이 프로젝트가 시작되는 곳입니다. 업데이트가 없으면 쓸모가 없는 구형 스마트폰이라도 다음 Netflix/YouTube/Amazon Prime Video 등을 위한 편리한 리모컨으로 전환할 수 있는 기회입니다. 폭주. Node.js 백엔드 튜토리얼이기도 합니다. Express 프레임워크와 Pug(이전의 Jade) 템플릿 엔진을 사용하여 백엔드 JavaScript의 기본을 배울 수 있는 기회입니다.
그것이 어렵게 들린다면, 완전한 Node.js 프로젝트가 마지막에 제시될 것입니다. 독자는 학습에 관심이 있는 만큼만 배우면 되며, 경험이 많은 독자는 건너뛸 수 있는 몇 가지 기본 사항에 대한 부드러운 설명이 많이 있을 것입니다.
왜 그냥...?
독자들은 "왜 Node.js 백엔드를 코딩해야 합니까?"라고 궁금해 할 것입니다. (물론 학습기회는 빼고요.) "이미 그런 앱은 없나요?"
물론이죠. 많이요. 그러나 이것이 바람직하지 않을 수 있는 두 가지 주요 이유가 있습니다.
- 구형 전화기의 용도를 변경하려는 사람들에게는 내가 사용하고 싶었던 Windows Phone 8.1 장치의 경우와 같이 더 이상 옵션이 아닐 수 있습니다. (앱 스토어는 2019년 말에 공식적으로 폐쇄되었습니다.)
- 신뢰(또는 신뢰 부족). 모든 모바일 플랫폼에서 볼 수 있는 수많은 앱과 마찬가지로 사용자가 앱이 수행하는 작업에 필요한 것보다 훨씬 더 많은 권한을 부여해야 하는 경우가 많습니다. 그러나 이러한 측면이 적절하게 제한되더라도 원격 제어 앱의 특성으로 인해 사용자는 앱 개발자가 스파이웨어 또는 기타 맬웨어를 포함하여 솔루션의 데스크톱 측에서 권한을 남용하지 않는다는 것을 사용자가 여전히 신뢰해야 함을 의미합니다.
이러한 문제는 오랫동안 존재해 왔으며 GitHub에서 발견된 2014년 유사한 프로젝트의 동기이기도 합니다. nvm
을 사용하면 이전 버전의 Node.js를 쉽게 설치할 수 있으며 몇 가지 종속성 업그레이드가 필요한 경우에도 Node.js는 이전 버전과 호환된다는 평판을 얻었습니다.
안타깝게도 비트로트가 이겼습니다. 완고한 접근 방식과 Node.js 백엔드 호환성은 Grunt, Bower 및 기타 수십 가지 구성 요소의 이전 버전 사이에서 끝없는 지원 중단 및 불가능한 종속성 루프와 일치하지 않았습니다. 몇 시간 후, 처음부터 다시 시작하는 것이 훨씬 더 쉬울 것이라는 사실이 분명해졌습니다. 그럼에도 불구하고 바퀴를 재발명하지 말라는 이 저자의 조언입니다.
기존의 새로운 기즈모: Node.js 백엔드를 사용하여 전화기를 원격 제어로 용도 변경
먼저, 이 Node.js 프로젝트는 현재 Linux에만 해당되며 특히 Linux Mint 19 및 Linux Mint 19.3에서 개발 및 테스트되었지만 다른 플랫폼에 대한 지원이 확실히 추가될 수 있습니다. 이미 Mac에서 작동 할 수 있습니다 .
최신 버전의 Node.js가 설치되어 있고 프로젝트 루트 역할을 할 새 디렉토리에 명령 프롬프트가 열려 있다고 가정하면 Express를 시작할 준비가 된 것입니다.
npx express-generator --view=pug
참고: 여기에서 npx
는 Node.js와 함께 제공되는 Node.js 패키지 관리자인 npm
과 함께 제공되는 편리한 도구입니다. Express의 애플리케이션 스켈레톤 생성기를 실행하는 데 사용하고 있습니다. 이 글을 쓰는 시점에서 제너레이터는 기본적으로 Jade라는 템플릿 엔진을 가져오는 Express/Node.js 프로젝트를 만듭니다. Jade 프로젝트는 버전 2.0부터 "Pug"로 이름이 바뀌었지만. 따라서 최신 상태를 유지하고 즉시 Pug를 사용하고 사용 중단 경고를 방지하려면 npx에서 실행되는 express-generator
스크립트의 명령줄 옵션인 npx
--view=pug
를 사용합니다.
완료되면 package.json
에 새로 채워진 Node.js 프로젝트의 종속성 목록에서 일부 패키지를 설치해야 합니다. 이를 수행하는 전통적인 방법은 npm i
i
"설치"의 경우 i)를 실행하는 것입니다. 그러나 일부는 여전히 Yarn의 속도를 선호하므로 이를 설치했다면 매개변수 없이 간단히 yarn
을 실행하십시오.
이 경우 로컬 네트워크에서 필요에 따라 액세스가 유지되는 한 Pug의 하위 종속성 중 하나에서 (곧 수정될 예정인) 사용 중단 경고를 무시하는 것이 안전해야 합니다.
빠른 yarn start
또는 npm start
다음 브라우저에서 localhost:3000
으로 이동하면 기본 Express 기반 Node.js 백엔드가 작동함을 알 수 있습니다. Ctrl+C
로 죽일 수 있습니다.
Node.js 백엔드 튜토리얼, 2단계: 호스트 시스템에서 키 입력을 보내는 방법
리모컨 부분이 이미 반쯤 완성되었으므로 제어 부분으로 시선을 돌립시다. 우리는 Node.js 백엔드를 실행할 머신을 프로그래밍 방식으로 제어할 수 있는 무언가가 필요합니다. 키보드의 키를 누르는 것처럼 가장합니다.
이를 위해 공식 지침을 사용하여 xdotool
을 설치합니다. 터미널에서 예제 명령에 대한 빠른 테스트:
xdotool search "Mozilla Firefox" windowactivate --sync key --clearmodifiers ctrl+l
... Mozilla Firefox가 그 당시에 열려 있다고 가정할 때, 정확히 말한 대로 수행해야 합니다. 좋아요! 곧 보게 될 xdotool
과 같은 명령줄 도구를 호출하도록 Node.js 프로젝트를 얻는 것은 쉽습니다.
Node.js 백엔드 튜토리얼, 3단계: 기능 디자인
이것은 모든 사람에게 해당되는 것은 아니지만 개인적으로 많은 현대식 물리적 리모콘에는 내가 사용하게 될 것보다 약 5배 많은 버튼이 있다는 것을 알았습니다. 따라서 이 프로젝트에서 우리는 3x3 그리드의 멋지고 크고 대상 지정하기 쉬운 버튼이 있는 전체 화면 레이아웃을 보고 있습니다. 그 9개의 버튼이 무엇인지는 개인의 취향에 달려 있습니다.
Netflix, YouTube 및 Amazon Prime Video에서 가장 간단한 기능의 키보드 단축키도 동일하지 않은 것으로 나타났습니다. 또한 이러한 서비스는 기본 음악 플레이어 앱과 같은 일반 미디어 키와 함께 작동하지 않습니다. 또한 모든 서비스에서 특정 기능을 사용하지 못할 수 있습니다.
따라서 우리가 해야 할 일은 각 서비스에 대해 다른 원격 제어 레이아웃을 정의하고 이들 간에 전환하는 방법을 제공하는 것입니다.
원격 제어 레이아웃 정의 및 키보드 단축키에 매핑
소수의 사전 설정으로 작업하는 빠른 프로토타입을 만들어 보겠습니다. 둘 이상의 파일에서 가져온 이 데이터를 포함하기 때문에 common/preset_commands.js
—“common”에 둘 것입니다.
module.exports = { // We could use ️ but some older phones (eg, Android 5.1.1) won't show it, hence ️ instead 'Netflix': { commands: { '-': 'Escape', '+': 'f', '': 'Up', '⇤': 'XF86Back', '️': 'Return', '': 'Down', '': 'Left', '': 'Right', '': 'm', }, }, 'YouTube': { commands: { '⇤': 'shift+p', '⇥': 'shift+n', '': 'Up', 'CC': 'c', '️': 'k', '': 'Down', '': 'j', '': 'l', '': 'm', }, }, 'Amazon Prime Video': { window_name_override: 'Prime Video', commands: { '⇤': 'Escape', '+': 'f', '': 'Up', 'CC': 'c', '️': 'space', '': 'Down', '': 'Left', '': 'Right', '': 'm', }, }, 'Generic / Music Player': { window_name_override: '', commands: { '⇤': 'XF86AudioPrev', '⇥': 'XF86AudioNext', '': 'XF86AudioRaiseVolume', '': 'r', '️': 'XF86AudioPlay', '': 'XF86AudioLowerVolume', '': 'Left', '': 'Right', '': 'XF86AudioMute', }, }, };
키코드 값은 xev
를 사용하여 찾을 수 있습니다. (저의 경우 "오디오 음소거" 및 "오디오 재생" 항목은 이 방법으로 검색할 수 없었으므로 미디어 키 목록도 참조했습니다.)
독자는 space
과 Return
의 대소문자 차이를 알 수 있습니다. 이유에 xdotool
이 올바르게 작동하려면 이 세부 사항을 준수해야 합니다. 이와 관련하여 우리는 의도를 명확하게 유지하기 위해 명시적으로 작성된 몇 가지 정의가 있습니다(예: P
도 작동하더라도 shift+p
).
Node.js 백엔드 튜토리얼, 4단계: API의 "핵심" 엔드포인트(말장난 사면)
POST
에 대한 엔드포인트가 필요하며 xdotool
을 사용하여 키 입력을 시뮬레이션합니다. 보낼 수 있는 키 그룹이 다르기 때문에(서비스별로 하나씩) 특정 group
에 대한 엔드포인트를 호출합니다. route/users.js 의 이름을 routes/users.js
routes/group.js
변경하고 app.js
에서 해당 변경 사항을 적용하여 생성된 users
엔드포인트의 용도를 변경합니다.
// ... var indexRouter = require('./routes/index'); var groupRouter = require('./routes/group'); // ... app.use('/', indexRouter); app.use('/group', groupRouter); // ...
주요 기능은 routes/group.js
의 시스템 셸 호출을 통해 xdotool
을 사용하는 것입니다. 우리는 테스트 목적으로 YouTube
를 당분간 선택 메뉴로 하드 코딩할 것입니다.
const express = require('express'); const router = express.Router(); const debug = require('debug')('app'); const cp = require('child_process'); const preset_commands = require('../common/preset_commands'); /* POST keystroke to simulate */ router.post('/', function(req, res, next) { const keystroke_name = req.body.keystroke_name; const keystroke_code = preset_commands['YouTube'].commands[keystroke_name]; const final_command = `xdotool \ search "YouTube" \ windowactivate --sync \ key --clearmodifiers ${keystroke_code}`; debug(`Executing ${final_command}`); cp.exec(final_command, (err, stdout, stderr) => { debug(`Executed ${keystroke_name}`); return res.redirect(req.originalUrl); }); }); module.exports = router;
여기에서 keystroke_name
이라는 매개변수 아래 POST
요청의 본문( req.body
)에서 요청된 키 "이름"을 가져옵니다. 그것은 ️
와 같을 것입니다. 그런 다음 이를 사용하여 preset_commands['YouTube']
의 commands
개체에서 해당 코드를 찾습니다.
최종 명령은 둘 이상의 행에 있으므로 각 행 끝에 있는 \
s는 모든 부분을 단일 명령으로 결합합니다.
- "YouTube"를
search "YouTube"
하면 제목에 "YouTube"가 있는 첫 번째 창을 가져옵니다. -
windowactivate --sync
는 가져온 창을 활성화하고 키 입력을 받을 준비가 될 때까지 기다립니다. -
key --clearmodifiers ${keystroke_code}
는 키 입력을 전송하여 전송을 방해할 수 있는 Caps Lock과 같은 수정 키를 일시적으로 지웁니다.
이 시점에서 코드는 유효한 입력을 제공한다고 가정합니다. 이는 나중에 더 주의할 것입니다.
간단하게 하기 위해 코드는 제목에 "YouTube"가 포함된 응용 프로그램 창이 하나만 열려 있다고 가정합니다. 일치하는 항목이 두 개 이상인 경우 의도한 창에 키 입력을 보낼 것이라는 보장이 없습니다. 그게 문제라면 원격 제어할 창 이외의 모든 창에서 브라우저 탭을 전환하여 창 제목을 간단히 변경할 수 있는 것이 도움이 될 수 있습니다.
준비가 되면 서버를 다시 시작할 수 있지만 이번에는 디버깅이 활성화된 상태에서 debug
호출의 출력을 볼 수 있습니다. 그렇게 하려면 DEBUG=old-fashioned-remote:* yarn start
또는 DEBUG=old-fashioned-remote:* npm start
를 실행하기만 하면 됩니다. 실행되면 YouTube에서 비디오를 재생하고 다른 터미널 창을 열고 cURL 호출을 시도합니다.
curl --data "keystroke_name=️" http://localhost:3000/group
그러면 요청된 키 입력 이름이 있는 POST
요청을 포트 3000
의 로컬 머신으로 보냅니다. 이 포트는 백엔드가 수신 대기 중인 포트입니다. 해당 명령을 실행하면 npm
창에 Executing
및 Executed
에 대한 메모가 출력되어야 하며, 더 중요한 것은 브라우저를 불러오고 해당 비디오를 일시 중지해야 한다는 것입니다. 해당 명령을 다시 실행하면 동일한 출력이 제공되고 일시 중지가 해제되어야 합니다.
Node.js 백엔드 튜토리얼, 5단계: 다중 원격 제어 레이아웃
백 엔드가 아직 완료되지 않았습니다. 또한 다음을 수행할 수 있어야 합니다.
-
preset_commands
에서 원격 제어 레이아웃 목록을 생성합니다. - 특정 리모콘 레이아웃을 선택한 후 키스트로크 "이름" 목록을 생성합니다. (우리는 이미 JavaScript이기 때문에 프론트 엔드에서
common/preset_commands.js
를 직접 사용하도록 선택할 수도 있었고 거기에서 필터링되었습니다. 이것이 Node.js 백엔드의 잠재적인 이점 중 하나이며 여기서는 사용하지 않습니다. .)
이 두 기능 모두 Node.js 백엔드 튜토리얼이 우리가 빌드할 Pug 기반 프론트 엔드와 교차하는 곳입니다.
Pug 템플릿을 사용하여 원격 제어 목록 표시
방정식의 백엔드 부분은 다음과 같이 routes/index.js
를 수정하는 것을 의미합니다.
const express = require('express'); const router = express.Router(); const preset_commands = require('../common/preset_commands'); /* GET home page. */ router.get('/', function(req, res, next) { const group_names = Object.keys(preset_commands); res.render('index', { title: 'Which Remote?', group_names, portrait_css: `.group_bar { height: calc(100%/${Math.min(4, group_names.length)}); line-height: calc(100vh/${Math.min(4, group_names.length)}); }`, landscape_css: `.group_bar { height: calc(100%/${Math.min(2, group_names.length)}); line-height: calc(100vh/${Math.min(2, group_names.length)}); }`, }); }); module.exports = router;
여기에서는 preset_commands
파일에서 Object.keys
를 호출하여 원격 제어 레이아웃 이름( group_names
)을 가져옵니다. 그런 다음 res.render()
를 통해 자동으로 호출되는 Pug 템플릿 엔진에 필요한 다른 데이터와 데이터를 보냅니다.
여기에서 keys
의 의미 Object.keys
는 JavaScript에서 객체를 구성하는 키-값 쌍 의 모든 키 를 포함하는 배열(순서화된 목록)을 제공합니다.

const my_object = { 'a key' : 'its corresponding value' , 'another key' : 'its separate corresponding value' , };
common/preset_commands.js
를 보면 위의 패턴을 볼 수 있으며 키 (객체 의미에서)는 'Netflix'
, 'YouTube'
등의 그룹 이름입니다. 해당 값은 my_object
가 위에 있는 것과 같은 간단한 문자열은 자체 키, 즉 commands
및 가능한 window_name_override
가 있는 전체 개체 자체입니다.
여기에 전달되는 사용자 정의 CSS는 확실히 약간의 해킹입니다. 현대적인 플렉스박스 기반 솔루션을 사용하는 대신 이 솔루션이 필요한 이유는 훨씬 더 멋진 구형 버전에서 모바일 브라우저의 놀라운 세계와의 더 나은 호환성을 위해서입니다. 이 경우 주목해야 할 주요 사항은 가로 모드에서 화면당 두 개 이하의 옵션을 표시하여 버튼을 크게 유지한다는 것입니다. 세로 모드에서 4.
그러나 그것이 실제로 HTML로 변환되어 브라우저로 보내지는 곳은 어디입니까? 여기에서 views/index.pug
가 나타나며 다음과 같이 표시됩니다.
extends layout block header_injection style(media='(orientation: portrait)') #{portrait_css} style(media='(orientation: landscape)') #{landscape_css} block content each group_name in group_names span(class="group_bar") a(href='/group/?group_name=' + group_name) #{group_name}
첫 번째 줄이 중요합니다. extends layout
은 Pug가 이 파일을 views/layout.pug
컨텍스트에서 가져갈 것임을 의미합니다. 이는 여기에서 그리고 다른 보기에서도 재사용할 상위 템플릿의 일종입니다. 최종 파일이 다음과 같이 보이도록 link
라인 뒤에 몇 줄을 추가해야 합니다.
doctype html html head title= title link(rel='stylesheet', href='/stylesheets/style.css') block header_injection meta(name='viewport', content='user-scalable=no') body block content
여기서는 HTML의 기본 사항에 대해 설명하지 않겠지만 HTML에 익숙하지 않은 독자를 위해 이 Pug 코드는 거의 모든 곳에서 볼 수 있는 표준 요금 HTML 코드를 반영합니다. 그것의 템플릿 측면은 우리가 res.render
를 통해 Pug를 전달하는 객체의 title
키에 해당하는 값으로 HTML 제목을 설정하는 title= title
로 시작합니다.
header_injection
이름의 block
을 사용하여 나중에 두 줄을 템플릿화하는 다른 측면을 볼 수 있습니다. 이와 같은 블록은 현재 블록을 확장하는 템플릿으로 대체할 수 있는 자리 표시자입니다. (관련 없이 meta
라인은 단순히 모바일 브라우저에 대한 빠른 해결 방법이므로 사용자가 볼륨 컨트롤을 연속으로 여러 번 탭하면 전화가 확대 또는 축소되지 않습니다.)
block
으로 돌아가기: 이것이 views/index.pug
가 views/layout.pug
에서 찾은 동일한 이름으로 자체 block
을 정의하는 이유입니다. header_injection
의 경우 휴대전화가 들어갈 세로 또는 가로 방향에 특정한 CSS를 사용할 수 있습니다.
content
는 웹 페이지의 주요 보이는 부분을 두는 곳입니다. 이 경우에는 다음과 같습니다.
-
group_names
배열을 반복하여 전달합니다. - CSS 클래스
group_bar
가 적용된 각 요소에 대해<span>
요소를 생성하고, -
group_name
을 기반으로 각<span>
내에 링크를 생성합니다.
CSS 클래스 group_bar
는 views/layout.pug
, 즉 public/stylesheets/style.css
를 통해 가져온 파일에서 정의할 수 있습니다.
html, body, form { padding: 0; margin: 0; height: 100%; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; } .group_bar, .group_bar a, .remote_button { box-sizing: border-box; border: 1px solid white; color: greenyellow; background-color: black; } .group_bar { width: 100%; font-size: 6vh; text-align: center; display: inline-block; } .group_bar a { text-decoration: none; display: block; }
이 시점에서 npm start
가 여전히 실행 중이면 데스크톱 브라우저에서 http://localhost:3000/
으로 이동하면 Netflix 및 YouTube에 대한 두 개의 매우 큰 버튼이 표시되어야 하며 나머지는 아래로 스크롤하여 사용할 수 있습니다.
그러나 이 시점에서 클릭하면 링크가 연결되는 경로를 아직 정의하지 않았기 때문에 작동하지 않습니다( /group
의 GET
ting).
선택한 리모컨 레이아웃 표시
그렇게 하기 위해 우리는 이것을 routes/group.js
에 마지막 module.exports
라인 바로 앞에 추가할 것입니다:
router.get('/', function(req, res, next) { const group_name = req.query.group_name || ''; const group = preset_commands[group_name]; return res.render('group', { keystroke_names: Object.keys(group.commands), group_name, title: `${group_name.match(/([AZ])/g).join('')}-Remote` }); });
이렇게 하면 끝점으로 그룹 이름이 전송되고(예: /group/
끝에 ?group_name=Netflix
를 추가하여) 해당 그룹에서 commands
값을 가져오는 데 사용합니다. 해당 값( group.commands
)은 개체이고 해당 개체의 키는 원격 제어 레이아웃에 표시할 이름( keystroke_names
)입니다.
참고: 경험이 없는 개발자는 작동 방식에 대해 자세히 알아볼 필요가 없지만 title
값은 약간의 정규 표현식을 사용하여 그룹/레이아웃 이름을 약어로 변환합니다. 예를 들어 YouTube 리모컨에는 브라우저 제목이 있습니다. YT-Remote
. 그렇게 하면 전화에서 시도하기 전에 호스트 컴퓨터에서 디버깅하는 경우 제어하려는 창 대신 원격 제어 브라우저 창 자체를 잡는 xdotool
이 없을 것입니다. 한편, 우리의 전화기에서는 리모컨을 북마크에 추가하려는 경우 제목이 멋지고 짧을 것입니다.
이전에 res.render
를 만났을 때와 마찬가지로 이 데이터는 views/group.pug
템플릿과 섞이도록 데이터를 보냅니다. 우리는 그 파일을 생성하고 다음과 같이 채울 것입니다:
extends layout block header_injection script(type='text/javascript', src='/javascript/group-client.js') block content form(action="/group?group_name=" + group_name, method="post") each keystroke_name in keystroke_names input(type="submit", name="keystroke_name", value=keystroke_name, class="remote_button")
views/index.pug
와 마찬가지로 views/layout.pug
의 두 블로그를 재정의합니다. 이번에는 헤더에 넣는 것은 CSS가 아니라 클라이언트 측 JavaScript입니다. 곧 다루게 될 것입니다. (그리고 예, 끈질긴 순간에 잘못 복수화된 javascripts
의 이름을 바꿨습니다...)
여기의 주요 content
은 각 keystroke_name
에 대해 하나씩, 여러 제출 버튼으로 구성된 HTML 양식입니다. 각 버튼은 양식과 함께 보내는 값으로 표시되는 키 입력 이름을 사용하여 양식을 제출합니다( POST
요청 작성).
또한 기본 스타일시트 파일에 CSS가 조금 더 필요합니다.
.remote_button { float: left; width: calc(100%/3); height: calc(100%/3); font-size: 12vh; }
이전에 끝점을 설정할 때 다음을 사용하여 요청 처리를 완료했습니다.
return res.redirect(req.originalUrl);
이는 브라우저가 양식을 제출할 때 Node.js 백엔드가 양식이 제출된 페이지, 즉 기본 원격 제어 레이아웃으로 돌아가도록 브라우저에 지시하여 응답한다는 것을 의미합니다. 페이지를 전환하지 않고도 더 우아할 것입니다. 그러나 우리는 낡아빠진 모바일 브라우저의 이상하고 멋진 세계와 최대한의 호환성을 원합니다. 이런 식으로 프론트 엔드 JavaScript가 전혀 작동하지 않더라도 Node.js 백엔드 프로젝트 는 여전히 작동해야 합니다.
프런트 엔드 JavaScript의 대시
양식을 사용하여 키 입력을 제출할 때의 단점은 브라우저가 대기한 다음 추가 왕복을 실행해야 한다는 것입니다. 그런 다음 페이지와 해당 종속성을 Node.js 백엔드에서 요청하고 전달해야 합니다. 그런 다음 브라우저에서 다시 렌더링해야 합니다.
독자들은 이것이 얼마나 많은 영향을 미칠지 궁금해 할 것입니다. 결국 페이지는 작고 종속성이 극히 적으며 최종 Node.js 프로젝트는 로컬 Wi-Fi 연결을 통해 실행됩니다. 대기 시간이 짧은 설정이어야 합니다. 맞나요?
적어도 Windows Phone 8.1 및 Android 4.4.2를 실행하는 구형 스마트폰에서 테스트할 때 그 효과는 불행히도 빠르게 탭하여 재생 볼륨을 몇 단계 높이거나 낮추는 일반적인 경우에서 상당히 눈에 띄게 나타납니다. HTML 양식을 통한 수동 POST
의 우아한 폴백에서 벗어나지 않고 JavaScript가 도움이 될 수 있는 부분은 다음과 같습니다.
이 시점에서 우리의 최종 클라이언트 JavaScript( public/javascript/group-client.js
)는 더 이상 지원되지 않는 이전 모바일 브라우저와 호환되어야 합니다. 그러나 우리는 많은 것이 필요하지 않습니다.
(function () { function form_submit(event) { var request = new XMLHttpRequest(); request.open('POST', window.location.pathname + window.location.search, true); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.send('keystroke_name=' + encodeURIComponent(event.target.value)); event.preventDefault(); } window.addEventListener("DOMContentLoaded", function() { var inputs = document.querySelectorAll("input"); for (var i = 0; i < inputs.length; i++) { inputs[i].addEventListener("click", form_submit); } }); })();
여기서 form_submit
함수는 비동기 호출을 통해 데이터를 전송하고 마지막 줄은 브라우저의 정상적인 전송 동작을 방지하여 서버 응답에 따라 새 페이지가 로드됩니다. 이 스니펫의 후반부는 페이지가 로드될 때까지 기다린 다음 모든 제출 버튼을 연결하여 form_submit
을 사용합니다. 모든 것이 IIFE에 싸여 있습니다.
최종 터치
Node.js 백엔드 튜토리얼 코드의 최종 버전에는 대부분 더 나은 오류 처리를 목적으로 위의 스니펫에 많은 변경 사항이 있습니다.
- Node.js 백엔드는 이제 그룹 이름과 그룹 이름을 확인하고 그룹 이름이 존재하는지 확인합니다. 이 코드는
routes/group.js
의GET
및POST
함수 모두에 재사용되는 함수에 있습니다. - 그렇지 않은 경우 Pug
error
템플릿을 사용합니다. - 프론트 엔드 JavaScript 및 CSS는 이제 서버의 응답을 기다리는 동안 일시적으로 버튼 윤곽선을 회색으로 만들고, 신호가
xdotool
을 통해 문제 없이 끝까지 전달되자마자 녹색으로, 예상대로 작동하지 않으면 빨간색으로 버튼을 만듭니다. . - Node.js 백엔드는 스택 트레이스가 죽으면 스택 추적을 인쇄합니다. 위의 경우에는 그럴 가능성이 적습니다.
독자는 GitHub에서 전체 Node.js 프로젝트를 정독(및/또는 복제)할 수 있습니다.
Node.js 백엔드 튜토리얼, 5단계: 실제 테스트
이제 npm start
와 영화 또는 음악 플레이어를 실행하는 호스트와 동일한 Wi-Fi 네트워크에 연결된 실제 전화에서 시도해 볼 시간입니다. 스마트폰의 웹 브라우저가 호스트의 로컬 IP 주소(접미사 :3000
이 붙음)를 가리키면 됩니다. hostname -I | awk '{print $1}'
호스트의 터미널에서 hostname -I | awk '{print $1}'
.
Windows Phone 8.1 사용자가 알아차릴 수 있는 한 가지 문제는 192.168.2.5:3000
과 같은 항목으로 이동하려고 하면 오류 팝업이 표시된다는 것입니다.
고맙게도 낙담할 필요는 없습니다. 단순히 http://
를 접두사로 붙이거나 뒤에 /
를 추가하면 추가 불만 없이 주소를 가져올 수 있습니다.
거기에서 옵션을 선택하면 작동하는 리모컨으로 이동해야 합니다.
추가 편의를 위해 사용자는 라우터의 DHCP 설정을 조정하여 항상 동일한 IP 주소를 호스트에 할당하고 레이아웃 선택 화면 및/또는 즐겨찾는 레이아웃을 북마크에 추가할 수 있습니다.
풀 리퀘스트 환영
모든 사람이 이 프로젝트를 있는 그대로 좋아하지는 않을 것입니다. 다음은 코드를 더 자세히 살펴보고 싶은 사람들을 위해 개선을 위한 몇 가지 아이디어입니다.
- 레이아웃을 조정하거나 Disney Plus와 같은 다른 서비스를 위해 새 레이아웃을 추가하는 것은 간단해야 합니다.
- 아마도 일부는 "조명 모드" 레이아웃과 전환 옵션을 선호할 것입니다.
- 되돌릴 수 없기 때문에 Netflix에서 물러나면 실제로 "확실합니까?"를 사용할 수 있습니다. 일종의 확인.
- 이 프로젝트는 Windows 지원의 이점을 확실히 누릴 것입니다.
-
xdotool
의 문서에는 OSX가 언급되어 있습니다. 이 프로젝트가 최신 Mac에서 작동합니까? - 고급 라운지의 경우 Netflix/Amazon Prime Video 영화를 하나 선택하거나 컴퓨터에서 YouTube 재생 목록을 만드는 대신 영화를 검색하고 탐색하는 방법입니다.
- 제안된 변경 사항으로 인해 원래 기능이 중단되는 경우를 대비하여 자동화된 테스트 제품군.
이 Node.js 백엔드 튜토리얼과 결과적으로 향상된 미디어 경험을 즐겼기를 바랍니다. 즐거운 스트리밍과 코딩!