Skip to content

Latest commit

 

History

History
432 lines (388 loc) · 18.1 KB

README.md

File metadata and controls

432 lines (388 loc) · 18.1 KB

💰 ꞈ 거래 서비슀

💬 프로젝튞 소개

ꞈ을 한찜 엎심히 팔고 있던 알레테읎아는, ꞈ을 판맀하고 구맀하는 서비슀륌 제공하Ʞ로 결정했습니닀!
알레테읎아는 앱을 통핎 구맀, 판맀 죌묞을 ꎀ늬하렀고 합니닀!
또한 믞래에 서비슀가 확장될 것을 고렀하여, 읞슝을 닎당하는 서버륌 별도로 구축하Ʞ로 결정합니닀.

💡 요구사항

  1. RESTful API륌 활용하여 구맀, 판맀 죌묞 CRUD륌 수행하는 서버 A 구현
  2. 서버 A와 gRPC륌 통핎 소통하며, 읞슝만을 닎당하는 서버 B 구현

🛠 Ʞ술 슀택


🏷 목찚

  1. 🏃‍♀ Quick Start
  2. 📊 ERD
  3. 📁 디렉터늬 구조
  4. 📑 구현 ë‚Žìš©
  5. 💌 API 명섞
  6. ⚡ 튞러랔 슈팅
  7. 🀔 고믌 흔적

🏃‍♀ Quick Start

  1. .env 파음
  • 자원 서버
DB_URL=
DB_USERNAME=
DB_PASSWORD=
  • 읞슝 서버
DB_URL=
DB_USERNAME=
DB_PASSWORD=

JWT_SECRET_KEY="Key 섀정"
ACCESS_TOKEN_EXPIRATION=액섞슀 토큰 만료 시간
REFRESH_TOKEN_EXPIRATION=늬프레시 토큰 만료 시간
  1. gradle build
  2. 싀행
✋ Java 버전 충돌로 였류가 발생하는 겜우
    현재 프로젝튞는 Java 17 버전을 사용쀑입니닀.
    따띌서 버전읎 닀륞 겜우 17 버전 jdk 파음을 닀욎로드 후
    root 겜로에 gradle.properties 파음을 생성핎 아래와 같읎 닀욎로드 받은 파음의 겜로륌 섀정핎죌섞요.
    org.gradle.java.home=C:/corretto-17.0.12

📊 ERD

☝ User 테읎랔곌 Order 테읎랔읎 1:N ꎀ계로 연결되었지만 싀제로는 서버륌 분늬했Ʞ 때묞에 연결되얎있지 ì•Šë‹€.

Untitled


📁 디렉터늬 구조

자원 서버 디렉터늬 구조
src
├─main
│  ├─java
│  │  └─com
│  │      └─wanted
│  │          └─gold
│  │              │  GoldApplication.java
│  │              │
│  │              ├─client
│  │              │  │  AuthGrpcClient.java
│  │              │  │
│  │              │  └─dto
│  │              │          UserResponseDto.java
│  │              │
│  │              ├─config
│  │              │      SwaggerConfig.java
│  │              │
│  │              ├─exception
│  │              │  │  BadRequestException.java
│  │              │  │  BaseException.java
│  │              │  │  ConflictException.java
│  │              │  │  ErrorCode.java
│  │              │  │  ErrorResponse.java
│  │              │  │  ForbiddenException.java
│  │              │  │  NotFoundException.java
│  │              │  │  UnauthorizedException.java
│  │              │  │
│  │              │  └─handler
│  │              │          GlobalExceptionHandler.java
│  │              │
│  │              ├─order
│  │              │  ├─controller
│  │              │  │      DeliveryController.java
│  │              │  │      OrderController.java
│  │              │  │      PaymentController.java
│  │              │  │
│  │              │  ├─domain
│  │              │  │      Delivery.java
│  │              │  │      DeliveryStatus.java
│  │              │  │      Order.java
│  │              │  │      OrderStatus.java
│  │              │  │      OrderType.java
│  │              │  │      Payment.java
│  │              │  │      PaymentStatus.java
│  │              │  │
│  │              │  ├─dto
│  │              │  │      CreateOrderRequestDto.java
│  │              │  │      DeliveryResponseDto.java
│  │              │  │      ModifyDeliveryRequestDto.java
│  │              │  │      ModifyPaymentRequestDto.java
│  │              │  │      OrderDetailResponseDto.java
│  │              │  │      OrderListPaginationResponseDto.java
│  │              │  │      OrderListResponseDto.java
│  │              │  │      PaymentResponseDto.java
│  │              │  │
│  │              │  ├─repository
│  │              │  │      DeliveryRepository.java
│  │              │  │      OrderRepository.java
│  │              │  │      PaymentRepository.java
│  │              │  │
│  │              │  └─service
│  │              │          DeliveryService.java
│  │              │          OrderService.java
│  │              │          OrderValidator.java
│  │              │          PaymentService.java
│  │              │
│  │              └─product
│  │                  ├─controller
│  │                  │      PriceController.java
│  │                  │
│  │                  ├─domain
│  │                  │      GoldType.java
│  │                  │      Price.java
│  │                  │      PriceType.java
│  │                  │      Product.java
│  │                  │
│  │                  ├─dto
│  │                  │      CreatePriceRequestDto.java
│  │                  │
│  │                  ├─repository
│  │                  │      PriceRepository.java
│  │                  │      ProductRepository.java
│  │                  │
│  │                  └─service
│  │                          PriceService.java
│  │
│  ├─proto
│  │      auth.proto
│  │
│  └─resources
│          application.yml
│
└─test
    └─java
        └─com
            └─wanted
                └─gold
                        GoldApplicationTests.java
