Code Monkey home page Code Monkey logo

project_1_jangyongjin's Introduction

♻️ 멋사마켓 - 중고 거래 플랫폼

                                                                                                            from:  . / 멋쟁이 사자처럼 / 백엔드 스쿨 / 5th / 미션형 프로젝트_1

1️⃣ 프로젝트 소개

  • ♻️ 멋사마켓은 많은 사람들이 사용 중인 🥕당근마켓, 🧱중고나라 에 착안하여 자신만의 중고거래 플랫폼을 만드는 미니 프로젝트 입니다.
  • 사용자가 중고 물품을 올리고, 댓글을 통해 소통하며, 구매 제안을 수락할 수 있는 중고거래 플랫폼의 백엔드를 구성 하였습니다.

⚙️ 개발 환경

  • Framework : Spring Boot 3.1.1
  • Language : Java 17
  • IDE : IntelliJ IDEA
  • DataBase : SQLite
    • ORM (Object Relational Mapping) : JPA (Java Persistent API)
  • Security : Spring Security

📄 참고 ERD


db_erd

2️⃣ 구현 기능

1. Endpoint 정리

===========================================================================

a. 회원가입(Register Member)

회원 가입 진행

요청 Method Mapping URL
회원 가입 POST /users/register

b. 로그인(Login)

_로그인 진행_ | 요청 | Method | Mapping URL | |:-- | :--: | :-- | | 로그인 | POST | /users/login |

c. 상품(Sales_Item)

중고 거래할 물품을 (판매자) 등록, 수정, 이미지 등록, 삭제 (모두) 전체 조회, 단일 조회

요청 Method Mapping URL
상품 등록 POST /items
상품 수정 PUT /items/{itemId}
상품 이미지 등록 PUT /items/{itemId}/image
상품 삭제 DELETE /items/{itemId}
상품 전체 조회 GET /items/read
상품 단일 조회 GET /items/read/{itemsId}

d. 댓글(Comments)

해당 물품에 대한 댓글을 (구매자) 등록, 수정, 삭제 (판매자) 답글 등록, (모두) 댓글 전체 조회

요청 Method Mapping URL
댓글 등록 POST /items/{itemId}/comments
댓글 수정 PUT /items/{itemId}/comments/{commentId}
댓글 삭제 DELETE /items/{itemId}/comments/{commentId}
답글 등록 PUT /items/{itemId}/comments/{commentId}/reply
댓글 전체 조회 GET /items/{itemId}/comments/read

e. 구매 제안(Negotiation)

해당 물품에 대한 구매제안을 (구매자) 등록, 수정, 삭제, 구매 확정 (판매자) 수락 or 거절 (모두) 조회

요청 Method Mapping URL
제안 등록 POST /items/{itemId}/proposals
제안 수정 PUT /items/{itemId}/proposals/{proposalId}
제안 삭제 DELETE /items/{itemId}/proposals/{proposalId}
제안 수락or거절 PUT /items/{itemId}/proposals/{proposalId}
구매 확정 PUT /items/{itemId}/proposals/{proposalId}
제안 조회 GET /items/{itemId}/proposals/{proposalId}?page={페이지 번호}
===========================================================================

2. 상세 API 명세

===========================================================================

a. 회원가입(Register Member)

회원가입 - 성공
  • 요청
    • POST /users/register
    • Header :
      // 추가요소 없음
    • Body :
    {
      "username" : "gaga",
      "password" : "1234",
      "passwordCheck" : "1234",
      "email" : "[email protected]",
      "phone" : "010-1588-1588",
      "city" : "Suwon"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "회원가입이 완료되었습니다."
    }
회원가입 - 비밀번호 불일치
  • 요청
    • POST /users/register
    • Header :
      // 추가요소 없음
    • Body :
    {
      "username" : "gaga",
      "password" : "1234",
      "passwordCheck" : "5678",
      "email" : "[email protected]",
      "phone" : "010-1588-1588",
      "city" : "Suwon"
    }
  • 응답
    • Status : 400
    • Body :
    {
      "message": "비밀번호가 일치하지 않습니다."
    }
회원가입 - 이미 존재하는 이름
  • 요청
    • POST /users/register
    • Header :
      // 추가요소 없음
    • Body :
    {
      "username" : "gaga",
      "password" : "1234",
      "passwordCheck" : "1234",
      "email" : "[email protected]",
      "phone" : "010-1588-1588",
      "city" : "Suwon"
    }
  • 응답
    • Status : 400
    • Body :
    {
      "message": "이미 존재하는 이름 입니다."
    }

b. 로그인(Login)

로그인 - 성공(jwt 토큰 발급)
  • 요청
    • POST /users/login
    • Header :
      // 추가요소 없음
    • Body :
    {
      "username" : "gaga",
      "password" : "1234"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "token": "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJnYWdhIiwia.BfM5nLtLs3aFPNL8Amy-IJhUBG6G1tOwn6vAhUjMdE-"
    }
