[Spring boot] Spring boot Security๋ฅผ ์ด์šฉํ•œ OAuth2 ์ธ์ฆ ๊ตฌํ˜„ 2 - User Entity ์—ฐ๋™

๋ฐ˜์‘ํ˜•

์›น ์„œ๋น„์Šค๋ฅผ ๊ฐœ๋ฐœํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ–์ถฐ์ ธ์•ผ ํ•  ๊ฒƒ์€ ๋ฐ”๋กœ ์‚ฌ์šฉ์ž ์ธ์ฆ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ์„œ๋น„์Šค์— ๊ฐ€์ž…ํ•œ ์‚ฌ์šฉ์ž์ธ์ง€๋ฅผ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ๊ณผ ๋”๋ถˆ์–ด, ๋‹จ๊ณจ์ธ์ง€, ์•„๋‹Œ์ง€ ๋“ฑ์ด๋‚˜ ์‚ฌ์ดํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ด€๋ฆฌ์ž ๋“ฑ์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ฐ ์žˆ์–ด, ์‚ฌ์šฉ์ž ์ธ์ฆ์€ ํ•„์ˆ˜์ ์ธ ์š”์†Œ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ ์„œ๋น„์Šค์— ์žˆ์–ด ๊ฐ€์žฅ ๋ฒˆ๊ฑฐ๋กœ์šด ๊ฒƒ์€ ์‚ฌ์šฉ์ž ๋“ฑ๋ก์„ ์œ„ํ•œ ํšŒ์› ๊ฐ€์ž…์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ž์‹ ์˜ ๊ฐœ์ธ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ•˜๊ณ , ๋ณธ์ธ ์ธ์ฆ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•˜๋ฉฐ, ์ฃผ์†Œ์™€ ์ „ํ™”๋ฒˆํ˜ธ ๋“ฑ์„ ์ž…๋ ฅํ•จ๊ณผ ๋”๋ถˆ์–ด, ๋˜ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ๋•Œ๋งˆ๋‹ค ID์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” OAuth2 ์ธ์ฆ์„ ํ†ตํ•ด ์ ‘์†ํ•œ ์‚ฌ์šฉ์ž๋“ค์„ ์ €์žฅํ•˜๋Š” User Entity๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

 

Create User Entity

์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ ์ž‘์—…ํ–ˆ๋˜ ๋‚ด์šฉ์„ ์ด์–ด์„œ User Entity๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/9/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@Getter
@NoArgsConstructor
@Entity
@Table
public class User implements Serializable {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idx;
@Column
private String name;
@Column
private String password;
@Column
private String email;
@Column
private String principal;
@Column
@Enumerated(EnumType.STRING)
private SocialType socialType;
@Column
private LocalDateTime createdDate;
@Column
private LocalDateTime updatedDate;
@Builder
public User(String name, String password, String email, String principal,
SocialType socialType, LocalDateTime createdDate, LocalDateTime updatedDate) {
this.name = name;
this.password = password;
this.email = email;
this.principal = principal;
this.socialType = socialType;
this.createdDate = createdDate;
this.updatedDate = updatedDate;
}
}
view raw User.java hosted with โค by GitHub

๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ–์ถฐ์ ธ์•ผ ํ•  Primary Key์™€ ์•„์ด๋””, ํŒจ์Šค์›Œ๋“œ ๊ทธ๋ฆฌ๊ณ  E-mail ์ฃผ์†Œ ์นผ๋Ÿผ์„ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค. principal์€ Spring Security์—์„œ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋  ๊ถŒํ•œ๋“ค์„ ๋„ฃ์–ด ๋†“์„ ์นผ๋Ÿผ์ž…๋‹ˆ๋‹ค. 

 

์—ฌ๊ธฐ์— Lombok์—์„œ ์ง€์›ํ•˜๋Š” Builder ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•˜์—ฌ Builder ํŒจํ„ด์„ ์ด์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ์ถ”๊ฐ€ํ•ด์ค์‹œ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/11/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
view raw UserRepository.java hosted with โค by GitHub

Spring Data JPA์—์„œ ์ œ๊ณตํ•˜๋Š” JpaRepository๋ฅผ ์ƒ์† ๋ฐ›๊ณ , E-mail์„ ์ด์šฉํ•˜์—ฌ User ์ •๋ณด๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก findByEmail ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/9/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
public enum SocialType {
GOOGLE("google");
private final String ROLE_PREFIX = "ROLE_";
private String name;
SocialType(String name) {
this.name = name;
}
public String getRoleType() {
return ROLE_PREFIX + name.toUpperCase();
}
public String getValue() {
return name;
}
public boolean isEquals(String authority) {
return this.getRoleType().equals(authority);
}
}
view raw SocialType.java hosted with โค by GitHub

