Spring/MSA

[스프링 MSA] MSA_S4 : Users Microservice (1)

ajeong7038 2023. 11. 8. 16:25

 

`Spring Cloud로 개발하는 마이크로서비스 애플리케이션 (MSA)` 강의를 듣고 정리한 자료입니다

 

✨ Users Microservice 개요

- Front-end 없이 생성

- Business Logic : Spring, SpringBoot

    -> 신규 회원 등록

    -> 회원 로그인

    -> 상세 정보 확인

    -> 회원 정보 수정/삭제

    -> 상품 주문

    -> 주문 내역 확인

- Database : H2

- API Gateway 사용 시 엔드포인트 앞에 `/user-service/` 가 붙는다 (Microservice 이름)


✨ Users Microservice 프로젝트 생성

- `@EnableDiscoveryClient` 애노테이션을 붙여야 유레카 서버 등록이 가능하다는 것을 잊지 말자!

랜덤 포트 사용

instanceId:${spring.application.name}:${spring.application.instanceid:${random.value}}

✨ yml 파일 데이터 값 가져오기

- Application.yml 파일에 등록되어진 정보를 가져오는 두 가지 방법

// Application.yml
greeting:
  message: Welcome to the Simple E-commerce.

 

`Environment`

1. `Alt + Insert` 키로 생성자 추가

private Environment env;

@Autowired
public UserController(Environment env) {
    this.env = env;
}

 

2. greeting 밑 message 불러오기

@GetMapping("/welcome")
public String welcome() {
    return env.getProperty("greeting.message");
}

`@Value`

1. 새로운 빈 생성

2. Value 애노테이션 달기

import org.springframework.beans.factory.annotation.Value;
@Data
@Component
public class Greeting {
    @Value("${greeting.message}")
	private String message;
}

 

- @Value 안 yml 파일 정보를 가져올 때는 `${}` 같이 써주기

 

3. Controller에서 사용 (주입)

@Autowired
private Greeting greeting;
@GetMapping("/welcome")
    public String welcome() {
//        return env.getProperty("greeting.message");
        return greeting.getMessage();
    }

 

- getMessage() 메소드가 존재하지는 않지만 message를 등록하면 lombok이 알아서 getter, setter을 지원해준다

 

H2 Database

- 자바로 작성된 오픈소스 RDBMS

- Embedded, Server-Client 가능

- JPA 연동 가능

- h2 설정 추가

spring:
  h2:
    console:
      enabled: true
      settings:
        web-allow-others: true
      path: h2-console

 

- RequestUser 에서 받아온 값을 저장하고 다른 쪽으로 넘기기 위한 변환 클래스가 필요함 => 패키지명 : `dto`

- 인터페이스를 구현한 자바 클래스는 일반적인 자바 클래스 등록보다는 데이터 값이 빈으로 등록되게끔 만들어두기

    -> `@Service` 추가

- mapper : 하나의 클래스가 갖고 있는 정보를 다른 클래스로 변환해준다

- 변환할 때 userEntity 타입의 인스턴스를 필요로 한다

PostMapping

- 매개변수로 넘겨 받는 것이 `RequestUser` 타입이라는 것을 잊지 말자!

public String createUser(@RequestBody RequestUser user) { }

 

- 반환값에 String 대신 ResponseEntity 넣기

// 201번 성공 코드 반환값
return new ResponseEntity(HttpStatus.CREATED);

 

ResponseUser responseUser = mapper.map(user, ResponseUser.class);

return ResponseEntity.status(HttpStatus.CREATED).body(responseUser);

 

- 사용자에게 원하는 값도 함께 넘길 수 있다


✨ Spring Security 연동

- 회원가입 시 입력하는 password를 데이터베이스 저장 시 암호화하는 작업

- Spring Security 라이브러리 이용

    -> Authentication + Authorization : 인증 + 권한 작업 (두 가지 메소드 재정의)

방법

1. 애플리케이션에 spring security jar을 Dependency 추가

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

2. WebSecurityConfigurerAdapter을 상속받는 Security Configuration 클래스 생성

3. Security Configuration 클래스에 `@EnableWebSecurity` 추가

4. Authentication -> Configure(AuthenticationManageBuilder auth) 메소드 재정의

5. Password encode를 위한 BCryptPasswordEncoder 빈 정의

6. Authorization -> configure(HttpSecurity http) 메소드 재정의

http.headers().frameOptions().disable();

 

- 추가해주지 않으면 h2-console 접근 X

