2022. 3. 31. 08:00ใProgramming Project ์์ ์ค/๋ด์ฉ ์ ๋ฆฌ
๐ง๐ป๐ป Git Hub ์ฃผ์
๐ ๋ชฉ์ฐจ
โ [BackEnd][Maven-PJ] ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : ๋ชฉ๋ก ์กฐํ
โ [BackEnd][Maven-PJ]๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : ์์ธ ์กฐํ
โ [BackEnd][Maven-PJ]๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : ์ญ์
โ [BackEnd][Maven-PJ] ์ฌ๋ด ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ : ๋ต๋ณ ๋ฑ๋ก / ์์
โ [BackEnd][Maven-PJ] ์ฌ๋ด ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ : ๋ต๋ณ ์ญ์
๐จ๐ฉ๐ง๐ฆ ํ์ ๊ด๋ จ
โ [BackEnd][Maven-PJ] ์ฌ๋ด ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ํ์ ๊ด๋ จ : ํ์ ๊ฐ์
๐๋ถ ๋ก
โ [BackEnd][Maven-PJ]๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : Paging์ฒ๋ฆฌ
โ [Spring] @Valid๋ฅผ ์ด์ฉํ @RequestBody ๊ฒ์ฆ / Exception Handling / ์ ๊ท ํํ์
๐ค ๋ด๊ฐ ๋ง๋ Exception
โ [Exception ์ ๋ฆฌ] org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
โ [Vue.js][Spring] Post Data ์ ์ก ๊ฐ null๊ฐ ์ ์ก ๋ฌธ์
๐ ํ์ ๊ด๋ จ - ํ์ ๊ฐ์
๐ฝ Data Base Table ๊ตฌ์ฑ
๐ฝ Swagger
๐ฝ Code ๋ถ์
๐ฆ CustomUserDetails.java
@Override
public Collection<? extends GrantedAuthority> getAuthorities() { // ์ด์ฉ์ ๊ถํ ๋ชฉ๋ก ๋ฐํ Method
ArrayList<GrantedAuthority> auth = new ArrayList<>();
auth.add(new SimpleGrantedAuthority(authority));
return auth;
} // getAuthorities() ๋
@Override
public boolean isAccountNonExpired() { // ๊ณ์ ๋ง๋ฃ ์ฌ๋ถ | true : ๋ง๋ฃ ์๋จ, false : ๋ง๋ฃ
return true;
} // isAccountNonExpired() ๋
@Override
public boolean isAccountNonLocked() { // ๊ณ์ ์ ๊น ์ฌ๋ถ | true : ์ ์ ๊น, false : ์ ๊น
return true;
}
@Override
public boolean isCredentialsNonExpired() { // ๋น๋ฐ๋ฒํธ ๋ง๋ฃ ์ฌ๋ถ | true : ๋ง๋ฃ ์๋จ, false : ๋ง๋ฃ
return true;
} // isCredentialsNonExpired() ๋
@Override
public boolean isEnabled() { // ๊ณ์ ํ์ฑํ ์ฌ๋ถ | true : ํ์ฑํ, false : ๋น ํ์ฑํ
return true;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getUserPhone() {
return userPhone;
}
public void setUserPhone(String userPhone) {
this.userPhone = userPhone;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public String getUserKind() {
return userKind;
}
public void setUserKind(String userKind) {
this.userKind = userKind;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
} // class ๋
์ฃผ๋ํ๋์ ํ์๊ฐ์ ๋ฐ Login ์ ์ด์ฉ๋ Value Object ๊ฐ์ฒด๋ฅผ `UserDetails`๋ฅผ ๊ตฌํํ Class๋ฅผ ๋ง๋ค์ด์ ๊ตฌํํ ๊ฒ์ด์์.
๐ฆ DuplicateByIdInfoDTO.java
์ด DTO๋ ํ์๊ฐ์ ์์ ์ค๋ณต ํ์ธ๋ฑ์ ํ์ธ ์ ์ฐจ์์ ์ด์ฉ๋ ๊ฐ๋ค์ Meber ๋ณ์๋ก ์ด์ฉํ๋ DTO์ธ ๊ฒ์ด์์.
๐ฆ UserController.java
/**
* ํ์ ๊ด๋ จ Controller
* <pre>
* <b>History:</b>
* ์ฃผ๋ํ๋, 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* </pre>
*
* @author ์ฃผ๋ํ๋
* @version 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* @See ""
* @see <a href=""></a>
*/
@Api(tags = {"ํ์ ๊ด๋ฆฌ ๊ด๋ จ API"}) @Slf4j @RequiredArgsConstructor
@RequestMapping(ServiceURIMng.USER)
@RestController public class UserController {
private final UserService userService;
@ApiOperation(value = SwaggerApiInfo.DUPLICATE_ID, notes = "ํ์ ๊ฐ์
์ ID ์ค๋ณต ํ์ธ ์๋น์ค ์
๋๋ค.")
@ApiParam(name = "DuplicateByIdInfoDTO", value = "์ด์ฉ์ ์ํ๋ ์ด์ฉ์๊ฐ ํ์ ๊ฐ์
์ ์ํด ID ์ค๋ณต ํ์ธ ํฉ๋๋ค.", readOnly = true)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "์ฌ์ฉ ๊ฐ๋ฅ"),
@ApiResponse(code = 409, message = "์
๋ ฅ๊ฐ ์ค๋ณต"),
@ApiResponse(code = 500, message = "Server Internal Error")
})
@ResponseBody
@PostMapping("/duplicate/userid") public DefaultResponse duplicateUserID(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserController์ duplicateUserID(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ ํ์ธ : " + duplicateByIdInfoDTO.toString());
log.info("userService.duplicateUserID(duplicateByIdInfoDTO)๋ฅผ ํธ์ถํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค!");
return userService.duplicateUserID(duplicateByIdInfoDTO);
} // duplicateId(@RequestBody String username) ๋
@ApiOperation(value = SwaggerApiInfo.DUPLICATE_NICKNAME, notes = "ํ์ ๊ฐ์
์ ๋ณ๋ช
์ค๋ณต ํ์ธ ์๋น์ค ์
๋๋ค.")
@ApiParam(name = "DuplicateByIdInfoDTO", value = "์ด์ฉ์ ์ํ๋ ์ด์ฉ์๊ฐ ํ์ ๊ฐ์
์ ์ํด ๋ณ๋ช
์ค๋ณต ํ์ธ ํฉ๋๋ค.", readOnly = true)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "์ฌ์ฉ ๊ฐ๋ฅ"),
@ApiResponse(code = 409, message = "์
๋ ฅ๊ฐ ์ค๋ณต"),
@ApiResponse(code = 500, message = "Server Internal Error")
})
@ResponseBody
@PostMapping("/duplicate/nickname") public DefaultResponse duplicateUserNickName(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserController์ duplicateUserNickName(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ ํ์ธ : " + duplicateByIdInfoDTO.toString());
log.info("userService.duplicateUserNickName(duplicateByIdInfoDTO)๋ฅผ ํธ์ถํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค!");
return userService.duplicateUserNickName(duplicateByIdInfoDTO);
} // duplicateId(@RequestBody String username) ๋
@ApiOperation(value = SwaggerApiInfo.DUPLICATE_EMAIL, notes = "ํ์ ๊ฐ์
์ E-mail ์ค๋ณต ํ์ธ ์๋น์ค ์
๋๋ค.")
@ApiParam(name = "DuplicateByIdInfoDTO", value = "์ด์ฉ์ ์ํ๋ ์ด์ฉ์๊ฐ ํ์ ๊ฐ์
์ ์ํด mail ์ค๋ณต ํ์ธ ํฉ๋๋ค.", readOnly = true)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "์ฌ์ฉ ๊ฐ๋ฅ"),
@ApiResponse(code = 409, message = "์
๋ ฅ๊ฐ ์ค๋ณต"),
@ApiResponse(code = 500, message = "Server Internal Error")
})
@ResponseBody
@PostMapping("/duplicate/email") public DefaultResponse duplicateUserEmail(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserController์ duplicateUserEmail(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ ํ์ธ : " + duplicateByIdInfoDTO.toString());
log.info("userService.duplicateUserEmail(duplicateByIdInfoDTO)๋ฅผ ํธ์ถํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค!");
return userService.duplicateUserEmail(duplicateByIdInfoDTO);
} // duplicateId(@RequestBody String username) ๋
@ApiOperation(value = SwaggerApiInfo.DUPLICATE_PHONE_NUMBER, notes = "ํ์ ๊ฐ์
์ ํธ๋ํฐ ๋ฒํธ ์ค๋ณต ํ์ธ ์๋น์ค ์
๋๋ค.")
@ApiParam(name = "DuplicateByIdInfoDTO", value = "์ด์ฉ์ ์ํ๋ ์ด์ฉ์๊ฐ ํ์ ๊ฐ์
์ ์ํด ํธ๋ํฐ ๋ฒํธ ์ค๋ณต ํ์ธ ํฉ๋๋ค.", readOnly = true)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "์ฌ์ฉ ๊ฐ๋ฅ"),
@ApiResponse(code = 409, message = "์
๋ ฅ๊ฐ ์ค๋ณต"),
@ApiResponse(code = 500, message = "Server Internal Error")
})
@ResponseBody
@PostMapping("/duplicate/phone-number") public DefaultResponse duplicateUserPhoneNumber(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserController์ duplicateUserPhoneNumber(@RequestBody DuplicateByIdInfoDTO duplicateByIdInfoDTO)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ ํ์ธ : " + duplicateByIdInfoDTO.toString());
log.info("userService.duplicateUserPhoneNumber(duplicateByIdInfoDTO)๋ฅผ ํธ์ถํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค!");
return userService.duplicateUserPhoneNumber(duplicateByIdInfoDTO);
} // duplicateId(@RequestBody String username) ๋
@ApiOperation(value = SwaggerApiInfo.SIGN_UP, notes = "ํ์ ๊ฐ์
์๋น์ค ์
๋๋ค.")
@ApiParam(name = "customUserDetails", value = "์ด์ฉ์ ์ํ๋ ์ด์ฉ์๊ฐ ํ์ ๊ฐ์
์ ์ํด ์์ฑํ ๋ด์ฉ์ ๋ด์ ๊ฐ์ฒด ์
๋๋ค. \n ํ์ : ์๊ธฐ ์๊ฐ, ํ๋กํ ์ฌ์ง์ ์ ์ธํ ๋ชจ๋ ํญ๋ชฉ \n ๋น๋ฐ๋ฒํธ๋ ์ํธํ ์ฒ๋ฆฌ", readOnly = true)
@ApiResponses(value = {
@ApiResponse(code=200, message = "Email ์ค๋ณต"),
@ApiResponse(code=201, message = "๊ฐ์
์ฑ๊ณต"),
@ApiResponse(code = 500, message = "Server Internal Error")
})
@PostMapping("/signup") public ResponseEntity<DefaultResponse> signUp (@Valid @RequestBody CustomUserDetails customUserDetails) {
log.info("UserController์ signUp (@Valid @RequestBody UserSignUpRequestDTO userSignUpRequestDTO)์ด ํธ์ถ ๋์์ต๋๋ค!");
log.info("userService.signUp(userSignUpRequestDTO)๋ฅผ ํธ์ถํ์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค!");
return new ResponseEntity<>(userService.signUp(customUserDetails), HttpStatus.OK);
} // signUp (@Valid @RequestBody UserSignUpRequestDTO userSignUpRequestDTO) ๋
} // class ๋
๋ณธ๊ฒฉ์ ์ผ๋ก Controller๋ฅผ ๋ถ์ํด ๋ณผ ๊ฒ์ด์์. ์ผ๋จ, `signUp()`์ ์ ์ธํ ๋ชจ๋ Method๋ ๊ฐ ๊ฐ์ ์ค๋ณต ์ฌ๋ถ๋ฅผ ํ์ธํ๊ธฐ ์ํ Method์ธ ๊ฒ์ด์์. ๋ฐ๋ผ์ ์ด ๋ถ๋ถ์ ๋ํด์๋ `ID ์ค๋ณต ํ์ธ`์ ๋ํ ๊ฒ๋ง ๊ธ์ ์์ฑ ํด ๋ณด๋๋ก ํ ๊ฒ์ด์์.
โบ duplicateUserID()
์ต์ด Swagger๋ฅผ ์ด์ฉํ์ฌ ํด๋น API๊ฐ ์ด๋ค API์ธ์ง ํ์๋ฅผ ํด ์ค ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค `System.out.println()` ๋์ Console์ ๋์๋ค์ ํ์ธํ๊ธฐ ์ํด ์ถ๋ ฅํ `@Slf4j`๋ฅผ ์ ์ธํ๊ณ , final Member ๋ณ์๋ฅผ ์ด์ฉํ๋ฉด์ ์์ฑ์๋ฅผ ์์ฑํ๊ธฐ ์ํด `@RequiredArgsConstructor`๋ฅผ ์ ์ธํด ์ค ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค์ Service๋ฅผ DIํ๊ธฐ ์ํด Member ๋ณ์๋ก ์ ์ธ์ ํด ์ค ๊ฒ์ด์์.
`@ResponseBody`๋ฅผ ํตํด JSON Type์ Data๋ฅผ ๋ฐํํ ์ ์๋๋ก ์ ์ธ ํด ์ฃผ๊ณ , `@PostMapping`์ผ๋ก HTTP Method `POST`๋ฅผ ํตํด Data๋ฅผ ๋ฐ๊ฒ ๋ค๊ณ ์ ์ธํ๋ฉด์ ์ฐ๊ฒฐ ๋ URI๋ฅผ ์ค์ ํด ์ค ๊ฒ์ด์์. `DefaultResponse`๋ ์ฃผ๋ํ๋์ด ๋ง๋ ๊ฐ์ฒด์ธ๋ฐ, ์ดํด ๋ณด์๋ฉด
/**
* ์๋ต Message๋ฅผ ์ํ Class
* <pre>
* <b>History:</b>
* ์ฃผ๋ํ๋, 1.0.0, 2022.02.24 ์ต์ด ์์ฑ
* </pre>
*
* @author ์ฃผ๋ํ๋
* @version 1.0.0, 2022.02.24 ์ต์ด ์์ฑ
* @See ""
* @see <a href=""></a>
*/
@Data @AllArgsConstructor @Builder
public class DefaultResponse<T> {
// API ์ํ ์ฝ๋
private Integer statusCode;
// API ๋ถ๊ฐ ์ค๋ช
(ํ๊ธ)
private String MessageKo;
// API ๋ถ๊ฐ ์ค๋ช
(์์ด)
private String MessageEn;
// API ์๋ต ๋ฐ์ดํฐ
private T data;
// ์ํ ์ฝ๋ + ๋ถ๊ฐ ์ค๋ช
๋ฐํ
public static <T> DefaultResponse<T> response(final Integer statusCode, final String MessageKo, final String MessageEn){
return (DefaultResponse<T>) DefaultResponse.builder()
.statusCode(statusCode)
.MessageKo(MessageKo)
.MessageEn(MessageEn)
.build();
} // response(final Integer statusCode, final String MessageKo, final String MessageEn) ๋
// ์ํ ์ฝ๋ + ๋ถ๊ฐ ์ค๋ช
+ ์๋ต ๋ฐ์ดํฐ ๋ฐํ
public static <T> DefaultResponse<T> response(final Integer statusCode, final String MessageKo, final String MessageEn, final T data){
return (DefaultResponse<T>) DefaultResponse.builder()
.statusCode(statusCode)
.MessageKo(MessageKo)
.MessageEn(MessageEn)
.data(data)
.build();
} // response(final Integer statusCode, final String MessageKo, final String MessageEn, final T data) ๋
} // class ๋
๋ฐ๋ก ์ด๋ ๊ฒ ๋ง๋ค์ด์ง Class์ธ ๊ฒ์ด์์.
์ด Class๋ฅผ ์๋ต์ผ๋ก ๋์ ธ์ค๋ค๋ ๊ฒ์ ์๋ต Code, ์๋ต ๋ถ๊ฐ ์ค๋ช (ํ๊ธ), ์๋ต ๋ถ๊ฐ ์ค๋ช (์์ด), API ์๋ต Data๋ฅผ ๊ฐ์ฒด๋ก Client์๊ฒ ์ ๋ฌ ํด ์ฃผ๊ธฐ ์ํ Class์ธ ๊ฒ์ด์์.
์ฃผ๋ํ๋์ ์ด Method์์ ์์ฒญ์ `@RequestBody`๋ฅผ ํตํด `DuplicateByIdInfoDTO`๋ก ๋ฐ๊ธฐ๋ก ํ ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค์ ์ด Method๊ฐ ๋์ํ๋์ง ๋ฌด์์ ํ ๊ฒ์ธ์ง๋ฅผ Console์ ์ถ๋ ฅํ๊ณ ๋์ ๋ฐ๋ก Service์ ํด๋น Method๋ฅผ ํธ์ถํ๋๋ฐ, `DuplicateByIdInfoDTO`๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌํ๋ฉด์ ๋ฐํ๊ฐ์ด ์ค๋ฉด ๋ฐ๋ก ๋ฐํ๋๋๋ก ํ ๊ฒ์ด์์.
โบ signUp()
์ ๊ทธ๋ฆผ์์ ๋์ค๋ Method๋ ํ์ ๊ฐ์ ์ ์ฒ๋ฆฌ ํด ์ฃผ๋ Method์ธ ๊ฒ์ด์์.
`@Valid`๋ฅผ ํตํด ์์ฒญ๊ฐ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๊ฒ ํ๊ณ , ๋งค๊ฐ ๋ณ์๋ก `CustomUserDetails` ๊ฐ์ฒด๋ฅผ ๋ฐ๊ณ ์๋ ๊ฒ์ด์์.
์ด Mehotd๋ ๋ฐํํ ๋, `ResponseEntity<DefaultResponse>`๋ฅผ ๋ฐํํ๊ณ ์์ด์ 122๋ฒ์งธ ์ค์์ ResponseEntity ๊ฐ์ฒด๋ฅผ ํ๋ ๋ง๋ค์ด ์ฃผ๊ณ , Service์ ํด๋น Method์ ๊ฒฐ๊ณผ๊ฐ์ด ์ค๋ฉด ๋ฐํ์ ํด ์ฃผ๋๋ฐ, ์์ ์ด ์ ์์ ์ผ๋ก ์งํ์ด ๋๋ฉด ๋ฐํ์ด ์ค๊ธฐ ๋๋ฌธ์ HTTP Status Code 200(HTTpStatus.OK)๋ฅผ ๊ฐ์ด ๋ฐํ ํด ์ฃผ๋ ๊ฒ์ด์์.
โ
๐ฆ UserService.java
/**
* ํ์ ๊ฐ์
๊ด๋ จ ๋น์ฆ๋์ค ๋ก์ง
* <pre>
* <b>History:</b>
* ์ฃผ๋ํ๋, 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* ์ฃผ๋ํ๋, 1.0.1, 2022.03.24 ID ์ค๋ณต ํ์ธ Logic ๊ตฌํ
* </pre>
*
* @author ์ฃผ๋ํ๋
* @version 1.0.1, 2022.03.24 ID ์ค๋ณต ํ์ธ Logic ๊ตฌํ
* @See ""
* @see <a href=""></a>
*/
public interface UserService {
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
DefaultResponse duplicateUserID(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
DefaultResponse duplicateUserNickName(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
DefaultResponse duplicateUserEmail(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
DefaultResponse duplicateUserPhoneNumber(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์๋น์ค
* @param customUserDetails - ํ์ ๊ฐ์
์ ์ํ ์ด์ฉ์ ์
๋ ฅ๊ฐ์ ๋ด์ Object
* @return DefaultResponse - ์๋ฒ ์ฒ๋ฆฌ ์ฌ๋ถ์ ํด๋นํ๋ Status Code ๋ฐํ์ ์ํ ๊ฐ์ฒด
* @see ""
*/
DefaultResponse signUp(CustomUserDetails customUserDetails);
} // interface ๋
UserService๋ ๋จ์ํ ์ถ์ Method๋ฅผ ๋ง๋ค์ด์ ๊ฐ Logic์ ๋ง๊ฒ ๊ตฌํํ ๊ฒ์ด์์.
๐ฆ UserServiceImpl.java
/**
* ํ์ ๊ฐ์
๊ด๋ จ ๋น์ฆ๋์ค ๋ก์ง
* <pre>
* <b>History:</b>
* ์ฃผ๋ํ๋, 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* </pre>
*
* @author ์ฃผ๋ํ๋
* @version 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* @See ""
* @see <a href=""></a>
*/
@RequiredArgsConstructor @Slf4j
@Service public class UserServiceImpl implements UserService {
private final PasswordEncoder passwordEncoder;
private final UserMapper userMapper;
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ID ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
@Override
public DefaultResponse duplicateUserID(DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserServiceImpl์ duplicateUserID(String username)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ : " + duplicateByIdInfoDTO);
log.info("DB์์ ํ์ ๊ฐ์
์์ฒญ ์ด์ฉ์๊ฐ ์
๋ ฅํ UserId(username)๋ฅผ ํตํด ํด๋น ํ์์ด ๋ฑ๋ก ๋์ด ์๋์ง ์ฐพ๊ฒ ์ต๋๋ค!");
Optional<DuplicateByIdInfoDTO> findByUserID = userMapper.findByUserID(duplicateByIdInfoDTO);
if (findByUserID.isEmpty()) {
log.info("์ค๋ณต ๋๋ ๊ฐ์ด ์์ต๋๋ค! 200 Code์ ํจ๊ป \"์ฌ์ฉ ๊ฐ๋ฅ!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(200, "์ฌ์ฉ ๊ฐ๋ฅ", "OK", findByUserID);
} else {
log.info("์ด๋ฏธ ์กด์ฌํ๋ ID ์
๋๋ค! 409 Code์ ํจ๊ป \"์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ ์
๋๋ค!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(409, "์ด๋ฏธ ์กด์ฌํ๋ ID ์
๋๋ค!", "Conflict");
} // // if-else (checkEmail.isEmpty()) ๋
} // duplicateId(String username) ๋
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ๋ณ๋ช
์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
@Override
public DefaultResponse duplicateUserNickName(DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserServiceImpl์ duplicateUserID(String username)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ : " + duplicateByIdInfoDTO);
log.info("DB์์ ํ์ ๊ฐ์
์์ฒญ ์ด์ฉ์๊ฐ ์
๋ ฅํ ๋ณ๋ช
์ ํตํด ํด๋น ํ์์ด ๋ฑ๋ก ๋์ด ์๋์ง ์ฐพ๊ฒ ์ต๋๋ค!");
Optional<DuplicateByIdInfoDTO> findByUserNickName = userMapper.findByUserNickName(duplicateByIdInfoDTO);
if (findByUserNickName.isEmpty()) {
log.info("์ค๋ณต ๋๋ ๊ฐ์ด ์์ต๋๋ค! 200 Code์ ํจ๊ป \"์ฌ์ฉ ๊ฐ๋ฅ!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(200, "์ฌ์ฉ ๊ฐ๋ฅ", "OK", findByUserNickName);
} else {
log.info("์ด๋ฏธ ์กด์ฌํ๋ ๋ณ๋ช
์
๋๋ค! 409 Code์ ํจ๊ป \"์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ ์
๋๋ค!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(409, "์ด๋ฏธ ์กด์ฌํ๋ ๋ณ๋ช
์
๋๋ค!", "Conflict");
} // // if-else (checkEmail.isEmpty()) ๋
}
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ Email ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
@Override
public DefaultResponse duplicateUserEmail(DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserServiceImpl์ duplicateUserID(String username)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ : " + duplicateByIdInfoDTO);
log.info("DB์์ ํ์ ๊ฐ์
์์ฒญ ์ด์ฉ์๊ฐ ์
๋ ฅํ UserId(username)๋ฅผ ํตํด ํด๋น ํ์์ด ๋ฑ๋ก ๋์ด ์๋์ง ์ฐพ๊ฒ ์ต๋๋ค!");
Optional<DuplicateByIdInfoDTO> findByUserEmail = userMapper.findByUserEmail(duplicateByIdInfoDTO);
if (findByUserEmail.isEmpty()) {
log.info("์ค๋ณต ๋๋ ๊ฐ์ด ์์ต๋๋ค! 200 Code์ ํจ๊ป \"์ฌ์ฉ ๊ฐ๋ฅ!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(200, "์ฌ์ฉ ๊ฐ๋ฅ", "OK", findByUserEmail);
} else {
log.info("์ด๋ฏธ ์กด์ฌํ๋ Email ์
๋๋ค! 409 Code์ ํจ๊ป \"์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ ์
๋๋ค!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(409, "์ด๋ฏธ ์กด์ฌํ๋ Email ์
๋๋ค!", "Conflict");
} // // if-else (checkEmail.isEmpty()) ๋
}
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ํธ๋ํฐ ๋ฒํธ ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
@Override
public DefaultResponse duplicateUserPhoneNumber(DuplicateByIdInfoDTO duplicateByIdInfoDTO) {
log.info("UserServiceImpl์ duplicateUserID(String username)๊ฐ ํธ์ถ ๋์์ต๋๋ค! Client๋ก ๋ถํฐ ์ ๋ฌ๋ ๊ฐ : " + duplicateByIdInfoDTO);
log.info("DB์์ ํ์ ๊ฐ์
์์ฒญ ์ด์ฉ์๊ฐ ์
๋ ฅํ UserId(username)๋ฅผ ํตํด ํด๋น ํ์์ด ๋ฑ๋ก ๋์ด ์๋์ง ์ฐพ๊ฒ ์ต๋๋ค!");
Optional<DuplicateByIdInfoDTO> findByUserphoneNumber = userMapper.findByUserPhoneNumber(duplicateByIdInfoDTO);
if (findByUserphoneNumber.isEmpty()) {
log.info("์ค๋ณต ๋๋ ๊ฐ์ด ์์ต๋๋ค! 200 Code์ ํจ๊ป \"์ฌ์ฉ ๊ฐ๋ฅ!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(200, "์ฌ์ฉ ๊ฐ๋ฅ", "OK", findByUserphoneNumber);
} else {
log.info("์ด๋ฏธ ์กด์ฌํ๋ ํธ๋ํฐ ๋ฒํธ ์
๋๋ค! 409 Code์ ํจ๊ป \"์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ ์
๋๋ค!\" ๋ฐํ ํ๊ฒ ์ต๋๋ค!");
return DefaultResponse.response(409, "์ด๋ฏธ ์กด์ฌํ๋ ํธ๋ํฐ ๋ฒํธ ์
๋๋ค!", "Conflict");
} // // if-else (checkEmail.isEmpty()) ๋
}
/**
* ํ์ ๊ฐ์
์๋น์ค
* @param customUserDetails - ํ์ ๊ฐ์
์ ์ํ ์ด์ฉ์ ์
๋ ฅ๊ฐ์ ๋ด์ Object
* @return DefaultResponse - ์๋ฒ ์ฒ๋ฆฌ ์ฌ๋ถ์ ํด๋นํ๋ Status Code ๋ฐํ์ ์ํ ๊ฐ์ฒด
* @see ""
*/
@Override
public DefaultResponse signUp(CustomUserDetails customUserDetails) {
log.info("UserServiceImpl์ signUp(CustomUserDetails customUserDetails)์ด ํธ์ถ ๋์์ต๋๋ค!");
log.info("DB์์ ํ์ ๊ฐ์
์์ฒญ ์ด์ฉ์๊ฐ ์
๋ ฅํ UserId(username)๋ฅผ ํตํด ํด๋น ํ์์ด ๋ฑ๋ก ๋์ด ์๋์ง ์ฐพ๊ฒ ์ต๋๋ค!");
log.info("์ด์ฉ์์ ํจ์ค์๋๋ฅผ ์ํธํ ํ๊ฒ ์ต๋๋ค!");
customUserDetails.setPassword(passwordEncoder.encode(customUserDetails.getPassword()));
userMapper.signUp(customUserDetails);
return DefaultResponse.response(200, "ํ์ ๊ฐ์
์๋ฃ!", "Success Sign up");
} // signUp(CustomUserDetails customUserDetails) ๋
} // class ๋
๐ฆ UserMapper.java
/**
* ํ์ ๊ด๋ จ Mapper
* <pre>
* <b>History:</b>
* ์ฃผ๋ํ๋, 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* </pre>
*
* @author ์ฃผ๋ํ๋
* @version 1.0.0, 2022.03.24 ์ต์ด ์์ฑ
* @See ""
* @see <a href=""></a>
*/
@Mapper @Repository public interface UserMapper {
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
Optional<DuplicateByIdInfoDTO> findByUserID(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ - ๋ณ๋ช
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
Optional<DuplicateByIdInfoDTO> findByUserNickName(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ - E-mail
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
Optional<DuplicateByIdInfoDTO> findByUserEmail(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ๋ฑ๋ก๋ ์ ๋ณด ์ธ์ง ํ์ธ - ํธ๋ํฐ ๋ฒํธ
* @param duplicateByIdInfoDTO - ํ์ ๊ฐ์
์ ๋ฑ๋ก ๋์ด ์๋ ์ ๋ณด ์ธ์ง ํ์ธ์ ์ํ ์ด์ฉ์ ์
๋ ฅ ์ ๋ณด DTO
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
Optional<DuplicateByIdInfoDTO> findByUserPhoneNumber(DuplicateByIdInfoDTO duplicateByIdInfoDTO);
/**
* ํ์ ๊ฐ์
์ ์ํ ์ถ์ Method
* @param customUserDetails - ํ์ ๊ฐ์
์ ์ด์ฉ์๊ฐ ์
๋ ฅํ ์ ๋ณด ๋ด์ ๊ฐ์ฒด
* @return CustomUserDetails - ํด๋น ํ์์ ์ ๋ณด ๋ฐํ
* @see ""
*/
void signUp(CustomUserDetails customUserDetails);
} // interface ๋
โบ duplicateUserID()
์ด ์น๊ตฌ๊ฐ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋น์ฆ๋์ค Logic์ ๋ด๋นํ๊ฒ ๋ UserService๋ฅผ Implements(๊ตฌํ)ํ ๊ตฌํ์ฒด์ธ ๊ฒ์ด์์.
๋จผ์ ํด๋น Class๋ฅผ Spring Bean์ ํด๋น Class๋ฅผ Service๋ก ์๋ ์ฃผ์ ํ๊ธฐ ์ํด `@Service`๋ฅผ ์ ์ธํด ์ค ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค์ ํ์ ๊ฐ์ ์ ํ ๋, ์ด์ฉ์์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํ ํ๊ธฐ ์ํด `PasswordEncoder` ๊ฐ์ฒด๋ฅผ ์ ์ธํ๊ณ , DB๋ฅผ ์ด์ฉํ๊ธฐ ์ํด `UserMapper `๊ฐ์ฒด๋ฅผ ์ ์ธํ ๊ฒ์ด์์. ์ด ์น๊ตฌ๋ค์ final๋ก ์ ์๋์ด ์๊ณ , ์ด ๋๋ฌธ์ `@RequiredArgsConstructor`๋ฅผ ์ ์ธํ์ฌ ์์ฑ์๋ฅผ ์ด์ฉํ ์ ์๋๋ก ํด ์ค ๊ฒ์ด์์.
์ต์ด ์ด Method๊ฐ ํธ์ถ๋๋ฉด `Mapper`์ ํด๋น Method๋ฅผ ํตํด `DuplicateByIdInfoDTO`๋ฅผ ์ ๋ฌํด์ ํธ์ถํ๋๋ฐ, ์ด ๋ ์ด์ฉ์๊ฐ ID ์ค๋ณต ํ์ธ ๋ฒํผ์ ๋๋ฅด๊ฒ ๋๋ฉด ํด๋น ID๋ฅผ DB์ Selectํ๊ฒ ๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ ๊ฐ์ `Optional`๋ก `NPE(Null Point Exception)` ๋ฐฉ์ง๋ฅผ ํตํด `DuplicateByIdInfoDTO` ๊ฐ์ฒด ์๋ฃํ Type์ ๋ณ์ `findByuserID`์ ๋ด์ ์ฃผ๋ ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค 47๋ฒ์งธ ์ค์ if๋ฌธ์ ํตํด ํด๋น ๋ณ์์ ๊ฐ์ด ๋น์ด ์๋ค๋ฉด ์ค๋ณต๋๋ ID๊ฐ ์๋ค๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ฐํ ํ ๋, HTTP Status Code 200๊ณผ ํจ๊ป ์๋ต Message๋ก ํ๊ธ์ `์ฌ์ฉ ๊ฐ๋ฅ`๊ณผ ์์ด๋ก๋ `OK`๋ฅผ ๋ฐํํ๊ณ , ํด๋น ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ธฐ ์ํด ๊ฐ์ฒด๋ฅผ ์ถ๊ฐ๋ก ๋ฐํ ํด ์ฃผ๋ ๊ฒ์ด์์.
๋ง์ฝ ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์๋ค๋ฉด ํด๋น ID๋ ์กด์ฌํ๋ค๋ ์๋ฏธ๊ฐ ๋๊ณ , ๋ฐํ ํ ๋, HTTP Status Code๋ฅผ 409์ ํจ๊ป ์๋ต Message๋ก ํ๊ธ์ `์ด๋ฏธ ์กด์ฌํ๋ ID ์ ๋๋ค!`์ ์์ด๋ก `Confilct`๋ฅผ ๋ฐํ ํด ์ฃผ๋ ๊ฒ์ด์์.
โบ signUp()
ํ์ ๊ฐ์ ์ ๋ํ ๋น์ฆ๋์ค ๋ก์ง์ ์ด ๊ณณ์์ ์ฒ๋ฆฌ๊ฐ ๋๋ ๊ฒ์ด์์.
์ต์ด ์ด ์น๊ตฌ๊ฐ ๋์์ ํ๊ฒ ๋๋ฉด ์ด์ฉ์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํ ํ๊ธฐ ์ํด `PasswordEncoder`์ `encode()`๋ฅผ ํธ์ถํ๋๋ฐ, ์ด ๋ ์ด์ฉ์๊ฐ ๋ณด๋ธ `CustomUserDetails` ๊ฐ์ฒด ์์ ์ ๋ ฅ๋ password๋ผ๋ Member ๋ณ์์ ๊ฐ์ ๊ฐ์ ธ์์ ๊ทธ ๊ฐ์ ์ํธํ ํ๊ณ , ๊ทธ๊ฒ์ ๋ค์ setter๋ฅผ ํตํด ์ ์ฅํด ๋๋ ๊ฒ์ด์์.
์ฐธ๊ณ ๋ก ๋จ์ํ ์ด๋ ๊ฒ `PasswordEncoder`๋ฅผ ์ด์ฉํ๊ฒ ๋๋ฉด Exception์ด ๋จ๊ฒ ๋๋๋ฐ, ์ด๋ `PasswordEncoder`๊ฐ ํ๋ ์ญํ ์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํํ๋๋ฐ, ์ด๋ฅผ ๊ตฌํํ๋ ๊ตฌํ์ฒด๋ค์ด ํ๋ ์ญํ ์ด ๋ฐ๋ก ์ด ์ํธํ๋ฅผ ์ด๋ค ๋ฐฉ์์ผ๋ก ํ ๊ฒ์ธ์ง ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ๋ํ ์ ์๊ฐ ์๋ ๊ฒ์ด์์.
์ด ๋๋ฌธ์ `PasswordEncoder`์ ๊ตฌํ์ฒด๋ฅผ ๋์ ํด์ฃผ๊ณ , ์ด๋ฅผ Spring Bean์ ๋ฑ๋กํ๋ ๊ณผ์ ์ด ์์ด์ผ ํ๋๋ฐ,
์์ Code๋ก๋ง ๋ณด์์ ๋๋ ์ด ๊ณผ์ ์ด ์๋ต๋์ด ์๋ ๊ฒ์ด์์.
`Spring Security`์ ๋ํด ํ์ํ ์ค์ ์ ํ๋ Config ๊ฐ์ฒด๋ฅผ ์์ฑํด์ ์์ ์ค์ ๋ค์ ํด ์ฃผ๋ฉด ๋๋ ๊ฒ์ด๋๋๋ค.
Config ๊ฐ์ฒด๋ `WebSecurityConfigurerAdapter`๋ฅผ ์์ ๋ฐ์ `configure()`๋ฅผ ๊ตฌํํ๋ฉด ๋๋ ๊ฒ์ด์์.
์ฃผ๋ํ๋์ `Spring Security` Config ๊ฐ์ฒด๋ฅผ ์์ ๊ฐ์ด ์ ์๋ฅผ ํ ๊ฒ์ด์์.
์ต์ด 28๋ฒ์งธ ์ค์ `@Configuration`์ ํตํด ํด๋น Class๊ฐ 1๊ฐ ์ด์์ Bean์ ์ ๊ณตํ๋ค๊ณ ์๋ ค ์ฃผ๋ ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค์ 29๋ฒ์งธ ์ค์ `@EnableWebSecurity`๋ฅผ ํตํด `Spring Security`๊ฐ ์๋ํ๋๋ก ์๋ Button์ ๋๋ฌ์ฃผ๋ ๊ฒ์ด์์.
30๋ฒ์งธ ์ค์ `@EnableGlobalMethodSecurity(prePostEnabled = true)`๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๊ฐ ์ฒ๋ฆฌ๋ฅผ ํ๋๋ฐ, ํน์ Method๊ฐ ํธ์ถ ๋ ์ด ์ ๊ณผ ์ด ํ ํธ์ถ์ ์์ฒญํ ์ด์ฉ์์ ๊ถํ์ ํ์ธํ๊ธฐ ์ํจ์ธ ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค `@Bean`์ ํตํด `Srping Framwork`์์ ํด๋น ๊ฐ์ฒด๋ฅผ Bean์ผ๋ก ์ฃผ์ ํ ์ ์๊ฒ ์ ์ธํด ์ค ๊ฒ์ด์์.
์ฆ, `@Autowired`๋ฅผ ์ด์ฉํ์ฌ `Spring Framwork`์์ `DI(Dependncy Injection)์ ์ด์ฉํ ์ ์๋ค๋ ๊ฒ์ด์์. ์ด๋ ๊ฒ ํด์ฃผ๋ฉด ์ธ๋ถ Class์์ `PasswordEncoder`๋ฅผ `@Autowird`๋ฅผ ์ด์ฉํ์ฌ ์ฝ๊ฒ `DI`ํ ์ ์๋ต๋๋ค!
์ฐธ๊ณ ๋ก ์ฃผ๋ํ๋์ `@Autowird` ๋์ `@RequiredArgsConstructor`๋ฅผ ์ด์ฉํ ๊ฒ์ด์์.
๋ค์ ์ด ๊ณณ์ผ๋ก ๋์์์ 162๋ฒ์งธ ์ค์ userMappe์ ํด๋น Method๋ฅผ ํธ์ถํ๋๋ฐ, `CustomUserDetails` ๊ฐ์ฒด๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ ํด ์ฃผ๋ ๊ฒ์ด์์.
๊ทธ๋ฐ ๋ค Controller์๊ฒ ๋ฐํํ ๋, HTTP Status Code 200 ์ซ์์ ํจ๊ป, ํ๊ธ Message ํ์ ๊ฐ์ ์๋ฃ!์ ์์ด Success Sign up์ ์ ๋ฌ ํด ์ฃผ๋ ๊ฒ์ด์์.
๐ฆ UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.devcommunity.junyharang.mapper.user.UserMapper">
<!-- ๊ธฐ ๋ฑ๋ก๋ ํ์ ์ ๋ณด๊ฐ ์๋์ง ํ์ธ ID -->
<select id="findByUserID" parameterType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO"
resultType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO">
select username
from user
where username = #{username}
</select>
<!-- ๊ธฐ ๋ฑ๋ก๋ ํ์ ์ ๋ณด๊ฐ ์๋์ง ํ์ธ ๋ณ๋ช
-->
<select id="findByUserNickName" parameterType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO"
resultType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO">
select nickname
from user
where nickname = #{nickname}
</select>
<!-- ๊ธฐ ๋ฑ๋ก๋ ํ์ ์ ๋ณด๊ฐ ์๋์ง ํ์ธ Email -->
<select id="findByUserEmail" parameterType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO"
resultType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO">
select userEmail
from user
where userEmail = #{userEmail}
</select>
<!-- ๊ธฐ ๋ฑ๋ก๋ ํ์ ์ ๋ณด๊ฐ ์๋์ง ํ์ธ ํธ๋ํฐ ๋ฒํธ -->
<select id="findByUserPhoneNumber" parameterType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO"
resultType="com.devcommunity.junyharang.model.dto.user.DuplicateByIdInfoDTO">
select userPhone
from user
where userPhone = #{userPhone}
</select>
<!-- ํ์ ๊ฐ์
์ ์ํด DB์ ํ์ ์ ๋ณด ์ ์ฅ -->
<insert id="signUp" parameterType="com.devcommunity.junyharang.model.vo.member.CustomUserDetails">
<![CDATA[
insert into user (
username,
password,
nickname,
userEmail,
userPhone,
enable,
authority
) values (
#{username},
#{password},
#{nickname},
#{userEmail},
#{userPhone},
1,
"ROLE_USER"
)
]]>
</insert>
</mapper>
โบ duplicateUserID()
ํด๋น ๊ธฐ๋ฅ์ ID ์ค๋ณต ํ์ธ์ธ ๊ฒ์ด์์. `Service Layer`์์ ํด๋น Mapper๋ฅผ ํธ์ถํ์ฌ ์ป๊ณ ์ ํ๋ ๊ฒ์ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ๋ ์ด์ฉ์๊ฐ ์ฌ์ฉํ๊ณ ์ ํ๋ ID๊ฐ ์กด์ฌํ๋์ง ์ฌ๋ถ๋ฅผ ์๊ณ ์ถ์ ๊ฒ์ด์์.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ SQL์ `SELECT`๋ฅผ ํตํด username Column์ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ ๋ DTO์์ ์์ username์ด ์๋์ง ์ฐพ๋๋ก ํ๊ณ , ์ด๋ฅผ ๋ค์ `DuplicateByIdInfoDTO`์ ๋ด์ ๋ฐํํ๊ฒ ํ ๊ฒ์ด์์.
โบ signUp()
ํด๋น ๊ธฐ๋ฅ์ ๋ณธ๊ฒฉ์ ์ธ ํ์ ๊ฐ์ ์ ์ํด DB์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์ถ์ ๊ฒ์ด์์.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ SQL์ `INSERT`๋ฅผ ํตํด ํ์ ๊ฐ์ ์ ์๋ํ๋ ์ด์ฉ์๊ฐ ๋ณด๋ธ ๊ฐ์ ๊ฐ Column์ ์ ๋ ฅํ์ฌ ์ ์ฅ ๋๊ฒ ํ๊ณ , ํด๋น ๊ณ์ ์ด ํ์ฑํ ๋์ด ์๋ค๊ณ ํ์ํ๊ธฐ ์ํด `enable` Column์ `1` ๊ฐ์ ๋ฃ์ด์ฃผ๊ณ , ํด๋น ์ด์ฉ์์ ๊ธฐ๋ณธ ๊ถํ์ `ROLE_USER`๋ก ๋ฃ์ด์ค ๊ฒ์ด์์.
๐ ๊ฒฐ๊ณผ
๐ฝ ID ์ค๋ณต ํ์ธ
๐ฆ ๋ฑ๋ก๋์ง ์์ ID
๐ฆ ๋ฑ๋ก๋ ID
๐ฝ ํ์ ๊ฐ์
์ง์! ๐
์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋๊ณ ์๋ ๊ฒ์ด์์.
๐ ์์ ์ฌํญ - Validation
์์ ๊ธ์์๋ ์ ํจ์ฑ ๊ฒ์ฌ (Validation)์ด ์ ํ ์งํ๋๊ณ ์์ง ์์ ๊ฒ์ด์์.
์ฌ๊ธฐ์ ๋ํ ๋ด์ฉ์ '์ด ๊ณณ'์ ์ค๋น ํด ๋์์ต๋๋ค!
๐ฝ ํ์ ID ์ค๋ณต ํ์ธ - ์ ํจ์ฑ ๊ฒ์ฌ
๐ฆ ๊ณต๋ฐฑ ์ ๋ ฅ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ
๐ฆ ์๋ฌด ๋ด์ฉ๋ ์ ๋ ฅํ์ง ์์์ ๋ ์ ํจ์ฑ ๊ฒ์ฌ
๐ฆ Null ์ ๋ ฅ์ ๋ํ ์ ํจ์ฑ ๊ฒ์ฌ
๐ฆ ํน์ ๋ฌธ์ ์ ๋ ฅ ์ ์ ํจ์ฑ ๊ฒ์ฌ
์ ํจ์ฑ ๊ฒ์ฌ๋ ๋ชจ๋ ์ค๋ณต ํ์ธ ๋ฐ ํ์ ๊ฐ์ ์ ์ถ๊ฐ๋ฅผ ํด ๋ ๊ฒ์ด์์.
์์ธํ ์ค๋ช ์ ๋ฐ๋ก ๋ด์ฉ์ ์ ๋ฆฌ ํด ๋์์ผ๋ ํ์ ๊ฐ์ ์ ๋ํ ๋ด์ฉ์ ์ฌ๊ธฐ์ ๋ง์น๋๋ก ํ๊ฒ ์ต๋๋ค!