์ถํ์ Kafka์ RabbitMQ์ ๊ฐ์ ์ค์ ๋ ์ถ๊ฐํ ๊ฑฐ์ง๋ง ๊ทธ๊ฑด ๊ทธ๋ ์๊ฐํ๊ณ ์ฐ์ ๋น์ฅ์ ์ฌ์ฉํ ๊ฑฐ ๊ฐ์ ์์กด์ฑ๋ง ์ถ๊ฐํด๋ดค๋ค. ์๊ฐ๋ณด๋ค ๋ง๋ค...ใ
@SpringBootApplication
@EnableDiscoveryClient
public class LoginServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LoginServiceApplication.class, args);
}
}
Eureka์ ๋ฑ๋ก๋๋๋ก @EnableDiscoveryClient
๋ฅผ ์ถ๊ฐํด์ฃผ๊ณ
server:
port: 0 #๋๋ค์ผ๋ก ํฌํธ ์ค์
spring:
application:
name: login-service #Eureka์ ๋ฑ๋ก๋๋ ์๋น์ค ์ด๋ฆ
eureka:
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}} #ํฌํธ๊ฐ ์ค๋ณต์ผ๋ก ์ค์ ๋์ด ๊ตฌ๋ถํ๊ธฐ ์ํ ์ธ์คํด์ค ์์ด๋ ๊ฐ ์ค์
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka
๋ค์ ์ค์ ๋ด์ฉ์ config server git์ ์ฌ๋ ค๋์ or application.yml์ ๊ทธ๋๋ก ๋ฑ๋กํด๋ ๋๋ค.
application.yml
server:
port: 0 #๋๋ค์ผ๋ก ํฌํธ ์ค์
spring:
application:
name: login-service #Eureka์ ๋ฑ๋ก๋๋ ์๋น์ค ์ด๋ฆ
eureka:
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}} #ํฌํธ๊ฐ ์ค๋ณต์ผ๋ก ์ค์ ๋์ด ๊ตฌ๋ถํ๊ธฐ ์ํ ์ธ์คํด์ค ์์ด๋ ๊ฐ ์ค์
bootstrap.yml
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka
bootstrap์ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํด์ค๋ค.
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' implementation 'org.springframework.boot:spring-boot-starter-actuator'
spring initialization์ผ๋ก ๋ง๋ค์๋ ํ๋ก์ ํธ์์ ์ ์ ์๋์ ํ์ง ์์์ ๋ค์ ์์กด์ฑ์ ๋ ์ถ๊ฐํด์ฃผ์๋ค.
config์ ๊ฒฝ์ฐ
${}
๊ณผ ๊ฐ์ด ๋ณ์?๋ฅผ ๋ฐ์์ค๋ ์์ ์ ์ ์์ ์ผ๋ก ์งํ๋์ง ์๋๋ผ. config์ชฝ์์ ๋ฐ์์ค๋ ์ ๋ณด๋ ์ต๋ํ ๊ณ ์ ๊ฐ์ด ์ ํด์ง ๊ฐ์ผ๋ก๋ง ๋ฐ๊ณ ๋๋จธ์ง๋ application config๋ก ์คํํ์.
์ค์ ๊ณผ ํจ๊ป ์ ๋ฑ๋ก๋ ๊ฒ์ ๋ณผ์ ์๋ค.
์ด๋ ค์ง ํฌํธ๋ก ์ ์ํ๋ฉด security ์ค์ ์ผ๋ก ์ธํด ๋ชจ๋ ์ ๊ทผ์ด ๋งํ์๋ค. ์ด์ ์ด๊ฑธ ์ฐ๋ฆฌ๊ฐ ์ค์ ํด๋ณด์.
runtimeOnly 'com.h2database:h2:1.3.176'
์ฐ์ ์ h2๋ก ํ ์คํธ ์งํํ ๊ฒ์ด๋ฏ๋ก 1.3.176์ผ๋ก ์ฌ์ฉํ์ ์๋ํ๋ฉด ์ด ์์๋ฒ์ ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋๋ฐ ๊ทธ๊ฑธ ํด๊ฒฐํ๋ฉด์ ์งํํ๋ ค๋ฉด ์๊ฐ ๋ ๊ฑธ๋ฆฐ๋ค ๊ทธ๋ฅ 1.3.176์ผ๋ก ์ฐ์
spring:
h2:
console:
enabled: true
settings:
web-allow-others: true
path: /h2-console
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
password:
๋ค์ ์ค์ ๊ฐ์ application.yml์ ์ค์ ํด์ค๋ค. bootstrap์ ์ค์ ํด์ฃผ๋ ค๊ณ ํ๋ web-allow-others ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/**").permitAll();
http.headers().frameOptions().disable(); //h2 error
}
}
๊ทธ ํ ๋ค์๊ณผ ๊ฐ์ด security ์ค์ ์ ํตํด ๋ชจ๋ url์ ์ฐ์ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋๋ก ํ์ด๋์. ๊ทธ ํ์ ์ฐจ์ฐจ ์ ๊ทผ ๊ถํ์ ์ค์ ํด๋๊ฑฐ๋ค.
์ ์ ๊ทผ์ด ๋๋ค.
Controller์์ ํ ์คํธํ๊ธฐ ์ํด port๊ฐ ์ฐํ ๋์ค๋ url์ ํ๋ ๋ง๋ค์ด๋ณด์
@RestController
@RequestMapping(value = "/")
@RequiredArgsConstructor
public class HelloController {
private final Environment env;
@GetMapping("check")
public ResponseEntity<String> check(){
return ResponseEntity.ok().body(String.format("hello Login Service Port = %s", env.getProperty("local.server.port")));
}
}
ํฌํธ์ ์ง์ ๋ค์ด๊ฐ์ check๋ก ์์ฒญํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ ์ ์์ฒญ์ด ๋๋ค.
์ด์ gateway๋ฅผ ์ฐ๊ฒฐํด์ ์ฌ์ฉํด๋ณด์.
server:
port: 8000
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka
spring:
application: #gateway service ์ด๋ฆ๋ฆ
name: gateway-service
cloud:
gateway: #gateway ์ค์
routes:
- id: login-service #Service id
uri: lb://LOGIN-SERVICE #Eureka์ ๋ฑ๋ก๋ Service ์ด๋ฆ
predicates:
- Path=/login-service/** #๊ตฌ๋ถ๋ url
- Method=GET, POST #์์ฒญ ๊ฐ๋ฅํ Method
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/login-service(?<segment>.*), /$\{segment} #๋ค์ด์จ ์์ฒญ์ ๋ํด ์๋์ผ๋ก /login-service/๋ฅผ ๋ถ์ฌ์ ์คํ
config์ ์ค์ ํด๋จ๋ gateway์ ymlํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ฃผ์๋ค.
์ฌ์คํ ํ๋๋ผ ํฌํธ๊ฐ ๋ณ๊ฒฝ๋์์ง๋ง ์ด์ gateway๋ก ์์ฒญํ ์ ์๊ฒ ๋์๋ค.
๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๋ง๋ค๊ธฐ ์ ์ ์ฐ์ ํ์๊ฐ์ ์ ํตํด User์ ์ ๋ณด๋ฅผ ๋ฑ๋กํ User Entity๋ฅผ ๋ง๋ค์ด๋๋ ค๊ณ ํ๋ค.
@Table(name = "USERS")
@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "user_id", nullable = false, unique = true, length = 10)
private String userId;
@Column(nullable = false, length = 20)
private String name;
@Column(nullable = false, length = 150)
private String pw;
@Column(nullable = false, length = 10)
private String address1;
@Column(nullable = false, length = 50)
private String address2;
@Column(nullable = false, length = 50)
private String address3;
@Column(nullable = false, length = 20)
private String tel;
@CreationTimestamp
private LocalDateTime createdAt = LocalDateTime.now();
@Builder
public UserEntity(@NonNull Long id, @NonNull String userId, @NonNull String name, @NonNull String pw, @NonNull String address1, @NonNull String address2, @NonNull String address3, @NonNull String tel) {
this.id = id;
this.userId = userId;
this.name = name;
this.pw = pw;
this.address1 = address1;
this.address2 = address2;
this.address3 = address3;
this.tel = tel;
}
}
UserEntity
๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ๋ค.
@AllArgsConstructor
@Getter
public class RequestUser {
private String userId;
private String pw;
private String name;
private String address1; //์ฐํธ๋ฒํธ
private String address2; //๋๋ก๋ช
์ฃผ์
private String address3; //์์ธ ์ฃผ์
private String tel; //์ ํ๋ฒํธ
}
RequestUser
๋ผ๋ Vo๋ฅผ ์ ์ํ์ฌ Controller์์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์๊ฑฐ๊ณ
@SpringBootApplication
@EnableDiscoveryClient
public class LoginServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LoginServiceApplication.class, args);
}
//๋น๋ฐ๋ฒํธ ์ํธํ์ฉ encoder
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
๋น๋ฐ๋ฒํธ ์ํธํ๋ฅผ ์ํด Security์์ ์ ๊ณตํ๋ Encoder๋ฅผ Bean์ผ๋ก ๋ฑ๋กํด์ค๋ค.
@Getter
@AllArgsConstructor
@Builder
public class ResponseUser {
String userId;
}
Vo ResponseUser
๋ฅผ ์ถ๊ฐํ๊ณ
public interface UserService {
ResponseUser join(RequestUser user);
}
service interface๋ฅผ ์ถ๊ฐํด์ค๋ค.
ModelMapper์ ๊ฐ์ ์๋ ๋งคํผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์์ง๋ง ์ฑ๋ฅ์ ์ ํ๋ ์ค์ ์ ์์ด์ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์๋ ์ฌ์ฉํ๋ builder ํจํด์ผ๋ก ์์ฑํ๋ค.
@Repository
public interface UserRepository extends CrudRepository<UserEntity, Long> {
}
repository๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๊ณ
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService{
private final BCryptPasswordEncoder passwordEncoder;
private final UserRepository userRepository;
@Override
public ResponseUser join(RequestUser user) {
UserEntity userEntity = UserEntity.builder()
.userId(user.getUserId())
.pw(passwordEncoder.encode(user.getPw()))
.name(user.getName())
.address1(user.getAddress1())
.address2(user.getAddress2())
.address3(user.getAddress3())
.tel(user.getTel())
.build();
UserEntity save = userRepository.save(userEntity);
return ResponseUser.builder().userId(save.getUserId()).build();
}
}
UserServiceImpl
์ ํ์๊ฐ์
๋ก์ง์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.
์ด์ ํฌ์คํธ๋งจ์ ํตํด ์์ฒญํด๋ณด์.
๋ค์๊ณผ ๊ฐ์ด ์์ฒญํ๊ณ
๋ฐ์ดํฐ๋ ์ ๋ค์ด์๋ค.
ํ์ง๋ง ์๋ฌ๊ฐ ๋ฐ์ํ๋๋ฐ... ์ด์ ๋ pw์ ๊ธธ์ด๋ฅผ ๋๋ฌด ์งง๊ฒ ์ก์๋จ๋ค. ์ํธํ ์ดํ์ ๊ธธ์ด๊ฐ 60๊น์ง ๊ธธ์ด์ ธ๋ฒ๋ ค์ ์ค๋ฅ๊ฐ ๋ฌ๋ค. ๊ธธ์ด๋ฅผ 150๊น์ง ๋๋ ค๋ฒ๋ฆฌ์.
์ ์์ ์ผ๋ก ์ ๋ฑ๋ก๋์๋ค!
DB์๋ ์ ์ ๋ฑ๋ก๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
์ ์ ์คํ์ ๋์ง๋ง api์ฒ๋ผ ๋ญ๊ฐ ํ์์ด ์์ด ๊ทธ๋ฅ ๋ด๊ฐ ๋ฐํํ๊ณ ์ถ์๋๋ก ๋ฐํ์ด ๋๋ค. api๋ผ๋ฉด ์ผ์ ํ ๊ท์น์ด ์๋ ์คํ์ ์ ์ํด๋๊ณ ํด๋น ์คํ์ผ๋ก ๋ฐํํด์ฃผ๋ ๊ฒ์ด ์ฌ์ฉ์์๊ฒ๋ ์ข๊ธฐ ๋๋ฌธ์ด๋ค.
@Getter
public class CommonResponse<T>{
private String code;
private String msg;
private T data;
@Builder
public CommonResponse(String code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
CommonResponse
class๋ฅผ ์ ์ํด์ ์ฌ์ฉํด๋ณด์.
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/")
@Slf4j
public class UserController {
private final UserService userService;
@PostMapping("/join")
public ResponseEntity<CommonResponse<Object>> join(@RequestBody RequestUser user){
log.debug("user = {}", user.toString());
ResponseUser responseUser = userService.join(user);
CommonResponse<Object> response = CommonResponse.builder()
.code("200") //api ์ ์๋ ์ฝ๋
.msg("ํ์๊ฐ์
์ ์์คํ") //api ์ ์๋ ๋ฉ์ธ์ง
.data(responseUser) //๋ฐ์ดํฐ
.build();
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
}
UserController
๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์คฌ๋ค.
์ด์ ๋ค์ ์คํํด๋ณด๊ณ ๊ฒฐ๊ณผ๊ฐ์ ํ์ธํด๋ณด์!
๊ฒฐ๊ณผ ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ด ๋์ค๋๋ฐ ์ด์ ์๊ทผ api ๊ฐ์ด ๋ฐํํ๋ค. Exception ์ฒ๋ฆฌ๋ ํด์ค์ผํ๋๋ฐ. ์ฐ์ jwt๋ ์ ์ฉํด์ผํ๋ ๋ค ํด๋๊ณ ํด๋ณด์!