๋‹ค์–‘ํ•œ ์†Œ์…œ ๋กœ๊ทธ์ธ ๊ณ„์ •์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ์†Œ์…œ ํƒ€์ž…์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์—ด๊ฑฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

 

 

 

Argument Resolver

๋งŒ์•ฝ ๋กœ๊ทธ์ธ ํ–ˆ์„ ๋•Œ ๊ณ„์ •์ด ์†Œ์…œ ๋กœ๊ทธ์ธ๋œ ๊ณ„์ •์ด๋ผ๋ฉด, ๊ธฐ์กด์˜ ๊ณ„์ •๊ณผ ๋งคํ•‘ํ•ด์ฃผ๊ฑฐ๋‚˜, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ํšŒ์› ๊ฐ€์ž…์€ Form์„ ์ด์šฉํ•ด์„œ ๊ฐ์ข… ์ •๋ณด๋ฅผ ๋ฐ›๊ณ , JPA๋ฅผ ์ด์šฉํ•ด ์ •๋ณด๋ฅผ ๋„ฃ๊ณ  DB์— ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ, ์†Œ์…œ๋กœ ๋กœ๊ทธ์ธ๋œ ๊ณ„์ •์€ ์–ด๋–ป๊ฒŒ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋‚ด๊ฐ€ ๋งŒ๋“  View์—์„œ Form์ด ์ž…๋ ฅ๋˜๋Š” ๊ฒƒ๋„ ์•„๋‹ˆ๊ณ , ๊ทธ๋ ‡๋‹ค๋ฉด ์†Œ์…œ ๊ณ„์ • ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ •๋ณด๋ฅผ ๋ฐ›์•„์™€์•ผ ํ•˜๋Š”๋ฐ, ์ด๋ฏธ Google ๊ณ„์ •๊ณผ์˜ ์—ฐ๋™์€ Spring Security์—์„œ ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ์„ ์‚ฌ์šฉํ–ˆ์œผ๋‹ˆ ์ด๊ฒƒ์„ ์žฌ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ฑธ๊นŒ์š”?

 

์ด๋Ÿด ๋•Œ๋Š” Java์˜ ์–ด๋…ธํ…Œ์ด์…˜๊ณผ ํ•จ๊ป˜ Spring์—์„œ ์ œ๊ณตํ•˜๋Š” Argument Resolver๋ฅผ ์ด์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. oAuth2Login ๋ฉ”์†Œ๋“œ ๋ฐ‘์œผ๋กœ defaultSuccessfulUrl์„ ์ง€์ •ํ•˜์—ฌ ์†Œ์…œ ์‚ฌ์ดํŠธ๋กœ๋ถ€ํ„ฐ ๋กœ๊ทธ์ธ์ด ์„ฑ๊ณตํ•˜์˜€์„ ๋•Œ, API๋ฅผ ํ•œ ๊ฐœ ์ƒ์„ฑํ•˜๊ณ , ํ•ด๋‹น ๋ฉ”์†Œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํŠน์ • ์–ด๋…ธํ…Œ์ด์…˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์œผ๋กœ ์„ค์ •ํ•ด์ฃผ๋ฉด, ํ•ด๋‹น Resolver๊ฐ€ ํ˜ธ์ถœ๋˜๊ฒŒ๋” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์™ธ์—๋„ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

๋จผ์ € ๊ธฐ์กด์— ์šฐ๋ฆฌ๊ฐ€ ์„ค์ •ํ–ˆ๋˜ SecurityConfig ํŒŒ์ผ์„ ์กฐ๊ธˆ ๊ณ ์ณ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/9/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.antMatchers("/", "/oauth2/**", "/login/**", "/css/**",
"/images/**", "/js/**", "/console/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login().defaultSuccessUrl("/loginSuccess").failureUrl("/loginFailure")
.and()
.headers().frameOptions().disable()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
.and()
.formLogin().successForwardUrl("/board")
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/").deleteCookies("JSESSIONID").invalidateHttpSession(true)
.and()
.csrf().disable();
}
}
view raw SecurityConfig.java hosted with โค by GitHub

