카테고리 없음

[TIL] Cookie / Session (로그인 인증)

mooncommit 2026. 4. 22. 17:28

Spring Boot Lv4 로그인 기능 구현을 위해 Cookie와 Session 개념을 공부했다.


왜 Session이 필요한가?

HTTP는 기본적으로 무상태(Stateless) 프로토콜이다.

즉, 서버는 각 요청을 독립적으로 처리하기 때문에 이전 요청을 기억하지 못한다.

✔️ 1번 요청: "나 스파르타야, 로그인할게"
✔️ 2번 요청: "나 스파르타야, 장바구니 보여줘"
⭐️ 서버 입장에서는 1번이랑 2번이 같은 사람인지 알 수 없다 🥲
  • 그래서 "나는 로그인한 사람이야!" 를 증명할 수단이 필요 → Session

Cookie vs Session

 

✔️ 비유로 알아보기

🎡 세션 = 놀이공원 입장 명부 (서버에 있음)
🍪 쿠키 = 내 손목에 찍힌 도장 (브라우저에 있음)

📝 손목 도장(쿠키)을 보여주면 서버가 명부(세션)에서 확인하는 것!

✔️ 전체 흐름

1. 클라이언트가 이메일 + 비밀번호로 로그인 요청
2. 서버가 확인 후 세션 생성 (세션 ID : abc123)
3. 서버가 세션 ID를 쿠키에 담아서 브라우저에 전달
4. 이후 요청마다 브라우저가 쿠키(세션 ID)를 자동으로 서버에 전송
5. 서버가 세션 ID로 "이 사람 로그인한 사람이구나!" 확인
6. 로그아웃 시 세션 삭제

⭐️ 핵심 : 기억하는 건 세션(서버), 전달해주는 건 쿠키(브라우저)


HttpSession에 대해서 알고 가자

 

session 객체는 HttpSession 타입이다.
setAttribute, getAttribute, invalidate 메서드는 직접 구현할 필요 없이, 기본으로 제공된다!

 

🍬 HttpSession 기본 제공 메서드


🍬 주요 메서드

HttpSession session = request.getSession();

// 세션에 데이터 저장
session.setAttribute("loginUser", user);

// 세션에서 데이터 꺼내기
session.getAttribute("loginUser");

// 세션 전체 삭제 (로그아웃)
session.invalidate();

 

🍬 getSession() vs getSession(false)

// getSession()        → 세션이 없으면 새로 생성
// getSession(false)   → 세션이 없으면 null 반환 (생성 X)

HttpSession session = request.getSession(false); // 로그인 확인 시 사용

 

getSession() → 세션 있으면 가져오고, 없으면 새로 생성
getSession(false) → 세션 있으면 가져오고, 없으면 null 반환

 


실제 구현 패턴

✔️ 로그인 API

@PostMapping("/login")
public ResponseEntity<?> login(
        @RequestBody LoginRequestDto request,
        HttpServletRequest servletRequest) {

    // 세션 생성
    HttpSession session = servletRequest.getSession();

    // 로그인 성공 시 세션에 유저 저장
    session.setAttribute("loginUser", user);

    return ResponseEntity.ok(...);
}

 

✔️ 세션 확인 (로그인 필요한 API)

@GetMapping
public ResponseEntity<?> getSchedules(HttpServletRequest servletRequest) {

    HttpSession session = servletRequest.getSession(false);

    if (session == null || session.getAttribute("loginUser") == null) {
        throw new RuntimeException("로그인이 필요합니다.");
    }

    // 이후 로직 처리
}

 

✔️ 로그아웃 API

@PostMapping("/logout")
public ResponseEntity<Void> logout(HttpServletRequest servletRequest) {
    HttpSession session = servletRequest.getSession(false);
    if (session != null) {
        session.invalidate(); // 세션 삭제
    }
    return ResponseEntity.ok().build();
}

Lv4 로그인 구현 실습

 

1. UserRepository에 이메일 조회 메서드 추가

Optional<User> findByEmail(String email);
  • JPA가 메서드 이름만 보고 자동으로 쿼리를 만들어 준다.

 

2. LoginRequestDto 생성

public class LoginRequestDto {

    private String email;
    private String password;

    public String getEmail() {
        return email;
    }

    public String getPassword() {
        return password;
    }
}
  • 이메일, 비밀번호 필드 추가

 

