본문 바로가기

Spring Boot

[Spring Boot] HTTP Cookie 사용하기

728x90

이번 글에서는 HTTP 쿠키를 사용하여 쿠키를 생성한 후 클라이언트의 쿠키에 저장하고, 요청이 들어왔을 때 쿠키의 유무를 파악 및 쿠키를 통해 정보를 전달하는 예제를 다룹니다.

UserRepository

@Component
public class UserRepository {
    // 메모리에 저장할 사용자 리스트
    private final List<UserEntity> userList = new ArrayList<>();

    // ID로 사용자 찾기
    public Optional<UserEntity> findById(String id) {
        return userList.stream()
                .filter(it -> it.getId().equals(id))
                .findFirst();
    }

    // 이메일로 사용자 찾기
    public Optional<UserEntity> findByEmail(String email) {
        return userList.stream()
                .filter(it -> it.getEmail().equals(email))
                .findFirst();
    }

    // 애플리케이션 시작 시 사용자 데이터를 초기화하는 메소드
    @PostConstruct
    public void init() {
        // 초기 사용자 데이터 추가
        userList.add(UserEntity.builder()
                .id(UUID.randomUUID().toString()) // 랜덤으로 생성된 유니크 ID
                .email("shs00925@naver.com")
                .password("1234")
                .build());

        userList.add(UserEntity.builder()
                .id(UUID.randomUUID().toString())
                .email("test1@naver.com")
                .password("1234")
                .build());

        userList.add(UserEntity.builder()
                .id(UUID.randomUUID().toString())
                .email("user1234@naver.com")
                .password("1234")
                .build());
    }
}

 

 

이 예제는 데이터베이스를 생성하지 않고 메모리에 데이터를 저장하여 사용합니다. @PostConstruct 애노테이션은 프로젝트가 실행될 때 자동으로 해당 메소드를 실행시킵니다. UUID.randomUUID() 메소드는 랜덤으로 유니크한 값을 생성하며, 실무에서도 자주 사용되는 방법입니다.

  • findById(): UUID를 통해 생성된 ID로 사용자를 찾는 메소드입니다.
  • findByEmail(): 사용자가 로그인할 때 이메일을 통해 사용자를 찾는 메소드입니다.

UserEntity 및 LoginRequest

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
public class UserEntity {
    private String id;
    private String email;
    private String password;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
public class LoginRequest {
    private String email;
    private String password;
}
  • UserEntity: 데이터베이스에 접근하는 객체로, 사용자 정보를 저장합니다.
  • LoginRequest: 로그인할 때 필요한 데이터를 받는 객체입니다.

UserApiController

@RestController
@RequestMapping("/user") // "/user" 경로로 들어오는 요청 처리
@RequiredArgsConstructor
public class UserApiController {
    private final UserService userService; // UserService 의존성 주입

    // 로그인 요청 처리
    @PostMapping("/login")
    public void login(
            HttpServletResponse httpServletResponse, // 클라이언트에게 응답할 때 사용
            @RequestBody LoginRequest loginRequest // 요청 바디에서 로그인 정보 받기
    ) {
        userService.login(loginRequest, httpServletResponse); // 로그인 서비스 호출
    }

    // 사용자 정보 조회 요청 처리
    @GetMapping("/info")
    public String userInfo(
            HttpServletRequest httpServletRequest, // 클라이언트 요청 정보
            @CookieValue(name = "USER", required = false) String cookie // 쿠키에서 USER 정보 가져오기
    ) {
        return userService.userInfo(httpServletRequest, cookie); // 사용자 정보 서비스 호출
    }
}
  • login 메소드: HttpServletResponse 인자는 해당 메소드로 응답을 보낼 때 쿠키를 담아 보낼 수 있습니다.
  • info 메소드: HttpServletRequest 인자는 클라이언트의 여러 설정과 값을 볼 수 있도록 합니다. @CookieValue는 쿠키의 이름을 통해 해당 값을 가져옵니다.

UserService

@Slf4j // 로깅을 위한 어노테이션
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository; // UserRepository 의존성 주입