로그인 - 비밀번호 불일치
  • 요청
    • POST /users/login
    • Header :
      // 추가요소 없음
    • Body :
    {
      "username" : "gaga",
      "password" : "5678"
    }
  • 응답
    • Status : 400
    • Body :
    {
      "message": "비밀번호가 일치하지 않습니다."
    }
로그인 - 존재하지 않는 유저
  • 요청
    • POST /users/login
    • Header :
      // 추가요소 없음
    • Body :
    {
      "username" : "nana",
      "password" : "1234"
    }
  • 응답
    • Status : 400
    • Body :
    {
      "message": "등록되지 않은 사용자 입니다."
    }  

a. 상품(Sales_Item)

상품 등록
  • 요청
    • POST /items
    • Header :
      // 추가
      "authorization" :  "{ jwt-token }"
    • Body :
    {
      "title": "중고 맥북 팝니다",
      "description": "2019년 맥북 프로 13인치 모델입니다",
      "minPriceWanted": 1000000
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "등록이 완료되었습니다. "
    }
상품 수정
  • 요청
    • PUT /items/1
    • Header :
      // 추가
      "authorization" :  "{상품 등록 유저의 jwt-token }"
    • Body :
    {
      "title": "중고 맥북 팝니다",
      "description": "2019년 맥북 프로 13인치 모델입니다",
      "minPriceWanted": 1260000
    }  
  • 응답
    • Status : 200
    • Body :
    {
      "message": "물품이 수정되었습니다."
    }
상품 이미지 등록
  • 요청
    • PUT /items/1/image
    • Header :
      // 추가
      "authorization" :  "{상품 등록 유저의 jwt-token }"
    • Body :
    // form-data 
    "image" = 사진.png
  • 응답
    • Status : 200
    • Body :
    {
      "message": "이미지가 등록되었습니다."
    }
상품 삭제
  • 요청
    • DELETE /items/1
    • Header :
      // 추가
      "authorization" :  "{상품 등록 유저의 jwt-token }"
    • Body :
    {
      "writer": "jang.dev",
      "password": "1234"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "물품을 삭제했습니다."
    }
상품 전체 조회
  • 요청

    • GET /items/read?page=0&limit=25
    • Header : X
    • Body : X
  • 응답

    • Status : 200
    • Body :
    {
      "content": [
          {
              "id": 1,
              "username": "gaga",
              "title": "중고 맥북 팝니다",
              "description": "2019년 맥북 프로 13인치 모델입니다",
              "minPriceWanted": 1260000,
              "imageUrl": null,
              "status": "판매중",
              "comments": [
                  {
                      "id": 1,
                      "username": "nana",
                      "content": "50,000원 정도 할인 가능하신가요?",
                      "reply": null
                  },
                  {
                      "id": 2,
                      "username": "nana",
                      "content": "할인 가능하신가요?",
                      "reply": null
                  },
                  {
                      "id": 3,
                      "username": "nana",
                      "content": "할인 가능하신가요?2",
                      "reply": null
                  }
              ]
          },
          {
              "id": 2,
              "username": "nana",
              "title": "콜드브루 드립기 팝니다",
              "description": "미개봉 1회사용 제품입니다.",
              "minPriceWanted": 20000,
              "imageUrl": null,
              "status": "판매중",
              "comments": []
          }
      ],
      "pageable": {
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "offset": 0,
          "pageNumber": 0,
          "pageSize": 25,
          "unpaged": false,
          "paged": true
      },
      "last": true,
      "totalPages": 1,
      "totalElements": 2,
      "size": 25,
      "number": 0,
      "sort": {
          "empty": false,
          "sorted": true,
          "unsorted": false
      },
      "first": true,
      "numberOfElements": 2,
      "empty": false
    }
상품 단일 조회
  • 요청

    • GET /items/read/1
    • Header: X
    • Body : X
  • 응답

    • Status : 200
    • Body :
    {
      "id": 1,
      "username": "gaga",
      "title": "중고 맥북 팝니다",
      "description": "2019년 맥북 프로 13인치 모델입니다",
      "minPriceWanted": 1260000,
      "imageUrl": null,
      "status": "판매중",
      "comments": [
          {
              "id": 1,
              "username": "nana",
              "content": "50,000원 정도 할인 가능하신가요?",
              "reply": null
          },
          {
              "id": 2,
              "username": "nana",
              "content": "할인 가능하신가요?",
              "reply": null
          },
          {
              "id": 3,
              "username": "nana",
              "content": "할인 가능하신가요?2",
              "reply": null
          }
      ]
    }

b. 댓글(Comments)

