[241202 TIL]

프로젝트 관리 심화

MSA 개인 프로젝트


1단계: 초기 환경 설정

1. 프로젝트 설계

  • 서비스 정의
    • Eureka Server: 서비스 등록/발견.
    • Gateway: API Gateway 역할로 라우팅, 인증/인가 담당.
    • Product Service: 상품 관리.
    • Order Service: 주문 관리.
    • Auth Service: 사용자 인증/인가.
  • 기술 스택
    • Spring Boot, Spring Cloud Netflix (Eureka, Gateway).
    • Spring Security (OAuth2, JWT).
    • Redis (캐싱), RabbitMQ (비동기 처리).
    • Zipkin (분산 추적).

2. 환경 설정

  • 공통 설정
    • application.yml을 dev/prod 환경으로 나눠 설정.
    • Eureka Server 실행 후 서비스들이 정상적으로 등록되도록 구성.
  • Docker Compose
    • Redis, Zipkin 등 의존성 추가.
    version: '3.8'
    services:
      redis-stack:
        image: redis/redis-stack
        container_name: redis-stack-compose
        restart: always
        ports:
          - 6379:6379
          - 8001:8001
      zipkin:
        image: openzipkin/zipkin:2.24.0
        container_name: zipkin
        ports:
          - 9411:9411
    

3. 기본 모듈 생성

  1. 각 서비스의 디렉토리 구조를 생성하고 Spring Boot 프로젝트로 초기화.
  2. 각 서비스에 application.yml 작성:
    spring:
      application:
        name: product-service
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:19090/eureka/
    

2단계: API 설계 및 기본 기능 구현

1. Eureka Server

  • 구현 방법
    • Spring Boot 프로젝트 생성 후 @EnableEurekaServer 추가.
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServerApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServerApplication.class, args);
        }
    }

2. Gateway

  • 라우팅 설정
spring:
  cloud:
    gateway:
      routes:
        - id: auth-service
          uri: lb://auth-service
          predicates:
            - Path=/auth/**
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/products/**
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/orders/**
  • JWT 인증 필터
@Component
public class LocalJwtAuthenticationFilter implements GlobalFilter {
    @Value("${service.jwt.secret-key}")
    private String secretKey;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // JWT 검증 로직
        String token = extractToken(exchange);
        if (token == null || !validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
}

3. Auth Service

  • 회원가입 API
@RestController
@RequestMapping("/auth")
public class AuthController {
    @PostMapping("/sign-up")
    public ResponseEntity<?> signUp(@RequestBody SignupRequestDto requestDto) {
        return ResponseEntity.status(HttpStatus.CREATED).body(authService.signUp(requestDto));
    }
}
  • JWT 생성
public String createAccessToken(String username, UserRoleEnum role) {
    return Jwts.builder()
            .claim("username", username)
            .claim("role", role)
            .signWith(secretKey, SignatureAlgorithm.HS512)
            .compact();
}

4. Product Service

  • 상품 추가 API
    @PostMapping("/products")
    public ResponseEntity<Product> addProduct(@RequestBody Product product) {
        return ResponseEntity.ok(productService.addProduct(product));
    }

5. Order Service

  • 주문 추가 API
    @PostMapping("/orders")
    public ResponseEntity<OrderResponseDto> createOrder(@RequestBody OrderRequestDto requestDto) {
        return ResponseEntity.ok(orderService.createOrder(requestDto));
    }

+ Recent posts