//////
Search
❤️

첫 번째 미션

상태
미션 공개 완료
목차
2022.12.20 테스트 코드 작성-포스트상세-Controller 내용 수정 - 5가지 항목 → 4가지 항목

수행 사항

 필수과제

회원가입
Swagger
AWS EC2에 Docker 배포
Gitlab CI & Crontab CD
로그인
포스트 작성, 수정, 삭제, 리스트

 도전과제

화면 UI 개발
회원가입, 로그인, 글쓰기, 조회
ADMIN 회원으로 등급업하는 기능
초기 ADMIN 회원은 하나가 존재하고 ADMIN 회원은 일반회원의 권한을 ADMIN으로 승격시킬 수 있다.
ADMIN 회원이 일반 회원을 ADMIN으로 승격시키는 기능
POST /users/{id}/role/change
Body {”role”:”admin” | “user”} admin 또는 user로 변경할 수 있습니다.
ADMIN 회원이 로그인 시 자신이 쓴 글이 아닌 글과 댓글에 수정, 삭제를 할 수 있는 기능

Architecture(아키텍처)

▲ 위 Layered Architecture 구조에 맞게 작성 해주세요.
Println 사용 추천
Controller와 Service와 Repository의 호출 여부 확인
디버깅시 유용함
각 단에 데이터를 전달 받을시 DTO 형태로 전달한다.

ERD

주의 AWS EC2에 배포되지 않은 기능은 점수로 들어가지 않습니다. 배포가 아무것도 되지 않았다면 0점 입니다.

미션 개요 - 요구사항 정의

 Swagger 3.0.0

ex)
API에 접근하기 편하게 하기 위해 Swagger를 추가 해주세요.
hint 6주차 수업로그를 참고하기.

 AWS EC2에 Docker로 배포

AWS EC2에 Docker로 배포해주세요.

 Gitlab CI & Crontab CD 구성

Gitlab에 Push하면 Docker Build되어 Container Registry에 배포되고 1분에 1번씩 Crontab을 걸어 Docker에도 바뀐 내용이 반영되게 해주세요.
Crontab설정

 회원가입과 로그인

회원은 일반회원(USER)과 ADMIN 회원이 있다.
회원가입
회원가입 성공 시 "회원가입 성공" 을 리턴한다.
로그인
Spring Security와 JWT를 사용하여 구현한다.
로그인 성공 시 token 을 리턴한다.
{”jwt”:”eyJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Imt5~~~”}

 포스트 작성, 상세조회, 수정, 삭제, 목록

포스트 상세 (1개 조회)
회원, 비회원 모두 볼 수 있다.
글의 제목, 내용, 글쓴이, 작성날짜, 마지막 수정날짜가 표시된다.
회원만이 글 작성을 할 수 있다.
포스트 수정 / 삭제
ADMIN회원이나 글을 작성한 일반회원이 글에 대한 수정과 삭제를 할 수 있다.
리스트
회원, 비회원 모두 볼 수 있다.
제목, 글쓴이, 마지막 수정날짜가 표시된다.
포스트를 클릭하면 포스트의 상세 내역을 볼 수 있다.
목록 기능은 페이징 기능이 포함된다. (Pageable 사용)
한 페이지당 default 피드 갯수는 20개이다.
총 페이지 갯수가 표시된다.
작성날짜 기준으로 최신순으로 Sort한다.

 공통 에러처리

1. ErrorCode에서 정의한 HttpStatus를 StatusCode로 Return하게 할 것
ex) join할 때 duplicated면 409 나올 것
2. result.errorCode 존재 할 것 ex)️ DUPLICATED_USER_NAME
3. message 존재 해야 함
ex)
{ "resultCode":"ERROR", "result":{ "errorCode":"POST_NOT_FOUND", "message":"Post not founded" } }
JavaScript
복사

엔드 포인트

기본 url : /api/v1/

회원 인증·인가

회원 url : /users

회원가입

POST /join
입력 폼 (JSON 형식)
{ "userName" : "user1", "password" : "user1234" }
JSON
복사
리턴 (JSON 형식)
{ "resultCode": "SUCCESS", "result": { "userId": 5, "userName": "test1" } }
JSON
복사

로그인

POST /login
입력폼 (JSON 형식)
{ "userName" : "user1", "password" : "user1234" }
JSON
복사
리턴 (JSON 형식)
{ "resultCode": "SUCCESS", "result": { "jwt": "eyJhbGciOiJIU", } }
JSON
복사

포스트

포스트 url : /posts

포스트 리스트

