ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 4. HTTP 프로토콜, 쿠키와 세션
    Node.js 2022. 2. 14. 00:46
    <목차>

    1. HTTP 프로토콜
        1-1. HTTP 프로토콜이란?
        1-2. request, response
        1-2. Connectionless & Stateless
    2. 쿠키
        2-1. 쿠키는 무엇이고 왜 필요할까?
        2-2. 쿠키를 생성하는 방법
    3. 세션
        3-1. 세션은 무엇이고 쿠키와는 무슨 차이일까?
        3-2. 세션을 사용해야 하는 이유
        3-3. 세션을 생성하는 방법

     

     

    1. HTTP 프로토콜

    1-1. HTTP 프로토콜이란?

    HTTP ( Hypertext Transfer Protocol)
    : 인터넷 상에서 데이터를 주고받기 위해 서버/클라이언트 모델을 따르는 프로토콜(규약)

    HTTP는 어떤 종류의 데이터든 상관없이 모두 전송할 수 있다. HTML 문서, 텍스트, 이미지, 동영상, 오디오 등등 모두!

    여러 종류의 데이터를 hypertext(=링크)로 Transfer(전송)해줄 수 있도록 만들어진 Protocol(체계이자 약속)인 것이다.

    이 약속은 서버/클라이언트 모델을 따른다.

    클라이언트(브라우저, 사용자)에서 요청을 보내고 서버는 그 요청을 받아 처리 후 응답을 보내는 방식이라는 말이다.

     

    HTTP 프로토콜 = 서버와 클라이언트 간의 요청-응답

     

     

    1-2. request, response 형식

    서버와 클라이언트 간의 요청과 응답은 메세지(텍스트)로 주고받는다.

    메세지의 구조는 아래와 같다. 크게 헤더와 바디로 나눠진다. 

    1. Start-line (시작라인, 첫 줄)
    2. Header 👈 데이터 전송에 필요한 부가 정보 (브라우저 개발자도구 - 네트워크 탭에서 확인가능)
    3. (공백줄) : 헤더와 바디를 구분하기위해
    4. Body 👈 실제로 전송할 데이터

     

    -request

    GET / HTTP/3
    Host: www.google.com
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.5,en;q=0.3
    ...
    (공백)
    BODY

    요청헤더의 첫 줄에는 HTTP Method (GET/POST), 요청대상(경로), HTTP버전의 정보가 담겨있다.

    바디에는 post, put 요청을 보낼 때 데이터가 담겨있다. (get, delete 요청시는 불필요함)

     

    -response

    HTTP/3 200 OK
    accept-ranges: bytes
    content-type: image/png
    cross-origin-resource-policy: cross-origin
    date: Sat, 12 Feb 2022 10:58:54 GMT
    expires: Sat, 12 Feb 2022 10:58:54
    ...
    (공백)
    BODY

    응답헤더의 첫 줄에는 HTTP버전의 정보, 상태코드, 상태문구가 있다.

    ❗️상태 코드: 200(성공), 300(리다이렉션), 400(클라이언트 오류), 500(서버 오류)

    response body에는 랜더링할 페이지의 컨텐츠가 들어가게 된다 (html)

     

     

     

    1-3. Connectionless & Stateless

    HTTP프로토콜의 특징으로 Connectionless와 Stateless가 있다.

    • Connectionless(비연결 지향) : 클라이언트가 요청을 하고 해당 요청에 대한 응답을 서버에서 받고나면 클라이언트와 서버의 네트워크 연결(TCP/IP 연결)이 끊김.
    • Stateless(무상태) : 클라이언트의 이전 상태가 서버에 남아있지 않음.

    브라우저에서 누가 로그인을 한 상태인지, 쇼핑몰에서 어떤 물건을 선택해 장바구니에 담았는지 이런 정보가 서버엔 하나도 저장이 되지 않는다는 뜻이다. 서버 입장에서는 매번 사용자가 요청을 보낼 때 이 사용자가 누구인지, 이전에는 어떤 요청을 보냈던 사용자인지 이런 정보를 아무것도 모른 채로 요청을 처리한다. 

    비유를 하자면 기억력이 1초인 점원이 있는 카페에서 손님이 실컷 메뉴를 불러준 뒤에 카드를 내밀면 점원이 메뉴는 어떤걸 고르셨죠? 하고 묻는 상황인 것이다.

    이런 상황에서 주문을 제대로 처리하기 위해서는 어떻게 해야할까?

    내 이름이 적힌 주문서에 메뉴를 적은 뒤 카드와 함께 점원에게 건네주는 방식으로 주문을 해야한다.

     

    여기서 '내 이름이 적힌 주문서'가 바로 쿠키라고 할 수 있다.

     

     

    2. 쿠키

    2-1. 쿠키는 무엇이고 왜 필요할까?

    쿠키(Cookie)
    : 하이퍼 텍스트의 기록서(HTTP)의 일종으로, 인터넷 사용자가 어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를 통해 인터넷 사용자의 컴퓨터에 설치되는(로컬에 저장되는) '작은 기록 정보 파일'을 일컫는다. 

    위에서 설명한 http 프로토콜의 stateless라는 특성 때문에 서버는 요청을 보내는 사용자가 누구인지 알 지 못한다. 그래서 요청을 보낼 때 항상 '저는 누구입니다'라는 정보를 함께 보내주어야한다. 이 때 사용하는 것이 바로 쿠키이다. 

    쿠키는 서버에서 클라이언트 측에 발급을 해준다. 브라우저는 자신이 이 쿠키를 가지고 있으면서 서버에 request를 보낼 때마다 이 쿠키를 자동으로 요청헤더에 담아 보내게된다.

     

    이 쿠키를 활용하면

    1. 사용자가 로그인을 한 채 페이지 이동을 할 수 있게 해주고 (다른 사이트에 접속한 뒤 다시 돌아와도 로그인이 된 상태유지)

    2. 웹페이지에 접속 시 뜨는 팝업창을 하루동안 뜨지 않도록 설정

    3. 로그인 하지 않은 채로 물건을 장바구니에 담아 저장

    이런 일이 가능해진다!

     

    쿠키는 이름, 값, 유효시간, 도메인, 경로정보 등으로 구성되어 있다. 

    쿠키를 생성할 때 유효시간을 정할 수 있는데 이는 은행사이트의 자동로그아웃기능, 일정기간동안 팝업창 보지않기 설정 등에 이용된다.

     

     

     

    2-2. 쿠키를 생성하는 방법

    쿠키는 웹서버에서 생성되어 응답의 헤더에 담아 클라이언트측으로 보내지게 된다.

    이렇게 받은 쿠키를 브라우저는 저장해두고서 요청을 보낼 때 매번 헤더에 담아 서버로 전송한다.

     

    헤더에 쿠키를 담는다는 것은 어떤 의미일까?

    먼저, 응답헤더를 작성하는 법을 알아야 한다.

     

     

    Response Header 추가해보기

    app.get('/', (req,res)=> {
        res.setHeader('headerName', 'headerValue')
        res.send('네트워크에서 응답헤더를 확인해보자')
    })

    위와같은 라우터를 만들어 서버를 실행시켜보자

    Response Header에서

    headerName : headerValue 라는 항목이 추가된 것을 볼 수 있다.

     

     

    set-Cookie 헤더 만들기

    app.get('/', (req,res)=> {
        res.setHeader('Set-Cookie', 'cookieName=cookieValue')
        res.send('네트워크에서 응답헤더를 확인해보자')
    })

    이제 헤더의 이름에 'Set-Cookie'를 넣어 쿠키를 만들어주는 역할을 하는 헤더를 만들어보자

    헤더가 생성되며 쿠키가 만들어졌다.

    Application 탭에서 쿠키의 확인이 가능하다.

     

     

     

    로그인 시 쿠키 생성

    app.post('/login', (req, res) => {
        const userid = req.body.userid
        const userpw = req.body.userpw
    
        if (userid === user.userid && userpw === user.userpw) {
            //로그인 성공
            res.setHeader('Set-Cookie', `login=${userid}`) // 쿠키설정
            res.redirect('/')
        }
        else {
            //로그인 실패
            res.redirect('/login')
        }
    })

    로그인을 하면 body로 받아온 정보를 서버에 있는 아이디 데이터와 비교한 뒤 일치 시에는 해당 아이디의 값을 가진 login쿠키를 발급한다.

    이런 식으로 아이디가 쿠키값에 들어가게 된다.

    이제 해당 도메인에서는 서버에 요청을 보낼때마다 login = hbhb 라는 쿠키를 함께 보내게 된다.

    라우터에서 요청을 처리할 때 쿠키정보가 필요한 경우

    req.headers.cookie

    위 코드를 사용하여 받아 올 수 있다.

    하지만 위의 값은 'login=hbhb' 문자열에 해당하므로

    const cookie = req.headers.cookie.split('=')
    const cookieID = cookie[1]

    이렇게 ID 값만 빼낼 수 있다.

     

     

     

     

    3. 세션

    3-1. 세션은 무엇이고 쿠키와는 무슨 차이일까?

    세션(Session)
     : 일정 시간동안 같은 사용자(브라우저)로부터 들어오는 일련의 요구를 하나의 상태로 보고, 그 상태를 일정하게 유지시키는 기술.
    여기서 일정 시간은 방문자가 웹 브라우저를 통해 웹 서버에 접속한 시점으로부터 웹 브라우저를 종료하여 연결을 끝내는 시점을 말한다.

    세션은 기본적으로 쿠키와 마찬가지로 임시 데이터 저장이 목적이다. 세션은 쿠키를 기반으로 하고 있다.

    하지만 사용자정보를 브라우저에서 관리하는 쿠키와 달리 세션은 사용자정보를 서버에서 관리할 수 있다.

    이렇게 서버에서 관리하는 세션을 사용하면 좋은 점은 무엇이 있을까?

     

     

    3-2. 세션을 사용해야 하는 이유

    브라우저에서 저장하는 쿠키는 사용자가 그 정보를 열람할 수 있고 임의로 삭제하거나 수정하는 것이 가능하다.

    만약 유저의 중요한 개인정보가 쿠키에 담겨 전송이 된다면 보안에 심각한 문제가 발생할 것이다.

    따라서 쿠키에는 누군가가 훔쳐보거나, 변조를 해도 큰 문제가 없는 수준의 정보만 담아야 한다.

     

    쿠키의 이러한 단점을 개선하기 위해서 사용되는 것이 세션이다.

    세션을 사용하여 중요한 데이터는 서버에 저장해 아무나 열람할 수 없도록 한 뒤, 사용자 별로 세션id를 발급하여 이를 쿠키에 담아 보낸다.

    세션을 사용하면 위와같이 랜덤한 세션id가 쿠키에 담겨 들어온다. 해당 키에 해당하는 사용자의 실제 데이터는 서버의 세션에 모두 저장되어있는 상태이다. 브라우저에서 요청을 보낼 때 저 세션id를 함께 보내면 서버는 세션에서 해당하는 id를 찾아 사용자를 구분하여 알맞게 요청을 처리하게 된다.

    세션을 사용하면 보안성은 높아지지만 그만큼 서버측에 많은 정보를 저장하고 관리해야해서 성능과 비용 문제가 발생한다. 처리 속도 역시 쿠키에 비해 느리다.

    또한, 쿠키는 만료기간을 정해 해당 기간동안은 브라우저를 닫더라도 쿠키가 남아있는데 반해 세션은 브라우저가 종료되면 만료기간과 상관없이 삭제된다.

    이러한 특징을 고려하여 쿠키와 세션을 적절히 나누어 상황에 따라 병행 사용하는 것이 필요하다.

     

     

    3-3. 세션을 생성하는 방법

    // 세션과 관련된 코드만 적어둠
    // 패키지 설치
    const session = require('express-session')
    const Memorystore = require('memorystore')(session)
    
    // 세션 생성 (❗️이부분은 정확히 모르겠음..)
    const maxAge = 5 * 60 * 1000 // 5분
    let sessionObj = {
        secret: 'hbhb',
        resave: false,
        saveUninitialized: true,
        store: new Memorystore({ checkPeriod: maxAge }), //클래스이므로 new를 이용해서 생성. 5분으로 해둠
        cookie: {
            maxAge: maxAge
        }
    }
    app.use(session(sessionObj)) // session() : 로그인 시 처음 쿠키를 생성한 후 클라이언트가 매번 요청을 보낼 때 쿠키를 확인하는 미들웨어
    
    // 로그인 : 세션 생성
    app.post('/login', (req, res) => {
        let { userid, userpw } = req.body
        let [item] = user.filter(v => (v.userid == userid && v.userpw == userpw))
        //array 내부의 객체만 item에 할당하고 싶어서 item을 []로 감싸줌!
        if (item != undefined) {
            //로그인 할 수 있는 경우
            req.session.user = { ...item } // 세션생성
            res.redirect('/')
        }
        else {
            //로그인 못하는 경우
            res.send(alertmove('/user/login', '아이디와 패스워드를 확인해주세요'))
            res.redirect('/user/login')
        }
    })
    
    
    // 로그아웃 : 세션 삭제
    app.get('/logout', (req, res) => {
        req.session.destroy(() => {
            req.session
        })
        res.send(alertmove('/', '로그아웃이 완료되었습니다.'))
    })

    세션을 다루는 방식을 아직 정확히 모르겠다.. 더 공부하고 다시 정리해야겠다.

    코드가 이해가 안되네...ㅠㅠ

     

     

     

     

    'Node.js' 카테고리의 다른 글

    5. Hash와 JWT  (0) 2022.03.03
    3. Node.js - 로그인 기능 구현  (0) 2022.02.07
    2. Node.js - 게시판 CRUD 구현  (0) 2022.02.07
    1. Node.js 시작해보기  (0) 2022.01.26
    0. Node.js 시작 전 설정하기  (0) 2022.01.25
Designed by Tistory.