Users Microservice 개요
Front-end UI는 가지고 있지 않음
APIs
기능 | URI(API Gateway 사용시) | URI(API Gateway 미사용시) | HTTP Method |
사용자 정보 등록 | /user-service/users | /users | POST |
전체 사용자 조회 | /user-service/users | /users | GET |
사용자 정보, 주문 내역 조회 | /user-service/users/{user_id} | /users/{user_id} | GET |
작동 상태 확인 | /user-service/users/health_check | /users/health_check | GET |
환영 메시지 | /user-service/users/welcome | /users/welcome | GET |
Users Microservice - 프로젝트 생성
Dependencies
DevTools, Lombok, Web, Eureka Discovery Client
앞에서 만든 user-service 사용
UserController 에서 healthcheck
package com.example.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class UserController {
@GetMapping("health_check")
public String status(){
return "It's Working in User Service";
}
}
application.yml에 추가
greeting:
message: Welcome to the Simple E-commerce
사용하기 위해서는 Enviroment를 사용하거나 @Value로 사용
private Environment env;
@Autowired
public UserController(Environment env) {
this.env = env;
}
@GetMapping("/welcome")
public String welcome(){
return env.getProperty("greeting.message");
}
package com.example.vo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Data
public class Greeting {
@Value("${greeting.message}")
private String message;
}
@Autowired
private Greeting greeting;
@GetMapping("/welcome")
public String welcome() {
// return env.getProperty("greeting.message");
return greeting.getMessage();
}
Users Microservice - DB
H2 Database 사용
https://mvnrepository.com/artifact/com.h2database/h2
pom.xml에 dependency 추가 (scope을 test에서 runtime으로 변경)
1.3.176 버전으로 사용 (상위 버전은 보안상 spring boot에서 처음에 db 생성해주지 않음)
application.yml 에 추가
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
Users Microservice - 회원가입

