이번에는 쿠키와 세션에 서버 데이터를 담아 전달하는 방법에 대해 알아보겠습니다.

1. 개념 : 쿠키와 세션 모두 사용자의 데이터를 담을 수 있습니다. 하지만 가장 큰 차이점은

쿠키는 클라이언트에 쿠키가 저장이 되어 보안에 취약합니다.

세션은 서버에 저장되어 쿠키에 비해 보안적으로 안전합니다.

1. 쿠키 저장해 보기

// http 모듈 import
const http = require('http');
// 미리 생성한 html 파일을 읽기 위한 fs 모듈 임포트
const fs = require('fs');

const server = http.createServer((req, res) => { // req : 요청, res : 응답
    // 쿠키를 지정 : 키 = 값 형식으로 ; 를 기준으로 설정
    res.writeHead(200, {'Set-Cookie' : 'mycookie=value1'});
    res.writeHead(200, {'Set-Cookie' : 'mycookie2=value2'});
    
    res.end('cookie save test');
});

server.listen(8081, () => {
    console.log('8081 server is lisening');
});

node app.js 로 서버 실행 후 http://localhost:8081/ 로 브라우저를 열고 F12 개발자 도구를 켠 다음 'application'탭을 보면 설정한 쿠키값들이 보임을 알 수 있다.

mycookie = value1

mycookie2 = value2

 

이번엔 쿠키를 이용해 간단한 로그인을 구현해 보도록 하겠다.

로그인 페이지에서 입력한 사용자의 이름을 쿠키에 name=hyr 처럼 저장한 후 쿠키값이 있을 경우 hyr님 반갑습니다.를 응답한다.

<app.js>

// http 모듈 import
const http = require('http');
// 미리 생성한 html 파일을 읽기 위한 fs 모듈 임포트
const fs = require('fs');
const url = require('url');
const qs = require('querystring');

// 쿠키 파싱 함수
const parseCookies = (cookie = '') => {
    // cookie => mycookie=value1;mycookie2=value2
    
    // eachCookies = [mycookie=value1, mycookie2=value2]
    let eachCookies = cookie.split(';');
    // [ [mycookie, value1], [mycookie2, value2] ]
    return eachCookies.map(e => e.split('='))
                      .reduce((acc, [key, val]) => { // acc : 누적
                          acc[key.trim()] = decodeURIComponent(val); // acc에 동적으로 key값에 value추가
                          return acc;
                      }, {});    
}
    
const server = http.createServer((req, res) => { // req : 요청, res : 응답
    // 쿠키 접근(req.headers.cookie)
    console.log(req.headers.cookie); // 문자열이기 때문에 파싱이 필요
    
    // 쿠키 파싱 함수를 통해 쿠키객체 얻어옴
    const cookies = parseCookies(req.headers.cookie);
  
    // req.url > 요청한 url 주소가 담겨있다.
    if(req.url.startsWith('/login')){ // /login으로 시작하는 url요청일 경우
        // http://localhost:8081/login?name=sooingkr 에서 ?name=sooingkr 부분인 쿼리스트링 부분을 가져온다.
        // 해당 정보가 객체로 query에 들어오게 됨
        const { query } = url.parse(req.url); 
        const { name } = qs.parse(query); // querystring 모듈로 name값을 파싱함

        // 저장할 쿠키 데이터의 유효시간을 지정하기 위함
        const expires = new Date();
        expires.setMinutes(expires.getMinutes() + 5); // 제한 시간 설정
        res.writeHead(302, // 302 코드 > redirection코드로 Location에 지정한 곳으로 리다이렉션한다. 
            {
                Location : '/',
                // expire 유효시간 Http통신 요청만 가능, / 요청에 대해서만 등 다양한 옵션을 설정할 수 있다.
                'Set-Cookie' : `name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()}; HttpOnly; Path=/`
            }
        );

        res.end('<p>end</p>'); // 요청 응답 끝
    } else if(cookies.name) { // 로그인을 통해 쿠키에 name값이 존재하면
        
        res.writeHead(200, {'Content-Type':'text/html; charset=utf-8'});
        // 쿠키에 저장된 name값을 응답
        res.end(`${cookies.name}님 안녕하세요`);
    } else { // 로그인 페이지
        // 로그인 페이지 html 을 읽어 로그인 페이지로 이동
        fs.readFile('./server2.html', (err,data) => {
            res.end(data);
        });
    }
});

server.listen(8081, () => {
    console.log('8081 server is lisening');
});

 

<server2.html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>로그인 페이지</title>
</head>
<body>
    <h1>로그인페이지 입니다.</h1>
    <form action="/login" method="GET">
        <input type="text" id="name" name="name" />
        <button type="submit">로그인</button>
    </form>
</body>
</html>

<결과>

로그인 페이지(server2.html)

로그인 후 화면

 

세션은 다음 페이지에서 이어 설명하도록 하겠습니다.

 

[   Node 객체에 대하여(NODE 객체와 NODE객체 컨트롤하기)   ]



-> 자바스크립트의 모든 DOM ELEMENT들은 최상위로 NODE를 상속하고 있기 때문에 NODE가 가지고 있는 속성을 사용할 수 있다.


Node 객체는 Node 간의 관계 정보를 담고 있는 일련의 API를 가지고 있다. 다음은 관계와 관련된 프로퍼티들이다.


[ 1. Node의 자식 및 형제 Node에 접근하는 프러퍼티 ]

  • Node.childNodes
        자식노드들을 유사배열에 담아서 리턴한다.
  • Node.firstChild
        첫번째 자식노드
  • Node.lastChild
        마지막 자식노드
  • Node.nextSibling
        다음 형제 노드
  • Node.previousSibling
        이전 형제 노드