GET
최신 순으로 20개씩 표시 (Pageable 사용)
리턴 (JSON 형식)
{ "resultCode": "SUCCESS", "result": { "content": [ { "id": 10, "title": "글이 들어온다아아아", "body": "글들어온다아앙", "userName": "손흥민", "createdAt": "2022/12/22 10:43:25", "lastModifiedAt": "2022/12/22 10:43:25" }, { "id": 9, "title": "`12`1", "body": "2`12`12`12", "userName": "손흥민", "createdAt": "2022/12/22 10:42:44", "lastModifiedAt": "2022/12/22 10:42:44" }, { "id": 8, "title": "오늘은 더 추워", "body": "집이 최고", "userName": "손흥민", "createdAt": "2022/12/22 10:08:10", "lastModifiedAt": "2022/12/22 10:08:10" }, { "id": 6, "title": "오늘 춥네요", "body": "눈이 엄청왔어요", "userName": "string", "createdAt": "2022/12/21 13:29:02", "lastModifiedAt": "2022/12/21 13:29:02" } ], "pageable": "INSTANCE", "last": true, "totalPages": 1, "totalElements": 4, "size": 4, "number": 0, "sort": { "empty": true, "sorted": false, "unsorted": true }, "first": true, "numberOfElements": 4, "empty": false } }
JSON
복사

포스트 상세

GET /posts/{postsId}
id, 제목, 내용, 작성자, 작성날짜, 수정날짜
리턴 (JSON 형식)
{ "resultCode":"SUCCESS", "result":{ "id" : 1, "title" : "title1", "body" : "body", "userName" : "user1", "createdAt" : yyyy-mm-dd hh:mm:ss, "lastModifiedAt" : yyyy-mm-dd hh:mm:ss } }
JSON
복사

포스트 등록

POST /posts
입력폼 (JSON 형식)
{ "title" : "title1", "body" : "body1" }
JSON
복사
리턴 (JSON 형식)
{ "resultCode":"SUCCESS", "result":{ "message":"포스트 등록 완료", "postId":0 } }
JSON
복사

포스트 수정

PUT /posts/{id}
입력폼 (JSON 형식)
{ "title" : "modified title", "body" : "modified body" }
JSON
복사
리턴 (JSON 형식)
{ "resultCode":"SUCCESS", "result":{ "message":"포스트 수정 완료", "postId":0 } }
JSON
복사

포스트 삭제

DELETE /posts/{id}
리턴 (JSON 형식)
{ "resultCode":"SUCCESS", "result":{ "message":"포스트 삭제 완료", "postId":0 } }
JSON
복사

ErrorCode

1.
DUPLICATED_USER_NAME(HttpStatus.CONFLICT, "UserName이 중복됩니다.")
2.
USERNAME_NOT_FOUND(HttpStatus.NOT_FOUND,"Not founded")
3.
INVALID_PASSWORD(HttpStatus.UNAUTHORIZED, "패스워드가 잘못되었습니다.")
4.
INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "잘못된 토큰입니다.")
5.
INVALID_PERMISSION(HttpStatus.UNAUTHORIZED, "사용자가 권한이 없습니다.")
6.
POST_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 포스트가 없습니다.")
7.
DATABASE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "DB에러")

테스트 코드 작성

목표

1. controller / 2. service로 나눠서 테스트를 진행해야 함.
1. 성공, 2. 실패 테스트 케이스를 모두 통과하는 실제 코드 작성.
Exception 처리는 enum Error코드에 작성 후 호출 해서 사용
실패의 경우 enum값의 errorCode로처리하기
when(어떤 상황일 때)를 각각 설계해보고, Test case에 따라 예상되는 결과값을 작성해주기
Controller, Service 두 클래스의 테스트 코드 작성하기

회원가입

Controller

회원가입 성공
회원가입 실패 - userName중복인 경우

Service

없음

로그인

Controller

로그인 성공
로그인 실패 - userName없음
로그인 실패 - password틀림

Service

없음

포스트 상세

Controller

GET /posts/1 로 조회시
조회 성공 - id, title, body, userName 4가지 항목이 있는지 검증

Service

조회 성공

포스트 등록

Controller

포스트 작성 성공
포스트 작성 실패(1) - 인증 실패 - JWT를 Bearer Token으로 보내지 않은 경우
포스트 작성 실패(2) - 인증 실패 - JWT가 유효하지 않은 경우

Service

등록 실패 : 유저가 존재하지 않을 때
등록 성공

포스트 수정

Controller

포스트 수정 실패(1) : 인증 실패
포스트 수정 실패(2) : 작성자 불일치
포스트 수정 실패(3) : 데이터베이스 에러
포스트 수정 성공

Service

수정 실패 : 포스트 존재하지 않음
수정 실패 : 작성자!=유저
수정 실패 : 유저 존재하지 않음

포스트 삭제

Controller

포스트 삭제 성공
포스트 삭제 실패(1) : 인증 실패
포스트 삭제 실패(2) : 작성자 불일치
포스트 삭제 실패(3) : 데이터베이스 에러

Service

삭제 실패 : 유저 존재하지 않음
삭제 실패 : 포스트 존재하지 않음

포스트 리스트

Controller

조회 성공 : 0번이 1번보다 날짜가 최신

Service

없음
참고자료