하나의 객체를 다른 객체로 변환하는 Mapper 사용 (Mapstruct, modelMapper, BeanUtils... 여기선 modelMapper 사용)
아시아에서 한국과 일본은 ModelMapper를 중국은 MapStruct에 대한 관심도가 높은 것 같습니다.
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.8</version>
</dependency>
UserService
package com.example.userservice.service;
import com.example.userservice.dto.UserDto;
import com.example.userservice.jpa.UserEntity;
import com.example.userservice.jpa.UserRepository;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class UserServiceImpl implements UserService{
UserRepository userRepository;
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDto createUser(UserDto userDto) {
userDto.setUserId(UUID.randomUUID().toString());
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); // 속성이 모두 맞아 떨어지지 않으면 안되게 세팅
UserEntity userEntity = mapper.map(userDto, UserEntity.class);
userEntity.setEncryptedPwd("encrypted_password");
userRepository.save(userEntity);
UserDto returnUserDto = mapper.map(userEntity, UserDto.class);
return returnUserDto;
}
}
UserController
@PostMapping("/users")
public ResponseEntity<ResponseUser> createUser(@RequestBody RequestUser user) {
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserDto userDto = mapper.map(user, UserDto.class);
userService.createUser(userDto);
ResponseUser responseUser = mapper.map(userDto, ResponseUser.class);
return ResponseEntity.status(HttpStatus.CREATED).body(responseUser);
}
Users Microservice - Security
Spring Security -> Authentication(인증) + Authorization(권한)
- 어플리케이션에 Spring Security jar Dependency 추가
- WebSecurityConfigurerAdapter를 상속받는 Secutiry Configuration 클래스 생성
- Security Configuration 클래스에 @EnableWebSecurity 추가
- Authentication -> configure(AuthenticationManagerBuilder auth) 메서드 재정의
- Password encode 를 위한 BCryptPasswordEncoder 빈 정의
- Authorization -> configure(HttpSecurity http) 메서드를 정의
1. 어플리케이션에 Spring Security jar Dependency 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. WebSecurityConfigurerAdapter를 상속받는 Secutiry Configuration 클래스 생성
3. Security Configuration 클래스에 @EnableWebSecurity 추가
6. Authorization -> configure(HttpSecurity http) 메서드를 정의
package com.example.userservice.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
// 여러 configure 중 권한 관련
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/users/**").permitAll();
// h2에선 데이터가 프레임 별로 나눠져 있는데 그걸 무시해야 h2-console 사용가능
http.headers().frameOptions().disable();
}
}
Spring Security password 표시됨
나중에 인증작업할 수 있다. 아니면 임의로 password 설정해서 사용가능

http.header().frameOptions().disable() 추가하지 않으면 h2-console 접근 안됨
5. Password encode 를 위한 BCryptPasswordEncoder 빈 정의
Password 를 해싱하기 위해 Bcrypt 알고리즘 사용
랜덤 Salt를 부여하여 여러번 Hash를 적용한 암호화 방식
-> 랜덤 Salt로 해싱하기 때문에 같은 데이터가 들어와도 다른 결과를 반환한다.
BcryptPasswordEncoder 인스턴스도 빈으로 등록을 해줘야 한다.
가장 먼저 실행되는 클래스에 등록
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
암호화
userEntity.setEncryptedPwd(passwordEncoder.encode(userDto.getPwd()));
UserService - 사용자 조회
전체 사용자 조회 : GET, /users
사용자 정보, 주문 내역 조회 : GET, /users/{user_id}
health_check 포트번호 확인할 수 있게 수정
@GetMapping("/health_check")
public String status() {
return String.format("It's Working in User Service on Port %s", env.getProperty("local.server.port"));
}
apigateway-service 에 연동
apigateway-service에 user-service추가
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/user-service/**
작동 확인

http://172.30.1.39:8000/user-service/health_check 로 작동하면 404에러 나오게 됨
이유?
User service의 URI와 API Gateway의 URI가 다르기 때문이다.
user-service/health_check 에 해당하는 URI가 User service에 등록되어 있지 않고 그냥 /health_check로 등록되어 있다.
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseUser {
private String email;
private String name;
private String userId;
private List<ResponseOrder> orders;
}
@JsonInclude -> null인 데이터를 버림
@Data
public class ResponseOrder {
private String productId;
private Integer qty;
private Integer unitPrice;
private Integer totalPrice;
private Date createdAt;
private String orderId;
}
UserDto에 추가
private List<ResponseOrder> orders;
전체 사용자 조회 / 사용자 정보, 주문 내역 조회
@Override
public UserDto getUserByUserId(String userId) {
UserEntity userEntity = userRepository.findByUserId(userId);
if (userEntity == null) {
throw new UsernameNotFoundException("User not found");
}
UserDto userDto = new ModelMapper().map(userEntity, UserDto.class);
List<ResponseOrder> orders = new ArrayList<>();
userDto.setOrders(orders);
return null;
}
@Override
public Iterable<UserEntity> getUserByAll() {
return userRepository.findAll();
}
UserRepository 추가
UserEntity findByUserId(String userId);
UserController 작성
@GetMapping("/users")
public ResponseEntity<List<ResponseUser>> getUsers() {
Iterable<UserEntity> userList = userService.getUserByAll();
List<ResponseUser> result = new ArrayList<>();
userList.forEach(v -> {
result.add(new ModelMapper().map(v, ResponseUser.class));
});
return ResponseEntity.ok(result);
}
@GetMapping("/users/{userId}")
public ResponseEntity<ResponseUser> getUser(@PathVariable String userId) {
UserDto userDto = userService.getUserByUserId(userId);
ResponseUser returnValue = new ModelMapper().map(userDto, ResponseUser.class);
return ResponseEntity.ok(returnValue);
}
'Spring > [인프런] Spring Cloud' 카테고리의 다른 글
Users Microsservice - Login (0) | 2022.06.20 |
---|---|
Catalogs, Orders Microservice (0) | 2022.06.19 |
E-commerce 어플리케이션 (0) | 2022.06.18 |
API Gateway Service (0) | 2022.06.17 |
Service Discovery (0) | 2022.05.29 |