3. UserController에 로그인 API 추가

@PostMapping("/login")
public ResponseEntity<String> login(
        @RequestBody LoginRequestDto request,
        HttpServletRequest servletRequest) {
        
        // Service에 이메일, 비밀번호 확인 요청해서 유저 가져오기
}

 

 

4. UserService에 Login 메서드 추가

// Login
@Transactional(readOnly = true)
public User login(LoginRequestDto request) {
    // 1. request 값 꺼내오기
    String email = request.getEmail();
    String password = request.getPassword();
    
    // 2. email로 유저 찾기
    User findUser = userRepository.findByEmail(email)
            .orElseThrow(() -> new RuntimeException("유저를 찾을 수 없습니다."));
    
    // 3. 찾은 유저 비밀번호 가져오기
    String findPassword = findUser.getPassword();
    
    // 4. 비밀번호 비교하기 (틀리면 예외처리)
    if (!password.equals(findPassword)) {
        throw new RuntimeException("비밀번호가 맞지 않습니다.");
    }
    
    // 5. 유저 반환
    return findUser;
}

 

 

5. UserController - 세션 저장

// 1. service에서 찾은 유저 가져오기
User user = userService.login(request);

// 2. 세션 가져오기 (없으면 새로 생성)
HttpSession session = servletRequest.getSession();

// 3. 세션에 유저 저장하기
session.setAttribute("loginUser", user); // 키, 값

// 4. 반환 객체 만들기
ResponseEntity<String> response = new ResponseEntity<>("로그인 성공", HttpStatus.OK);

// 5. 반환
return response;
Cookie는 servletRequest.getSession() 호출하면 Spring이 자동으로
세션 생성, 세션 ID를 쿠키에 담아서 브라우저에 전달

Postman 테스트

users 테이블 정보

 

로그인 성공


로그인 실패


실습하며 헷갈린 부분 정리

 

✔️ HttpServletRequest가 뭔지?

  • 클라이언트가 서버에 보낸 요청 정보를 담고 있는 객체
  • 세션, 쿠키, 헤더 등을 꺼낼 수 있다

✔️ 세션 처리는 Controller vs Service?

  • 세션 처리는 Controller 담당
  • Service는 비즈니스 로직만 담당하고, 세션 저장은 Controller가 담당

✔️ session.setAttribute("키", 값)

  • "키" → 세션에 저장할 때 쓰는 이름표, 나중에 꺼낼 때 이 이름으로 찾는다.
  • 값 → 실제로 저장할 데이터, 이번 실습에는 유저 객체를 저장
  • 예시 : session.setAttribute("loginUser", user) → "loginUser"라는 이름으로 user 객체 저장

✔️ getSession() vs getSession(false)

  • getSession() → 세션 없으면 새로 생성 (로그인할 때)
  • getSession(false) → 세션 없으면 null 반환 (다른 API에서 확인할 때)

느낀 점

 

오늘 Lv4 로그인 기능을 구현하면서 처음에는 막막할 줄 알았는데, Cookie와 Session 개념을 먼저 공부하고 실습에 들어가니 생각보다 어렵지 않았다.

 

어려웠다기보다는 처음 써보는 기능이라 코드에 어떻게 녹여야 할지 감이 잡히지 않았다. 특히 HttpServletRequest가 왜 필요한지 이해하는 데 시간이 걸렸는데, 여기저기 알아본 결과 "클라이언트가 보낸 요청 봉투" 라고 생각하니 자연스럽게 이해가 되었다.

 

session.setAttribute()도 처음엔 낯설었지만 키와 값의 개념을 이해하고 나서는 전혀 어렵지 않았다.

 

이번 실습때는 바로 코드부터 보지 않고 개념부터 내가 헷갈리지 않을 정도로 잡고 시작했더니 전보다 수월했다. 앞으로도 처음 접하는 개념은 먼저 확실히 이해하고 코드로 넘어가는 방식으로 공부법을 바꿔야겠다!


 

🕶️ NEXT

 

  • 수정/삭제 API에 세션 검증 추가 (비밀번호 검증 → 로그인 여부 확인으로 변경)
  • 지금까지 배운 내용을 새로운 주제로 처음부터 혼자 구현해보기

TIL 끝⎝⍥⎠⎝⍢⎠⋆◡̎⋆ 🔥