읞슝 서버 디렉터늬 구조
src
├─main
│  ├─java
│  │  └─com
│  │      └─wanted
│  │          └─gold
│  │              │  GoldApplication.java
│  │              │
│  │              ├─config
│  │              │      SwaggerConfig.java
│  │              │
│  │              ├─exception
│  │              │  │  BadRequestException.java
│  │              │  │  BaseException.java
│  │              │  │  ConflictException.java
│  │              │  │  ErrorCode.java
│  │              │  │  ErrorResponse.java
│  │              │  │  NotFoundException.java
│  │              │  │  UnauthorizedException.java
│  │              │  │
│  │              │  └─handler
│  │              │          GlobalExceptionHandler.java
│  │              │
│  │              ├─server
│  │              │      AuthServer.java
│  │              │
│  │              └─user
│  │                  ├─config
│  │                  │      SecurityConfig.java
│  │                  │      TokenAuthenticationFilter.java
│  │                  │      TokenProvider.java
│  │                  │
│  │                  ├─controller
│  │                  │      TokenController.java
│  │                  │      UserController.java
│  │                  │
│  │                  ├─domain
│  │                  │      Role.java
│  │                  │      Token.java
│  │                  │      User.java
│  │                  │      UserDetail.java
│  │                  │
│  │                  ├─dto
│  │                  │      SignUpRequestDto.java
│  │                  │      SignUpResponseDto.java
│  │                  │      TokenRequestDto.java
│  │                  │      TokenResponseDto.java
│  │                  │      UserLoginRequestDto.java
│  │                  │      UserLoginResponseDto.java
│  │                  │
│  │                  ├─repository
│  │                  │      TokenRepository.java
│  │                  │      UserRepository.java
│  │                  │
│  │                  └─service
│  │                          AuthServiceGrpcImpl.java
│  │                          TokenService.java
│  │                          UserDetailService.java
│  │                          UserService.java
│  │                          UserValidator.java
│  │
│  ├─proto
│  │      auth.proto
│  │
│  └─resources
│          application.yml
│
└─test
    └─java
        └─com
            └─wanted
                └─gold
                        GoldApplicationTests.java

📑 구현 ë‚Žìš©

회원가입

  • 계정명곌 비밀번혞 유횚성 검사
  • 쀑복 계정명 방지 Ʞ능

로귞읞

  • 로귞읞 시 액섞슀 토큰곌 늬프레시 토큰 발꞉
  • 몚든 죌묞 서비슀에 로귞읞 한 회원만 ì ‘ê·Œ 가능한 Ʞ능

액섞슀 토큰 재발꞉

  • 액섞슀 토큰 만료 시 늬프레시 토큰읎 유횚할 겜우 액섞슀 토큰 재발꞉

죌묞 생성

  • 죌묞 생성에 필요한 정볎듀 입력 시 죌묞 생성
  • 죌묞하는 수량 입력 시 소수 둘짞자늬까지만 허용하Ʞ 위한 유횚성 검사
  • 재고의 횚윚적읞 ꎀ늬륌 위핎 구맀 죌묞 시 죌묞 수량읎 재고볎닀 많을 겜우 죌묞 불가 및 죌묞읎 가능한 겜우 상품 재고 찚감

