프로젝트

블로그 만들기 - cookie와 util 클래스를 static으로?

ernest45 2025. 3. 30. 23:24

 

Oauth2 구글을 활용하기 위해 클라이언트에 내려줄 cookie를 설정해주는 작업을 해봤다..

 

사실 예전에 프로젝트에서 jwt 토큰으로 인증까진 성공했었는데 oauth는 쓰린 실패의 맛을 봤어서

 

다시 차근차근 공부하고 있다.

 

 

쿠키는 크기 제한이(보통 4KB)이 있으므로, 큰 데이터는 세션이나 DB에 저장하는 게 낫다.

 

나는 간단하게 토큰 값만 저장할 거라서 쿠키에 저장하면 좋겠다 싶었음

 

쿠키는 되게 간단하다.

 

package me.hanjun.util;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.SerializationUtils;

import java.util.Base64;

public class CookieUtil {
    //요청 값(이름,값,만료 기간)을 바탕으로 쿠키 추가
    public static void addCookie(HttpServletResponse response, String name, String value,
    int maxAge) {
        Cookie cookie = new Cookie((name), value);
        cookie.setPath("/");
        //모든 경로에서 쿠키 사용
        cookie.setMaxAge(maxAge);
        // -1 브라우저 종료시 삭제 0 즉시 삭제 등 의미가 있음
        response.addCookie(cookie);
    }

    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response
            , String name) {

        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return;
        }

        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                cookie.setValue("");
                cookie.setPath("/");
                cookie.setMaxAge(0);
                response.addCookie(cookie);

            }
        }
    }
    // 쿠키를 직렬화해 쿠키의 값으로 변환
    public static String serialize(Object object) {
        return Base64.getUrlEncoder()
                .encodeToString(SerializationUtils.serialize(object));
    }

    public static <T> T deserialize(Cookie cookie, Class<T> cls) {
        return cls.cast(
                SerializationUtils.deserialize(
                        Base64.getUrlDecoder().decode(cookie.getValue())
                )
        );

    }
}

 

 

설명하자면,

 

1. 쿠키 추가

 

HttpServletResponse.addCookie()로 새 쿠키를 설정!
 
 

2.  쿠키삭제

request.getCookies()

삭제를 위해 기존 쿠키를 가져와서 만료시키고 만료시킨 쿠키를 저장시킴

 

 

3. 직렬화

쿠키는 보통 문자열로 저장되기에 


객체를 직렬화(Serialization)하고 Base64로 인코딩해 문자열로 변환

 

 

 

4.역직렬화

쿠키에 저장된 Base64 인코딩된 값을 역직렬화해 원래 객체로 복원
 
 
 
 

 

 

5. 왜 CookieUtilstatic으로 만들까?

 

 

 
"이거 static으로 만들면 인스턴스 안 만들고 그냥 쓰니까 편하려나?" 이런 생각이 스쳤는데, 막상

 

 
"왜?"라고 딱 물어보니까 완벽하게 설명할 자신이 없어서 알아보고 정리해봤다.
 
 

 

 

쿠키랑 static이랑 무슨 상관?

 

쿠키 자체는 각 클라이언트(브라우저)마다 독립적으로 저장.
 
내가 CookieUtil.addCookie(response, "userId", "hanjun", 3600)을 호출하면
내 브라우저에 "userId=hanjun"이 저장되고,
 
다른 사용자가 같은 메서드로 "userId=other"를 설정하면 그 사람 브라우저에 따로 저장됨
 
이건 HttpServletRequestHttpServletResponse가 요청마다 새로 생기니까 당연하다...
 
 

CookieUtilstatic이든 아니든 쿠키 자체엔 영향을 안 줌!

 

그럼 왜 왜 static으로 했냐?"는 질문은 쿠키 데이터가 아니라 클래스 설계 방식에 초점을 맞춰야 한다는 뜻이다
.
 
static 메서드의 장점 : 인스턴스 없이 쓰기
 
솔직히 static의 가장 큰 장점은  new로 객체 안 만들고 바로 호출할 수 있다.
 
 
 
 

static의 경우 :

 
 
CookieUtil.addCookie(response, "key", "value", 3600);
 
 
 
 

비-static의 경우:

 
 
CookieUtil util = new CookieUtil();
util.addCookie(response, "key", "value", 3600);
 
 
이렇게 한 줄 더 써야한다.
 
이러면 귀찮다. 근데 단순히 귀찮음 때문만은 x. 
상태가 없으면 static가 좋아보임
 
 
 
 
 

addCookie():

 
 
public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
    Cookie cookie = new Cookie(name, value);
    cookie.setPath("/");
    cookie.setMaxAge(maxAge);
    response.addCookie(cookie);
}
 

 

 
이 메서드를 보면 클래스 내부에 뭔가를 저장하거나 유지하지 않는다.
 
그냥 입력값(response, name, value, maxAge) 받아서 쿠키 만들어서 응답에 붙이는 역할
이런 걸 **상태 비저장(stateless)**
생각해보면 상태를 안 유지한다면 굳이 객체를 만들 이유가 없다.
 
 
 

if) CookieUtil이 이런 식이었다면?

 
 
public class CookieUtil {
    private String defaultPath; // 상태 저장

    public CookieUtil(String defaultPath) {
        this.defaultPath = defaultPath;
    }

    public void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath(defaultPath); // 상태 사용
        cookie.setMaxAge(maxAge);
        response.addCookie(cookie);
    }
}
이럴 땐 new CookieUtil("/app")처럼 객체를 만들어서 기본 경로를 설정할 수 있으니까
비-static을 쓰겠지만. 근데 지금 CookieUtil상태가 없으니 static으로 해도 충분!
 
 
 
 
 

Java에서 상태 없는 도구 클래스는 보통 static으로 만듦

 
ex) Math.max(), Arrays.sort(), Collections.shuffle()..

 

이러한 클래스들을 보니 "아, 이건 유틸리티 클래스구나" 하고 바로 감이 오니까 편리함.

 

 

 

 

성능이랑 메모리

 static 메서드는 클래스가 로드될 때 한 번만 메모리에 올라가고,
인스턴스 만들 때마다 객체를 힙에 할당하는 비-static보다 살짝 효율적

 

 

 

결론: 상태가 없고 util 클래스니 static을 쓰자!

 

 

 

 

 

 

번외

 

 

 

SerializationUtils.deserialize();  <- deprecated된 메서드!

테스트 메서드 중deprecated된 메서드가 있음을 우연히 발견해 자세히 알아보기 위해 build.gradle에 추가!
이럼 빌드 시 알려줌!

 

 

 이놈이구만..