Giter VIP home page Giter VIP logo

wanted-pre-onboarding-backend's Introduction

wanted-pre-onboarding-backend


1️⃣ 지원자의 성명

  • 김유연

2️⃣ 애플리케이션의 실행 방법

  • 배포 주소
    비용 문제로 8.21부터 서버를 내림

  • 빌드 및 실행

    $ git clone https://github.com/yooyouny/wanted-pre-onboarding-backend.git
    $ cd wanted-pre-onboarding-backend  
    $ ./gradlew clean build
    $ docker-compose up --build
    

    💡테스트 제외 빌드 시 ./gradlew clean build -x test로 빌드

  • 엔드포인트 호출 방법

    description HTTP Method End Point
    회원가입 POST /api/v1/members/register
    로그인 POST /api/v1/members/login
    포스트 등록 POST /api/v1/posts
    특정 포스트 조회 GET /api/v1/posts/{postId}
    특정 포스트 수정 PUT /api/v1/posts/{postId}
    특정 포스트 삭제 PATCH /api/v1/posts/{postId}
    포스트 목록 조회 GET /api/v1/posts

3️⃣ 시스템 구조 및 기술스택

📌 ERD

ERO.png

📌 System Diagram

System Diagram.png

📌 Skill

  • Java 17
  • Spring Boot 3.1
  • Spring Data JPA
  • Spring Security
  • Gradle
  • MySQL 8.0
  • Junit5
  • Docker
  • AWS EC2

4️⃣ 구현한 API의 동작을 촬영한 데모 영상

https://youtu.be/5sEk1KytqeM


5️⃣ 요구사항 및 구현한 내용 설명

📌 요구사항

✔️ 데이터 저장소로 MySQL 8.0 사용

✔️ JWT 인증 방식 적용

✔️ 통합 테스트 또는 단위 테스트 코드 추가

✔️ docker compose를 이용한 애플리케이션 환경 구성

✔️ 클라우드 환경(AWS)에 배포 환경을 설계하고 애플리케이션을 배포

📌 구현내용

✔️ 유효성 검사

  • spring validation 적용
  • DTO인 request 객체에서 필수 String 값인 email, password의 @NotEmpty 체크

✔️ 비밀번호 암호화

  • BCryptPasswordEncoder 적용하여 인코딩 된 비밀번호를 DB에 저장

✔️ 중복코드 최소화

  • JpaAuditing 적용으로 엔티티의 생성시간, 수정시간 자동관리
  • 엔드포인트 별 request/response DTO 분리로 layer별 의존성을 줄임

✔️ Soft delete 처리

  • 데이터를 완전히 삭제하지 않고 delete flag 값을 true로, delete_at에 LocalDateTime.now() 갱신하여 처리

✔️ 트랜잭션 처리

  • 쓰기작업(Create, Update, Delete)에 @Transactional 처리로 데이터 정합성 유지

✔️ Pagenation 적용

  • Spring Data Jpa가 제공하는 페이징 기능을 활용하여 사용자가 요구하는 Page Number, size에 따른 결과 제공

✔️ 응답 및 예외처리

  • @RestControllerAdice로 공통 예외 처리
  • ApiRespose 객체로 규격화된 응답 처리
  • @AuthenticationPrincipal로 claims에 저장된 member정보와 비교하여 수정, 삭제 시 FORBIDDEN 처리

✔️️ 테스트 코드

  • layer 별 단위테스트 수행(repository, service, controller, domain)
  • controller 통합테스트 수행으로 코드의 신뢰성을 높임

✔️️ 배포

  • docker-compose 활용으로 어플리케이션 환경을 쉽게 구성

6️⃣ API 명세(request/response 포함)

1. 회원가입

  • POST /api/v1/members/register

    ➡️ request

    {
      "email": "[email protected]",
      "password" : "password"
    }
    

    ✅️ response

    • 200 OK
      {
       "status": "OK",
       "message": "SUCCESS",
       "data": {
            "id": 2,
            "email": "[email protected]",
            "password": "$2a$10$Fym8KNIMMFfLmbSF7mF/wunQNPGDBPKgZBFdqq7jFu8YVQeqMwVB2",
            "registeredAt": "2023-08-15T06:13:38.085124274"
        }
      }
      
    • 400 Bad Request
      {
       "status": "BAD_REQUEST",
       "message": "BAD_REQUEST",
       "data": [
           "이메일에 '@' 문자가 포함되어 있어야 합니다",
           "비밀번호는 최소 8자 이상이어야 합니다" 
       ]
      }
      
    • 409 Conflict
       {
          "status": "CONFLICT",
          "message": "Email is duplicated",
          "data": null
       }
      

2. 로그인

  • POST /api/v1/members/login

    ➡️ request

    {
      "email": "[email protected]",
      "password" : "password"
    }
    

    ✅️ response

    • 200 OK
      {
        "status": "OK",
        "message": "SUCCESS",
        "data": {
            "token": "eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6IndhdGVkX3VzZXJAbmF2ZXIuY29tIiwiaWF0IjoxNjkyMDgxMzc5LCJleHAiOjE2OTQ2NzMzNzl9.lo2_4AGAOz3GRqeJnMML-c3V7F_9y0Hiyox3i4z-jGo"
        }
      }
      
      
    • 401 Unauthorized
      {
        "status": "UNAUTHORIZED",
        "message": "Password is invalid",
        "data": null
      }
      
    • 404 Not Found
      {
         "status": "NOT_FOUND",
         "message": "Email not founded",
         "data": null
      }  
       
      

