# 구글 로그인 테스트
## 미션
---
로그인 버튼을 클릭하여,

구글 로그인을 수행하고,

로그인 여부를 DB등을 통해 확인하시오.

## 개념
---
## 튜토리얼
---
#### ⭐️ 로그인/로그아웃 버튼 만들기
1) 헤더 변경: "layouts/header.mustache"
```
...
<!-- navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
...
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="/articles">Article</a>
</li>
</ul>
<!-- 부분 화면, 불러오기! -->
{{>layouts/_login-nav}}
</div>
</nav>
```
2) 부분 화면 생성: "layouts/_login-nav.mustache"
```
<!-- 로그인 상태 창 -->
<ul class="navbar-nav ml-auto">
<!-- 로그인 버튼 -->
<li class="nav-item active">
<!-- "/oauth2/authorization/google", 스프링 시큐리티 OAuth2의 구글 로그인 주소 -->
<a class="nav-link" href="/oauth2/authorization/google">로그인</a>
</li>
<!-- 로그아웃 버튼 -->
<li class="nav-item active">
<!-- "/logout", 스프링 시큐리티의 기본 로그아웃 URL! 스프링 시큐리티에서 변경 가능 -->
<a class="nav-link" href="/logout">로그아웃</a>
</li>
</ul>
```
#### ⭐️ 로그인 해보기
3) 로그인 하기: 로그인 클릭 후, 구글 로그인 페이지로 이동!

4) 로그인 성공 후, 사용자 DB 확인: "현재 GUEST 권한 임!"

#### ⭐️ 글 써보기
5) 글쓰기 테스트: "GUEST"는 글 쓸 수 없음!

6) 권한 부여 및 재도전: "GUEST"를 "USER"로 바꾸고, 재 로그인 후, 글쓰기!

#### ⭐️ 로그인 상태 별, 버튼 보이기
7) 로그인/로그아웃 내용 변경: "layouts/_login-nav.mustache"
```
<!-- 로그인 상태 창 -->
<ul class="navbar-nav ml-auto">
<!-- 로그인이 안된 경우(userName이 없다면?) -->
{{^userName}}
<!-- 로그인 버튼 -->
<li class="nav-item active">
<!-- "/oauth2/authorization/google", 스프링 시큐리티 OAuth2의 구글 로그인 주소 -->
<a class="nav-link" href="/oauth2/authorization/google">로그인</a>
</li>
{{/userName}}
<!-- 로그인 된 경우(userName이 있다면?) -->
{{#userName}}
<!-- 로그아웃 버튼 -->
<li class="nav-item active">
<!-- "/logout", 스프링 시큐리티의 기본 로그아웃 URL! 스프링 시큐리티에서 변경 가능 -->
<a class="nav-link" href="/logout">로그아웃</a>
</li>
{{/userName}}
</ul>
```
8) 사용자 이름 등록: "controller/ArticleController#index()"
```
...
public class ArticleController {
private final ArticleRepository articleRepository;
// HTTP 통신의 Session 객체가 자동 삽입! 위에서 @RequiredArgsConstructor 했음!
private final HttpSession httpSession;
@GetMapping("/articles")
public String index(Model model) {
Iterable<Article> articleList = articleRepository.findAll();
model.addAttribute("articles", articleList);
// 세션에서 키가 "user"인 객체를 가져와, 이를 캐스팅(Object -> SessionUser)해 가져옴!
SessionUser user = (SessionUser) httpSession.getAttribute("user");
// 사용자가 있다면? 사용자 이름을 등록!
if (user != null) {
model.addAttribute("userName", user.getName());
}
// 뷰 페이지 설정
return "articles/index";
}
...
}
...
```
9) 결과 확인: 로그인 사용자는 로그아웃이 출력되고, 비로그인 사용자는 로그인 버튼이 나옴! (세션이 남아있어 에러 날 수 있음! 로그아웃 후 진행 할 것)

## 훈련하기
---
- 소셜 로그인으로 회원 가입 시, 바로 USER가 될 수 있게 해보자.
- 위 튜토리얼은 "로그인/로그아웃" 버튼 출력에 문제가 있다. 이는 `/articles` URL에서만 정상 동작하는데, 왜 그런지 설명하시오.
## 면접 질문
---
- 모든 url에서 정상 동작하게 하려면 어떻게 해야할까?
- 필터, 인터셉터, AOP 차이? (https://goddaehee.tistory.com/154)
- 인터셉터란? (https://congsong.tistory.com/24)
- 스프링 시큐리티란? (https://sjh836.tistory.com/165)