    // 로그인 처리 메소드
    public void login(LoginRequest loginRequest, HttpServletResponse httpServletResponse) {
        var email = loginRequest.getEmail(); // 로그인 시 입력된 이메일
        var password = loginRequest.getPassword(); // 로그인 시 입력된 비밀번호

        // 이메일로 사용자 찾기
        var optionalUser = userRepository.findByEmail(email);

        // 이메일이 등록되지 않은 경우 예외 발생
        if (optionalUser.isEmpty()) {
            throw new RuntimeException("해당 이메일은 가입되지 않았습니다");
        }

        var user = optionalUser.get(); // 사용자가 존재하는 경우

        // 비밀번호 확인
        if (!user.getPassword().equals(password)) {
            throw new RuntimeException("비밀번호가 맞지 않습니다");
        }

        // 로그인 성공 후 쿠키 생성
        Cookie cookie = new Cookie("USER", user.getId()); // USER라는 이름의 쿠키 생성
        cookie.setDomain("localhost");  // 쿠키의 도메인 설정 (localhost)
        cookie.setPath("/"); // 모든 경로에서 쿠키 사용 가능
        cookie.setHttpOnly(true); // JavaScript에서 접근 불가, 보안 강화
        cookie.setMaxAge(-1);  // 브라우저 종료 시 쿠키 삭제
        cookie.setSecure(false); // HTTP에서도 쿠키 사용 가능

        httpServletResponse.addCookie(cookie); // 응답에 쿠키 추가
    }

    // 사용자 정보 조회 메소드
    public String userInfo(HttpServletRequest httpServletRequest, String cookie) {
        // 쿠키가 없는 경우 로그인 요청
        if (cookie == null) {
            return "로그인을 먼저 해주세요";
        }

        // 쿠키로 사용자 찾기
        var optionalUser = userRepository.findById(cookie);
        if (optionalUser.isEmpty()) {
            return "다시 로그인을 해주세요"; // 사용자 정보가 없으면 로그인 요청
        }

        // 자동 로그인 성공
        var user = optionalUser.get();
        return user.toString(); // 사용자 정보 반환
    }
}
  • 로그인 파트: Cookie cookie = new Cookie("key", "value")를 통해 쿠키의 키와 값을 설정합니다.
  • cookie.setDomain("localhost"): 쿠키의 도메인을 설정합니다.
  • cookie.setPath("/"): 쿠키가 사용될 경로를 설정합니다.
  • cookie.setHttpOnly(true): JavaScript로 접근할 수 없도록 설정하여 보안을 강화합니다.
  • cookie.setSecure(false): HTTP에서도 쿠키를 사용할 수 있도록 설정합니다.
  • cookie.setMaxAge(-1): 유효기간을 설정하여 브라우저 종료 시 쿠키가 삭제되도록 합니다.
  • 로그인 유지 기능: cookie.setMaxAge(60 * 60 * 24);와 같이 유효 기간을 설정하여 로그인 상태를 유지할 수 있습니다.

 

 

결과 화면

로그인을 하지 않고 유저 정보에 접근했을 때 (쿠키 X)
사용자가 로그인하지 않은 경우, 정보에 접근할 수 없다는 메시지가 표시됩니다.

 

로그인에 성공한 후 (쿠키 O)
로그인 성공 후, 쿠키를 통해 사용자 정보가 정상적으로 반환됩니다.

 

728x90

'Spring Boot' 카테고리의 다른 글

[Spring Boot] JWT 사용하기  (2) 2024.10.23
[Spring Boot] JWT 의존성 설정하기  (1) 2024.10.22
[Spring Boot] Http Session 사용하기  (8) 2024.10.19
[Spring Boot] AOP 포인트 컷 사용하기  (0) 2024.10.16
[Spring Boot] AOP  (0) 2024.10.14