3. 포스트 등록

  • POST /api/v1/posts

  • Headers Authorization: Bearer {token}

    ➡️ request

    {
      "title": "title",
      "body" : "body"
    }
    

    ✅️ response

    • 200 OK

      {
       "status": "OK",
       "message": "SUCCESS",
       "data": {
          "id": 1,
          "title": "title",
          "body": "password",
          "email": "[email protected]",
          "registeredAt": "2023-08-15T03:54:26.298941179"
       }
      }
      
    • 400 Bad Request

      {
       "status": "BAD_REQUEST",
       "message": "BAD_REQUEST",
       "data": [
           "게시글 내용은 필수입니다",
           "게시글 제목은 필수입니다"
        ]
      }
      
    • 401 Unauthorized

      {
         Token is invalid
      }
      

4. 특정 포스트 조회

  • GET /api/v1/posts/{postId}

  • Headers Authorization: Bearer {token}

    ✅️ response

    • 200 OK
      {
        "status": "OK",
        "message": "SUCCESS",
        "data": {
            "id": 5,
            "title": "test",
            "body": "contents",
            "email": "[email protected]",
            "registeredAt": "2023-08-15T07:04:50.374106",
            "modifiedAt": "2023-08-15T07:04:50.374106"
            "deletedAt": null
        }
      }
      
    • 404 Not Found
      {
        "status": "NOT_FOUND",
        "message": "Post not founded",
        "data": null
      }
      

5. 특정 포스트 수정

  • PUT /api/v1/posts/{postId}

  • Headers Authorization: Bearer {token}

    ➡️ request

    {
      "title": "modified title",
      "body" : "modified body"
    }
    

    ✅️ response

    • 200 OK
      {
        "status": "OK",
        "message": "SUCCESS",
        "data": {
          "id": 5,
          "title": "modified title",
          "body": "modified contents",
          "email": "[email protected]",
          "registeredAt": "2023-08-15T07:04:50.374106",
          "modifiedAt": "2023-08-15T07:28:21.442714841"
          "deletedAt": null
        }
      }
      
    • 400 Bad Request
      {
       "status": "BAD_REQUEST",
       "message": "BAD_REQUEST",
       "data": [
           "게시글 내용은 필수입니다",
           "게시글 제목은 필수입니다"
        ]
      }
      
    • 401 Unauthorized
      {
         Token is invalid
      }
      
    • 403 Forbidden
      {
        "status": "FORBIDDEN",
        "message": "This post is accessible only to the author of the post",
        "data": null
      }
      
    • 404 Not Found
      {
        "status": "NOT_FOUND",
        "message": "Post not founded",
        "data": null
      }
      

6. 특정 포스트 삭제

  • DELETE /api/v1/posts/{postId}

  • Headers Authorization: Bearer {token}

    ✅️ response

    • 200 OK
      {
        "status": "OK",
        "message": "SUCCESS",
        "data": null
      }
      
    • 401 Unauthorized
      {
         Token is invalid
      }
      
    • 403 Forbidden
      {
          "status": "FORBIDDEN",
          "message": "This post is accessible only to the author of the post",
          "data": null
      }
      
    • 404 Not Found
      {
          "status": "NOT_FOUND",
          "message": "Post not founded",
          "data": null
      }
      

7. 포스트 목록 조회

  • GET /api/v1/posts

  • Headers Authorization: Bearer {token}

    ✅️ response

    • 200 OK
      {
          "status": "OK",
          "message": "SUCCESS",
          "data": {
              "content": [
                {
                    "id": 5,
                    "title": "modified title",
                    "body": "modified contents",
                    "email": "[email protected]",
                    "registeredAt": "2023-08-15T07:04:50.374106",
                    "modifiedAt": "2023-08-15T07:52:32.165673"
                },
                {
                    "id": 4,
                    "title": "wanted",
                    "body": "contents",
                    "email": "[email protected]",
                    "registeredAt": "2023-08-15T07:04:28.243249",
                    "modifiedAt": "2023-08-15T07:04:28.243249"
                }
              ],
              "pageable": {
              "sort": {
                  "empty": false,
                  "sorted": true,
                  "unsorted": false
              },
              "offset": 0,
              "pageNumber": 0,
              "pageSize": 5,
              "paged": true,
              "unpaged": false
              },
              "totalPages": 1,
              "totalElements": 2,
              "last": true,
              "size": 5,
              "number": 0,
              "sort": {
                  "empty": false,
                  "sorted": true,
                  "unsorted": false
              },
              "numberOfElements": 2,
              "first": true,
              "empty": false
              }
          }   
      

wanted-pre-onboarding-backend's People

Stargazers

 avatar  avatar

Watchers

 avatar

wanted-pre-onboarding-backend's Issues

게시글 생성 기능 추가

  • Post Entity 구현
  • validation 체크 추가
  • BaseEntity 구현
  • 게시글 생성 엔드포인트 구현
  • 예외처리
  • 테스트 코드 작성

로그인 기능 추가

  • 로그인 엔드포인트 구현
  • 필터생성 및 security 설정
  • UserDetails 구현
  • 유효성 검사
  • 테스트 코드 작성

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.