죌묞 목록 조회

  • 볞읞의 죌묞 목록만 조회 가능
  • ꎀ늬자의 겜우 몚든 죌묞 목록 조회 가능
  • 조회 시 데읎터륌 페읎지넀읎션윌로 응답

죌묞 상섞 조회

  • 죌묞 상섞 조회 시 죌묞 정볎 뿐만 아니띌 죌묞에 핎당하는 배송 정볎와 결제 정볎도 핚께 응답
  • 음반 회원의 겜우 닀륞 회원의 죌묞 정볎 조회 불가

죌묞 삭제

  • 볞읞의 죌묞만 삭제 가능
  • 결제가 진행된 겜우 삭제 불가

가격 등록

  • ꎀ늬자만 ì ‘ê·Œ 가능
  • 각 품목 별로 죌묞 유형별로 가격 등록 가능

결제 정볎 수정

  • 볞읞의 결제 정볎만 수정 가능
  • 회원에게서 정볎 입력받아 수정하는 Ʞ능
  • 수정할 정볎륌 하나도 입력하지 않을 겜우 수정 불가
  • 읎믞 결제가 완료된 상태에서는 수정 불가

배송 정볎 수정

  • 볞읞의 배송 정볎만 수정 가능
  • 회원에게서 정볎 입력받아 수정하는 Ʞ능
  • 수정할 정볎륌 하나도 입력하지 않을 겜우 수정 불가
  • 읎믞 배송읎 완료도니 상태에서는 수정 불가

결제 상태 수정

  • ꎀ늬자만 ì ‘ê·Œ 가능
  • 결제가 완료되멎 ꎀ늬자가 확읞 후 결제 상태륌 완료로 업데읎튞하는 Ʞ능

배송 상태 수정

  • ꎀ늬자만 ì ‘ê·Œ 가능
  • 배송읎 완료되멎 ꎀ늬자가 확읞 후 배송 상태륌 완료로 업데읎튞하는 Ʞ능

💡 자원 서버와 읞슝 서버 gRPC 연결

  • 자원 서버의 RESTful API 포튞는 9999번, grpc 포튞는 50052번
  • 읞슝 서버의 RESTful API 포튞는 8888번, grpc 포튞는 50051번
  • 두 서버륌 각각 분늬핎 gRPC 연결 후 자원 서버에서 회원 읞슝읎 필요할 시 읞슝 서버에 읞슝 요청을 볎낎는 Ʞ능

💌 API 명섞

🔗 Swagger API 묞서


⚡ 튞러랔 슈팅

⚡ 빌드 시 Java 버전읎 닀륞 묞제

    gRPC 사용을 위핎서는 .proto 파음을 컎파음핎알한닀. 귞런데 빌드 시도륌 하니 였류가 발생했닀. 현재 프로젝튞륌 위핎서 Java와 gradle 몚두 17 버전을 사용하고 있고 섀정도 귞에 맞게 핎쀬지만 빌드륌 시도하멎 계속 자바 11 버전을 가젞와 충돌하는 묞제였닀.
    귞래서 root 겜로에 gradle.properties 파음을 생성핎 자바 섀치 겜로륌 아래와 같읎 명시핎쀬닀.
    org.gradle.java.home=C:/corretto-17.0.12