์ด์ „์— ์ž‘์„ฑํ–ˆ๋˜ OAuth2Login์—์„œ ๋กœ๊ทธ์ธ ์„ฑ๊ณตํ–ˆ์„ ๋•Œ ํฌ์ธํŠธ์™€ ์‹คํŒจํ–ˆ์„ ๋•Œ ํฌ์ธํŠธ๋ฅผ ์žก์•˜์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์ถ”๊ฐ€๋กœ ๋กœ๊ทธ์•„์›ƒ ๋ถ€๋ถ„๊นŒ์ง€ ์„ค์ •ํ•˜๋ฉด ์ข‹๊ฒ ์ฃ .

 

์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ ์ž‘์„ฑํ–ˆ๋˜ ๊ฒƒ ๊ทธ๋Œ€๋กœ Argument Resolver๋ฅผ ์ƒ์„ฑํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํ˜น์‹œ๋ผ๋„ ํฌ์ŠคํŠธ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ๋‹ค๋ฉด ์•„๋ž˜์˜ ๋งํฌ๋ฅผ ๊ผญ ์ฐธ๊ณ ํ•ด์„œ ๋ณด๊ณ  ์ง„ํ–‰ํ•ด์ฃผ์„ธ์š”.

 

https://blog.neonkid.xyz/238

 

[Spring] Argument Resolver๋ฅผ ์ด์šฉํ•œ ์œ ์—ฐ์„ฑ ์žˆ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์ฒ˜๋ฆฌ

์„œ๋น„์Šค๋ฅผ ์šด์˜ํ•˜๋‹ค๋ณด๋ฉด ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿด ๋•Œ๋งˆ๋‹ค Controller ๋ถ€๋ถ„์—์„œ ์ด๋ฅผ ์ „์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ฐ Controller์— ์ „์ฒ˜๋ฆฌ ํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜ํ™” ํ•˜๊ฑฐ๋‚˜ Utils ํด

blog.neonkid.xyz

๋จผ์ € ์–ด๋…ธํ…Œ์ด์…˜๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/11/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface SocialUser {
}
view raw SocialUser.java hosted with โค by GitHub

์ ๋‹นํ•œ ์ด๋ฆ„์„ ์ฃผ๊ณ , Target์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ•˜์—ฌ๊ธˆ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ•œ ๊ฐœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/11/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@RequiredArgsConstructor
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
private final UserRepository userRepository;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(SocialUser.class) != null &&
parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpSession session = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest().getSession();
User user = (User) session.getAttribute("user");
return getUser(user, session);
}
private User getUser(User user, HttpSession session) {
if (user == null) {
try {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
Map<String, Object> map = token.getPrincipal().getAttributes();
User convertUser = convertUser(token.getAuthorizedClientRegistrationId(), map);
user = userRepository.findByEmail(convertUser.getEmail());
if (user == null)
user = userRepository.save(convertUser);
setRoleIfNotSame(user, token, map);
session.setAttribute("user", user);
} catch (ClassCastException ex) {
return user;
}
}
return user;
}
private User convertUser(String authority, Map<String, Object> map) {
if (GOOGLE.getValue().equals(authority))
return getModernUser(GOOGLE, map);
return null;
}
private User getModernUser(SocialType socialType, Map<String, Object> map) {
return User.builder()
.name(String.valueOf(map.get("name")))
.email(String.valueOf(map.get("email")))
.principal(String.valueOf(map.get("id")))
.socialType(socialType)
.createdDate(LocalDateTime.now())
.updatedDate(LocalDateTime.now())
.build();
}
private void setRoleIfNotSame(User user, OAuth2AuthenticationToken token, Map<String, Object> map) {
if (!token.getAuthorities().contains(
new SimpleGrantedAuthority(user.getSocialType().getRoleType()))) {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(map, "N/A",
AuthorityUtils.createAuthorityList(user.getSocialType().getRoleType())));
}
}
}

์œ„์—์„œ ๋งŒ๋“  Repository๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž…ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋Œ€์ถฉ ์•„์‹œ๊ฒ ์ง€๋งŒ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…์„ ๋“œ๋ฆฐ๋‹ค๋ฉด, ๋จผ์ € ์†Œ์…œ ์œ ์ €๋กœ ๋กœ๊ทธ์ธ ํ•œ ๋’ค, ์„ธ์…˜์—์„œ ์œ ์ € ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ต๋‹ˆ๋‹ค. ๊ธฐ์กด ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ์ด๋ฉ”์ผ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐ€์ž…์„ ํ–ˆ๋‹ค๋ฉด ํ•ด๋‹น ์œ ์ €์™€ ์†Œ์…œ ๋กœ๊ทธ์ธ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฐ๋™๋˜์–ด ์ง€๊ณ , ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ƒˆ๋กœ์ด ์‚ฌ์šฉ์ž๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

