ํ์๊ฐ์ ๊น์ง ๋ง๋ค์๋ค.
์ด์ ํ์๊ฐ์ ํ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ก
๋ก๊ทธ์ธ์ ํด๋ณด์!
[SpringBoot] (IntelliJ, vue.js, H2) ํ์๊ฐ์ ํ์ด์ง ๋ง๋ค๊ธฐ 1ํธ : dto ๋ง๋ค๊ณ ์ด๋ฆ, ํจ์ค์๋, ์ ํ๋ฒํธ ํจ
๋๋ถ๋ถ์ ์น์ฌ์ดํธ๋ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๊ฐ์ง๋ค.๊ทธ ์ค ํ์๊ฐ์ ๊ธฐ๋ฅ์ ๋ง๋ค์ด๋ณด์! 1. ํ๋ฉด ๋์๊ณผ ์ ์ฒด์ฝ๋ํ์๊ฐ์ ์์ ํ์๊ฐ์ ์ค๋ณต ๋๋ ํ ๋ฆฌ์ ํด๋์ค Vue์ Spring์ ์ฐ๊ฒฐํด์ฃผ๋ dto
post-this.tistory.com
[SpringBoot] (IntelliJ, vue.js, H2) ํ์๊ฐ์ ํ์ด์ง ๋ง๋ค๊ธฐ 2ํธ : ์์ด๋, ์ด๋ฉ์ผ ์ค๋ณต์ฒดํฌ ๋ง๋ค๊ธฐ.
์ด๋ฆ, ๋น๋ฐ๋ฒํธ, ์ ํ๋ฒํธ๋ฅผํจํด ์ฒดํฌ๋ฅผ ํ์๋ค.์ด๋ฒ์๋ ์์ด๋์ ์ด๋ฉ์ผ์์ค๋ณต ์ฒดํฌ ํด๋ณด์! [ ํ์๊ฐ์ ํ์ด์ง ๋ง๋ค๊ธฐ 1ํธ : ์ด๋ฆ, ํจ์ค์๋, ์ ํ๋ฒํธ ํจํด ์ฒดํฌ ]์ด๊ณณ์ ๋ค์ด๊ฐ์๋ฉด ํ์ด์ง
post-this.tistory.com
1. ํ๋ฉด ๋์๊ณผ ์ ์ฒด ์ฝ๋
- ํ๋ฉด ๋์
- LoginView ์ฝ๋(vue)
Register-Web-frontend/src/views/LoginView.vue at master · hyeong-ing/Register-Web-frontend
์ผ๋ฐ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ, ๊ฐํธ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ์ ๊ตฌํํ์ต๋๋ค. WebStrom์ผ๋ก Vue.js์ Vite๋ฅผ ์ฌ์ฉํ์ต๋๋ค. - hyeong-ing/Register-Web-frontend
github.com
- CustomerRight ์ฝ๋(vue)
Register-Web-frontend/src/components/customer/CustomerRight.vue at master · hyeong-ing/Register-Web-frontend
์ผ๋ฐ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ, ๊ฐํธ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ์ ๊ตฌํํ์ต๋๋ค. WebStrom์ผ๋ก Vue.js์ Vite๋ฅผ ์ฌ์ฉํ์ต๋๋ค. - hyeong-ing/Register-Web-frontend
github.com
- login ๋๋ ํฐ๋ฆฌ(spring)
Register-Web-backend/src/main/java/com/example/JoinWeb/login at master · hyeong-ing/Register-Web-backend
์ผ๋ฐ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ, ๊ฐํธ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ์ ๊ตฌํํ์ต๋๋ค. Contribute to hyeong-ing/Register-Web-backend development by creating an account on GitHub.
github.com
- ๋๋ ํฐ๋ฆฌ์ ํด๋์ค
2. ์ด๋ป๊ฒ ๋ง๋ค๊น?
- ๋ก๊ทธ์ธ ํ๋ฉด
์์ด๋์ ํจ์ค์๋๊ฐ ์ ๋ ฅ๋์ง ์์ผ๋ฉด, ๊ทธ์ ๋ง๋ alert์ด ์ถ๋ ฅ๋๋ค. ๊ทธ๋ฆฌ๊ณ DB์ ์ ์ฅ๋์ด ์๋ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ํ์ธํ๊ณ ๋ง์ผ๋ฉด ๋ก๊ทธ์ธ์ด ๋๋๋ก ๋ง๋ค์๋ค.
ํ์๊ฐ์ ๋ณด๋ค ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๋ง๋๋ ๊ฒ ๋ ๊ฐ๋จํ๋ค. ๋ค๋ง ์ ๋ฐ์ ์๋ ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ์ด ์ฃฝ์ ๋ง์ด์๋ค. ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ ํฌ์คํ ์ ๋ค์์...๐
๋ก๊ทธ์ธ์ ๋๋ฅด๊ณ ์ฑ๊ณตํ๋ฉด ๋ก๊ทธ์ธ์ด ๋์๋ค๋ ๋ฉ์์ง๊ฐ ๋ํ๋๊ณ , ์คํจํ๋ฉด ์์ด๋๋ ๋น๋ฐ๋ฒํธ๋ฅผ ํ์ธํด ๋ฌ๋ผ๋ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๋ค.
๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๊ฒ ๋๋ฉด ํ๋ฉด์ด ์ ํ๋๋๋ฐ, ์ฌ์ฉ์์ ์์ด๋๊ฐ ํ์๋๋๋ก ํ๋ค.
- ๋ก๊ทธ์ธ ์ฑ๊ณต ํ๋ฉด
3. LoginView.vue
<template> ์ฝ๋
<div class="login-container">
<div class="id-box">
<p>เท ID </p>
<input v-model="userId" @input="userId" type="text" name="userId" placeholder="id"/>
</div>
<div class="pw-box">
<p>เท PW </p>
<input v-model="pw" type="password" name="password" placeholder="password"/>
</div>
<button class="login-text" @click="login"> SIGN IN </button>
</div>
์์ด๋์ ํจ์ค์๋๋ฅผ ์ ๋ ฅํ ์ ์๋ ์นธ์ ๋ง๋ค์๋ค. ์ฝ๋์์ ์์ด๋์ ํจ์ค์๋์ v-model์ ์ ์ํ๋ค. v-model์ ์๋ฐฉํฅ ๋ฐ์ธ๋ฉ์ผ๋ก ์ ๋ ฅ์ฐฝ ๊ฐ์ด ๋ฐ๋๋ฉด ๋ฐ์ดํฐ๊ฐ ์๋์ผ๋ก ์ ๋ฐ์ดํธ๋๊ณ , ๋ฐ๋๋ก ๋ฐ์ดํฐ๊ฐ ๋ฐ๋๋ฉด ํ๋ฉด์ ์ ๋ ฅ๊ฐ๋ ์๋์ผ๋ก ๋ฐ๋๋ค.
<script> ์ฝ๋
name: 'LoginView',
data() {
return {
userId: "",
pw: ""
};
},
v-model์ ์ด ์์ด๋์ ํจ์ค์๋๋ input๊ณผ ์ฐ๊ฒฐ๋๊ณ ์ ๋ ฅ์ฐฝ์ ๊ฐ์ด ๋ฐ๋๋ฉด data( ) ๊ฐ์ด ์๋์ผ๋ก ๋ฐ๋๋ค.
/* ํ์ ์ฝ๋๊ฐ ์์ ๋์์ต๋๋ค.(๋ก๊ทธ์ธ ์ฑ๊ณต ํ ํ๋ฉด ์ฝ๋๊ฐ ๋ฐ๋) */
methods: {
async login() {
/* ๋ก๊ทธ์ธ ์ฑ๊ณต ์ฝ๋ */
try {
/* ์ต์ ๋ฐ์ดํฐ๋ฅผ ํด๋น ๊ฒฝ๋ก๋ก ๋ณด๋ด๊ธฐ */
const res = await axios.post("http://localhost:8080/api/login", {
/* ๋ณด๋ผ ๋ฐ์ดํฐ */
userId: this.userId,
pw: this.pw
});
/* ๋ก๊ทธ์ธ ์ฑ๊ณต ๋ฉ์์ง */
alert("๋ก๊ทธ์ธ๋์์ต๋๋ค.");
/* userId๋ฅผ ์ ์ ์ ์ฅ */
localStorage.setItem("displayName", this.userId);
/* ๋ก๊ทธ์ธ ์ฑ๊ณตํ๋ฉด path์ ์ ํ ๊ฒฝ๋ก๋ก ๋๊น, query์ ์ ์ ๋ฐ์ดํฐ์ ํจ๊ป */
this.$router.push({
path: "/customer-view",
query: { userId: this.userId }
});
} catch (e) { /* ๋ก๊ทธ์ธ ์คํจ ์ฝ๋ */
alert(e.response.data); /* ์คํจ ์์ธ์ ๋ง๋ ์ค๋ฅ๋ฉ์์ง */
}
}
}
spring์ผ๋ก ์์ด๋์ ํจ์ค์๋๋ฅผ ๋ณด๋ด ๋ก์ง์ ์ฒ๋ฆฌํ์ฌ ๋ก๊ทธ์ธ์ด ๋๋๋ก ๋ง๋ค ๊ฒ์ด๋ค. ๊ทธ๋์ post๋ก ํด๋น ๊ฒฝ๋ก์ ๊ฐ์ฅ ์ต์ ๊ฐ์ธ userId์ pw๋ฅผ ๋ณด๋๋ค. ์ต์ ๊ฐ์ด ์ฌ ์ ์๋ ์ด์ ๋ v-model์ ์ผ๊ธฐ ๋๋ฌธ!
try์๋ ๋ก๊ทธ์ธ์ด ์ฑ๊ณต๋๊ธฐ ์ํ ์ฝ๋์ ์ฑ๊ณต ์ดํ์ ๋ํ ์ฝ๋๋ฅผ ์ ๋๋ค. catch๋ ์คํจํ ๊ฒฝ์ฐ์ ๋ํ ์ฝ๋๋ฅผ ์ ๋๋ค๊ณ ๋ณด๋ฉด ๋๋ค. ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๊ฒ ๋๋ฉด "๋ก๊ทธ์ธ๋์์ต๋๋ค."๊ฐ alert ๋๊ณ , ๋ก๊ทธ์ธ์ด ๋๋ฉด ๋ณด์ฌ์ค ํ์ด์ง๋ฅผ ์ ์๋ค. ์ด ๋ถ๋ถ์ ํ์ ์์ ํ๊ฒ ๋ค.
๋ก๊ทธ์ธ์ ์คํจํ ๊ฒฝ์ฐ ์ ์คํจํ๋์ง์ ๋ํ ๊ฐ๋จํ ๋ฉ์์ง๋ฅผ spring์๊ฒ ๋ฐ์ ๊ฒ์ด๋ค. ๊ทธ๋์ response.data๋ผ๊ณ ๋์ด์๋ค. ์๋ต์ผ๋ก ์จ ๋ฉ์์ง๋ฅผ ๊ทธ๋๋ก ์ถ๋ ฅํ๋ค.
์์ธํ ์ฝ๋๋ git์ ์์ผ๋ ํ์ธํด ๋ณด์ธ์! +) ์ฐธ๊ณ ๋ก Git์ ์นด์นด์ค ๋ก๊ทธ์ธ์ด๋ ๊ฐ์ด ๋์ด์์ด์ ์ฌ๊ธฐ์ ์ฌ๋ฆฐ ์ฝ๋๊น์ง๊ฐ ๋ก๊ทธ์ธ ๊ด๋ จ์ด๊ณ ๊ทธ ๋ฐ์ ์๋ ์ฝ๋๋ ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ ์ฝ๋์ ๋๋ค.
4. LoginRequest.class (Spring)
- DTO: vue์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ด๊ณณ์์ ๋ฐ์๋
@Getter
@Setter
@ToString(exclude="pw")
public class LoginRequest {
private String userId;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String pw;
}
์คํ๋ง์ผ๋ก ๋์๊ฐ์ ๋ก๊ทธ์ธ ๋ก์ง์ ์ฒ๋ฆฌํ ๊ฒ์ด๋ค. LoginRequest๋ vue๋ก ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ ํด๋์ค๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค. ํ์๊ฐ์ ์์ ํ์ง ์์๋ ๋ณด์์ ์์ฃผ ์ด์ง ์ฒ๋ฆฌํด ๋ดค๋ค.
๋จผ์ @ToString(exclude="pw")์ ๋ํด ์ค๋ช ํ๊ฒ ๋ค. ๋ง์ฝ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ด ๋๋์ง ํ์ธํ๊ณ ์ถ๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ๋ฐ์๋ ์ ๋๋ก ๋์๊ฐ๋์ง ํ์ธํ๊ธฐ ์ํด ๋ก๊ทธ๋ฅผ ์ฐ์ด๋ณผ ๊ฒ์ด๋ค. ๊ทธ๋ฅ @ToString๋ง ์ค์ ํด ๋๋ฉด ๋ชจ๋ ํ๋๊ฐ ๋ค ์ฐํ ๋น๋ฐ๋ฒํธ๊ฐ ๋ ธ์ถ๋๋ ๋ณด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋์ exclude๋ฅผ ์ด์ฉํด pw์ธ ํจ์ค์๋๋ ๋ฌธ์์ด์ ํฌํจ๋์ง ์๋๋ก ์ค์ ํ๋ค.
@JsonProperty๋ Jackson์ด JSON๊ณผ ๊ฐ์ฒด๋ก(ํน์ ๊ทธ ๋ฐ๋๋ก) ๋ณํํ ๋ pw ํ๋๋ ์ ๋ ฅ๋ง ํ์ฉํ๊ณ ์ถ๋ ฅ์ ํฌํจํ์ง ์๋๋ก ์ค์ ํ ๊ฒ์ด๋ค. ๋ก๊ทธ์ธ ๋ก์ง์ ์ฒ๋ฆฌํ๊ธฐ ์ํด vue์์ pw๋ฅผ ๋ฐ์์ฌ ๊ฒ์ด๋ค. ๊ทธ๋ฌ๋ ์ค์๋ก ์ปจํธ๋กค๋ฌ๊ฐ DTO๋ฅผ ๋ฐํํ๊ฒ ๋๋ค๋ฉด(๋ฐ์์จ ๊ฒ๊ณผ ๋ฐ๋๋ก vue๋ก ์ ๋ณด๋ฅผ ๋ณด๋ด๊ฒ ๋๋ค๋ฉด) ํด๋น ์ด๋ ธํ ์ด์ ์ค์ ์ผ๋ก ์ธํด pw๋ ์์์ ๋น ์ง๊ฒ ๋๋ ๊ฒ์ด๋ค.
5. CheckLogin.class (Spring)
- ์์ด๋์ ๋น๋ฐ๋ฒํธ๊ฐ null, ๊ณต๋ฐฑ, ๋์ด์ฐ๊ธฐ๋ง ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ์์๊ฒ ๋์ธ ๋ฉ์์ง
public class CheckLogin {
public static String checkId(String userId) {
if(userId == null || userId.isBlank()) {
return "์์ด๋๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.";
}
return "ok";
}
public static String checkPw(String pw) {
if(pw == null || pw.isBlank()) {
return "๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.";
}
return "ok";
}
}
ํ์๊ฐ์ ์์ ์ ์๋ ์ฝ๋ ์ค ํ์ํ ๋ถ๋ถ๋ง ๊ฐ์ ธ์๋ค. ๋ก๊ทธ์ธ ํ๋ฉด์์ ์์ด๋์ ๋น๋ฐ๋ฒํธ ์ ๋ ฅ์ฐฝ์ ๊ฐ์ด ์ ํ์์ง ์์ผ๋ฉด, ํด๋น ๋ฉ์์ง๋ฅผ ๋ฆฌํดํ๋๋ก ํ๊ณ , ๋ฌธ์ ๊ฐ ์์ผ๋ฉด ok๊ฐ ๋ฆฌํด๋๋๋ก ํ๋ค.
6. MemberRepository.interface (Spring)
- ๋ ํฌ์งํ ๋ฆฌ๋ก ์์ด๋๋ฅผ ์ฐพ์ ๋ฐํํ๋ ๊ณณ
public interface MemberRepository extends JpaRepository<Member, Long> {
//์ด๋ฉ์ผ ์์ด๋ ์ค๋ณต ์ฒดํฌ -> ํ์๊ฐ์
๋ถ๋ถ
boolean existsByUserId(String userId);
boolean existsByEmail (String email);
// @@ userId ๋ ํฌ์งํ ๋ฆฌ์์ ์ฐพ๊ธฐ @@
Optional<Member> findByUserId(String userId);
}
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ์ ์ ๋ ฅํ ์์ด๋๋ฅผ ๊ฐ์ง๊ณ ํด๋น ์์ด๋๊ฐ ์๋์ง ์ฐพ๋๋ค. ์ฌ๊ธฐ์ Optional์ด๋ ํ์ ์ ์ฌ์ฉํ๋๋ฐ, ๊ทธ ์ด์ ๋ ์์ด๋๊ฐ ์์ ๊ฒฝ์ฐ null ์์ธ๊ฐ ์๊ธฐ๋ ๊ฑธ ๋ฐฉ์งํ๊ณ ์ ์ฌ์ฉํ๋ค. Optional <T>๋ null์ด ์ฌ ์ ์๋ ๊ฐ์ ๊ฐ์ธ๋ Wrapper ํด๋์ค๋ก, ์ฐธ์กฐํ๋๋ผ๋ NPE(Null Pointer Exception)๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋์์ค๋ค.
<Member>๊ฐ Optional์ ๊ฐ์ด ์ ํ์๋ ์ด์ ๋ extends JpaRepository <Member, Long>์ ๋ณด๋ฉด ์ ์ ์๋ค. ํ์๊ฐ์ ์ ๋ง๋ค๋ฉด์ ๋ ํฌ์งํ ๋ฆฌ์ ์ฐ๊ฒฐํ ํด๋์ค๋ฅผ ๋ง๋ค์๋๋ฐ ๊ทธ ํด๋์ค ์ด๋ฆ์ด Member์๋ค. ๊ทธ๋์ Member๋ฅผ ์ ์ด๋ ๊ฒ์ด๋ค. (Member ํด๋์ค๋ฅผ ํตํด ๋ ํฌ์งํ ๋ฆฌ์ ์ ์ฅ, ์กฐํ๋ฅผ ํ๋ค.) Optional<Member>๋ Member ํ์ ๊ฐ์ด ๋ค์ด์์ ์๋ ์๊ณ ์๋ ์๋ ์๋ค๋ ๋ป์ด๋ค.
findByUserId๋ Spring Data JPA์ ๋ฉ์๋ ์ด๋ฆ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ๋ผ๋ ๊ฒ์ผ๋ก ์ํฐํฐ ํ๋ ์ด๋ฆ์ ํด์ํด์ JPQL์ ๋ง๋ค์ด ์คํํด ์ค๋ค. ๊ทธ๋ฅ ์ฝ๊ฒ ์ค๋ช ํด์ ๊ท์น์ ๋ฐ๋ผ ์ด๋ฆ์ ์ค์ ํ๋ฉด Spring Data JPA๋ผ๋ ์ ๊ฐ ๊ท์น์ ๋ง์ถฐ ์ด๋ฆ์ ํด์ํด ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ค๋ค๊ณ ์๊ฐํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค. ์ง๊ธ์ findByUserId๋๊น, SELECT m FROM Member m WHERE m.userId = :id ์ด๋ฐ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ง ๊ฒ์ด๋ค.(์๋ง๋?) ์์ฃผ ๊ฐํธํ๋ค!
7. MemberService.class (Spring)
- ๋ ํฌ์งํ ๋ฆฌ์ ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํด๋์ค, ํจ์ค์๋ ๋งค์น ํ์ธํ๋ ๊ณณ
public class MemberService {
//์์กด์ฑ ์ฃผ์
@Autowired
private MemberRepository memberRepository;
@Autowired
private PasswordEncoder passwordEncoder;
//์์ด๋, ์ด๋ฉ์ผ ์ค๋ณต ์ฒดํฌ -> ํ์๊ฐ์
public Boolean existByUserId (String userId) {
return memberRepository.existsByUserId(userId);
}
public Boolean existByEmail (String email) {
return memberRepository.existsByEmail(email);
}
//ํ์๊ฐ์
์, ํจ์ค์๋ ์ํธํ -> ํ์๊ฐ์
public Member save(Member member) {
member.setPw(passwordEncoder.encode(member.getPw()));
return memberRepository.save(member);
}
// @@ ๋ก๊ทธ์ธ ์์ด๋ ์๋์ง ํ์ธํ๊ณ , ์ํธํ๋ ๋น๋ฐ๋ฒํธ ๋น๊ตํ๊ธฐ @@
public boolean validateMember(LoginRequest loginRequest) {
return memberRepository.findByUserId(loginRequest.getUserId())
.map(member -> passwordEncoder.matches(loginRequest.getPw(), member.getPw()))
.orElse(false);
}
}
LoginRequest ํ๋(์์ด๋์ ํจ์ค์๋)๋ฅผ ๋ชจ์กฐ๋ฆฌ ๋ค๊ณ ์๋ค. ์์ด๋๊ฐ ์๋์ง, ์๋ค๋ฉด ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋งค์นํด์ ๋ง๋์ง ํ์ธํ ๊ฒ์ด๋ค. ์์ด๋์ ๋น๋ฐ๋ฒํธ๊ฐ ๋ง์ผ๋ฉด true, ํ๋ฆฌ๋ฉด false๋ฅผ ๋ฐํํ ๊ฑฐ๋ผ ๋ฐํํ์ ์ boolean์ด ๋๋ค.
memberRepository.findByUserId(loginRequest.getUserId()) ์ด ๋ถ๋ถ์ ์ดํด๋ณด๋ฉด, loginRequest์์ userId ํ๋๋ฅผ ๊ฐ์ ธ์ memberRepository์ ์๋ findByUserId ๋ฉ์๋์ ๋ฃ์ด๋ผ ๋ผ๋ ๋ง์ด ๋๋ค. ๊ทธ๋ฆฌ๊ณ LoginRequest ํ๋๋ฅผ ๋ค๊ณ ์จ ์ด์ ๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์์ด๋์ ํจ์ค์๋๋ฅผ ๊บผ๋ด์ ์ฌ์ฉํ๊ธฐ ์ํจ์ด๋ค. findByUserId์์ Optional<Member>๋ก ๋๋ ค๋ฐ๋๋ก ํ๋ค. ๊ทธ๋์ ์ฌ์ฉ์๊ฐ ์์ผ๋ฉด Optional.of(member)๊ฐ ์ฌ ํ ๊ณ ์๋ค๋ฉด Optional.empty( )๊ฐ ์ค๊ฒ ๋๋ค.
.map(member -> passwordEncoder.matches(loginRequest.getPw(), member.getPw())) ์ด ๋ถ๋ถ์ ์ดํด๋ณด์. ์ฌ๊ธฐ ์ฝ๋๊ฐ ์คํ๋ ๋๋ ๊ฐ์ด ์์ ๊ฒฝ์ฐ๊ฐ ๋๋ค. ๊ฐ์ด ์์ ๋ ์คํ๋๋ ์ด์ ๋ map์ ์๋ค. Optional์์ ์ฒด์ด๋์ด๋ ๊ฑด๋ฐ, map. filter, flatMap, orElse ๊ฐ์ ์ฐ์ฐ์ ์ฐ๊ฒฐํด์ ๊ฐ์ด ์์ ๋ ์์๋๋ก ์ฒ๋ฆฌํ๊ณ , ์์ผ๋ฉด ๋น ์ ธ๋์ค๋ ํจํด์ด๋ค. loginRequest์์ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์ฐฝ์ ์ ๋ ฅํ ํจ์ค์๋๋ฅผ ๋ฐ์์ค๊ณ , member๋ฅผ ํตํด ์๋ ์ ์ฅ๋์ด ์๋ ๋น๋ฐ๋ฒํธ๋ฅผ ๊ฐ์ ธ์จ๋ค. ํ์ฌ ํ๋ก์ ํธ์์ spring security๋ฅผ ์ด์ฉํด passwordEncoder๋ฅผ ํด์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํ์ํจ ์ฑ ์ ์ฅํ๋ค. ๊ทธ๋์ ๋์ด ๋น๊ตํ ๋๋ passwordEncoder.matches๋ฅผ ํด์ค์ผ ํ๋ค. ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ํ๋ฌธ ๋น๋ฐ๋ฒํธ์ DB์ ํด์๋ ๋น๋ฐ๋ฒํธ๋ฅผ ๋น๊ตํด boolean์ ๋๋ ค์ค๋ค.
.orElse(false);๋ ์์ด๋๊ฐ ์์ ๊ฒฝ์ฐ false๋ฅผ ๋ฐํํ๋ค. ๋ก๊ทธ์ธ ์ปจํธ๋กค๋ฌ์์ ๋ก๊ทธ์ธ์ ์๋ํ๊ฒ ๋๋ฉด MemberService์์ boolean ๊ฐ์ผ๋ก ๋ฐ์์ค๊ฒ ๋ ๊ฒ์ด๋ค.
8. CheckLogin.class (Spring)
- ๋ก๊ทธ์ธ ์ปจํธ๋กค๋ฌ, ๋ฐฉ๊ธ๊น์ง ๋ง๋ ํด๋์ค์ ์ฝ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ด๊ณณ์์ ์ต์ข ์ ์ผ๋ก ์ฒ๋ฆฌ ํ vue๋ก ์๋ต
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:5173")
public class LoginController {
// ์์กด์ฑ ์ฃผ์
@Autowired
private MemberService memberService;
// login ๊ฒฝ๋ก๋ก ์ค๋ฉด login ๋ฉ์๋ ์คํ
@PostMapping("/login")
// ๋ฐํํ์
์ ResponseEntity<String>์ด๊ณ @RequestBody๋ก ์์ฒญ ๋ฐ์์ด
public ResponseEntity<String> login(@RequestBody LoginRequest loginRequest) {
//loginRequest์์ id์ pw๋ฅผ ๊บผ๋ด์ checkํ๊ธฐ.
String idCheckResult = CheckLogin.checkId(loginRequest.getUserId());
if (!"ok".equals(idCheckResult)) { //ok๊ฐ ์๋๋ฉด
//๋ฉ์์ง ๋ณด๋ด๊ธฐ, checkId ๋ฉ์๋์์ ๋ฐํํ ํ
์คํธ๊ฐ ์ด๊ณณ์ ๋ฐ๋๋ก ์ค๋ฆฐ๋ค.
return ResponseEntity.badRequest().body(idCheckResult);
}
String pwCheckResult = CheckLogin.checkPw(loginRequest.getPw());
if (!"ok".equals(pwCheckResult)) {
return ResponseEntity.badRequest().body(pwCheckResult);
}
//loginRequest์ ์๋ ํ๋๋ฅผ validateMember ๋ฉ์๋๋ก ๋ณด๋
boolean validated = memberService.validateMember(loginRequest);
if (!validated) { //validated๊ฐ ์๋๋ฉด ํด๋น ๋ฉ์์ง ๋ณด๋
return ResponseEntity.badRequest().body("์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ค์ ํ์ธํด์ฃผ์ธ์.");
}
// ๊ด์ฐฎ์ผ๋ฉด ok ๋ณด๋
return ResponseEntity.ok("ok");
}
}
์ํ ์ฝ๋์ ํจ๊ป ๋ด์ฉ์ ๋ณด๋ด๊ธฐ ์ํด, login๋ฉ์๋์ ๋ฐํํ์ ์ ResponseEntity<String>์ด ๋๋ค. ์ฌ๊ธฐ์ return ์ฝ๋๋ฅผ ๋ณด๋ฉด ResponseEntity๊ฐ ๋ถ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ค์ badRequest ํน์ ok๊ฐ ๋ฐ๋ผ์จ๋ค. ์ด badRequest์ ok๊ฐ ์ํ ์ฝ๋๋ฅผ ๋ํ๋ธ๋ค. ok๋ ๋ณดํต 200์ ์๋ฏธํ๊ณ , badRequest๋ ๋ณดํต 400์ ์๋ฏธํ๋ค. body ๊ดํธ ์์ ๋ฌธ๊ตฌ๋ฅผ ์ ์๋ค. ๊ฐ ์ค๋ฅ์ ๋ง์ถฐ ์ฌ์ฉ์๋ ๋ฉ์์ง๋ฅผ ๋ฐ๊ฒ ๋๋ค. vue์์ ์ ์ alert(e.response.data); ์ฝ๋๊ฐ ๋ณด์ฌ์ฃผ๋ ์ญํ ์ ํ๋ค.
์ฌ์ฉ์๊ฐ ์์ด๋์ ํจ์ค์๋๋ฅผ ์ ๋ ฅํ๋ฉด ์ปจํธ๋กค๋ฌ์ ๋์ฐฉํด์ ์์๋๋ก ํ์ธํ๋ค. ๋ง์ฝ ์ ๋ ฅํ ๊ฐ์ด ์๋ ์ํ์์ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋๋ฅด๋ฉด "์์ด๋๋ฅผ ์ ๋ ฅํด ์ฃผ์ธ์"์ ๊ฐ์ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๋ค. ๋ง์ฝ ๊ฐ์ด ๋ค์ด์๋ค๋ฉด MemberService ํด๋์ค์ ์๋ validateMember ๋ฉ์๋๋ฅผ ์๋์ํจ๋ค. ์๊น validateMember๋ ์์ด๋๊ฐ ์๋์ง ํ์ธํ๊ณ , ์์ผ๋ฉด ํจ์ค์๋๋ฅผ ๋น๊ตํ์ฌ ๊ทธ ๊ฐ์ boolean์ผ๋ก ๋ฐํํ๋ค๊ณ ํ๋ค. ๊ทธ๋์ boolean validated๋ผ๊ณ ๋์ด์๋ ์ด์ ๊ฐ ๋ฐํ๊ฐ์ด boolean์ด๋ผ์ ๊ทธ๋ ๋ค. ๋ฐํ๋ ๊ฐ(true ํน์ false)์ validated์ ๋ณด๊ดํ๊ณ ๊ทธ ๊ฐ์ด false์ด๋ฉด "์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ค์ ํ์ธํด ์ฃผ์ธ์" ๋ฉ์์ง๋ฅผ badRequest ์ํ ์ฝ๋์ ํจ๊ป ๋ณด๋ธ๋ค. ๊ทธ๋ฆฌ๊ณ true์ด๋ฉด ok ์ํ ์ฝ๋์ ํจ๊ป "ok"๋ผ๋ ๋ฉ์์ง๊ฐ ๋ณด๋ด์ง๋ค.
+) ์ฐธ๊ณ ๋ก ๋ณด์์ ๋ฉ์์ง๋ ๋ชจํธํ๊ฒ ์ ๋๊ฒ ์ข๋ค. ์์ด๋, ๋น๋ฐ๋ฒํธ ์ค ์ด๋ค๊ฒ ํ๋ ธ๋์ง ์๋ ค์ฃผ๋ฉด ํด์ปค๊ฐ ๊ทธ ๋ถ๋ถ๋ง ์ด์ฌํ ํ๋ฉด ๋๋๊น..!
+) ๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ์ธ ์คํจ๋ 401 ์ํ ์ฝ๋๋ฅผ ์ฐ๋๊ฒ ๋ง๋ค๊ณ ํ๋ค. 401์ Unauthorized๋ผ๊ณ ์ฌ์ฉ์ ์ด๋ฆ, ๋น๋ฐ๋ฒํธ, ๋๋ API ํค ๋ฑ ์
๋ ฅํ ์ธ์ฆ ์ ๋ณด๊ฐ ์๋ชป๋์์ ๋ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๋ค๊ณ ํ๋ค.
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("์์ด๋ ๋๋ ๋น๋ฐ๋ฒํธ๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค.");
- ํ์ํ ๊ฐ๋ ์ ์ด๊ณณ์
'๐ท Spring/๊ฐ๋ ' ์นดํ ๊ณ ๋ฆฌ์ ๊ธ ๋ชฉ๋ก
๐ง๐ป ๐งธ ๐ ๐ข
post-this.tistory.com
๋ก๊ทธ์ธ ์ฑ๊ณต ํ๋ฉด์ ๋ค์ ํฌ์คํ ์์...