js에서 버튼을 클릭하면 메뉴가 표시되고 다시 누르면
메뉴가 사라지는 것에 대한 내용을 예제를 통해 정리한다.
버튼 클릭 시, 오른쪽에 숨겨져있던 메뉴가 표시된다.
다시 클릭하면 메뉴가 들어가는 간단한 예제이다.
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>숨김 메뉴(drawer menu) 만들기 예제</title>
</head>
<body>
<button id="drawer-opener">OPEN MENU</button>
<div class="drawer">
<h2>숨김 메뉴</h2>
<ul>
<li>항목 1</li>
<li>항목 2</li>
</ul>
</div>
<script>
function Drawer(el, open = false) { // A
this.el = el;
this.isOpen = open;
Object.assign(this.el.style, {
display: 'block',
position: 'fixed',
top: 0,
bottom: 0,
right: 0,
width: '200px',
padding: '10px',
backgroundColor: 'white',
boxShadow: '0 0 36px 0 rgba(0,0,0,0.1)',
transition: 'all 0.4s ease-out'
});
(this.isOpen) ? this.open() : this.close();
}
Drawer.prototype.open = function() { // B
this.isOpen = true;
this.el.style.transform = 'translate(0px)';
}
Drawer.prototype.close = function() {
this.isOpen = false;
this.el.style.transform = 'translate(220px)';
}
const sideMenu = new Drawer(document.querySelector('.drawer')); // C
document.getElementById('drawer-opener')
.addEventListener('click', e => {
(!sideMenu.isOpen) ? sideMenu.open() : sideMenu.close();
});
</script>
</body>
</html>
위에 주석친 부분을 문단단위로 정리한다.
[A] Drawer()메소드를 정의한다. 숨김메뉴가 적용될 요소와 메뉴의 초기 열림상태를 전달받는다.
Object.assign()메소드를 통해 메뉴가 숨겨진 상태의 스타일 값을 지정한다.
메뉴의 초기 열림상태에 따라 prototype으로 정의한 메소드를 실행한다. (true면 open, false면 close)
메뉴의 초기 열림상태의 Default값은 false이다.
[B] Drawer()메소드를 prototype으로 정의한 open()메소드는 transform값을 이용해서 x축으로 0픽셀 이동하여 화면에 표시한다.
Drawer()메소드를 prototype으로 정의한 close()메소드는 transform값을 이용해서 x축으로 220픽셀 이동하여 화면에 표시한다.
[C] 숨김메뉴를 적용하기 위해 'drawer'를 클래스로 갖는 요소를 Drawer() 메소드로 전달하여 인스턴스를 생성한다.
'drawer-opener'를 id로 갖는 요소에 클릭 이벤트 리스너를 등록한다.
해당 요소를 클릭했을 경우 Drawer()를 통해 생성한 인스턴스의 변수 isOpen값이
false면(즉, 메뉴가 닫혀 있으면 open 하고) isOpen값이 true면(즉, 메뉴가 열려 있으면 close 한다.)
js에서 커스텀 이벤트에 대한 내용을 예제를 통해 정리한다.
주문하기 버튼 클릭 시, 로그인을 해달라는 문구가 표시 된 영역이 생성된다.
이 영역의 닫기버튼을 눌렀을 때 커스텀이벤트가 발생되는 간단한 예제이다.
example.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>사용자 이벤트 생성하기 예제</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="order-area">
<div>상품정보: 노트북 1대</div>
<button id="order-btn">주문하기</button>
</div>
<script>
function buildAlert(title, message) { // A
const alert = document.createElement('div');
const id = Math.ceil(Math.random() * 1000);
alert.id = id;
alert.className = 'alert';
alert.innerHTML = `<span class="close">×</span>
<h3>${title}</h3>
<p>${message}</p>`;
alert.querySelector('span.close').addEventListener('click', e => { // B
const closeEvt = new CustomEvent('close', { bubbles: true,
detail: {id, message} });
alert.dispatchEvent(closeEvt);
alert.remove();
});
document.body.append(alert); // C
return alert;
}
document.getElementById("order-btn").addEventListener('click', e => {
const alertE1 = buildAlert('에러', '로그인을 해주세요.');
alertE1.addEventListener('close', e => {
console.log(e.detail);
console.log('error 창을 닫았습니다.');
})
});
</script>
</body>
</html>
위에 주석친 부분을 문단단위로 정리한다.
[A] 알림창을 생성하는 메소드를 정의한다.
createElement() 메소드를 통해 div를 생성한다.
이 알림창의 고유키를 부여하기 위해 랜덤번호를 부여한다.
×(특수문자 'x')를 통해 div내부에 닫기버튼을 표시한다.
[B] 닫기버튼에 클릭 이벤트 리스너를 등록한다.
new키워드를 통해 CustomEvent()메소드로 커스텀이벤트 인스턴스를 생성한다.
생성할 때, 이벤트명과(close) 옵션객체(고유번호 및 오류문구)를 매개변수로 전달한다.
dispatchEvent()메소드를 통해 이벤트 발생 시, 커스텀이벤트가 발생되게 한다.
커스텀이벤트가 발생되면 remove()메소드를 통해 해당 알림창이 삭제된다.
[C] 알림창을 body의 가장 아래에 추가한다.
위에 추가해도 되고 아래에 추가해도 되는데 append()를 통해 아래에 추가하였다.
이것과 유사한 메소드의 특징은 다음과 같다.
append() - 콘텐츠를 선택한 요소 내부의 끝 부분에서 삽입
prepend() - 콘텐츠를 선택한 요소 내부의 시작 부분에서 삽입
after() - 선택한 요소 뒤에 컨텐츠 삽입
before() - 선택된 요소 앞에 컨텐츠 삽입
https://teddy8.github.io/2019/08/13/NODE-api-get/
지난 포스팅에서 간단하게 GET요청을 할 때 http의 get()메소드를 사용했다.
이번에는 더 직관적으로 사용할 수 있는 request로 요청하는 방법을 예제를 통해 정리한다.
테스트할 url을 간단히 설명하면
'uinames.com/api' 라는 api url에서 테스트를 진행한다.
region에 'korea'를 넣으면 그 지역에 해당하는 데이터만,
amount에 적은 숫자로 반환 될 데이터의 양을 설정할 수 있다.
const request = require('request');
const options = {
url : 'http://uinames.com/api',
json : true,
qs : {
region: 'korea',
amount: 3
}
};
request.get(options, (err, res, result) => {
if (err) return console.log('err', err);
if (res && res.statusCode >= 400) return console.log(res.statusCode);
result.forEach(person2 => {
console.log(`${person2.name}${person2.surname} 님의 성별은 ${person2.gender}입니다.`);
});
});
request 모듈을 npm으로 설치한 뒤, requeire로 가져온다.
url은 'uinames.com/api'이며,
json을 'true'로 설정해 json형태로 읽어들인다.
qs에 region: 'korea', amount: 3을 넣음으로 써
url뒤에 'uinames.com/api?region=korea&amount' 이런식으로 붙여서 요청하게 된다.
request.get()메소드를 통해 설정한 객체값을 넣어주고
상태코드가 400이상이거나(비정상), 에러 유무를 확인한다.
그 후, result변수로 response받은 내용을 하나씩 꺼내어 출력한다.
출력결과
탁예원님의 성별은 female입니다.
곽영철님의 성별은 male입니다.
모민지님의 성별은 female입니다.
추가로 헤더값을 설정할 수 있으며,
POST요청, 이미지전송, 비동기처리도 가능하다.
더 자세한 사항은 공식문서에서 확인할 수 있다.
공식문서
https://github.com/request/request#readme
https://github.com/request/request-promise-native
node.js에서 request와 cheerio를 이용하여 크롤링하는 방법을 예제를 통해 정리한다.
테스트에 사용할 사이트는 위키백과의 HTML 페이지 이다.
목차를 보면 1. 역사, 1.1 개발 1.2 최종 규격 등등이 적힌 것을 확인할 수 있다.
여기서 역사, 개발, 최종 규격같이 숫자를 제외한 한글만 수집한다.
크롬의 F12 개발자 도구를 통해 확인해보면 한글 부분은 모두
span이라는 태그에 class명이 'toctext'라는 공통점이 있다는 것을 확인할 수 있다.
const cheerio = require('cheerio');
const request = require('request');
request('https://ko.wikipedia.org/wiki/HTML', (err, res, html) => {
if (err) return console.log(err);
if (res && res.statusCode >= 400) return console.log(res.statusCode);
const $ = cheerio.load(html);
console.log($('span[class=toctext]').text());
});
npm으로 설치한 cheerio와 request 외부 모듈을
reuqest()메소드를 통해 특정 url을 설정하여 실행한 후,
비정상 상태코드(res.statusCode 400 이상) 및 에러반환을 하지 않았다면,
필요한 정보만 골라내기 위해 cheerio모듈의 load()메소드를 통해
response 받은 내용이 담긴 html변수를 넣어주면 반환값을 통해
셀렉터(Selector)형식으로 원하는 내용을 쉽게 접근할 수 있다.
'span[class=toctext]'의 text()메소드를 통해 출력한 결과는 같다.
출력결과
역사개발최초 규격표준 버전의 역사HTML 버전 스케줄HTML 초안 버전 스케줄XHTML 버전마크업HTML 요소HTML 요소의 일반적인 형태HTML 요소의 가장 보편적인 형태태그의 기본적인 형태단락 구획주석 사용HTML에서 사용되는 마크업 요소의 형태주요 HTML 요소들속성데이터 형식문서 형식 선언시맨틱 웹전송HTTPHTML 전자 우편명명 규칙HTML 애플리케이션위지위그 편집기같이 보기각주외부 링크
참고로 크롤링의 난이도는 사이트의 구조에 따라서 천차만별이다.
만약 전달받은 값이 인코딩으로 인해 깨진 다면 iconv 모듈을 통해 인코딩의 타입을 변환하여 해결해야한다.
예를들어 해당 페이지의 인코딩 방식이 'CP949' 경우 아래와 같이 'UTF8'로 변환할 수 있다.
const Iconv = require('iconv').Iconv;
const iconv = new Iconv('CP949', 'utf-8//translit//ignore');
const html = iconv.convert(result).toString();
Node.js에서 npm에 대해 정리한다.
npm은 node package manager의 줄임말이다.
Node.js를 설치하면 npm은 기본적으로 설치된다.
파이썬에 pip, 자바에 Maven이 있다면 자바스크립트에는 npm이 있다.
더 자세하게 설명하면 다음과 같다.
프로그래밍에서 사용하게 되는 라이브러리와 패키지들을 관리한다.
자신만의 패키지를 간편하게 생성/관리할 수 있다.
남이 만든 패키지를 가져올 수 있으며 자신이 만든 패키지를 공유할 수도 있다.
npm install npm@6.4.1 -g
특정 버전 설치
npm update -g npm
최신 버전 설치
npm -v
현재 버전 확인
npm init
패키지에 필요한 기본 파일들을 자동 생성한다.
패키지이름,버전,설명 등의 설정을 지정할 수 있는데
기본 값으로 하고 싶다면 그냥 enter만 계속 누르면 된다.
완료되면 package.json파일과 node_modules폴더가 생성된다.
npm install <패키지명>
원하는 패키지를 다운 받을 수 있다.
npm install <패키지명> --save를 하면 package.json파일의
dependencies속성에 자동으로 버전 정보가 기록된다.
npm install
어떤 프로젝트에 이미 package.json 파일이 작성되있다면
npm install 명령어만 실행하면 된다.
그럼 package.json파일의 dependencies속성 정보를 읽어서
지정된 패키지들을 자동으로 설치한다
더 자세한 사항은 공식문서에서 확인할 수 있다.
공식문서 : https://www.npmjs.com
Node.js에서 api를 작성하는 방법을 예제를 통해 정리한다.
api는 기본적으로 요청/응답한다.
이번에는 POST 메소드를 통한 요청/응답하는 api이다.
example.js
"use strict";
const http = require('http');
const qs = require('querystring');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
switch (req.method) {
case 'POST':
let body = '';
req.on('data', (chunk) => { // A
body += chunk;
});
req.on('end', () => { // B
const obj = qs.parse(body);
res.writeHead(200);
res.end(JSON.stringify(obj));
});
req.on('error', (err) => {
console.error(err.stack);
});
break;
default:
res.end();
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
GET 요청과 다르게 POST 요청시엔 이벤트리스너를 통해 바디데이터를 주고 받는다.
위에 주석친 부분을 문단단위로 정리한다.
[A] on()메소드를 통해 'data'로 이벤트 등록하고
chunk(덩어리)로 전달받은 문자형 데이터를 덧셈 연산으로 받아준다.
[B] on()메소드를 통해 'end'로 이벤트 등록한다. (요청 전송이 완료되는 시점의 이벤트)
'data' 이벤트로 수집했던 문자열들은 querystring의 parse()메소드를 통해 객체 형식으로 파싱한다.
정상적으로 전달이 완료 된 경우 응답 상태 코드 200 반환하며,
res.end() 메소드를 통해 응답 전송을 완료한다.
GET 요청은 웹 브라우저에 url을 입력해서 호출하였다.
POST 요청은 'Postman'이라는 Tool을 사용하면 유용하다.
다운로드 링크 : https://www.getpostman.com/downloads/
Untitled Request밑에 요청형태를 "POST"로 바꾸고
url을 입력한다.(http://localhost:3000)
Body의 "x-www-form-urlencoded"를 선택하고
KEY와 VALUE에 값을 입력한 후
(a1과 1, a2와 2를 입력했다)
"Send"버튼을 누르면 보내진다.
그럼 아래의 영역에서 전달받은 내용이 표시된다.
({"a1":1,"a2":2})