- `@Configuration` 다른 빈보다 우선 순위로 등록

- 강의에서는 권한을 먼저 재정의했다

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
}

 

- Using generated security password: 암호

    -> 해당하는 스프링부트 프로젝트에서 인증 작업을 하기 위해 사용할 수도 있다

- h2 프레임별 데이터가 나뉘어 있어 오류 발생

- 무시할 수 있도록 아래의 코드 추가

http.headers().frameOptions().disable();

 

BCryptPasswordEncoder

- Password를 해싱하기 위해 Bcrypt 알고리즘 사용

- 랜덤 Salt를 부여하여 여러 번 Hash를 적용한 암호화 방식

- 기존 고정 방식에서 암호화된 패스워드로 교체

userEntity.setEncryptedPwd("encrypted_password");

 

- 필드 단위에서 `@AutoWired`를 통해 빈을 생성할 수 있지만 생성자를 통해 주입하는 것이 더 좋다


✨ Gradle

정의

- CI/CD를 위한 아래 Task들을 자동화 시켜주는 Build Tool

- Groovy를 기반으로 한 빌드 도구

- `Ant`와 `Maven`과 같은 이전 세대 빌드 도구의 단점을 보완하고 장점을 취합하여 만든 오픈소스로 공개된 빌드 도구

- 스프링부트와 안드로이드에서 사용

특징

1. 직관적인 코드와 자동완성

2. 다양한 Repository 사용 가능

3. 각 작업에 필요한 라이브러리들만 가져오는 작업 지원

4. 빌드 속도가 빠르다

    -> 점진적 빌드 : 바뀐 파일만 빌드

    -> Build Cache : 빌드 캐시를 이용해 이전 빌드의 결과물을 다른 빌드에서 이용

    -> Daemon Process : 서비스의 요청에 응답하기 위해 오랫동안 살아있는 프로세스 지원

5. 재사용에 용이 : 설정 주입 방식으로 정의


✨ Maven

정의

- 자바 프로젝트의 빌드를 자동화해주는 빌드 툴

    -> compile, package, deploy 자동화

- Apache Ant의 대안으로 만들어졌다

- XML 기반 작성

특징

- LifeCycle(미리 정해진 빌드 순서) 와 프로젝트 객체 모델 (POM) 개념 도입

- `Ant`의 장황한 빌드 스크립트 개선

- pom.xml에 필요한 라이브러리를 선언하면 자동으로 해당 프로젝트를 불러와준다

- 라이브러리끼리 의존하는 경우 복잡해질 가능성이 있다

- 간단한 설정을 통한 배포 관리가 가능하다


✨ Gradle vs Maven

- 아직까지는 Maven을 사용하는 곳이 많다

공통점

- 빌드 관리 도구

    -> 소스코드에서 애플리케이션 생성을 하면서 여러 가지 여부 라이브러리를 사용하는데, 이 빌드 관리 도구는 사용자가 - 직접 관리할 필요 없이 필요한 라이브러리들을 자동으로 관리한다

수행 작업

1. Compile : Kotlin 파일 or Java 파일을 바이트 코드로 변환

2. Test : 유닛 테스트, UI 테스트 등 지원

3. Packaging : 코드를 패키징해 jar or war 파일로 생성

4. Deploy & Run : 만들어진 스프링을 돌려 서버 실행

차이점

- Maven의 경우 모든 파일들이 xml로 이루어져 있어서 `Groovy` or `Kotlin` 으로 짜여진 Gradle보다 가독성이 떨어진다

cf) Groovy

- JVM에서 사용되는 스크립트 언어로, Java와 문법이 유사하다는 특징을 갖고 있다

- Java 클래스 파일을 그대로 Groovy 클래스 파일로 사용 가능

 


✨ 참고 자료

https://kotlinworld.com/311

https://madplay.github.io/post/what-is-gradle

https://jeong-pro.tistory.com/168

https://velog.io/@alicesykim95/Maven%EA%B3%BC-Gradle%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90


✨ 질문

1. 왜 변환하는가...

ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserEntity userEntity = mapper.map(userDto, UserEntity.class);
userEntity.setEncryptedPwd("encrypted_password");

userRepository.save(userEntity);

 

2. UserDto 정확히 하는 일이 뭘까...

3. 강사님 것만 오류 나는 원인은?

@Bean
public BCryptPasswordEncoder passwordEncoder() {
	return new BCryptPasswordEncoder();
}