# ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ - ์ฟ ํ‚ค, ์„ธ์…˜
Study Repository

๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ - ์ฟ ํ‚ค, ์„ธ์…˜

by rlaehddnd0422

๋กœ๊ทธ์ธ ์š”๊ตฌ์‚ฌํ•ญ

ํ™ˆ ํ™”๋ฉด - ๋กœ๊ทธ์ธ ์ „

ํ™ˆ ํ™”๋ฉด - ๋กœ๊ทธ์ธ ์ „

  • ํšŒ์› ๊ฐ€์ž… 
  • ๋กœ๊ทธ์ธ

ํšŒ์›๊ฐ€์ž… / ๋กœ๊ทธ์ธ ํผ ํ™”๋ฉด

 

ํ™ˆ ํ™”๋ฉด - ๋กœ๊ทธ์ธ ํ›„

๋กœ๊ทธ์ธ ํ›„ ํ™”๋ฉด

  • ๋ณธ์ธ ์ด๋ฆ„ ( ๋กœ๊ทธ์ธ : ~ )
  • ์ƒํ’ˆ ๊ด€๋ฆฌ
  • ๋กœ๊ทธ ์•„์›ƒ

์ƒํ’ˆ ๋ชฉ๋ก / ํ™ˆ ํ™”๋ฉด

๋ณด์•ˆ ์š”๊ตฌ์‚ฌํ•ญ

  • ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž๋งŒ ์ƒํ’ˆ์— ์ ‘๊ทผํ•˜๊ณ , ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒํ’ˆ ๊ด€๋ฆฌ์— ์ ‘๊ทผํ•˜๋ฉด ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ 

ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ์„ค๊ณ„

ํŒจํ‚ค์ง€ ๊ตฌ์กฐ - domain, web
๋„๋ฉ”์ธ์€ ์‹œ์Šคํ…œ์ด ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ์—…๋ฌด ์˜์—ญ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
๋‚˜์ค‘์— web์„ ๋‹ค๋ฅธ ๊ธฐ์ˆ ๋กœ ๋ฐ”๊พธ์–ด๋„ ๋„๋ฉ”์ธ์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
web์€ domain์„ ์˜์กดํ•˜์ง€๋งŒ domain์€ web์— ์˜์กดํ•˜์ง€ ์•Š๋„๋ก ์„ค๊ณ„ํ•ด์•ผ ํ•จ. 
๋”ฐ๋ผ์„œ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ๋ฅผ ์ž˜ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”.

๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

ํ™ˆ ํ™”๋ฉด

HomeController์— ์ถ”๊ฐ€ 

@GetMapping("/")
public String home() {
    return "home";
}

home.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <link th:href="@{/css/bootstrap.min.css}"
          href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container" style="max-width: 600px">
    <div class="py-5 text-center">
        <h2>ํ™ˆ ํ™”๋ฉด</h2> </div>
    <div class="row">
        <div class="col">
            <button class="w-100 btn btn-secondary btn-lg" type="button"
                    th:onclick="|location.href='@{/members/add}'|">
                ํšŒ์› ๊ฐ€์ž…
            </button>
        </div>
        <div class="col">
            <button class="w-100 btn btn-dark btn-lg"
                    onclick="location.href='items.html'"
                    th:onclick="|location.href='@{/login}'|" type="button">
                ๋กœ๊ทธ์ธ
            </button>
        </div>
    </div>
    <hr class="my-4">
</div> <!-- /container -->
</body>
</html>

 ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ -> URI "localhost:8080/members/add" ๋กœ ์ด๋™ 

๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ -> URI "localhost:8080/login"๋กœ ์ด๋™

 

 

Domain - Member

@Data
public class Member {
    private Long id;

    @NotEmpty
    private String loginId;

    @NotEmpty
    private String name;

    @NotEmpty
    private String password;

    public Member(){}

    public Member(String loginId, String name, String password) {
        this.loginId = loginId;
        this.name = name;
        this.password = password;
    }
}

ํšŒ์› ๊ฐ€์ž…, ๋กœ๊ทธ์ธ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

 

Domain - MemberRepository

@Slf4j
@Repository
public class MemberRepository {

    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;

    public Member save(Member member)
    {
        member.setId(++sequence);
        log.info("save : member = {}",member);
        store.put(member.getId(),member);
        return member;
    }

    public Member findById(Long id)
    {
        return store.get(id);
    }

    public Optional<Member> findByLoginId(String loginId)
    {
//        List<Member> members = findAll();
//        for (Member m : members) {
//            if(m.getLoginId() == loginId)
//            {
//                return Optional.of(m);
//            }
//        }
//        return Optional.empty();

        return findAll().stream()
                .filter(m -> m.getLoginId().equals(loginId))
                .findFirst();
    }

    public List<Member> findAll()
    {
        return new ArrayList<>(store.values());
    }

    public void clearStore()
    {
        store.clear();
    }

}

MemberRepository for member ์ €์žฅ.

(๋Œ€๊ฐœ ์ธํ„ฐํŽ˜์ด์Šค ๋ ˆ๋ฒจ๋กœ ์„ ์–ธํ•˜๊ณ  ๊ตฌํ˜„์ฒด๋ฅผ ๋ณ„๋„๋กœ ๊ตฌํ˜„ํ•ด์„œ ์“ฐ๋Š” ๊ฒŒ ์ •์„์ด๊ธด ํ•ฉ๋‹ˆ๋‹ค - ๊ฐˆ์•„๋ผ์šฐ๊ธฐ ์œ„ํ•ด)

ํšŒ์› ๊ฐ€์ž… ํ™”๋ฉด

@Controller
@RequiredArgsConstructor
@RequestMapping("/members")
public class MemberController {

    private final MemberRepository memberRepository;