⚡ JPA @ColumnDefault에 대한 였핎

    죌묞읎나 결제, 배송 객첎 생성 시 죌묞 타입, 죌묞 상태 등의 쎈Ʞ값을 자동윌로 넣고 싶었닀.
    귞래서 @ColumnDefault 얎녞테읎션윌로 필드의 쎈Ʞ값을 아래와 같읎 섀정핎쀬닀.

    @ColumnDefault("'PENDING'")
    private DeliveryStatus deliveryStatus; 

    읎렇게 지정핎죌멎 객첎가 생성될 때 핎당 필드의 값읎 자동윌로 얎녞테읎션 안의 값윌로 바뀌는 쀄 알았닀. (예륌 듀멎 deliveryStatus의 값은 PENDING읎띌는 값읎 자동윌로 생성)
    귞러나 생성 요청을 볎낞 결곌 핎당 필드의 값은 null 값읎었닀.
    왜 섀정핎쀀 값읎 자동윌로 듀얎가지 않을까 궁ꞈ핎서 찟아볞 결곌, @ColumnDefault에 대핎서 완전히 였핎하고 있었닀.
    @ColumnDefault는 테읎랔을 처음 생성할 때, default값을 생성핎 죌는 역할을 하는 얎녞테읎션읎었닀. 따띌서 핎당 얎녞테읎션읎 붙은 컬럌에 닀륞 값을 넣윌렀고 하멎 였류가 생Ʞ는 것읎닀.
    객첎 생성 시 엔티티 상닚에 @Builder륌 사용했Ʞ 때묞에 값을 지정하지 않은 필드는 null 값읎 듀얎가게 되므로, @ColumnDefault로 섀정한 값읎 듀얎가지 않게 된 것읎닀.
    읎륌 핎결하Ʞ 위핎 명시적윌로 핎당 필드에 Ʞ볞값을 넣얎쀬닀.


🀔 고믌 흔적

💭 ERD는 얎떻게 섀계하는 것읎 좋을까?

    요구사항을 분석하며 몚덞링을 진행하멎서 얎떻게 죌묞 로직을 짜는 것읎 좋을지 고믌읎 됐닀.
    핎당 서비슀는 서비슀 죌읞읎 회원에게 ꞈ 구맀와 판맀 죌묞을 제공하는 서비슀로, 구맀 죌묞곌 판맀 죌묞의 죌묞 곌정읎 상읎하Ʞ 때묞에 배송곌 죌묞 테읎랔을 구맀 죌묞곌 판맀 죌묞 따로 나누는 것읎 좋을지 고믌했닀.
    귞러나 죌묞의 섞부 로직은 닀륎지만 죌묞 → 결제 → 배송의 곌정을 거치는 것은 동음했Ʞ 때묞에 테읎랔을 같읎 쓰는 것읎 횚윚적읎띌고 생각했닀.
    따띌서 구맀 죌묞곌 판맀 죌묞 둘 ë‹€ 같은 죌묞, 결제, 배송 테읎랔을 쓰는 대신 죌묞 타입을 식별하Ʞ 위핎 각각 식별할 수 있는 Enum 큎래슀륌 사용하Ʞ로 했닀.
    (죌묞의 겜우 죌묞 타입, 결제의 겜우 결제 상태, 배송의 겜우 배송 상태)
    귞늬고 결제 상태와 배송 상태의 겜우 서비슀 ꎀ늬자가 변겜할 수 있도록 하는 것읎 볎안성 잡멎에서 좋닀고 생각핎 ꎀ늬자만 변겜할 수 있게 섀정하Ʞ로 했닀.

💭 Grpc Server와 Grpc Client륌 각각 ì–Žë–€ 서버로 섀정할까?

    gRPC는 구Ꞁ읎 최쎈로 개발한 였픈 소슀 원격 프로시저 혞출 시슀템읎닀. gRPC륌 사용하멎 서로 닀륞 위치에 졎재하는 공간에서 동음한 객첎륌 가젞닀 와서 사용할 수 있닀.
    읎 gRPC륌 사용핎 구맀, 판맀 죌묞을 닎당하는 서버와 읞슝만을 닎당하는 서버륌 소통하게 하렀고 한닀. 읎때 Grpc Server와 Grpc Client륌 각각 ì–Žë–€ 서버로 섀정핎알할지 고믌읎 됐닀.
    요구사항을 닀시 읜얎볎니 유저의 권한 확읞읎 필요한 겜우, grpc륌 통핎 읞슝을 닎당하는 서버 B에 JWT 토큰을 볎낎얎 읞슝 여부륌 확읞핎알 합니닀. 띌는 부분읎 있었닀.
    구맀, 판맀 죌묞 서버에서의 몚든 요청은 권한 확읞읎 필요하닀. 닀시 말핮 구맀, 판맀 죌묞 서버에서 읞슝 서버로 권한 요청을 하는 곌정읎 필요하닀.
    따띌서 구맀, 판맀 죌묞 서버륌 Grpc Client로, 읞슝 서버륌 Grpc Server로 섀정하고 구맀, 판맀 죌묞 서버에서 몚든 요청은 읞슝 서버에 요청을 핮 권한 읞슝 후 진행하Ʞ로 했닀.