[spring] 세션으로 사용자 정보 유지하기

Kaite.Kang·2023년 1월 17일
0
post-thumbnail

* 목표

HTTP 세션에 대해 알아보고 코드로 구현해보자.

1. 세션으로 사용자 정보 유지하기

1) HTTP 세션(session)은 왜 필요할까?

세션은 일정 시간 동안 사용자의 상태를 일정하게 유지시키는 기술이다.

사용자는 로그인할 때 개인 정보를 입력하는데 이 데이터는 서버에 임시로 저장된다. 아무런 설정을 해주지 않으면 이때 저장된 데이터는 페이지를 새로 고침하면 만료된다. 따라서 페이지가 새로 고침될 때마다 로그인해야 하는 불편함이 있다. 이때 세션을 활용하면 로그인 정보를 유지시킬 수 있다.

2) HTTP 세션을 언제 생성될까?

여기서 세션은 언제 만들어질까? 모든 요청에 대해 세션을 만드는 것이 아니라 세션을 사용할 때 생성한다. 스프링에서는 세션을 관리하기 위해 HttpSession 인터페이스를 제공한다. HttpSession은 setAttribute 혹은 getAttribute 같은 api를 호출하는 시점에 요청/생성한다.

HttpSession 인터페이스는 둘 이상의 page request에서 사용자를 식별하거나, 웹 사이트를 방문하고 해당 사용자에 대한 정보를 저장하는 방법을 제공한다.

Servlet container는 HttpSession를 사용하여 HTTP client - HTTP server 간의 세션을 생성한다. 이 때, 세션은 한 명의 사용자에 해당한다. 서버는 Cookie, rewriting URL와 같은 방법으로 세션을 유지하면서 관리할 수 있다. 객체를 세션에 바인딩하여 사용자 정보를 유지할 수 있다.

3) 세션으로 사용자 정보 유지하기

예시 코드를 통해 사용자 데이터를 세션에 어떻게 저장하고 가져오는지 확인해보자.

아래 코드는 MVC 구조에서 서비스 단인데 로그인 후 사용자 정보를 httpSession.setAttribute 를 통해 저장한다.

..

public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    private final UserRepository userRepository;
    private final HttpSession httpSession;

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
				...
	
        //OAuthAttributes 의 속성값을 가져옴.
        OAuthAttributes attributes = OAuthAttributes.of(registrationId, userNameAttributeName, oAuth2User.getAttributes());

        //가져온 속성값을 user 객체로 변환
        User user = saveOrUpdate(attributes);
        //세션에 사용자 정보를 저장하기 위해 user 객체를 SessionUser DTO로 변환
        httpSession.setAttribute("user", new SessionUser(user));
	
				...

    }
}

...

아래 코드는 ‘/’ 페이지를 호출하는 컨트롤러이다. 로그인에 성공했다면(= 세션에 사용자 데이터가 저장되어 있다면) 사용자 데이터를 모델에 저장한다.

httpSession.getAttribute("user") 의 반환값이 있다면 세션 정보를 저장한다. 즉, 로그인 성공 시에만 httpSession.getAttribute("user")에서 값을 가져올 수 있다.

if문에서는 model.addAttribute("key", "value") 를 이용해서 view로 key, value 쌍을 데이터로 전달한다.

@RequiredArgsConstructor
@Controller
public class IndexController {

    private final PostsService postsService;
    private final HttpSession httpSession;

    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("posts", postsService.findAllDesc());

        SessionUser user = (SessionUser) httpSession.getAttribute("user");
        if (user != null) {
            model.addAttribute("userName", user.getName());
        }

        return "index";
    }
}

컨트롤러에서 model에 저장된 "userName"는 view에서 사용할 수 있다. 세션에 저장된 값이 없다면 model에는 아무 값이 없는 상태이기 때문에 로그인 버튼이 보인다.

...
{{#userName}}
    Logged in as: <span id="user">{{userName}}</span>
    <a href="/logout" class="btn btn-info active" role="button">Logout</a>
{{/userName}}
{{^userName}}
    <a href="/oauth2/authorization/google" class="btn btn-success active" role="button">Google Login</a>
    <a href="/oauth2/authorization/naver" class="btn btn-secondary active" role="button">Naver Login</a>
{{/userName}}
...

참고로 SessionUser 클래스 구성은 다음과 같다.

...

@Getter
public class SessionUser implements Serializable {
    private String name;
    private String email;
    private String picture;

    public SessionUser(User user) {
        this.name = user.getName();
        this.email = user.getEmail();
        this.picture = user.getPicture();
    }
}

* 정리

  • 세션을 이용해서 로그인 정보를 일정하게 유지할 수 있다.
  • 스프링에서는 httpSession.setAttribute("Key", Value) 로 세션을 생성하고, httpSession.getAttribute**(**"Key") 로 세션에서 객체를 가져온다.
  • Controller에서 사용자에게 응답할 View를 생성할 때, Model을 이용하여 View에 데이터를 전달할 수 있다.
    • model.addAttribute(String name, Object value)
    • model addAttribute(Object value)

Reference

참고

도서 - 스프링 부트와 AWS로 혼자 구현하는 웹 서비스

0개의 댓글