    @GetMapping("/add")
    public String addForm(@ModelAttribute("member") Member member)
    {
        return "members/addMemberForm";
    }
  • ํšŒ์› ๊ฐ€์ž… ๋ฒ„ํŠผ ์‹œ -> /members/add๋กœ ์ด๋™ -> addMemberForm ๋ทฐํ…œํ”Œ๋ฆฟ์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • addMemberForm์—์„œ th:object=${member}"๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด @ModelAttribute Member member๋ฅผ argument๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • Model์„ argument๋กœ ์„ค์ •ํ•˜๊ณ  model.addAttribute("member",member)๋กœ ๋ชจ๋ธ์— ๊ฐ์ฒด๋ฅผ ๋‹ด๊ณ  addMemberForm ๋ทฐํ…œํ”Œ๋ฆฟ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
@PostMapping("/add")
public String save(@Validated @ModelAttribute("member") Member member, BindingResult bindingResult)
{
    if(bindingResult.hasErrors())
    {
        return "members/addMemberForm";
    }
    memberRepository.save(member);
    return "redirect:/";
}
  • addMemberForm์—์„œ HTML From ์ž…๋ ฅ์„ ํ†ตํ•ด ํšŒ์› ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ  ํ˜„์žฌ URL์— Post ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ( th:action์— ๋ณ„๋„์˜ URL์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ URL์— Post ์š”์ฒญ)
  • HTML Form POST ์ „์†ก์„ ํ†ตํ•ด ๊ฒ€์ฆ์„ ๊ฑฐ์ณ @ModelAttribute Member member์— ๋‹ด๊ณ  ๊ฒ€์ฆ ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ bindingResult์— ์˜ค๋ฅ˜๋ฅผ ๋‹ด์Šต๋‹ˆ๋‹ค. 
  • bindingResult์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ -> ๋“ฑ๋ก ํผ ์š”์ฒญ
  • bindingResult์— ์˜ค๋ฅ˜๊ฐ€ ์—†์„ ๊ฒฝ์šฐ -> ์ €์žฅ์†Œ์— ํšŒ์›๋‹ด๊ณ  home์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ

๋กœ๊ทธ์ธ ํ™”๋ฉด 

@GetMapping("/login")
public String loginForm(@ModelAttribute("loginForm") LoginForm loginForm)
{
    return "login/loginForm";
}
  • ํ™ˆ ํ™”๋ฉด์—์„œ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ -> "localhost:8080/login" URL ์š”์ฒญ  -> loginForm ๋ทฐ ํ…œํ”Œ๋ฆฟ ํ˜ธ์ถœ
  • loginForm์—์„œ th:object="${loginForm}" ์‚ฌ์šฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์— ๋‹ด์•„์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. 
@PostMapping("/login")
public String login(@Valid @ModelAttribute LoginForm loginForm, BindingResult bindingResult)
{
    if(bindingResult.hasErrors())
    {
        return "login/loginForm";
    }

    Member loginMember = loginService.login(loginForm.getLoginId(), loginForm.getPassword());

    // ์‹คํŒจ
    if(loginMember == null)
    {
        bindingResult.reject("loginFail","์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        return "login/loginForm";
    }


    // ์„ฑ๊ณต
    return "redirect:/";
}

 

  • loginForm ๋ทฐ ํ…œํ”Œ๋ฆฟ์˜ HTML Form์œผ๋กœ๋ถ€ํ„ฐ Post๋œ ๋ฐ์ดํ„ฐ๋“ค์„ @ModelAttribute loginForm์— ๋‹ด์•„ ๊ฒ€์ฆ๊ณผ์ •์„ ๊ฑฐ์นœ ํ›„ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์œผ๋ฉด bindingResult์— ๋‹ด์Šต๋‹ˆ๋‹ค.   ( th:action์— ๋ณ„๋„์˜ URL์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ URL์— Post ์š”์ฒญ) 
  • ์ด ๋•Œ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ bindingResult์— ์˜ค๋ฅ˜๊ฐ€ ๋‹ด๊ฒจ์žˆ์œผ๋ฉด loginForm ๋ทฐ ํ…œํ”Œ๋ฆฟ์„ ๋‹ค์‹œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
    • ์ฐธ๊ณ ๋กœ loginForm์—์„œ๋Š” ๊ธ€๋กœ๋ฒŒ์˜ค๋ฅ˜, ํ•„๋“œ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„์‹œ ํ•ด๋‹น ์˜ค๋ฅ˜์— ๋Œ€ํ•œ ์˜ค๋ฅ˜๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
Member loginMember = loginService.login(loginForm.getLoginId(), loginForm.getPassword());
  • loginService์—์„œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํ†ตํ•ด ์•„์ด๋””๋ฅผ ์ฐพ๊ณ  ํŒจ์Šค์›Œ๋“œ๊นŒ์ง€ ์ผ์น˜ํ•˜๋ฉด ํ•ด๋‹น ํšŒ์›์„ ๋ฆฌํ„ดํ•˜๊ณ ,  ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ null ๋ฆฌํ„ด
  • ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ ๊ธ€๋กœ๋ฒŒ ์˜ค๋ฅ˜์— ๋‹ด์•„์„œ ๋‹ค์‹œ loginForm ๋ทฐ ํ…œํ”Œ๋ฆฟ์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ home์œผ๋กœ redirectํ•ฉ๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ์„ ์„ฑ๊ณตํ•˜๋ฉด ๊ธฐ๋Œ€ํ™”๋ฉด ์ฒ˜๋Ÿผ ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ๋‚˜์˜จ ์ƒํƒœ๋กœ home์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•˜๋Š”๋ฐ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋Œ€ / ๊ฒฐ๊ณผ 

๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•œ ์‚ฌ์šฉ์ž๋Š” ํ™ˆ ํ™”๋ฉด์— ์ ‘๊ทผํ•  ๊ฒฝ์šฐ ๋กœ๊ทธ์ธ์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๊ณ ๊ฐ์˜ ์ด๋ฆ„์„ ๋ณด์—ฌ์ฃผ๊ฒŒ ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๋‹ด์€ ์ฑ„๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ฟ ํ‚ค๋‚˜ ์„ธ์…˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

์ง€๊ธˆ๊นŒ์ง€๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ ํผ๊ณผ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ด์šฉํ•ด ๋กœ๊ทธ์ธ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๊ตฌํ˜„๋งŒ ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ด์ œ ์ฟ ํ‚ค์™€ ์„ธ์…˜์„ ์‚ฌ์šฉํ•ด์„œ ๋กœ๊ทธ์ธ์„ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ 

์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HTTP๋Š” ๋ฌด์ƒํƒœ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค / ํด๋ผ์ด์–ธํŠธ - ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฃผ๊ณ ๋ฐ›์œผ๋ฉด ์—ฐ๊ฒฐ์ด ๋Š์–ด์ง.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋‹ค์‹œ ์š”์ฒญํ•˜๋ฉด ์„œ๋ฒ„๋Š” ์ด์ „ ์š”์ฒญ์„ ๊ธฐ์–ตํ•˜์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“  ์š”์ฒญ์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋•Œ ์ฟ ํ‚ค์— ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋‹ด์•„์„œ ์„œ๋ฒ„์— ๋‹ด์•„ ์ „์†กํ•œ๋‹ค๋ฉด ๋กœ๊ทธ์ธ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

 

https://rlaehddnd0422.tistory.com/45#article-5--http---%EC%BF%A0%ED%82%A4-%ED%97%A4%EB%8D%94

 

HTTP ํ‘œํ˜„ ํ—ค๋”

message body(ํŽ˜์ด๋กœ๋“œ)๋ฅผ ํ†ตํ•ด ํ‘œํ˜„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ํ‘œํ˜„ ๋ฐ์ดํ„ฐ๋Š” ์š”์ฒญ์ด๋‚˜ ์‘๋‹ต์—์„œ ์ „๋‹ฌํ•  ์‹ค์ œ ๋ฐ์ดํ„ฐ ํ‘œํ˜„ ํ—ค๋”๋Š” ํ‘œํ˜„ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๋ฅผ ์ œ๊ณต ํ•ด์„ ์ •๋ณด -> ๋ฐ์ดํ„ฐ ์œ ํ˜•,

rlaehddnd0422.tistory.com

โ—๏ธ์ฐธ๊ณ 
์ฟ ํ‚ค์—๋Š” ๋งŒ๋ฃŒ๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํ•ด๋‹น ๋‚ ์งœ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ( ์›น๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋‹ซ์•„๋„ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Œ) ์˜์† ์ฟ ํ‚ค์™€,
๋ธŒ๋ผ์šฐ์ € ์ข…๋ฃŒํ•˜๊ธฐ ์ „๊นŒ์ง€๋งŒ ์œ ์ง€๋˜๋Š” ์„ธ์…˜ ์ฟ ํ‚ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. 

๋กœ๊ทธ์ธ ์„ฑ๊ณต - ์ฟ ํ‚ค ์ƒ์„ฑ

๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ์— ์„ธ์…˜ ์ฟ ํ‚ค๋ฅผ ์ƒ์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

// ์‹คํŒจ
if(loginMember == null)
{
    bindingResult.reject("loginFail","์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
    return "login/loginForm";
}

// ์ฟ ํ‚ค set
Cookie idCookie = new Cookie("memberId",String.valueOf(loginMember.getId()));
response.addCookie(idCookie);

// ์„ฑ๊ณต
return "redirect:/";

๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•˜๋ฉด ์ฟ ํ‚ค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  response ์„œ๋ธ”๋ฆฟ ๊ฐ์ฒด์— ๋‹ด์•„์„œ ๋ณด๋‚ด์ฃผ์–ด์•ผ๊ฒ ์ฃ . 

์ฟ ํ‚ค ์ด๋ฆ„์€ "memberId"๋กœ ์„ค์ •ํ–ˆ๊ณ , ๊ฐ’์€ ํšŒ์›์˜ id๋ฅผ ๋‹ด์•„๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ์ข…๋ฃŒ ์ „๊นŒ์ง€ ํšŒ์›์˜ id๋ฅผ ์„œ๋ฒ„์— ๊ณ„์† ๋ณด๋‚ด์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๋กœ๊ทธ์ธ ํ›„ ํ™•์ธํ•ด ๋ณด๋ฉด

๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ HTTP ์‘๋‹ต ํ—ค๋”์— ์ฟ ํ‚ค๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

HTTP ์‘๋‹ต ํ—ค๋”์— ์ฟ ํ‚ค๊ฐ€ ์ถ”๊ฐ€๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถ”์–ด ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•˜๋ฉด ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ™ˆ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๋„๋ก ์„ค์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

//    @GetMapping("/")
//    public String home() {
//        return "home";
//    }

    @GetMapping("/")
    public String homeLogin(@CookieValue(name="memberId", required=false) Long memberId, Model model)
    {
        if(memberId==null)
        {
            return "home";
        }
        Member loginMember = memberRepository.findById(memberId);
        if(loginMember == null)
        {
            return "home";
        }

        model.addAttribute("member",loginMember);
        return "loginHome";
    }

@CookieValue๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฟ ํ‚ค๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ํ™ˆ ํ™”๋ฉด์—์„œ๋Š” ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ home ๋ทฐํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์ฟ ํ‚ค ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ

  • ๋กœ๊ทธ์ธ ์ฟ ํ‚ค(memberId) ๊ฐ€ ์žˆ์œผ๋ฉด memberId ๊ธฐ๋ฐ˜์˜ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์ „์šฉ ํ™ˆ ํ™”๋ฉด์ธ loginForm์œผ๋กœ ๋ณด๋‚ด๊ณ  
  • ๋กœ๊ทธ์ธ ์ฟ ํ‚ค๊ฐ€ ์—†์œผ๋ฉด home์œผ๋กœ ๋ณด๋‚ด๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • loginForm์—์„œ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•˜๊ธฐ ๋ชจ๋ธ์— member๋ฅผ ๋‹ด์•„ ํ˜ธ์ถœ
<h4 class="mb-3" th:text="|๋กœ๊ทธ์ธ: ${member.name}|">๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์ด๋ฆ„</h4>

...

 <div class="col">
            <button class="w-100 btn btn-secondary btn-lg" type="button"
                    th:onclick="|location.href='@{/items}'|">
                ์ƒํ’ˆ ๊ด€๋ฆฌ
            </button>
        </div>
        <div class="col">
            <form th:action="@{/logout}" method="post">
                <button class="w-100 btn btn-dark btn-lg" type="submit">
                    ๋กœ๊ทธ์•„์›ƒ
                </button>
            </form>
        </div>
  • loginForm์—์„œ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถœ๋ ฅ
  • ์ƒํ’ˆ๊ด€๋ฆฌ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ -> /items๋กœ ์ด๋™
  • ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ -> /logout์œผ๋กœ Post ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์•„์›ƒ์„ ํ•˜๋ฉด ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์‚ญ์ œํ•œ ์ƒํƒœ๋กœ homeํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋กœ๊ทธ์•„์›ƒ - ์ฟ ํ‚ค ์‚ญ์ œ

@PostMapping("/logout")
public String logout(HttpServletResponse response)
{
    expireCookie(response,"memberId");
    return "redirect:/";
}

private void expireCookie(HttpServletResponse response, String cookieName) {
    Cookie cookie = new Cookie(cookieName, null);
    cookie.setMaxAge(0);
    response.addCookie(cookie);
}

response์—๋Š” ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ๊ฐ„์ ‘์ ์œผ๋กœ ์ฟ ํ‚ค์˜ ์œ ํšจ์‹œ๊ฐ„์„ 0์œผ๋กœ ์„ค์ •ํ•ด์„œ ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

public void deleteCookie(HttpServletResponse res){
    Cookie cookie = new Cookie("์‚ญ์ œํ•˜๊ณ  ์‹ถ์€ ์ฟ ํ‚ค ID", null); // ์‚ญ์ œํ•  ์ฟ ํ‚ค์— ๋Œ€ํ•œ ๊ฐ’์„ null๋กœ ์ง€์ •
    cookie.setMaxAge(0); // ์œ ํšจ์‹œ๊ฐ„์„ 0์œผ๋กœ ์„ค์ •ํ•ด์„œ ๋ฐ”๋กœ ๋งŒ๋ฃŒ์‹œํ‚จ๋‹ค.
    res.addCookie(cookie); // ์‘๋‹ต์— ์ถ”๊ฐ€ํ•ด์„œ ์—†์–ด์ง€๋„๋ก ํ•จ
}

https://blog.naver.com/PostView.nhn?blogId=adamdoha&logNo=222081530284 

 

[Java] ์ฟ ํ‚ค(Cookie) ์ƒ์„ฑ, ์กฐํšŒ, ์‚ญ์ œ

์„œ๋ก  JWT๋กœ ํšŒ์› ์ธ์ฆ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๋•Œ, ์ฟ ํ‚ค๋ฅผ ํ™œ์šฉํ•ด๋ณผ ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ๋งˆ๋‹ค ์ž์ฃผ ์“ฐ์ด...

blog.naver.com


์ฟ ํ‚ค ๋ณด์•ˆ ๋ฌธ์ œ

์ฟ ํ‚ค๋Š” ์ž„์˜๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ ์ƒ ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฟ ํ‚ค๋ฅผ ๊ฐ•์ œ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋กœ ์„œ๋ฒ„์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋Œ€์•ˆ

  • ์ฟ ํ‚ค์— ์ค‘์š”ํ•œ ๊ฐ’์„ ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ , ์‚ฌ์šฉ์ž ๋ณ„๋กœ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ์ž„์˜์˜ ํ† ํฐ์„ ๋…ธ์ถœํ•˜๊ณ , ์„œ๋ฒ„์—์„œ ํ† ํฐ๊ณผ ์‚ฌ์šฉ์ž id๋ฅผ ๋งคํ•‘ํ•ด์„œ ์ธ์‹ํ•˜๋Š” ๋ฐฉ๋ฒ• + ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋„๋ก ์„œ๋ฒ„์—์„œ ํ•ด๋‹น ํ† ํฐ์˜ ๋งŒ๋ฃŒ์‹œ๊ฐ„์„ ์งง๊ฒŒ ์œ ์ง€

๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ - ์„ธ์…˜ 

์„ธ์…˜ ๋™์ž‘ ๋ฐฉ์‹

์ค‘์š”ํ•œ ์ •๋ณด๋Š” ๋ชจ๋‘ ์„œ๋ฒ„์— ์ €์žฅํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋Š” ์ถ”์ • ๋ถˆ๊ฐ€๋Šฅํ•œ ์ž„์˜์˜ ์‹๋ณ„์ž๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ์‹์„ ์„ธ์…˜์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ค‘์š”ํ•œ ์ •๋ณด์˜ ๊ฐ’์„ ์ง์ ‘ ์ฟ ํ‚ค๋กœ ์„ค์ •ํ•ด๋‘๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ’์„ ํ†ตํ•ด ์„œ๋ฒ„์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ์ „ 

1. ID, PASSWORD๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ๋กœ๊ทธ์ธ ์š”์ฒญ

2. ์„œ๋ฒ„์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ID, PASSWORD๋ฅผ ํ†ตํ•ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ํšŒ์› ์กฐํšŒ

3. ์ผ์น˜ํ•˜๋Š” ๋ฉค๋ฒ„ ๋ฆฌํ„ด

4. UUID ๊ธฐ๋ฐ˜ ํ† ํฐ์„ ํ•˜๋‚˜ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์„ธ์…˜์— Token - ๋ฉค๋ฒ„ ์ €์žฅ

5. response์— Token์„ ์ฟ ํ‚ค์— ๋‹ด์•„์„œ ํด๋ผ์ด์–ธํŠธ์— ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

 

๋กœ๊ทธ์ธ ์ดํ›„

6. ๋ฐ›์€ ์ฟ ํ‚ค์˜ ํ† ํฐ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ GET ์š”์ฒญ

+ ์„œ๋ฒ„๋Š” ์„ธ์…˜์ €์žฅ์†Œ์˜ ํ† ํฐ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฉค๋ฒ„๋ฅผ ๋ฆฌํ„ดํ•ด์„œ ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต

 

์ด๋ ‡๊ฒŒ ์„ธ์…˜์„ ์‚ฌ์šฉํ•ด ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ์„œ๋ฒ„์—์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ํ† ํฐ ๊ฐ’์„ ์ฟ ํ‚ค๋กœ ์„ค์ •ํ•ด ํด๋ผ์ด์–ธํŠธ๋Š” ์ฟ ํ‚ค๊ฐ’์„ ์˜ˆ์ธกํ•ด์„œ ์„ค์ •ํ•ด์„œ ์„œ๋ฒ„์— ์š”์ฒญํ•  ์ˆ˜ ์—†๋„๋ก ์„ค์ •ํ•ด ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์„ธ์…˜์„ ์ง์ ‘ ๊ฐœ๋ฐœํ•ด๋ณธ ํ›„, ์Šคํ”„๋ง์ด ์ง€์›ํ•˜๋Š” ์„ธ์…˜์„ ์‚ฌ์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์„ธ์…˜ ์ง์ ‘ ๊ฐœ๋ฐœ

SessionManager์— ์„ธ์…˜ ์ƒ์„ฑ, ์กฐํšŒ, ์‚ญ์ œ ๊ตฌํ˜„ 

public static final String SESSION_COOKIE_NAME = "mySessionId";

// key - uuid , value - ๊ฐ์ฒด
private Map<String, Object> sessionStore = new ConcurrentHashMap<>();

 

์„ธ์…˜ ์ƒ์„ฑ

private Map<String, Object> sessionStore = new ConcurrentHashMap<>();

// ์„ธ์„  ์ƒ์„ฑ
public void createSession(Object value, HttpServletResponse response)
{
    String sessionId = UUID.randomUUID().toString();
    sessionStore.put(sessionId,value);
    Cookie mySessionCookie = new Cookie(SESSION_COOKIE_NAME, sessionId);
    response.addCookie(mySessionCookie);
}
  • ์„ธ์…˜์„ ์ง์ ‘ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•ด Map์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. 
  • ์ƒ์„ฑํ•  ๋•Œ์—๋Š” UUID๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ํ† ํฐ์œผ๋กœ ์„ค์ •ํ•ด์„œ ์„ธ์…˜ ์ €์žฅ์†Œ์— ๋„ฃ์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒ์„ฑํ•œ ํ† ํฐ์„ ์ฟ ํ‚ค๋กœ ์„ค์ •ํ•ด์„œ response์— ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์„ธ์…˜ ์กฐํšŒ

// ์„ธ์…˜ ์กฐํšŒ
public Object getSession(HttpServletRequest request)
{
    Cookie sessionCookie = findCookie(request, SESSION_COOKIE_NAME);
    if(sessionCookie==null)
    {
        return null;
    }
    return sessionStore.get(sessionCookie.getValue());
}
private Cookie findCookie(HttpServletRequest request, String cookieName)
{
    if(request.getCookies()==null)
    {
        return null;
    }
    return Arrays.stream(request.getCookies())
            .filter(c -> c.getName().equals(cookieName))
            .findAny()
            .orElse(null);
}
  • request์—์„œ ์ฟ ํ‚ค๊ฐ€ ์—†์œผ๋ฉด null ๋ฆฌํ„ด
  • request์— cookieName์˜ ์ฟ ๊ธฐ๊ฐ€ ์žˆ์œผ๋ฉด ์„ธ์…˜ ์ €์žฅ์†Œ์—์„œ ํ† ํฐ์— ๋งค์นญ๋œ ํšŒ์› ๋ฆฌํ„ด, ์—†์œผ๋ฉด null ๋ฆฌํ„ด

์„ธ์…˜ ๋งŒ๋ฃŒ

// ์„ธ์…˜ ๋งŒ๋ฃŒ
public void expire(HttpServletRequest request)
{
    Cookie sessionCookie = findCookie(request,SESSION_COOKIE_NAME);
    if(sessionCookie!=null)
    {
        sessionStore.remove(sessionCookie.getValue());
    }
}
  • request์—์„œ ์„ธ์…˜์„ ์กฐํšŒํ•ด ํ•ด๋‹น ์„ธ์…˜์žˆ์œผ๋ฉด ์„ธ์…˜ ์ €์žฅ๋งต์—์„œ ์‚ญ์ œ

 

์ปจํŠธ๋กค๋Ÿฌ์— ์ ์šฉ

@PostMapping("/login")
public String loginV2(@Valid @ModelAttribute LoginForm loginForm, BindingResult bindingResult,
                      HttpServletResponse response)
{
    if(bindingResult.hasErrors())
    {
        return "login/loginForm";
    }

    Member loginMember = loginService.login(loginForm.getLoginId(),loginForm.getPassword());

    // ์‹คํŒจ
    if(loginMember == null)
    {
        bindingResult.reject("loginFail","์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        return "login/loginForm";
    }

    // ์„ธ์…˜๊ด€๋ฆฌ์ž๋ฅผ ํ†ตํ•ด ์„ธ์…˜์ƒ์„ฑ -> ํšŒ์›๋ฐ์ดํ„ฐ ๋ณด๊ด€
    sessionManager.createSession(loginMember,response);

    // ์„ฑ๊ณต
    return "redirect:/";
}
  • private final SessionManager sessionManager; - ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… 
  • sessionManager.createSession(loginMember, response);
    • ๋กœ๊ทธ์ธ ์„ฑ๊ณต์‹œ ์„ธ์…˜์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ์„ธ์…˜์— loginMember ๋ฅผ ์ €์žฅํ•ด๋‘๊ณ , ์ฟ ํ‚ค(ํ† ํฐ, loginMember)๋„ ๋ฐœํ–‰.

HomeController ๋ณ€๊ฒฝ - ๋กœ๊ทธ์ธ ํ›„ ํ™”๋ฉด

@GetMapping("/")
public String homeLoginV2(HttpServletRequest request, Model model)
{
    // ์„ธ์…˜๊ด€๋ฆฌ์ž์— ์ €์žฅ๋œ ํšŒ์› ์ •๋ณด ์กฐํšŒ
    Member member = (Member) sessionManager.getSession(request);
    if(member == null)
    {
        return "home";
    }

    model.addAttribute("member",member);
    return "loginHome";
}
  • ํ™ˆ์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ด์„œ Get ์š”์ฒญ์‹œ ์„ธ์…˜๊ด€๋ฆฌ์ž์— ์ €์žฅ๋œ ํšŒ์› ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด ๋ฆฌํ„ด๋ฐ›์€ Object๋ฅผ ํƒ€์ž…์„ ๋ฉค๋ฒ„๋กœ ๋ณ€ํ™˜ํ•ด์ค€ ํ›„ 
  • ํ•ด๋‹น ๋ฉค๋ฒ„๊ฐ€ ์—†์œผ๋ฉด home ๋ทฐํ…œํ”Œ๋ฆฟ ํ˜ธ์ถœํ•˜๊ณ 
  • ํ•ด๋‹น ๋ฉค๋ฒ„๊ฐ€ ์žˆ์œผ๋ฉด model์— ํ•ด๋‹น ๋ฉค๋ฒ„๋ฅผ ๋‹ด๊ณ  loginHome์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
@PostMapping("/logout")
public String logoutV2(HttpServletRequest request)
{
    sessionManager.expire(request);
    return "redirect:/";
}
// ์„ธ์…˜ ๋งŒ๋ฃŒ
public void expire(HttpServletRequest request)
{
    Cookie sessionCookie = findCookie(request,SESSION_COOKIE_NAME);
    if(sessionCookie!=null)
    {
        sessionStore.remove(sessionCookie.getValue());
    }
}
  • loginHome์—์„œ ๋กœ๊ทธ์•„์›ƒ ๋ฒ„ํŠผ ํด๋ฆญํ•˜๋ฉด /logout URL ์š”์ฒญ โ–ถ๏ธŽ request์—์„œ SESSION_COOKIE_NAME("mySessionId")์˜ ์ฟ ํ‚ค๋ฅผ ์ฐพ๊ณ  ๋งต์—์„œ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ญ์ œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ํ™ˆ์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ - ์„œ๋ธ”๋ฆฟ HTTP ์„ธ์…˜

์ด๋ ‡๊ฒŒ ์ง์ ‘ ์„ธ์…˜์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋Š”๋ฐ, ์‚ฌ์‹ค ์„ธ์…˜์ด๋ผ๋Š” ๊ฒƒ๋„ ๊ฒฐ๊ตญ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๋งˆ๋‹ค ์ด๋ ‡๊ฒŒ ์„ธ์…˜ ๊ฐœ๋…์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ๋„ ์ƒ๋‹นํžˆ ๋ถˆํŽธํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์„œ๋ธ”๋ฆฟ๋„ ์„ธ์…˜๊ฐœ๋…์„ ์ œ๊ณตํ•˜๋Š”๋ฐ ์„œ๋ธ”๋ฆฟ์ด ์ œ๊ณตํ•˜๋Š” ์„ธ์…˜์„ ์‚ฌ์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋™์ž‘ ๋ฐฉ์‹์€ ์ด์ „๊ณผ ๊ฑฐ์˜ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

 

์„œ๋ธ”๋ฆฟ์ด ์ œ๊ณตํ•˜๋Š” HttpSession์€ ์„ธ์…˜์„ ์ƒ์„ฑ, ์กฐํšŒ, ์‚ญ์ œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ง์ ‘ ๊ฐœ๋ฐœํ•  ๋•Œ ์‚ฌ์šฉํ•œ sessionManager์˜ ์—ญํ• ์„ HttpSession์œผ๋กœ ๋Œ€์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

login ์š”์ฒญ ์ปจํŠธ๋กค๋Ÿฌ

@PostMapping("/login")
public String loginV3(@Valid @ModelAttribute LoginForm loginForm, BindingResult bindingResult,
                      HttpServletRequest request)
{
    // Field, ํƒ€์ž… ์˜ค๋ฅ˜ ๊ฒ€์ฆ
    if(bindingResult.hasErrors())
    {
        return "login/loginForm";
    }

    Member loginMember = loginService.login(loginForm.getLoginId(),loginForm.getPassword());

    // ์‹คํŒจ
    if(loginMember == null)
    {
        bindingResult.reject("loginFail","์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        return "login/loginForm";
    }


    // ์„ฑ๊ณต์ฒ˜๋ฆฌ
    // ์„ธ์…˜์ด ์žˆ์œผ๋ฉด ์žˆ๋Š” ์„ธ์…˜ ๋ฐ˜ํ™˜, ์—†์œผ๋ฉด ์‹ ๊ทœ ์„ธ์…˜ ์ƒ์„ฑ
    HttpSession session = request.getSession(true);

    // ์„ธ์…˜์— ๋กœ๊ทธ์ธ ํšŒ์› ์ •๋ณด ๋ณด๊ด€
    session.setAttribute(SessionConst.LOGIN_MEMBER,loginMember);

    return "redirect:/";
}
// ์„ธ์…˜๊ด€๋ฆฌ์ž๋ฅผ ํ†ตํ•ด ์„ธ์…˜์ƒ์„ฑ -> ํšŒ์›๋ฐ์ดํ„ฐ ๋ณด๊ด€
sessionManager.createSession(loginMember,response);

์ด ์ „์— ์‚ฌ์šฉํ•˜๋˜ sessionmanager์˜ ์—ญํ• ์„ HttpSession์„ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

// ์„ฑ๊ณต์ฒ˜๋ฆฌ
// ์„ธ์…˜์ด ์žˆ์œผ๋ฉด ์žˆ๋Š” ์„ธ์…˜ ๋ฐ˜ํ™˜, ์—†์œผ๋ฉด ์‹ ๊ทœ ์„ธ์…˜ ์ƒ์„ฑ

HttpSession session = request.getSession(true);

// ์„ธ์…˜์— ๋กœ๊ทธ์ธ ํšŒ์› ์ •๋ณด ๋ณด๊ด€
session.setAttribute(SessionConst.LOGIN_MEMBER,loginMember);
  • request์— ์„ธ์…˜์ด ์žˆ์œผ๋ฉด ๊ธฐ์กด ์„ธ์…˜ ๋ฆฌํ„ด, ์—†์œผ๋ฉด ์ƒ์„ฑํ•ด์„œ ๋ฆฌํ„ด (true)
    • false์ผ ๊ฒฝ์šฐ ์„ธ์…˜์ด ์žˆ์œผ๋ฉด ๊ธฐ์กด ์„ธ์…˜ ๋ฆฌํ„ด, ์—†์œผ๋ฉด null ๋ฐ˜ํ™˜
  • ์„ธ์…˜์— ๋กœ๊ทธ์ธ ํšŒ์› ์ •๋ณด๋ฅผ setAttribute๋ฅผ ํ†ตํ•ด ๋ณด๊ด€ํ•˜๊ณ  ํ™ˆ์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.
    • ์—ฌ๊ธฐ์„œ Session.LOGIN_MEMBER๋Š” HttpSession์— ์„ธ์…˜์„ ๋ณด๊ด€ํ•˜๊ณ  ์กฐํšŒํ•  ๋•Œ ๊ฐ™์€ ์ด๋ฆ„์ด ์ค‘๋ณต๋˜์–ด ์‚ฌ์šฉ๋˜๋ฏ€๋กœ, ์ƒ์ˆ˜๋ฅผ "loginMember"๋กœ ์ •์˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ›„ ํ™”๋ฉด 

@GetMapping("/")
public String homeLoginV3(HttpServletRequest request, Model model)
{
    HttpSession session = request.getSession(false);
    if(session==null)
    {
        return "home";
    }

    // ์„ธ์…˜๊ด€๋ฆฌ์ž์— ์ €์žฅ๋œ ํšŒ์› ์ •๋ณด ์กฐํšŒ
    Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);

    // ์„ธ์…˜์— ํšŒ์› ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด home์œผ๋กœ ์ด๋™
    if(loginMember==null)
    {
        return "home";
    }

    // ์„ธ์…˜์ด ์œ ์ง€๋˜๋ฉด ๋กœ๊ทธ์ธ์œผ๋กœ ์ด๋™

    model.addAttribute("member",loginMember);
    return "loginHome";
}
  • ๋กœ๊ทธ์ธ ์‹œ์ ์˜ request์—์„œ ์„ธ์…˜์„ ์ฐพ๊ณ  ์„ธ์…˜์ด ์—†์œผ๋ฉด home ๋ทฐํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  • ์„ธ์…˜์ด ์žˆ์œผ๋ฉด ๋กœ๊ทธ์ธ ์‹œ์ ์— ์„ธ์…˜์— ๋ณด๊ด€ํ•œ ํšŒ์› ๊ฐ์ฒด๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. 
  • ์„ธ์…˜ ๊ด€๋ฆฌ์ž์— ์ €์žฅ๋œ ํšŒ์› ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด ํ•ด๋‹น ํšŒ์› ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด home์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  • ์„ธ์…˜์ด ์œ ์ง€๋˜๋ฉด loginHome์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์•„์›ƒ ์‹œ

@PostMapping("/logout")
public String logoutV3(HttpServletRequest request)
{
   HttpSession session = request.getSession(false);
   if(session!=null)
   {
       session.invalidate(); // ์„ธ์…˜ ์‚ญ์ œ
   }
   return "redirect:/";
}
  • false์˜ต์…˜์„ ํ†ตํ•ด ์„ธ์…˜์ด ์žˆ๋Š”๊ฒฝ์šฐ ๋ฆฌํ„ด, ์—†์œผ๋ฉด null ๋ฆฌํ„ด ( ์ƒ์„ฑํ•˜์ง€ ์•Š์Œ )
  • session์ด ์กด์žฌํ•˜๋ฉด invalidate()๋ฅผ ํ†ตํ•ด ์„ธ์…˜์„ ์‚ญ์ œํ•˜๊ณ  ํ™ˆ ํ™”๋ฉด์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•˜๊ฒŒ HttpSession์„ ์ด์šฉํ•ด ์ง์ ‘ ๊ฐœ๋ฐœํ•œ ์„ธ์…˜์„ ๋Œ€์ฒดํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์Šคํ”„๋ง์€ ์—ฌ๊ธฐ์„œ ๋” ๋‚˜์•„๊ฐ€ ์„ธ์…˜์„ ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก @SessionAttribute๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

 

@GetMapping("/")
public String homeLoginV3Spring(@SessionAttribute(name=SessionConst.LOGIN_MEMBER, required=false)
                                    Member loginMember, Model model)
{
    // ์„ธ์…˜์— ํšŒ์› ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด home์œผ๋กœ ์ด๋™
    if(loginMember==null)
    {
        return "home";
    }

    // ์„ธ์…˜์ด ์œ ์ง€๋˜๋ฉด ๋กœ๊ทธ์ธ์œผ๋กœ ์ด๋™

    model.addAttribute("member",loginMember);
    return "loginHome";
}

@SessionAttribute๋ฅผ ํ†ตํ•ด ์ด๋ฏธ ๋กœ๊ทธ์ธ ๋œ ์‚ฌ์šฉ์ž๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ธ์…˜์„ ์ฐพ๊ณ , ์„ธ์…˜์— ๋“ค์–ด์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๋Š” ๋ฒˆ๊ฑฐ๋กœ์šด ๊ณผ์ •์„ ์Šคํ”„๋ง์ด ํ•œ๋ฒˆ์— ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

HtttpSession์„ ์‚ฌ์šฉํ•œ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์ฒ˜์Œ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•˜๋ฉด ๋กœ๊ทธ์ธ ํ›„ ํ™”๋ฉด์—
http://localhost:8080/;jsessionid=F59911518B921DF62D09F0DF8F83F872 ์ฒ˜๋Ÿผ jessionid๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿด๋•Œ application.properties์— server.servlet.session.tracking-modes=cookie๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด URL ์ „๋‹ฌ ๋ฐฉ์‹ ์‚ฌ์šฉ์„ ํ•ด์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์„ธ์…˜ ํƒ€์ž„์•„์›ƒ ์„ค์ • ๋ฐ ์„ธ์…˜ ์ •๋ณด ํ™•์ธ

@GetMapping("/session-info")
public String sessionInfo(HttpServletRequest request)
{
    HttpSession session = request.getSession(false);
    if(session==null)
    {
        return "์„ธ์…˜์ด ์—†์Šต๋‹ˆ๋‹ค.";
    }

    session.getAttributeNames().asIterator()
            .forEachRemaining(name -> log.info("session name = {}, value = {}",name,session.getAttribute(name)));

    log.info("sessionId={}", session.getId());
    log.info("maxInactiveInterval={}", session.getMaxInactiveInterval());
    log.info("creationTime={}", new Date(session.getCreationTime()));
    log.info("lastAccessedTime={}", new Date(session.getLastAccessedTime()));
    log.info("isNew={}", session.isNew());
    return "์„ธ์…˜ ์ถœ๋ ฅ";
}

์„ธ์…˜์˜ ์œ ํšจ๊ธฐ๊ฐ„์€ application.properties์— server.servlet.session.timeout=60 ( ์ดˆ ๋‹จ์œ„ )์™€ ๊ฐ™์ด ๊ธ€๋กœ๋ฒŒํ•˜๊ฒŒ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๊ณ ,

setMaxInactiveInterval์„ ํ†ตํ•ด ์„ธ์…˜ ๋‹จ์œ„๋กœ ์œ ํšจ๊ธฐ๊ฐ„์„ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐฑ์‹ ์‹œ๊ฐ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ํšจ๊ธฐ๊ฐ„์ด ์ง€๋‚˜๋ฉด ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค.

session์€ lastAccessdTime์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ํšจ๊ธฐ๊ฐ„์ด ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.


<์ •๋ฆฌ>

  • ์ง€๊ธˆ๊นŒ์ง€ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„๋ถ€ํ„ฐ ์ฟ ํ‚ค๋ฅผ ํ†ตํ•œ ์ฒ˜๋ฆฌ, ์„ธ์…˜์„ ํ†ตํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„, ์„œ๋ธ”๋ฆฟ์ด ์ œ๊ณตํ•˜๋Š” HttpSession์„ ์‚ฌ์šฉํ•œ ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ๊นŒ์ง€ ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.
  • ์„œ๋ธ”๋ฆฟ์˜ HttpSession์ด ์ œ๊ณตํ•˜๋Š” ํƒ€์ž„ ์•„์›ƒ ๊ธฐ๋Šฅ ๋•๋ถ„์— ์„ธ์…˜์„ ์•ˆ์ „ํ•˜๊ณ  ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‹ค๋ฌด์—์„œ ์ฃผ์˜ํ• ์ ์€ ์„ธ์…˜์—๋Š” ์ตœ์†Œํ•œ์˜ ๋ฐ์ดํ„ฐ๋งŒ ๋ณด๊ด€ *๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ดˆ๊ณผ๋กœ ์„œ๋ฒ„ ์žฅ์• ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

<์ฐธ๊ณ ์ž๋ฃŒ>

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard

 

์Šคํ”„๋ง MVC 2ํŽธ - ๋ฐฑ์—”๋“œ ์›น ๊ฐœ๋ฐœ ํ™œ์šฉ ๊ธฐ์ˆ  - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋ชจ๋“  ์›น ๊ธฐ์ˆ ์„ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์ดํ•ดํ•˜๊ณ , ์™„์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MVC 2ํŽธ์—์„œ๋Š” MVC 1ํŽธ์˜ ํ•ต์‹ฌ ์›๋ฆฌ์™€ ๊ตฌ์กฐ ์œ„์— ์‹ค๋ฌด ์›น ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋ชจ๋“  ํ™œ์šฉ ๊ธฐ์ˆ ๋“ค์„ ํ•™์Šตํ•  ์ˆ˜ ์žˆ

www.inflearn.com

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