/**
* Created by Neon K.I.D on 8/9/20
* Blog : https://blog.neonkid.xyz
* Github : https://github.com/NEONKID
*/
@Controller
public class LoginController {
@GetMapping({"", "/"})
public String getAuthorizationMessage() {
return "home";
}
@GetMapping("/login")
public String login() {
return "login";
}
@GetMapping("/board")
public String board() {
return "board";
}
@GetMapping("/loginSuccess")
public String loginComplete(@SocialUser User user) {
return "redirect:/board";
}
}
view raw LoginController.java hosted with โค by GitHub

๋งˆ์ง€๋ง‰์œผ๋กœ Controller์— ์•„๊นŒ ์œ„์—์„œ ์—ฐ๋™ํ•œ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์—”๋“œํฌ์ธํŠธ์‹œ ์‹คํ–‰ํ•  ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ํ•ด๋‹น ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์œ„์—์„œ ๋งŒ๋“  ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์„œ ์—ฐ๋™ํ•ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ๋งŒ๋“  Argument Resolver๋ฅผ ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋์ž…๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ ์„ค๋ช…์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋žตํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 

Test

ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ •์„ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•˜์—ฌ H2 Database๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ์‚ฝ์ž…์ด ๋˜์–ด์ง€๋Š”์ง€๋ฅผ ๋ณด๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

spring:
datasource:
url: jdbc:h2:file:~/test;AUTO_SERVER=TRUE
driver-class-name: org.h2.Driver
h2:
console:
enabled: true
path: /console
view raw application.yml hosted with โค by GitHub

home ๋””๋ ‰ํ„ฐ๋ฆฌ ๋ฐ‘์œผ๋กœ test ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ , ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ์ƒ์„ฑ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

console ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์•„๋ฌด๋Ÿฐ ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ํŒจ์Šค์›Œ๋“œ๋„ ์„ค์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ๋ฐ”๋กœ Connect๋ฅผ ๋ˆŒ๋Ÿฌ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

 

๋ณด๋‹ค์‹œํ”ผ User ํ…Œ์ด๋ธ”์ด ๋งŒ๋“ค์–ด์กŒ๊ณ , ์กฐํšŒ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์•„๋ฌด๋Ÿฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ฉ”์ธ ํŽ˜์ด์ง€์— ์ ‘์†ํ•˜์—ฌ ๋กœ๊ทธ์ธ์„ ์‹œ๋„ํ•œ ํ›„ ์ฝ˜์†” ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋ฉด ์œ„์™€ ๊ฐ™์ด ์ƒˆ๋กœ์šด ๊ณ„์ •์ด ์ƒ์„ฑ์ด ๋˜์—ˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๋งˆ์น˜๋ฉฐ...

๋ญ”๊ฐ€ ์Šคํ”„๋ง ๊ธ€์„ ๊ณ„์† ์ž‘์„ฑํ•˜๋ฉด์„œ๋ถ€ํ„ฐ ๊ฐœ๋…์— ๋Œ€ํ•œ ๊ธ€ ๋ณด๋‹ค๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ์ค‘์‹ฌ์œผ๋กœ ๊ธ€์„ ์“ฐ๊ฒŒ ๋  ๊ฒฝ์šฐ, ์ „๋‹ฌ์ด ์ž˜ ์•ˆ๋˜๋Š” ๋А๋‚Œ์„ ๋ฐ›๋Š” ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ์ž์ฃผ ๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์•„๋ฌด๋ž˜๋„ ๋ทฐ์˜ ์ค‘์‹ฌ์ด ์•„๋‹Œ ๊ธฐ์ˆ ์— ๋Œ€ํ•œ ์ดํ•ด๋„์™€ ์ •์˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ๊ทธ ์˜์˜๋ฅผ ๋‘๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ด์„œ ๊ทธ๋Ÿฐ๊ฑด์ง€ ๋‹ค์Œ ๋ฒˆ ๊ธ€์„ ์“ธ ๋•Œ๋Š” ์ข€ ๋” ์ „๋‹ฌ๋ ฅ์ด ํ–ฅ์ƒ๋œ ๋ชจ์Šต์œผ๋กœ ๊ธ€์„ ์จ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

OAuth2 ๋กœ๊ทธ์ธ์€ ์ตœ๊ทผ ์›น์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋กœ๊ทธ์ธ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด์„œ๋„ ์ œ๊ณต๋˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ˆ ์›น ๊ฐœ๋ฐœํ•˜์‹œ๋Š” ๋ถ„๋“ค์—๊ฒŒ ์žˆ์–ด ๋„์›€์ด ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋ฐ˜์‘ํ˜•
TAGS.

Tistory Comments