yapp-github / 20th-web-team-1-be Goto Github PK
View Code? Open in Web Editor NEW[20th] Web 1팀 BackEnd
License: Apache License 2.0
[20th] Web 1팀 BackEnd
License: Apache License 2.0
이전, 다음 메세지 순서 변경
폴더 글자수 제한 현재 20자 -> 10자로 수정
처음 로그인시, 비트리 기본 메시지 발송 (가이드 내용)
유저 닉네임 변경 API
프론트 요청으로 메시지 상세조회 api 응답 dto에 폴더이름,폴더id 추가
메세지함, 서랍메뉴 관련 API
2022-07-09 18:45:19.906 ERROR 87468 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.yapp.betree.exception.BetreeException: JWT 토큰 파싱에 실패했습니다.: 헤더에 토큰이 존재하지 않습니다.] with root cause
com.yapp.betree.exception.BetreeException: JWT 토큰 파싱에 실패했습니다.: 헤더에 토큰이 존재하지 않습니다.
at com.yapp.betree.interceptor.TokenInterceptor.lambda$preHandle$0(TokenInterceptor.java:36) ~[classes!/:na]
at java.util.Optional.orElseThrow(Optional.java:290) ~[na:1.8.0_292]
at com.yapp.betree.interceptor.TokenInterceptor.preHandle(TokenInterceptor.java:36) ~[classes!/:na]
at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:148) ~[spring-webmvc-5.3.13.jar!/:5.3.13]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1062) ~[spring-webmvc-5.3.13.jar!/:5.3.13]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.13.jar!/:5.3.13]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.13.jar!/:5.3.13]
at org.springframework.web.servlet.FrameworkServlet.doOptions(FrameworkServlet.java:945) ~[spring-webmvc-5.3.13.jar!/:5.3.13]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.13.jar!/:5.3.13]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.13.jar!/:5.3.13]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.13.jar!/:5.3.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.13.jar!/:5.3.13]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.13.jar!/:5.3.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.13.jar!/:5.3.13]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.13.jar!/:5.3.13]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.55.jar!/:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.55.jar!/:na]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_292]
CORS 에러 -> 아마 CORS preflight 옵션 요청시에 헤더 토큰 검증이 있어서 에러나는 것 같음
tokenInterceptor preflight 처리 (options 메서드일때 토큰 검증 제외)
Add any other context about the problem here.
로그인/비로그인 유저 처리
현아님 코멘트
4. 비회원은 로그인 하지 않아도 물 주기와 나무 구경(메시지(=열매) 조회)을 할 수 있습니다. 그래서 지금 그려주신 플로우는 아니구요. 비회원 유저가 물 주기 클릭하면, 메시지 작성 화면으로 이동하게 됩니다.
// 시작하기 버튼이나, 알림/나무숲/메시지 탭을 클릭하면 '로그인해야 한다'는 얼럿이 뜨고, 확인 클릭 시 카카오로 시작하기 페이지로 이동하게 되는 플로우입니다. (이건 피그마에서 수정해놓거나 프로토타입 만들 때 반영해서 더 쉽게 이해하실 수 있도록 해두겠습니다.)
비로그인 상태에서 할 수 있는 기능 정리해 공유드립니다.
비로그인 상태에서 할 수 있는 기능 : 물 주기 / 나무 조회(나무 클릭) / 메시지 조회(열매 클릭)
그 외, 시작하기 버튼이나, 알림/나무숲/메시지 탭 클릭 시, "로그인해야 한다는 얼럿 > 확인 클릭 > 카카오로 시작하기 페이지로 이동" 플로우입니다.
폴더(나무) 최대 개수 4개로 제한됨
카카오 간편로그인을 이용하여 비트리 회원가입, 로그인 구현
WebClient vs RestTemplate
시나리오 작성
테스트코드
프론트 redirect uri 설정필요
메시지 CRUD를 위한 기본 폴더, 유저 데이터 생성 및 레파지토리 생성
다음 API 서버 테스트 배포까지 API 변경된 사항 리스트업
다음 배포는 7/9 이후 예정
2022.07.05 (화) ~ 2022.07.09 (토)
구분 | 변경 내용 | 관련 API | PR | 담당 | 기타 |
---|---|---|---|---|---|
수정 | - 로그인 관련 API HttpMethod GET->POST로 변경 | GET->POST /api/signin , GET->POST /api/refresh-token |
#57 | 강지수 | |
추가 | - 로그아웃 API 구현 | POST /api/logout |
#57 | 강지수 | 로그아웃시 헤더에 httpOnly로 들어있는 refreshToken 쿠키 삭제됨 |
추가 | - 메세지 읽음 처리 | PUT /api/messages/alreadyRead |
#49 | 김수빈 | |
추가 | - 유저 정보 조회 | GET /api/users/info |
#53 | 김수빈 | |
추가 | - 유저 닉네임 변경 | PUT /api/users/nickname |
#53 | 김수빈 | |
추가 | - 메세지 상세 조회 | GET /api/messages/{messageId} |
#56 | 김수빈 | |
추가 | - 폴더(나무) 삭제 | DELETE /api/forest/{treeId} |
#61 | 강지수 | 기본폴더는 삭제 불가 |
작업내용
에 정리하고 배포 다시 할때 디코 일반에 전달알림 나무 갱신 자동 설정 추가
알림나무 페이지에서 언리드 메시지 개수 처리를 위한 읽음 여부 응답 값 변경
프론트엔드와 통신할 기본 API 설계 (SPRINT 1)
리드미 수정
다음 API 서버 테스트 배포까지 API 변경된 사항 리스트업
다음 배포는 7/4 밤에 PR merge후 예정
2022.06.26 (월) ~ 2022.07.04 (월)
구분 | 변경 내용 | 관련 API | PR | 담당 | 기타 |
---|---|---|---|---|---|
수정 | - TreeRequestDto.name 최대 글자수 20->10자로 변경, 에러메시지 수정 | POST /api/forest ,PUT /api/forest/treeId |
#35 | 강지수 | |
수정 | 비로그인 유저 헤더에 토큰 없이도 요청할 수 있게 api 수정 | GET /api/forest GET /api/forest/{treeId} POST /api/messages |
#38 | 강지수 | |
추가 | 메세지 읽음 처리 API 추가 | PUT /api/messages/alreadyRead |
#34 #49 | 김수빈, 강지수 | 알림나무 갱신에도 반영 |
수정 | request 파라미터명 변경 messageIdList -> messageIds | PUT /api/messages/opening |
#34 | 김수빈 | |
수정 | TreeResponseDto에 열매타입 추가 | GET /api/forest |
#48 | 강지수 | 영민님건의 |
수정 | 응답값 void -> (Long) id 성공시 변경된 treeId 반환 | PUT /api/forest/{treeId} |
#48 | 강지수 | 영민님건의 |
수정 | 알림나무 url /api/notice ->/api/notices 로 변경 |
GET /api/notices GET /api/notices/batch |
#49 | 강지수 | |
수정 | 알림나무 조회 파라미터 userId -> X (헤더 토큰에서 로그인유저 정보얻어 사용하도록 변경) | GET /api/notices |
#49 | 강지수 |
작업내용
에 정리하고 배포 다시 할때 디코 일반에 전달프론트 쪽에서 withCredentials: true 를 통해 쿠키를 포함해서 api 요청을 보내니 다시 cors 에러가 나옴
public class WebConfig implements WebMvcConfigurer {
private final JwtTokenProvider jwtTokenProvider;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowCredentials(true)
.maxAge(3000);
}
WebConfig에 .allowCredentials(true)
추가 -> 그러면 기존 allowedOrigins("*")
로 와일드카드 지정을 할 수 없어서 allowedOriginPatterns
로 변경
디자인 기획에 맞춰 열매 타입 수정하기
즐겨찾기 메세지 상세 조회 추가
서랍메뉴 - 나무 공개 비공개 여부 설정
처음 로그인 유저 이미지 랜덤 저장
API 자동 문서화
메세지 상세 조회 API
유저엔티티 필드 nickName -> nickname 변경하면 좋을것같아요 ..!
성공시 응답 형식 고민 필요
전역 예외처리 및 예외 발생시 응답형식 통일을 위한 핸들링 필요
RuntimeException
을 상속받은 BetreeException
클래스 생성ErrorCode
, ErrorResponse
, GlobalExcpetionHandler
등 생성@Getter
@RequiredArgsConstructor
public enum ErrorCode {
// Common
INVALID_INPUT_VALUE(400, "C001", "Invalid input value"),
INTERNAL_SERVER_ERROR(500, "C002", "Internal server error"),
METHOD_NOT_ALLOWED(405, "C003", "Method not allowed"),
// Member
MEMBER_NOT_FOUND(404, "M001", "회원을 찾을 수 없습니다."),
;
private final int status;
private final String code;
private final String message;
}
이런식으로 예외 상황에 맞게 구분해서 HttpStatus, Code, Message 생성하면됨
새로운 예외 핸들러 생성 방식
// 예시 - header에 required 필드에 값이 들어오지 않은 경우
@ExceptionHandler(value = MissingRequestHeaderException.class)
public ResponseEntity<ErrorResponse> handleMissingRequestHeaderException(Exception e) {
ErrorCode errorCode = ErrorCode.INVALID_INPUT_VALUE;
ErrorResponse er = getErrorResponse(e.getMessage(), errorCode);
return getResponseEntity(errorCode, er, "handleMissingRequestHeaderException"); // 로그 출력, 공통 응답형식 생성
}
물 주기 (메세지 생성) API
7/15 논의사항 정리
"name":"익명" , "image":""
로그인 유저마다 고유한 접속 URL 필요
폴더 내 메세지 상세와 즐겨찾기 메세지 상세 구분 필요
메세지 삭제
매일 갱신되는 8개의 칭찬메시지가 생성되는 알림나무 API를 구현한다.
NoticeTree Entity
알림나무용 DB 테이블 생성 -> 메시지 id가 8개 들어감 (8개보다 적거나 많을 수 없음)
읽은 메시지 id 처리하는 필드 필요.
회원 탈퇴 기능과 탈퇴 이후에 loginUser 검증 필요성 (회원 탈퇴이후에도 accessToken에 1시간동안은 탈퇴된 회원도 그냥 토큰으로 정보가 남아있을 수가 있다)
나무, 나무숲, 물주기 추가작업
NEW
DB 기본 엔티티 생성
AWS 배포환경 설정
폴더 삭제 ( 폴더 삭제시 포함된 메세지도 같이 삭제 )
프론트엔드 건의사항 반영
forest-controller
GET /api/forest
(유저 나무숲 조회)
- Response
- 200
- 각 나무 데이터 객체에 포함될 것
- 나무 아이디
- 나무 이름
- 나무 열매 종류 ( 필요 ! )
2. POST /api/forest
(유저 나무 추가) - 이미 되어있는 것 같음
PUT /api/forest/{treeId}
(유저 나무 편집)
- Response
- 200
- 편집된 유저의 나무 아이디 반환 ( 필요하다고 생각 !
message-controller
POST - /api/message (물주기)
- Prameters
- requestDto
- folderId, receiverId 에 대한 description 이 필요 해보입니다 !
다음 API 서버 테스트 배포까지 API 변경된 사항 리스트업
2022.07.10 (화) ~ 2022.07.16 (일)
구분 | 변경 내용 | 관련 API | PR | 담당 | 기타 |
---|---|---|---|---|---|
추가 | - 나무숲 공개 API | GET /api/forest/opening |
#72 | 김수빈 | |
수정 | - 나무숲 조회 API 응답값에 default 나무는 조회되지 않도록 수정, opening여부(폴더 공개여부) 추가 | GET /api/forest |
#82 #77 | 강지수 | |
수정 | - senderProfileImageUrl , userImage 값 서버의 이미지 path로 수정 | /image/v1/user_{}.png 형식 |
#77 | 강지수 | |
수정 | - UserResponseDto.url 항상 "" 반환하도록 수정 |
GET /api/users/info |
#77 | 강지수 | |
수정 | - 메시지 읽음 API 음수 메시지도 읽음처리되도록 수정 | PUT /api/messages/alreadyRead |
#77 | 강지수 |
이미지 주소
서버주소/image/v1/user_1.png
서버주소/image/v1/user_2.png
서버주소/image/v1/user_3.png
서버주소/image/v1/user_4.png
서버주소/image/v1/user_unknwon.png
: 익명서버주소/image/v1/user_betree.png
: 비트리 편지작업내용
에 정리하고 배포 다시 할때 디코 일반에 전달로그아웃
프론트에 Authorization Header에 jwt accessToken을 담아서 전달하는데 리액트에 노출 안됨
폴더 4개 추가 레파지토리 테스트
나무 숲, 나무 관련 API (조회, 등록, 편집, 삭제)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.