2010. 12. 29. 23:49

자바스크립에서 쿠키를 제어하기 위해서는 손이 많이 가므로 미리 만들어둔 함수를 사용하는 것이 좋습니다.

인터넷 뒤저보면 여러 가지 구현과 라이브러리가 있으니 마음에 드는 걸 사용하면 됩니다.

 

이 포스팅에서는 간단하게 쿠키를 읽고 쓰는 함수를 만들어 봅시다.

쿠키를 굽자

 

 

1. 쿠키 쓰기

쿠키는 'document.cookie'에 표준에 맞게 넣기만 해도 알아서 처리됩니다.

예> document.cookie = "name=1234"

 

여기에 다양한 옵션을 추가하는 것으로 구현할 수 있습니다.

/**
 * 쿠키 쓰기
 * @param {string} sName 쿠키를 구분하기위한 이름
 * @param {string} sValue 쿠키에 기록할 데이터
 * @param {date} dateExpires 유효기간
 */
function CookieSet(
    sName
    , sValue
    , dateExpires)
{
    let todayDate = new Date();

    //쿠키유효기간 설정
    todayDate.setDate(todayDate.getDate() + dateExpires);

    //쿠키내용에 추가
    //document.cookie에 표준 형식(이름=값)으로 넣으면 쿠키에 자동으로 추가/수정 된다.
    document.cookie
        = sName + "=" + escape(sValue)
            + "; path=/ ; expires=" + todayDate.toUTCString() + ";";
}

 

 

2. 쿠키 읽기

쿠키는 'document.cookie'를 읽으면 됩니다.

 

이 값이 그냥 가지고 오면 문자열이므로 다양한 방법으로 '값'을 가지고 오는 방법을 구현할 수 있죠.

몇 가지 방법을 소개하겠습니다.

 

2-1. 문자열로 직접 다루는 방법(반복문) - 권장 안 함

문자열을 반복문으로 처리하는 방식입니다.

오래전에 퍼온 소스인데 출처를 잃어버렸습니다;;;

(아시는 분은 댓글로 달아주세요.)

 

지금 보면 왜 이렇게 구현돼있나 잘 모르겠습니다.

아마 아주 오래전 웹 표준에 맞게 구현된 게 아닌가 싶습니다.

/**
 * 쿠키 읽기 - 문자열로 직접 다루는 방법 - 권장 안함)
 * 쿠키를 직접 읽어 구분자로 잘라 필요한 이름을 찾는다.
 * @param {any} sName 찾을 쿠키 이름
 */
function CookieGetString1(sName) 
{
    let sQueryName = sName + "=";
    let x = 0;

    //쿠키를 분리한다.
    while (x <= document.cookie.length) 
    {
        //찾을 쿠키이름 길이 받아오기
        let y = (x + sQueryName.length);

        //찾을 쿠키 이름과 같은지?
        if (document.cookie.substring(x, y) == sQueryName) 
        {
            //같다면
            //쿠키에서 데이터를 구분자로 자른후 길이가 -1인지?
            if ((endOfCookie = document.cookie.indexOf(";", y)) == -1) 
            {
                //구분자가 없다면 쿠키 길이만큼 자른다.
                endOfCookie = document.cookie.length;
            }

            //잘라낸 쿠키에서 데이터만 분리한다.
            return unescape(document.cookie.substring(y, endOfCookie));
        }

        //다음 쿠키 시작지점으로 이동
        x = document.cookie.indexOf(" ", x) + 1;

        //더이상 이동할 것이 없다면 멈춘다.
        if (x == 0) 
        {
            break;
        }
    }

    return "";
}

 

2-2. 문자열로 직접 다루는 방법(indexOf)

일반적인 문자열 다루는 방식인 'indexOf'와 'substring'을 이용한 방법입니다.

제가 테스트용으로 만든 코드입니다.

/**
 * 쿠키 읽기 - 문자열로 직접 다루는 방법
 * 
 * @param {any} sName 찾을 쿠키 이름
 */
function CookieGetString2(sName)
{
    let sValueReturn = "";

    //구분용 이름이 같은 것이 있는지 확인한다.
    let nIdxStart = document.cookie.indexOf(sName + "=");
    if (-1 < nIdxStart)
    {//해당 이름의 쿠키가 있다.

        //인덱스 시작에서 처음 만나는 끝 구분자(;)의 위치를 찾는다
        let nIdxLast = document.cookie.indexOf("; ", nIdxStart);

        //해당 쿠키의 정보를 잘라낸다.
        let sTarget = document.cookie.substring(nIdxStart, nIdxLast);


        //정보에서 이름과 값을 구분하기위한 구분자(=)의 위치를 찾는다.
        let nIdxValue = sTarget.indexOf("=", nIdxStart);

        //값 부분만 잘라낸다.
        //nIdxValue는 구분자(=)까지 포함되어 있으므로 맨 앞에 구분자를 제외하고 잘라낸다.
        sValueReturn = sTarget.substring(nIdxValue + 1);
    }

    
    return sValueReturn;
}

 

2-3. 정규식을 이용한 방법

정규식을 이용하여 쿠키를 잘라내는 방법입니다.

(참고 : javascript.info - 쿠키와 document.cookie )

/**
 * 쿠키 읽기 - 정규식을 이용한 방법( https://ko.javascript.info/cookie )
 * @param {any} sName 찾을 쿠키 이름
 */
function CookieGetReg(sName)
{
    let matches = document.cookie.match(new RegExp(
        "(?:^|; )" + sName.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
    ));
    return matches ? decodeURIComponent(matches[1]) : "";
}

 

2-4. 스플릿과 람다 식(화살표 함수)를 이용한 방법

MDN에 나와 있는 스플릿과 람다 식(화살표 함수)을 이용한 방법입니다.

쿠키가 없는 경우 에러가 날 수 있어서 예외 처리를 추가했습니다.

(참고 : MDN -  Document.cookie )

/**
 * 쿠키 읽기 - 스플릿과 람다식(화살표 함수)를 이용한 방법(https://developer.mozilla.org/ko/docs/Web/API/Document/cookie)
 * @param {any} sName 찾을 쿠키 이름
 */
function CookieGetLambda(sName)
{
    let sValueReturn = "";

    //스플릿으로 끝 구분자(;)로 자른다음 시작 지점(startsWith)의 이름이 일치하는 대상을 찾는다.
    let sTarget
        = document.cookie
            .split('; ')
            .find(row => row.startsWith(sName));

    if (undefined !== sTarget)
    {//대상이 있다.

        //값을 구분하기위한 구분자(=)로 잘라서 값 부분을 구한다.
        sValueReturn = sTarget.split('=')[1];
    }

    return sValueReturn;
}

 

 

마무리

가능하면 오랫동안 유지보수되고 있는 라이브러리를 사용한 것이 좋습니다.

이런 기능들은 자기도 모르는 사이에 스펙이 변하는 경우가 있는데 그때그때 대응하기가 쉽지 않기 때문입니다.

그래도 어떻게 구현되고 있는 것인지는 알 필요가 있겠죠?