댓글 등록
  • 요청
    • POST /items/1/comments
    • Header :
      // 추가
      "authorization" :  "{유저의 jwt-token }"
    • Body :
    {
      "content": "할인 가능하신가요?"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "댓글이 등록되었습니다."
    }
댓글 수정
  • 요청
    • PUT /items/1/comments/1
    • Header :
      // 추가
      "authorization" :  "{댓글 등록 유저의 jwt-token }"
    • Body :
    {
      "content": "50,000원 정도 할인 가능하신가요?"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "댓글이 수정되었습니다."
    }
댓글 삭제
  • 요청
    • DELETE /items/1/comments/1
    • Header :
      // 추가
      "authorization" :  "{댓글 등록 유저의 jwt-token }"
    • Body : X
  • 응답
    • Status : 200
    • Body :
    {
      "message": "댓글을 삭제했습니다."
    }
답글 등록
  • 요청
    • PUT /items/1/comments/1/reply
    • Header :
      // 추가
      "authorization" :  "{상품 등록 유저의 jwt-token }"
    • Body :
    {
      "writer": "jang.dev",
      "password": "1234",
      "reply": "안됩니다"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "reply": "힘들 것 같습니다."
    }
댓글 전체 조회
  • 요청
    • GET /items/1/comments/read
    • Header :
      // 추가
      "page" : "0"
    • Body :
    {
      "writer": "jang.dev",
      "password": "1234",
      "reply": "안됩니다"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "content": [
          {
              "id": 1,
              "content": "50,000원 정도 할인 가능하신가요?",
              "reply": null
          }
      ],
      "pageable": {
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "offset": 0,
          "pageSize": 25,
          "pageNumber": 0,
          "unpaged": false,
          "paged": true
      },
      "last": true,
      "totalElements": 1,
      "totalPages": 1,
      "size": 25,
      "number": 0,
      "sort": {
          "empty": false,
          "sorted": true,
          "unsorted": false
      },
      "first": true,
      "numberOfElements": 1,
      "empty": false
    }

c. 구매제안(Negotiation)

제안 등록
  • 요청
    • POST /items/1/proposals
    • Header :
      // 추가
      "authorization" :  "{유저의 jwt-token }"
    • Body :
    {
      "suggestedPrice": 1200000
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "구매 제안이 등록되었습니다."
    }
제안 수정
  • 요청
    • PUT /items/1/proposals/1
    • Header :
      // 추가
      "mode" : "buyer"
      "authorization" :  "{제안 등록 유저의 jwt-token }"
    • Body :
    {
      "suggestedPrice": 1180000
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "제안이 수정되었습니다."
    }
제안 삭제
  • 요청
    • DELETE /items/1/proposals/1
    • Header :
      // 추가
      "authorization" :  "{제안 등록 유저의 jwt-token }"
    • Body : X
  • 응답
    • Status : 200
    • Body :
    {
      "message": "제안을 삭제했습니다."
    }
제안 수락 or 거절
  • 요청
    • PUT /items/1/proposals/1
    • Header :
      // 추가
      "mode" : "seller"
      "authorization" :  "{상품 등록 유저의 jwt-token }"
    • Body :
    {
      "status": "수락"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "제안의 상태가 변경되었습니다."
    }
구매 확정
  • 요청
    • PUT /items/1/proposals/1
    • Header :
      // 추가
      "mode" : "end"
      "authorization" :  "{제안 등록 유저의 jwt-token }"
    • Body :
    {
      "status": "확정"
    }
  • 응답
    • Status : 200
    • Body :
    {
      "message": "구매가 확정되었습니다."
    }
    • 하나의 제안이 "확정"이 될시 나머지 제안들은 자동으로 "거절" 로 상태가 바뀐다.
    • 해당 물품의 상태가 "판매 완료"로 바뀐다.
제안 조회
  1. [판매자]는 해당 상품에 대한 모든 제안을 확인 할수있다.
  • 요청(판매자)
    • /items/1/proposals?page=0
    • Header:
      // 추가
      "authorization" :  "{상품 등록 유저의 jwt-token }"
    - Body : X
    
    
  • 응답 (판매자)
    • Status : 200
    • Body :
     {
      "content": [
          {
              "id": 1,
              "suggestedPrice": 1200000,
              "status": "제안"
          },
          {
              "id": 2,
              "suggestedPrice": 1000000,
              "status": "제안"
          }
      ],
      "pageable": {
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "offset": 0,
          "pageSize": 25,
          "pageNumber": 0,
          "unpaged": false,
          "paged": true
      },
      "last": true,
      "totalElements": 2,
      "totalPages": 1,
      "size": 25,
      "number": 0,
      "sort": {
          "empty": false,
          "sorted": true,
          "unsorted": false
      },
      "first": true,
      "numberOfElements": 2,
      "empty": false
    }
  1. [구매자]는 해당물품에 대해 본인이 작성한 제안만 확인 할수있다.
  • 요청(구매자)
    • /items/1/proposals?page=0
    • Header:
      // 추가
      "authorization" :  "{제안 등록 유저의 jwt-token }"
    - Body : X
    
    
  • 응답 (구매자)
    • Status : 200
    • Body :
    {
      "content": [
          {
              "id": 2,
              "suggestedPrice": 1000000,
              "status": "제안"
          }
      ],
      "pageable": {
          "sort": {
              "empty": false,
              "sorted": true,
              "unsorted": false
          },
          "offset": 0,
          "pageSize": 25,
          "pageNumber": 0,
          "unpaged": false,
          "paged": true
      },
      "last": true,
      "totalElements": 1,
      "totalPages": 1,
      "size": 25,
      "number": 0,
      "sort": {
          "empty": false,
          "sorted": true,
          "unsorted": false
      },
      "first": true,
      "numberOfElements": 1,
      "empty": false
    }
