프로젝트명

    • MSA-Delivery

    프로젝트 인원

    • 김지수, 김예원, 윤홍찬, 이현민

    API 명세서

    허브

    생성

     

    수정

     

    삭제

     

    전체 조회 및 검색

     

    상세 조회


    허브간 이동 경로

    생성

     

    수정

     

    삭제

     

    전체 조회 및 검색

     

    상세 조회


    주문

    생성

     

    전체 조회 및 검색

     

    상세 조회

     

    수정

     

    삭제


    슬랙 메시지

    생성

     

    전체 조회 및 검색

     

    상세 조회

     

    수정

     

    삭제


    유저

    회원가입

     

    로그인

     

    전체 조회 및 검색

     

    수정

     

    상세 조회

     

    삭제


    배송

    배송 및 배송 경로 생성

     

    전체 조회 및 검색

     

    상세 조회

     

    수정

    삭제


    배송 경로

    전체 조회 및 검색

     

    상세 조회

     

    수정

     

    삭제

     


    배송 담당자

    생성

     

    전체 조회 및 검색

     

    상세 조회

     

    수정

     

    삭제


    업체

    생성

     

    전체 조회 및 검색

     

    상세 조회

     

    수정

     

    삭제

     


    상품

    생성

     

    전체 조회 및 검색

     

    상세 조회

     

    수정

     

    삭제


    테이블 명세서

     


    ERD 명세서


    인프라 설계서

    포트 번호

    • EUREKA : 19090
    • GATEWAY : 19091
    • SLACK : 19092
    • USER : 19094
    • COMPANY : 19096
    • ORDER: 19098
    • DELIVERY: 19100
    • HUB : 19102

    [241206 TIL]

    대규모 AI 시스템 설계 프로젝트


    1. 브랜치 생성 및 작업

    Step 1: 브랜치 생성

    develop 브랜치에서 새 브랜치를 생성합니다.

    git checkout develop  # develop 브랜치로 이동
    git pull origin develop  # 최신 상태로 동기화
    git checkout -b feature/add-templates  # 새 브랜치 생성
    

    2. 템플릿 파일 생성

    .github 디렉터리와 템플릿 파일을 생성합니다.

    Step 1: 디렉터리 생성

    mkdir -p .github/ISSUE_TEMPLATE  # 이슈 템플릿 디렉터리 생성
    

    Step 2: 파일 생성

    # Bug Report 템플릿 생성
    cat > .github/ISSUE_TEMPLATE/bug_report.md << EOF
    
    내용 작성
    
    EOF
    
    # Feature Request 템플릿 생성
    cat > .github/ISSUE_TEMPLATE/feature_request.md << EOF
    
    내용 작성
    
    EOF
    
    # Pull Request 템플릿 생성
    cat > .github/PULL_REQUEST_TEMPLATE.md << EOF
    
    내용 작성
    
    EOF

    3. 변경사항 커밋 및 푸시

    Step 1: 변경사항 확인

    git status  # 변경된 파일 확인
    

    Step 2: 스테이징

    git add .github/  # .github 디렉터리 및 내부 파일 추가
    

    Step 3: 커밋

    git commit -m "feat: add issue and PR templates"
    

    Step 4: 푸시

    git push -u origin feature/add-templates
    

    4. PR 생성

    GitHub 웹사이트에서 feature/add-templates 브랜치에 대해 PR을 생성하고, 코드 리뷰를 요청합니다.


    [241205 TIL]

    JPA 도움닫기


    REST API, Spring Security, JPA 연관관계와 영속성 컨텍스트 정리


    1. REST API 메서드와 역할

    REST API는 클라이언트-서버 간 통신을 위한 표준으로, 5가지 주요 메서드를 제공합니다.

    REST API 메서드

    1. GET
      • 서버의 리소스에 액세스.
      • 데이터를 필터링하기 위해 쿼리 파라미터 사용 가능.
      • 예: GET /users?id=1
    2. POST
      • 데이터를 서버에 전송하여 리소스를 등록하거나 저장.
      • Body에 JSON, XML 등의 데이터를 포함하여 전송.
      • 예: POST /users (Body: { "name": "John" })
    3. PUT
      • 서버의 기존 리소스를 전체 업데이트.
      • 제공된 데이터로 리소스의 모든 필드를 수정.
      • 예: PUT /users/1 (Body: { "name": "John", "age": 30 })
    4. PATCH
      • 서버의 기존 리소스를 부분 업데이트.
      • 예: PATCH /users/1 (Body: { "name": "John" } → "name" 필드만 수정)
    5. DELETE
      • 리소스를 제거.
      • 인증 및 권한이 필요.
      • 예: DELETE /users/1

    2. Spring Security - 인증과 인가

    Spring Security는 애플리케이션 보안을 위한 강력한 도구로, **인증(Authentication)**과 인가(Authorization) 기능을 제공합니다.

    Authentication (인증)

    • 사용자의 신원을 확인하는 과정.
    • 다양한 인증 방식을 지원:
      • Username/Password
      • OAuth2
      • Bearer Token
    • 인증 흐름: Authentication Filter에서 요청의 인증 정보를 추출 및 검증.

    Authorization (인가)

    • 사용자의 권한을 확인하여 특정 리소스에 대한 접근 제어.
    • 엔드포인트 별로 권한을 설정할 수 있음:
      • /admin/** → ADMIN 권한 필요.
      • /users/** → USER 권한 필요.
      • /auth/** → 인증 불필요.
    • 설정 예:
      http.authorizeRequests()
          .antMatchers("/auth/**").permitAll()
          .antMatchers("/admin/**").hasRole("ADMIN")
          .anyRequest().authenticated();
      

    3. JPA의 연관관계와 영속성 컨텍스트

    JPA는 데이터베이스의 테이블 간 관계를 객체지향적으로 매핑하여 관리합니다.

    JPA 연관관계

    1. 일대일(1:1)
      • 한 엔티티가 다른 엔티티와 1:1로 매핑.
      • 예: 상품 기본정보/상품 상세정보, 회원 정보/회원 프로필 정보.
    2. 일대다(1:N), 다대일(N:1)
      • 한 엔티티가 여러 개의 엔티티와 매핑.
      • 예: 게시글/좋아요, 주문/상품.
    3. 다대다(N:M)
      • 여러 엔티티가 여러 개의 다른 엔티티와 연결.
      • 예: 학생/과목, 게시글/태그.
      • 보통 중간 테이블을 사용하여 관리.

    Persistence Context (영속성 컨텍스트)

    JPA의 핵심 요소로, 엔티티 객체를 저장 및 관리하며 데이터베이스와의 작업을 효율화.

    상태

    1. 비영속 (Transient)
      • 엔티티가 영속성 컨텍스트에서 관리되지 않는 상태.
    2. 영속 (Managed)
      • 엔티티가 영속성 컨텍스트에서 관리되는 상태.
      • 변경 감지(Dirty Checking), 쓰기 지연 등의 기능 지원.
    3. 준영속 (Detached)
      • 관리되던 엔티티가 영속성 컨텍스트에서 분리된 상태.
    4. 삭제 (Removed)
      • 엔티티가 삭제 상태로 표시되며, 트랜잭션이 끝나면 데이터베이스에서도 삭제.

    장점

    • ACID 보장: 트랜잭션의 원자성, 일관성, 격리성, 지속성 보장.
    • 쓰기 지연 (Write-Behind)
    • 변경 감지 (Dirty Checking)

    영속 상태로 만드는 방법

    1. @Transactional 선언.
    2. Repository에서 엔티티를 저장하거나 조회.

    [241204 TIL]

    프로젝트 관리 심화

    대규모 스트림 처리 강의


     

    ⚠️ 트러블슈팅 ⚠️


    1. 문제 정의

    Kafka 실습 중 Docker Compose로 Kafka 환경을 구성했으나, Kafka UI에서 클러스터가 Offline 상태로 표시되고 정상적으로 동작하지 않음.


    2. 원인 추론

    1. Docker 이미지 아키텍처 문제
      • Docker Desktop에서 "image may have poor performance, or fail if run via emulation" 경고 메시지가 출력됨.
      • 이는 Docker 이미지가 호스트 아키텍처와 일치하지 않아 발생.
    2. Kafka UI 타임아웃 문제
      • Kafka UI 이미지를 다운로드하는 과정에서 TLS handshake timeout 오류 발생.
      • 네트워크 문제 또는 Docker Hub와의 연결 문제로 인해 이미지 다운로드 실패.
    3. Docker Compose 설정 문제
      • 기존 docker-compose.yml 파일이 AMD64 아키텍처용 이미지로 구성되어 ARM64 호스트 시스템에서 실행 불가.

    3. 해결 방안 및 결과

    1) 호스트 아키텍처 확인

    • uname -m 명령어를 실행하여 호스트 시스템 아키텍처를 확인:
      uname -m
      
    • 출력 결과: arm64
      → 호스트 시스템이 ARM64 아키텍처임을 확인.

    2) Docker Compose 이미지 교체

    • 기존 Docker Compose 파일에서 AMD64 전용 이미지ARM64 지원 이미지로 교체.

    변경된 Docker Compose 파일:

    version: '3.8'
    services:
      zookeeper:
        image: confluentinc/cp-zookeeper:latest
        platform: linux/arm64
        ports:
          - "2181:2181"
        environment:
          ZOOKEEPER_CLIENT_PORT: 2181
          ZOOKEEPER_TICK_TIME: 2000
    
      kafka:
        image: confluentinc/cp-kafka:latest
        platform: linux/arm64
        ports:
          - "9092:9092"
        environment:
          KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:29092,OUTSIDE://localhost:9092
          KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
          KAFKA_LISTENERS: INSIDE://0.0.0.0:29092,OUTSIDE://0.0.0.0:9092
          KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
          KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
    
      kafka-ui:
        image: provectuslabs/kafka-ui:latest
        platform: linux/arm64
        ports:
          - "8080:8080"
        environment:
          KAFKA_CLUSTERS_0_NAME: local
          KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:29092
          KAFKA_CLUSTERS_0_ZOOKEEPER: zookeeper:2181
          KAFKA_CLUSTERS_0_READONLY: "false"
    

    3) Kafka UI 이미지 수동 다운로드

    • Kafka UI 다운로드 시 타임아웃 오류 해결을 위해 수동으로 이미지를 다운로드:
      docker pull provectuslabs/kafka-ui:latest
      
    • 수동 다운로드 완료 후, docker-compose up 명령어로 다시 실행.

    결과

    1. Kafka UI에서 클러스터가 Online 상태로 표시됨.
    2. Zookeeper, Kafka, Kafka UI 모두 ARM64 환경에서 정상 실행.
    3. Kafka 실습을 성공적으로 진행 가능.

    [241203 TIL]

    프로젝트 관리 심화

    MSA 개인 프로젝트


    3단계: 핵심 기능 추가

    1. Weighted Load Balancing (상품 서비스)
      • 상품 서비스를 19093, 19094 포트로 각각 실행.
      • Weighted Load Balancing (70:30) 구성.
      • 상품 목록 조회 시 로드 밸런싱이 작동하는지 확인.
    2. Fallback 처리
      • Resilience4j를 Order Service에 적용하여 상품 서비스 호출 실패 시 Fallback 처리 구현.
      • Fallback 메서드에서 적절한 메시지 반환.
    3. Redis 캐싱
      • Product Service에 캐싱 적용 (GET /products).
      • 주문 서비스의 GET /orders/{id} 결과를 Redis에 캐싱하여 조회 성능 향상.
      • 캐싱 갱신
        • Product Service에서 상품 추가 시 Redis 캐시를 갱신하도록 구현.
    4. 주문에 상품 추가
      • PUT /orders/{orderId} API 구현.
      • Feign Client를 사용하여 상품 존재 여부 검증 후 주문에 상품 추가.

    [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