-> 이렇게 노드에 접근할 때 중요한 점은 줄바꿈 텍스트 또한 NODE를 상속하기 때문에 자식으로 가져올 때 주의해야 한다는 점이다. 아래의 크롬브라우저의 테스트 창을 보면서
    이해하기 바란다

   EX) Crome Browser 개발자도구(F12) console창에서 테스트하는 예
<body id="start">
<ul>
<li><a href="./532">html</a></li>
<li><a href="./533">css</a></li>
<li><a href="./534">JavaScript</a>
<ul>
<li><a href="./535">JavaScript Core</a></li>
<li><a href="./536">DOM</a></li>
<li><a href="./537">BOM</a></li>
</ul>
</li>
</ul>
</body>





[    2. Node의 타입을 알 수 있는 nodeType속성과 Node 이름을 알 수 이는 nodeName 속성    ]


노드 작업을 하게 되면 현재 선택된 노드가 어떤 타입인지를 판단해야 하는 경우가 있다. 이런 경우에 사용할 수 있는 API가 nodeType, nodeName이다. 


  • Node.nodeType
        node의 타입을 의미한다.  -> 타입값은 숫자로 나오게 된다. 주로 1(element), 3(TextNode), 9(document node) 를 주로 사용하게 된다.
  • Node.nodeName
        node의 이름 (태그명을 의미한다.)


  [ nodeType의 종류 ]


EX)


-> nodeType의 경우 1,2,3 숫자를 기억하기 어려울 수 있음으로 상수로 이를 대체하여 사용할 수도 있다.

EX)



[    노드 추가관련 프러퍼티    ]

노드의 추가와 관련된 API들은 아래와 같다.

노드를 추가하기 위해서는 추가할 엘리먼트를 생성해야 하는데 이것은 document 객체의 기능이다. 아래 API는 노드를 생성하는 API이다.



[    노드 제거    ]

노드 제거를 위해서는 아래 API를 사용한다. 이 때 메소드는 삭제 대상의 부모 노드 객체의 것을 실행해야 한다는 점에 유의하자.






[    노드 바꾸기    ]

노드 바꾸기에는 아래 API가 사용된다.



<ul>
<li>HTML</li>
<li>CSS</li>
<li id="target">JavaScript</li>
</ul>
<input type="button" onclick="callReplaceChild();" value="replaceChild()" />
<script>
function callReplaceChild(){
var a = document.createElement('a');
a.setAttribute('href', 'http://opentutorials.org/module/904/6701');
a.appendChild(document.createTextNode('Web browser JavaScript'));
var target = document.getElementById('target');
target.replaceChild(a,target.firstChild); // 새로 만든 a태그를 target의 첫번째 자식 엘리먼트와 교체한다.(즉 텍스트 JavaScript를 대체)
}
</script>



문자열로 노드 제어



위의 예들은 Node 객체를 생성한 뒤 제어했지만, 문자열로 붙이고 지우고 등을 할 수 있다. 아래는 그와 관련된 프러퍼티와 메서드이다.

1. innerHTML

innerHTML는 문자열로 자식 노드를 만들 수 있는 기능을 제공한다. 또한 자식 노드의 값을 읽어올 수도 있다. 


2. outerHTML

outerHTML은 선택한 엘리먼트를 포함해서 문자열로 가지고 오거나, 자신을 포함해서 문자열로 노드를 대체할 수 있다.


3. insertAdjacentHTML()

좀 더 정교하게 문자열을 이용해서 노드를 변경하고 싶을 때 사용한다.


EX) innerHTML

<ul id="target">
<li>HTML</li>
<li>CSS</li>
</ul>
<input type="button" onclick="get();" value="get" />
<input type="button" onclick="set();" value="set" />
<script>
function get(){
var target = document.getElementById('target');
alert(target.innerHTML); // target 내부의 HTML과 CSS li를 가지고 오게 된다.(문자열로)
}
function set(){
var target = document.getElementById('target');
target.innerHTML = "<li>JavaScript Core</li><li>BOM</li><li>DOM</li>";
}
</script>


EX) outerHTML

<ul id="target">
<li>HTML</li>
<li>CSS</li>
</ul>
<input type="button" onclick="get();" value="get" />
<input type="button" onclick="set();" value="set" />
<script>
function get(){
var target = document.getElementById('target');
alert(target.outerHTML); // target 전체를 가지고 오게 된다.(문자열로)
}
function set(){
var target = document.getElementById('target');
target.outerHTML = "<ol><li>JavaScript Core</li><li>BOM</li><li>DOM</li></ol>";
// ul태그 전체가 통째로 ol로 대체되게 된다.
}
</script>


EX) insertAdjacentHTML(arg1, arg2)

<ul id="target">
<li>CSS</li>
</ul>
<input type="button" onclick="beforebegin();" value="beforebegin" />
<input type="button" onclick="afterbegin();" value="afterbegin" />
<input type="button" onclick="beforeend();" value="beforeend" />
<input type="button" onclick="afterend();" value="afterend" />
<script>
function beforebegin(){
var target = document.getElementById('target');
target.insertAdjacentHTML('beforebegin','<h1>Client Side</h1>'); // 맨 첫번째 자식 앞에 삽입
}
function afterbegin(){
var target = document.getElementById('target');
target.insertAdjacentHTML('afterbegin','<li>HTML</li>'); // 첫번째 자식 뒤에 삽입
}
function beforeend(){
var target = document.getElementById('target');
target.insertAdjacentHTML('beforeend','<li>JavaScript</li>'); // 끝 자식 전에 삽입
}
function afterend(){
var target = document.getElementById('target');
target.insertAdjacentHTML('afterend','<h1>Server Side</h1>'); // 끝 자식 뒤에 삽입
}
</script>


+ Recent posts