===========================================================================

3. 예외 처리

===========================================================================

a. 회원가입(Register Member)

예외 클래스명 발생 상황 Staus Code 에러 메세지
ExistUsernameException() 회원가입시 이미 존재하는 이름을 등록하려고 할때 발생 400 - Bad Request "이미 존재하는 이름 입니다."
NotMatchedPasswordException() 회원가입시 비밀번호와 비밀번호 확인이 불일치 할때 발생 400 - Bad Request "비밀번호가 일치하지 않습니다."

b. 로그인(Login)

예외 클래스명 발생 상황 Staus Code 에러 메세지
NotExistUsernameException() 로그인시 등록되지 않은 이름으로 시도할때 발생 404 - Not Found "등록되지 않은 사용자 입니다."
NotMatchedPasswordException() 로그인시 비밀번호가 일치하지 않을때 발생 400 - Bad Request "비밀번호가 일치하지 않습니다."

c. 상품(Sales_Item)

예외 클래스명 발생 상황 Staus Code 에러 메세지
ItemNotFoundException() 요청한 상품이 존재하지 않을때 발생 404 - Not Found "해당 물품이 존재하지 않습니다."
ImageUpdateException() 이미지 등록과정에서 내부적으로 오류 났을때 발생 500 - Iternal Server Error "이미지 등록과정에서 문제가 발생하였습니다."
UnAuthItemEditException() 상품 등록자가 아닌 사람이 수정요청을 했을때 발생 400 - Bad Request "상품 등록자만 수정이 가능합니다."
UnAuthItemDeleteException() 상품 등록자가 아닌 사람이 삭제요청을 했을때 발생 400 - Bad Request "상품 등록자만 삭제가 가능합니다."

d. 댓글(Comments)

예외 클래스명 발생 상황 Staus Code 에러 메세지
CommentNotFoundException() 요청한 댓글이 존재하지 않을때 발생 404 - Not Found "해당 댓글이 존재하지 않습니다."
UnAuthCommentEditException() 댓글 등록자가 아닌 사람이 수정요청을 했을때 발생 400 - Bad Request "댓글 등록자만 수정이 가능합니다."
UnAuthCommentDeleteException() 댓글 등록자가 아닌 사람이 삭제요청을 했을때 발생 400 - Bad Request "댓글 등록자만 수정이 가능합니다."
UnAuthCommentReplyException() 답글 등록자가 아닌 사람이 수정요청을 했을때 발생 400 - Bad Request "답글 등록자만 수정이 가능합니다."

e. 구매제안(Negotiation)

예외 클래스명 발생 상황 Staus Code 에러 메세지
ProposalNotFoundException() 요청한 제안이 존재하지 않을때 발생 404 - Not Found "해당 제안이 존재하지 않습니다."
UnAuthNegoEditException() 제안 등록자가 아닌 사람이 수정요청을 했을때 발생 400 - Bad Request "제안 등록자만 수정이 가능합니다."
UnAuthNegoDeleteException() 제안 등록자가 아닌 사람이 삭제요청을 했을때 발생 400 - Bad Request "제안 등록자만 삭제가 가능합니다."
UnAuthNegoAcceptException() 상품 등록자가 아닌 사람이 수락,거절 요청을 했을때 발생 400 - Bad Request "상품 등록자만 수락 또는 거절이 가능합니다."
UnAuthNegoConfirmException() 제안 등록자가 아닌 사람이 구매확정 요청을 했을때 발생 400 - Bad Request "제안 등록자만 구매확정이 가능합니다."
WrongStatusException() 제안 등록자가 구매확정 요청을 했을때의 상태가 [수락]이 아닐경우 발생 400 - Bad Request "제안 등록자만 구매확정이 가능합니다."
===========================================================================

3️⃣ 별첨

project_1_jangyongjin's People

Contributors

jyj9111 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.