-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature/#10] 상위 목표 리스트 조회 기능 구현 #15
Conversation
- 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가
- Goal이라는 단어가 목표라는 의미를 더 잘 표현하는 것 같아서 변경하게 되었습니다
- Swagger에 있는 ApiResponse와 네이밍이 같아서 패키지 명 전체를 명시해야 함. 따라서 customResponse로 명칭 변경함
- 공통 예외 스펙과 exceptionHandler 추가
- 커서 기반 페이지네이션을 사용 - Service 통합 테스트 후 Controller 개발 예정
- 테스트 데이터간 독립성을 위해 databaseCleaner 추가
- 기존의 Slice의 반환 형식이 no offset 기반 페이징에서는 불필요하다고 판단되어 필요한 데이터만 파싱 처리함
|
||
// @RequestBody 및 @RequestParam, @PathVariable 값이 유효하지 않음 | ||
NOT_VALID_HEADER_ERROR(NOT_FOUND.value(), "COMMON-014", "Header에 데이터가 존재하지 않는 경우 "); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
지금 제가 넣어놓은 예외들은 비즈니스 예외 (ex. 멤버가 없습니다, 상위 목표가 없습니다)가 아니라 잘못된 입력, 서버상의 문제로 발생할 수 있는 에러들입니다!
저 에러들이 어떤 모습으로 반환되는지는 제가 노션 개발팀 2차 회의록 공통 응답 스펙에 첨부해놓은 이미지들 참고해주세요! 🙌
비즈니스 예외 코드의 경우 지금부터 민겸님이랑 저랑 정하면 될 것 같습니다~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 !! 작업하면서 생기는 비즈니스 예외 코드 정리해서 전달할게요~
// Querydsl | ||
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' | ||
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" | ||
annotationProcessor "jakarta.annotation:jakarta.annotation-api" | ||
annotationProcessor "jakarta.persistence:jakarta.persistence-api" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
querydsl 관련 의존성입니다! 다른 작업 없이 정상 작동하는거 확인했으니 민겸님도 pull 받아서 바로 적용해보시면 될꺼에요~~
error.getDefaultMessage())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Configuration | ||
public class QuerydslConfig { | ||
|
||
@PersistenceContext | ||
private EntityManager entityManager; | ||
|
||
@Bean | ||
public JPAQueryFactory jpaQueryFactory() { | ||
return new JPAQueryFactory(entityManager); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QueryDSL을 사용할 수 있도록 초기화해주는 작업입니다!
querydsl을 사용하는 객체에서는 저 jpaQueryFactory를 autowire로 의존성 주입 받아서 사용한다고 보시면 되요!
@ExceptionHandler(BusinessException.class) | ||
protected ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) { | ||
ErrorCode errorCode = e.getErrorCode(); | ||
ErrorResponse response = ErrorResponse.of(errorCode); | ||
return new ResponseEntity<>(response, HTTP_STATUS_OK); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
에러 종류가 되게 많은데요! BusinessException말고 다른 예외들은 고칠부분 있으면 제가 책임지고 수정할테니 민겸님은 BusinessExcetion에 집중해주세요!! 😊
public GoalListResponse getGoalList(Long goalId, Pageable pageable, GoalStatus goalStatus) | ||
{ | ||
Slice<GoalListResponseDto> goalList = goalQueryRepository.getGoalList(goalId, pageable, goalStatus); | ||
List<GoalListResponseDto> content = goalList.getContent(); | ||
Boolean next = goalList.hasNext(); | ||
return new GoalListResponse(content, next); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
민겸님도 아마 페이징 처리 해보셨을껀데, 저는 생각보다 Page 객체 내에서 필요한 데이터가 몇개 없어서 필요한 정보만 빼내서 IOS로 반환하는 식으로 구축했습니다~~
@Column(name = "entire_detail_goal_cnt", nullable = false) | ||
private Integer entireDetailGoalCnt; | ||
|
||
@Column(name = "completed_detail_goal_cnt", nullable = false) | ||
private Integer completedDetailGoalCnt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저희가 등록할 수 있는 하위 목표 개수도 유동적이고, 달성한 하위 목표 개수도 유동적이더라구요!
저희 피그마에 보면 상위 목표 리스트를 보여주는 메인 화면에서 각각의 상위 목표마다 하위 목표 달성률을 보여주는데,
조인으로는 구현하기가 너무 힘들어서 아예 1. 하위 목표 개수, 2. 달성한 하위목표 개수를 모두 상위 목표에 컬럼으로 만들었습니다!
// ) | ||
// List<GoalCountDto> countGoalByGoalStatus(); | ||
|
||
int countByGoalStatus(GoalStatus goalStatus); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분은 지금 구현중이라 무시해주셔도 되요 !!
- 기능 추가 및 테스트 진행 완료
- Swagger 어노테이션 수정
@@ -9,25 +9,25 @@ | |||
@Data | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
public class ApiResponse<T> { | |||
public class CustomeResponse<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
클래스명을 CustomResponse 으로 변경해야할 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
헉 오타가 있었군요...! 얼른 반영하겠습니다 👍
ApiResponse로 응답값을 제대로 표현할 수 없다고 판단되어 우선은 배제하기로 결정
private List<FieldError> errors; | ||
private String reason; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
상단의 FieldError에 reason 필드가 속해있는 것 같은데 ErrorResponse에 reason을 추가한 건 어떤 의도일까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아아 ExceptionHandler 코드를 보시면 Business 예외나 Validation 예외가 아닌 예외들이 ex.getMessage() 값을 파라미터로 ErrorReponse를 생성하고 있는데요!
저런 비즈니스적인 의미가 없는 예외들은 그냥 에러 메세지를 별도로 그대로 뿌려줘도 좋겠다고 생각해서 따로 reason이라는 필드를 만들었습니다!
제가 명시해놓은 예외들 말고도 여러 예외들이 있을건데, 그 예외들은 가장 하단의 Exception을 캐치하는 handler에서 잡힙니다!
그때도 그냥 reason이라는 필드로 에러 메세지 뿌려주는걸로 했어요!
public static ErrorResponse of(final ErrorCode code, final BindingResult bindingResult) { | ||
return new ErrorResponse(code, FieldError.of(bindingResult)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 함수가 실제로 예외처리 상황에서 어떻게 쓰이는지가 궁금합니다! BindingResult라는 클래스를 어느 경우에 사용하는걸까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제가 밑에 포스트맨 사진 공유해드린게 bindingResult의 결과를 뿌려준거에요!
저희 Controlller 단에서 validation을 진행하는데 그때 예외가 터지면 bindingResult에 검증 결과들이 쌓입니다~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
참고로 에러중에 bindException은 @ModelAttribute에서 검증할때 발생하고,
MethodArgumentNotValidException은 @RequestBody에서 검증할때 발생합니다~
public class BusinessException extends RuntimeException { | ||
|
||
private ErrorCode errorCode; | ||
|
||
|
||
public BusinessException(ErrorCode errorCode) { | ||
super(errorCode.getMessage()); | ||
this.errorCode = errorCode; | ||
} | ||
|
||
public ErrorCode getErrorCode() { | ||
return errorCode; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception을 throw 해야하는 경우에는 모두 ErrorCode만 담아서 BusinessException을 반환하면 되나요 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findById(id).orElseThrow(() -> {throw new BusinessException(ErrorCode.PLAN_NOT_FOUND);
요런식으로 ErrorCode만 넣어주면 되요~~
} | ||
|
||
final ErrorResponse response = ErrorResponse.of(errorCode, e.getBindingResult()); | ||
final ErrorResponse response = ErrorResponse.of(errorCode, bindingResult); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드 조금만 간결화 했습니다~
|
||
|
||
|
||
|
||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
함수 간 간격을 .. 일부로 크게 한것인가요? 😶
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
앜ㅋㅋㅋㅋㅋ 저거는 중간에서 뭐 하나 지운 흔적인것 같아용....😅
간견 줄여서 다시 올려놓을께요~~!!
|
||
private final GoalService goalService; | ||
|
||
@Tag(name = "상위 목표 리스트 조회", description = "상위 목표 리스트를 조회하는 API 입니다") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tag는 Controller 상단에 표시하는 어노테이션입니다!
@RestController
@RequiredArgsConstructor
@Tag(name = "goal", description = "상위 목표 API")
pubilc class GoalControllere {
private final GoalService goalService;
@Operation(summary = "상위 목표 리스트 조회" , description = "상위 목표 리스트를 조회하는 API입니다.")
....
}
와 같이 작성해야할 것 같아요 !!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
앗 무의식적으로 저렇게 달아버렸네요ㅠ 확인 감사합니다!!
* 상위 목표 엔티티 구현 (#5) * chore: Lombok, JPA 의존성 추가 * feat: plan 엔티티 내 유효성 검사 구현 * feat: PlanRepository 생성 * test: plan 엔티티 테스트 작성 - 상위 목표 제목 길이 validation 테스트 - 상위 목표 시작, 달성 날짜 validation 테스트 - 상위 목표 제목 길이 Figma 참고해서 15자 제한 * feat: 상위 목표 기간 LocalDate 타입으로 변경 (#3) 기간을 설정할때 연월일 까지만 데이터를 받기에 시,분까지 데이터를 받는 LocalDateTime은 불필요하다고 판단했음. * [Feature/#2] 소셜 로그인 구현 (#4) * feat: BaseEntity 작성 global/entity 폴더에 created_at, updated_at 필드를 넣는 BaseEntity 클래스를 작성하였습니다. * feat: User Entity 생성 (#2) DB에 매핑될 User 객체를 생성하였습니다. Kakao, Apple 두 개의 소셜 타입을 구분할 SocialType 필드를 enum Type으로 추가하였습니다. * chore: Swagger, Logging 클래스 global 폴더로 이동 * feat: OAuthController 생성 및 콜백 메서드 생성 1. 클라이언트가 AccessToken을 전달할 때 접근하는 'POST /auth' 콜백 주소를 연결할 메서드를 생성하였습니다. 2. 컨트롤러 메서드의 request, response dto를 record 클래스로 정의하였습니다. * feat: login 로직을 구현한 OAuthService 생성 1. 팩토리 메서드 패턴을 적용하여 OAuthClient 인터페이스를 provider에 따라 구현체를 매핑하도록 설정하였습니다. 2. OAuthClient에서 소셜 사용자의 정보를 불러오고 User 객체로 변환하였습니다. 3. User가 기 가입한 회원이라면 바로 반환, 그렇지 않다면 DB에 등록 후 반환하기 위해 UserService에서 로직을 구현하였습니다. 4. 마지막으로 회원에 대한 JWT 를 발급하여 반환하였습니다. * build: syntax error 수정 * build: syntax error 수정 * build: Junit Test 관련 권한 추가 * feat: WebClient를 이용해 카카오 인증서버에서 사용자 추출 (#2) KakaoClient 구현체에서 WebClient 라이브러리를 사용해 kapi.kakao.com 서버에 접근하여 사용자 정보 (KakaoUserInfo)를 추출하는 코드입니다. * feat: JwtProvider 클래스 생성 1. createToken 메서드 2. validateToken 메서드 * chore: .gitignore 수정 * feat: 애플 로그인 구현 * refactor: OAuthHandler에서 Provider별 클래스 분리 구현 * test: OAuthServiceTest 로그인 성공 테스트 생성(#2) * feat: KakaoClient BASE_URL과 URI 분리 * style: dto 폴더구조 request, response 나눠서 변경 * refactor: SocialId만 이용해서 사용자 조회하도록 변경 * refactor: BaseEntity에 자동으로 날짜를 주입하도록 설정 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#7] 설정 파일 submodule로 관리 (#8) * build: db 정보 암호화를 위한 submodules 설정(#7) * build: github Secrets 설정 수정 * fix: build.yml의 들여쓰기 오류 수정 * feat: 빌드 시 submodule 설정 파일 불러올 수 있도록 build.gradle 수정 * build: deploy.yml ACTION_TOKEN 추가 * build: build.gradle 라이브러리 중복 제거 * "build: build.gradle에 active profile 설정 추가 (#7) " * feat: dev 환경 데이터베이스 설정 추가 * build: dev 환경에서 빌드되도록 수정 * fix: build.yml의 test 명령어 수정 * fix: build.yml의 Publish unit test r구문 수정 * fix: build.yml test 파일 경로 수정" * "build: test 시 h2 database에서 작동하도록 application-tets.yml 추가 * chore: .gitignore 수정 * build: test profile을 test로 변경 * test: config 설정 수정 * build: build.yml의 Publish Unit Test Results에 토큰 추가 * build: test-results files 경로 수정 * build: github actions permissions를 write 권한으로 변경 * build: build.yml에 issues: write 권한 추가 * refactor: User 명칭을 Member로 변경 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#6] 공통 응답 추가 및 상위 목표 단건 조회 기능 구현 (#9) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * feat: 공통 응답 스펙 추가 * feat: 상위 목표 삭제 기능 추가 - Service에 삭제 기능 추가, 차후 테스트 필요 - 상위 목표 생성 Controller DTO 추가 * chore: application.yml 수정 * test: CI 테스트 * refactor: controller내 pathVariable 제거 * chore: build.yml을 테스트 환경에서 동작하도록 수정 * refactor: 소셜 로그인 시 input을 userId로 맞추어 수정 (#11) (#12) Co-authored-by: MingyeomKim <[email protected]> * [Feature/#13] TokenProvider 클래스 생성 및 Refresh Token 반환 (#14) * feat: Refresh token을 생성하도록 TokenProvider 클래스 추가 * test: TokenProvider 단위 테스트 생성 * test: TokenProviderTest 오류 수정 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#10] 상위 목표 리스트 조회 기능 구현 (#15) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * chore: git 캐시 초기화 * feat: 상위 목표 생성, 수정 기능 구현 (#10) * refactor: 상위 목표 도메인 명을 Plan에서 Goal로 변경 - Goal이라는 단어가 목표라는 의미를 더 잘 표현하는 것 같아서 변경하게 되었습니다 * refactor: 공통 응답 스펙명 CustomResponse로 변경 - Swagger에 있는 ApiResponse와 네이밍이 같아서 패키지 명 전체를 명시해야 함. 따라서 customResponse로 명칭 변경함 * feat: 공통 예외 스펙 추가 - 공통 예외 스펙과 exceptionHandler 추가 * chore: QueryDSL 세팅 * feat: 상위 목표 페이징 조회 기능 개발 - 커서 기반 페이지네이션을 사용 - Service 통합 테스트 후 Controller 개발 예정 * test: 상위 목표 페이징 조회 기능 테스트 - 테스트 데이터간 독립성을 위해 databaseCleaner 추가 * test: 페이징 기능 응답 스펙 변경 - 기존의 Slice의 반환 형식이 no offset 기반 페이징에서는 불필요하다고 판단되어 필요한 데이터만 파싱 처리함 * refactor: 상위 목표 통계 기능 삭제 및 테스트 수정 * feat: 상위 목표 상태별 개수 조회 기능 추가 - 기능 추가 및 테스트 진행 완료 * feat: 상위 목표 리스트에 dDay 컬럼 추가 - Swagger 어노테이션 수정 * feat: ErrorCode에 상위 목표 예외 추가 * test: GoalStatus 변경 * refactor: CustomResponse 오타 수정 * refactor: Swagger ApiResponse 제거 ApiResponse로 응답값을 제대로 표현할 수 없다고 판단되어 우선은 배제하기로 결정 * refactor: GlobalExceptionHandler 수정 * refactor: 클래스 내 빈공간 제거 * refactor: Tag와 Operation 재배치 * [Feature/#17] refresh token 발급 시 Redis에 저장하도록 설정 (#18) * feat: Redis 저장소 추가 및 세팅 (#17) * docs: @parameter 어노테이션으로 OAuthController 파라미터 설명 추가 * refactor: 소문자 provider를 대문자로 변경하는 함수 작성 * feat: OAuthController에 issue 메서드 추가 (#17) * refactor: socialId를 uid로, socialType을 provider로 명칭 변경 socialId가 사실상 사용자 식별 필드로 사용된다. 그러나 문자열인 socialId를 PK로 두는 것은 한계가 있기 때문에 uid로 명칭을 변경한다. 또한, Provider와 SocialType 명칭도 겹치기 때문에 provider라는 단어로 통일한다 * feat: RefreshToken, RefreshTokenRepository 작성 (#17) * feat: 액세스 토큰 만료 시 재발급 요청하는 reissue 서비스 코드 작성 (#17) * feat: 로그인 시 refresh token을 redis에 저장하는 기능 추가 (#17) * refactor: Auth 비즈니스 로직 Exception 처리 * feat: Redis 설정 수정 * refactor: login 호출 시 잘못된 provider가 입력되는 경우 예외처리 * test: reissue, login fail 테스트 케이스 추가 (#17) * refactor: CustomResponse를 사용하여 Controller 반환 * feat: @Valid 어노테이션 추가 * ci: 배포 시 테스트되지 않도록 deploy.yml 수정 * build: build.yml에 Redis 설정 추가 * build: redis port 입력 방식 수정 * refactor: 풀 리퀘스트 리뷰 반영 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#16] 하위 목표 기능 구현 (#20) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * feat: detail_goal 엔티티 설계 (#16) * feat: detailGoal 엔티티 설계 (#16) * feat: detailGoal 전체 조회 기능 구현 (#16) * feat: detailGoal 전체 조회 Controller 구현 * feat: detailGoal 저장 기능 구현 (#16) * refactor: 에러 코드 수정 - Goal 에러 코드 수정 - Detail Goal 에러 코드 추가 * feat: detail goal 상세 조회 응답값 변경 (#16) - 요일 정보를 EnumSet으로 관리하는걸 생각했으나 엔티티에는 적용이 되지 않아 List로 관리하기로 결정 * refactor: detail goal 요청 시 요일 정보 string으로 변경 * feat: detail goal 추가 시 goal 내부 카운트 증가 로직 추가 (#16) * feat: detail goal 수정, 삭제 기능 추가 (#16) * feat: detail goal 달성, 달성 해제 기능 구현 (#16) * test: detail goal 서비스 테스트 작성 (#16) * refactor: application-prod.yml 임시 파일 삭제 * feat: detail goal, goal 조회 쿼리에 isDeleted 판별 조건 추가 (#16) 기본적으로 soft delete를 사용하기 때문에 isDeleted에 대한 판별 조건을 포함해야 한다 * feat: goal 삭제 시 연관 detail goal 삭제 로직 추가 (#16) * feat: 전체 detail goal과 달성 detail goal 계산 및 조회 로직 추가 (#16) * [Feature/#21] 보관함 복구 기능, 회고 개수 조회 기능 구현 (#22) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * feat: 상위 목표 복구 기능 구현 (#21) * refactor: transactional 어노테이션 추가 * feat: LocalTime 요청 응답 값 오전/오후 반영하도록 변경 (#21) * feat: 상위 목표 제약 조건 수정 (#21) - 현재 보다 이전 날짜를 시작일로 선택 불가능하다는 조건이 없기에 조건 제거 - 보관함에서 복구 시 시작, 종료 날짜를 초기화 예정이기에 nullable을 true로 변경 * feat: 상위 목표 복구 기능 수정 (#21) - 복구 시 새로운 데이터로 초기화해야 복구가 완료 되도록 설정 * feat: 회고 작성 가능한 완료 목표 개수 조회 (#21) * feat: goal 생성시, goalstatus 생성자 주입으로 변경 - goalstatus 값을 변경해서 테스트 해야 할 경우들이 있다고 판단되어, 테스트 코드 편의성과 changeGoalStatus라는 setter 메서드를 제거하기 위해 작업을 진행함 * test: 테스트 작성 완료 * refactor: GoalController내 위치 변경 * application.yml 제거 * refactor: goalController 공통 URI 통일 * [Feature/#23] 하위 목표 모두 성공시 보상 제공 및 팝업 기능 구현 (#25) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * feat: 보상 제공 기능 구현 (#23) * feat: 상위 목표 달성 시 팝업 기능 구현 (#23) - 랜덤으로 보석 지급 기능 구현 - 상위 목표 리스트 조회 시 보석 enum도 조회 추가 - 보석 지급과 함께 complete 상태의 상위 목표 개수 조회 * test: 상위 목표 성공 시 기능 테스트 작성 (#23) * refactor: 상위 목표 개수 반환값 및 주석 수정 * [Feature/#24] 채움함 내 상위 목표의 종료 기간 경과 시 보관함으로 이동하는 스케쥴러 구현 (#26) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * feat: 0시 0분에 호출되는 스케쥴러 구현 (#24) * .gitignore 초기화 * test: 스케쥴러 테스트 작성 * test: 스케쥴러 테스트 작성 (#24) * feat: cron 수정 (#24) * Cicd test (#27) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * 서브 모듈 수정 * ci: redis container 설정 추가 * ci: SuperCharge의 Redis Server를 사용하도록 수정 * ci : build시 submodule을 가져오도록 설정 * ci: deploy 대상을 dev 브랜치로만 변경 * ci: deploy.yml의 submodule를 recursive로 설정 * ci: submodule 업데이트 * ci: dev profile로 빌드하도록 수정 및 submodule update 구문 추가 * [Feature/#19] 로그아웃, 회원 탈퇴 구현 및 Custom Filter 생성 후 Spring Security 적용 (#29) * feat: 로그아웃 기능 추가 (#19) * feat: Redis에 블랙 리스트 기능 추가 (#19) * refactor: BlackList 도메인에서 status 제외 * feat: 회원 탈퇴 기능 구현 (#19) * feat: reissue 시 refresh token도 새로 발급하도록 수정 * feat: Security Config 생성 및 OAuthController URI 통일 * feat: JwtFilter 구현 및 TokenProvider의 getAuthentication 작성 * feat: 인증, 인가 로직 실패 시 Exception Handler 작성 * feat: Q클래스 생성 * chore: SecurityConfig 작성 * feat: SecurityConfig 설정 추가 * test: TokenProviderTest의 멤버 호출 구문 Mocking * ci: build.yml, deploy.yml에서 submodule 자동 업데이트하도록 수정 * refactor: 토큰 유효성 검사 중복 제거 * feat: 회원 탈퇴 시 블랙 리스트에 추가 * feat: jwtFilter에서 블랙리스트 조회하는 로직 추가 * refactor: OAuthController의 함수 명칭을 일관되게 변경 * build: 라이브러리 꼬임 해결 * ci: java 실행 시 sudo 권한 추가 * docs: swagger cors에러 수정 * chore: 모든 URL 접근 가능하도록 설정 * refactor: jwtFilter에서 예외 던지지 않도록 수정 * chore: 모든 경로 접근 허용 * chore: 모든 경로 접근 허용 * refactor: JwtFilter에서 모든 Exception을 제외 * refactor: CORS 에러 해결 * chore: swagger에 authorization 인증 받을 수 있도록 수정 * chore: SwaggerConfig 수정 * build: run_new_was.sh 스크립트 들여쓰기 수정 * chore: run_new_was.sh가 동작 확인을 위한 로그 출력 * build: run_new_was.sh 에서 구동할 포트를 죽이는 명령어 수정 * feat: 회원 탈퇴 컨트롤러 URL추가 * [Feature/#31] 유저 로그인 시 fcm token을 저장하는 로직 구현 (#32) * feat: 로그인 시 fcm token을 함께 전달받도록 수정 * feat: Fcm Token 저장 및 조회 로직 추가 * [Feature/#28] 알림 요일과 시간에 따라 FCM 알림을 전송하는 기능 구현 (#35) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * 최신 사항 머지 * git cache 초기화 * feat: 푸시 알람 스케쥴러 구현 (#28) - 매일 30분 간격으로 작동하는 스케쥴러 구현 - FCM 서비스를 호출하는 event 구현 * feat: 요일, 시간별 알림 전송 스케쥴러 구현 (#28) * test: detailGoalQueryRepository 테스트 추가 (#28) * refactor: 공통 응답 스펙 수정 * docs: swagger 문서 수정 * docs: 코드,메세지 설명 추가 * feat: 응답 Response에 Schema 추가 (#36) * chore: 토큰의 만료시간 임의 변경 * locale (#39) * fix: locale 수정 * JsonFormat pattern 변경 (#41) * fix: localtime 형식 변경 * [Feature/#37] 회고 도메인 생성 및 저장, 조회 로직 구현 (#42) * refactor: fcmToken 조회 로직 수정, logout, withdraw에 추가 * feat: 회고 도메인 생성 (#37) * feat: 회고 도메인의 Repository 생성 * feat: 회고 저장 및 조회 로직 구현 (#37) * feat: 회고의 내용을 담는 RetroSpectContent 분리 (#37) * test: 회고 저장 및 조회 서비스 로직 테스트 * feat: 회고 저장 및 조회 컨트롤러 구현 (#37) * refactor: 의존성 관련 오류 수정 * [Refactor/#37] 회고 기능 관련 리팩토링 (#44) * LocalDate JSON 응답 형식 변경 (#45) * refactor: GoalController LocalTime 형식 변경 * chore: JPA의 ddl-auto를 create로 설정 * build: 빌드 시 워크플로우에서 secrets 불러오는 것 제외 * feat: Retrospect Response에 hasGuide 컬럼 추가 * build: build.yml 워크플로우에서 서브모듈 로직 제외 * refactor: contents의 @column 삭제 * chore: run_new_was.sh의 내용 일부 수정 * chore: config의 application-dev.yml 수정 * refactor: Retrospect와 Content를 양방향 매핑으로 변경 * refactor: retrospect content가 retrospect를 가져오지 못하는 부분 수정 * chore: ddl-auto를 create로 변경 * [Feature/#38] FCM 푸시 알림 기능 연동 후 하위 목표 알림 스케쥴러와 연결한다 (#46) * feat: FCM 알림 설정 및 연동 (#38) * refactor: GoalController LocalTime 형식 변경 * feat: FCM 알림 스케쥴링 기능 복구 * refactor: 테스트 수정 및 도메인 디렉토리 구조 변경 * refactor: DetailGoal 수정 시 locale 정보 변경 * submodule내 FCM 설정 파일 경로 수정 (#50) * fix: submodule에 fcm_key.json 경로 수정 * 하위 목표 시간 locale 응답 ko로 수정 (#51) * refactor: 하위 목표 응답 시간 locale ko로 수정 * 상위 목표 개수 카운트 쿼리 수정 (#52) - 삭제 여부 판단 로직을 쿼리의 having 부분에서 where 절로 옮김 * [Refactor/#47] 사용자 인증 필터에서 발생하는 예외 핸들러 필터 구현 (#49) * feat: 예외를 발생시키는 JwtExceptionFilter 클래스 생성 * refactor: TokenProvider의 validateToken이 JwtException을 반환하도록 수정 * refactor: 따로 처리가 필요한 인증 예외 클래스를 생성하고, Token 검증 오류 시 Throw한다. * feat: 블랙 리스트 Exception 클래스 생성, Authentication 필터 수정 * feat: 필터의 오류 핸들링 필터를 추가 (#47) * feat: 인증 필터를 핸들링하는 필터 작성 (#47) 추가로 궁금한 점 : (1) 토큰 만료 시 = reissue 요청 (2) 토큰이 없는 경우 = 로그인 요청 (3) 토큰이 잘못된 경우 = 올바르지 않다는 메시지 반환 이런 식으로 구현할려고 했는데, ErrorCode가 달라지는 것 말고는 별 다른 처리할 것이 없다고 생각해서 setErrorResponse 메소드 하나로 통일하여 예외를 처리하였다. 이렇게 획일화하고 나니 그냥 JwtException 하나로만 서로 다른 ErrorCode를 넣어서 구현해도 같은 결과를 가져올 것 같아서, Exception 클래스의 분리의 필요성을 못느꼈다. * refactor: jwt 토큰의 유효성 검증은 따로 Exception 처리 제외 * chore: config 수정 사항 반영 * 상위 목표 수정 기능 Service 파라미터 수정 및 Security Config 변경 (#53) * refactor: 상위 목표 수정 컨트롤러에서 Path Variable 사용하도록 변경 * refactor: SecurityConfig 설정 변경 * 기존에 전체 허용으로 열려있던 URL 경로 권한을 인증 URL로 제한 * Spring Security내 permitAll 동작할 수 있도록 JwtFilter 수정 (#54) * refactor: permitAll한 url은 token 예외가 발생하지 않도록 처리 * GoalResponse @jsonformat 수정 (#55) * refactor: GoalResponse의 JsonFormat 수정 * JWT 유효기간 수정 (#56) * refactor: JWT 만료 시간 수정 * 하위 목표 수정 문제 해결 및 상위 목표 페이징 커서 수정 (#57) * refactor: 페이징 커서 null에서 -1일때 전체 조회하도록 수정 * 회고 작성 시 보관함 내 목표 리마인드 기능 추가 (#58) * feat: 보관함 목표 리마인드 기능 개발 * 상위 목표 리스트 조회 시 리마인드 여부 컬럼 추가 (#59) * refactor: 상위 목표 리스트 반환 시 reminder 여부 컬럼 추가 * 보관함에 있는 목표 조회 시 d-day 0으로 계산 (#60) * 보관함에 있는 목표 d-day 계산 시 0 반환하도록 변경 * 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환 (#61) * 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환 * feat: 토큰 재발급 시, 재발급된 refresh token을 redis에 저장 * refactor: SecurityConfig 에서 exception Handling 제외 * refactor: reissue 시 refresh token을 조회할 수 없는 부분 수정 * hotfix: import 시 오타 수정 * refactor: /auth 경로를 Authentication Filter를 거치지 않도록 설정 * hotfix: URI와 Request Method 확인을 위한 로깅 처리 * refactor: 허용한 URL 이외의 요청에 인증을 거치도록 설정 * feat: 상위 목표, 세부 목표 API JWT 인증 거치도록 설정 * feat: 최초 로그인 시 관련 정보를 함께 Response에 전달 * 인증 유저 정보를 사용해서 사용자 상위 목표를 식별한다 (#62) - @AuthenticationPrincipal을 통해 인증 유저 식별자 가져옴 * refactor: 재로그인 시 refresh, fcm token 삭제하는 코드 제거 * refactor: 애플리케이션 실행 시 Asia/Seoul Timezone 설정 * test: 토큰 테스트를 위해 유효 기간을 짧게 설정 * refactor: 저장되지 않은 토큰 입력 시 401 에러 반환하도록 수정 * refactor: 토큰의 유효시간 정상화 * test: 토큰 유효시간 짧게 설정 * refactor: 리프레시 토큰 유효기간 정상화 * test: reissue 테스트를 위한 로그 추가 * refactor: refresh Token 객체 timeToLive설정 * refactor: @column에 unique=true를 추가하여 해결 (#65) * refactor: 토큰 유효시간 정상화 * 목표 달성 후 보상 지급 시, 로그인한 사용자의 달성 목표만 카운트 하도록 설정한다 (#66) * refactor: 보상 지급 시 달성 목표 카운트 수정 --------- Co-authored-by: Seo Jemin <[email protected]> Co-authored-by: MingyeomKim <[email protected]>
* 상위 목표 엔티티 구현 (#5) * chore: Lombok, JPA 의존성 추가 * feat: plan 엔티티 내 유효성 검사 구현 * feat: PlanRepository 생성 * test: plan 엔티티 테스트 작성 - 상위 목표 제목 길이 validation 테스트 - 상위 목표 시작, 달성 날짜 validation 테스트 - 상위 목표 제목 길이 Figma 참고해서 15자 제한 * feat: 상위 목표 기간 LocalDate 타입으로 변경 (#3) 기간을 설정할때 연월일 까지만 데이터를 받기에 시,분까지 데이터를 받는 LocalDateTime은 불필요하다고 판단했음. * [Feature/#2] 소셜 로그인 구현 (#4) * feat: BaseEntity 작성 global/entity 폴더에 created_at, updated_at 필드를 넣는 BaseEntity 클래스를 작성하였습니다. * feat: User Entity 생성 (#2) DB에 매핑될 User 객체를 생성하였습니다. Kakao, Apple 두 개의 소셜 타입을 구분할 SocialType 필드를 enum Type으로 추가하였습니다. * chore: Swagger, Logging 클래스 global 폴더로 이동 * feat: OAuthController 생성 및 콜백 메서드 생성 1. 클라이언트가 AccessToken을 전달할 때 접근하는 'POST /auth' 콜백 주소를 연결할 메서드를 생성하였습니다. 2. 컨트롤러 메서드의 request, response dto를 record 클래스로 정의하였습니다. * feat: login 로직을 구현한 OAuthService 생성 1. 팩토리 메서드 패턴을 적용하여 OAuthClient 인터페이스를 provider에 따라 구현체를 매핑하도록 설정하였습니다. 2. OAuthClient에서 소셜 사용자의 정보를 불러오고 User 객체로 변환하였습니다. 3. User가 기 가입한 회원이라면 바로 반환, 그렇지 않다면 DB에 등록 후 반환하기 위해 UserService에서 로직을 구현하였습니다. 4. 마지막으로 회원에 대한 JWT 를 발급하여 반환하였습니다. * build: syntax error 수정 * build: syntax error 수정 * build: Junit Test 관련 권한 추가 * feat: WebClient를 이용해 카카오 인증서버에서 사용자 추출 (#2) KakaoClient 구현체에서 WebClient 라이브러리를 사용해 kapi.kakao.com 서버에 접근하여 사용자 정보 (KakaoUserInfo)를 추출하는 코드입니다. * feat: JwtProvider 클래스 생성 1. createToken 메서드 2. validateToken 메서드 * chore: .gitignore 수정 * feat: 애플 로그인 구현 * refactor: OAuthHandler에서 Provider별 클래스 분리 구현 * test: OAuthServiceTest 로그인 성공 테스트 생성(#2) * feat: KakaoClient BASE_URL과 URI 분리 * style: dto 폴더구조 request, response 나눠서 변경 * refactor: SocialId만 이용해서 사용자 조회하도록 변경 * refactor: BaseEntity에 자동으로 날짜를 주입하도록 설정 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#7] 설정 파일 submodule로 관리 (#8) * build: db 정보 암호화를 위한 submodules 설정(#7) * build: github Secrets 설정 수정 * fix: build.yml의 들여쓰기 오류 수정 * feat: 빌드 시 submodule 설정 파일 불러올 수 있도록 build.gradle 수정 * build: deploy.yml ACTION_TOKEN 추가 * build: build.gradle 라이브러리 중복 제거 * "build: build.gradle에 active profile 설정 추가 (#7) " * feat: dev 환경 데이터베이스 설정 추가 * build: dev 환경에서 빌드되도록 수정 * fix: build.yml의 test 명령어 수정 * fix: build.yml의 Publish unit test r구문 수정 * fix: build.yml test 파일 경로 수정" * "build: test 시 h2 database에서 작동하도록 application-tets.yml 추가 * chore: .gitignore 수정 * build: test profile을 test로 변경 * test: config 설정 수정 * build: build.yml의 Publish Unit Test Results에 토큰 추가 * build: test-results files 경로 수정 * build: github actions permissions를 write 권한으로 변경 * build: build.yml에 issues: write 권한 추가 * refactor: User 명칭을 Member로 변경 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#6] 공통 응답 추가 및 상위 목표 단건 조회 기능 구현 (#9) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * feat: 공통 응답 스펙 추가 * feat: 상위 목표 삭제 기능 추가 - Service에 삭제 기능 추가, 차후 테스트 필요 - 상위 목표 생성 Controller DTO 추가 * chore: application.yml 수정 * test: CI 테스트 * refactor: controller내 pathVariable 제거 * chore: build.yml을 테스트 환경에서 동작하도록 수정 * refactor: 소셜 로그인 시 input을 userId로 맞추어 수정 (#11) (#12) Co-authored-by: MingyeomKim <[email protected]> * [Feature/#13] TokenProvider 클래스 생성 및 Refresh Token 반환 (#14) * feat: Refresh token을 생성하도록 TokenProvider 클래스 추가 * test: TokenProvider 단위 테스트 생성 * test: TokenProviderTest 오류 수정 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#10] 상위 목표 리스트 조회 기능 구현 (#15) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * chore: git 캐시 초기화 * feat: 상위 목표 생성, 수정 기능 구현 (#10) * refactor: 상위 목표 도메인 명을 Plan에서 Goal로 변경 - Goal이라는 단어가 목표라는 의미를 더 잘 표현하는 것 같아서 변경하게 되었습니다 * refactor: 공통 응답 스펙명 CustomResponse로 변경 - Swagger에 있는 ApiResponse와 네이밍이 같아서 패키지 명 전체를 명시해야 함. 따라서 customResponse로 명칭 변경함 * feat: 공통 예외 스펙 추가 - 공통 예외 스펙과 exceptionHandler 추가 * chore: QueryDSL 세팅 * feat: 상위 목표 페이징 조회 기능 개발 - 커서 기반 페이지네이션을 사용 - Service 통합 테스트 후 Controller 개발 예정 * test: 상위 목표 페이징 조회 기능 테스트 - 테스트 데이터간 독립성을 위해 databaseCleaner 추가 * test: 페이징 기능 응답 스펙 변경 - 기존의 Slice의 반환 형식이 no offset 기반 페이징에서는 불필요하다고 판단되어 필요한 데이터만 파싱 처리함 * refactor: 상위 목표 통계 기능 삭제 및 테스트 수정 * feat: 상위 목표 상태별 개수 조회 기능 추가 - 기능 추가 및 테스트 진행 완료 * feat: 상위 목표 리스트에 dDay 컬럼 추가 - Swagger 어노테이션 수정 * feat: ErrorCode에 상위 목표 예외 추가 * test: GoalStatus 변경 * refactor: CustomResponse 오타 수정 * refactor: Swagger ApiResponse 제거 ApiResponse로 응답값을 제대로 표현할 수 없다고 판단되어 우선은 배제하기로 결정 * refactor: GlobalExceptionHandler 수정 * refactor: 클래스 내 빈공간 제거 * refactor: Tag와 Operation 재배치 * [Feature/#17] refresh token 발급 시 Redis에 저장하도록 설정 (#18) * feat: Redis 저장소 추가 및 세팅 (#17) * docs: @parameter 어노테이션으로 OAuthController 파라미터 설명 추가 * refactor: 소문자 provider를 대문자로 변경하는 함수 작성 * feat: OAuthController에 issue 메서드 추가 (#17) * refactor: socialId를 uid로, socialType을 provider로 명칭 변경 socialId가 사실상 사용자 식별 필드로 사용된다. 그러나 문자열인 socialId를 PK로 두는 것은 한계가 있기 때문에 uid로 명칭을 변경한다. 또한, Provider와 SocialType 명칭도 겹치기 때문에 provider라는 단어로 통일한다 * feat: RefreshToken, RefreshTokenRepository 작성 (#17) * feat: 액세스 토큰 만료 시 재발급 요청하는 reissue 서비스 코드 작성 (#17) * feat: 로그인 시 refresh token을 redis에 저장하는 기능 추가 (#17) * refactor: Auth 비즈니스 로직 Exception 처리 * feat: Redis 설정 수정 * refactor: login 호출 시 잘못된 provider가 입력되는 경우 예외처리 * test: reissue, login fail 테스트 케이스 추가 (#17) * refactor: CustomResponse를 사용하여 Controller 반환 * feat: @Valid 어노테이션 추가 * ci: 배포 시 테스트되지 않도록 deploy.yml 수정 * build: build.yml에 Redis 설정 추가 * build: redis port 입력 방식 수정 * refactor: 풀 리퀘스트 리뷰 반영 --------- Co-authored-by: MingyeomKim <[email protected]> * [Feature/#16] 하위 목표 기능 구현 (#20) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * feat: detail_goal 엔티티 설계 (#16) * feat: detailGoal 엔티티 설계 (#16) * feat: detailGoal 전체 조회 기능 구현 (#16) * feat: detailGoal 전체 조회 Controller 구현 * feat: detailGoal 저장 기능 구현 (#16) * refactor: 에러 코드 수정 - Goal 에러 코드 수정 - Detail Goal 에러 코드 추가 * feat: detail goal 상세 조회 응답값 변경 (#16) - 요일 정보를 EnumSet으로 관리하는걸 생각했으나 엔티티에는 적용이 되지 않아 List로 관리하기로 결정 * refactor: detail goal 요청 시 요일 정보 string으로 변경 * feat: detail goal 추가 시 goal 내부 카운트 증가 로직 추가 (#16) * feat: detail goal 수정, 삭제 기능 추가 (#16) * feat: detail goal 달성, 달성 해제 기능 구현 (#16) * test: detail goal 서비스 테스트 작성 (#16) * refactor: application-prod.yml 임시 파일 삭제 * feat: detail goal, goal 조회 쿼리에 isDeleted 판별 조건 추가 (#16) 기본적으로 soft delete를 사용하기 때문에 isDeleted에 대한 판별 조건을 포함해야 한다 * feat: goal 삭제 시 연관 detail goal 삭제 로직 추가 (#16) * feat: 전체 detail goal과 달성 detail goal 계산 및 조회 로직 추가 (#16) * [Feature/#21] 보관함 복구 기능, 회고 개수 조회 기능 구현 (#22) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * feat: 상위 목표 복구 기능 구현 (#21) * refactor: transactional 어노테이션 추가 * feat: LocalTime 요청 응답 값 오전/오후 반영하도록 변경 (#21) * feat: 상위 목표 제약 조건 수정 (#21) - 현재 보다 이전 날짜를 시작일로 선택 불가능하다는 조건이 없기에 조건 제거 - 보관함에서 복구 시 시작, 종료 날짜를 초기화 예정이기에 nullable을 true로 변경 * feat: 상위 목표 복구 기능 수정 (#21) - 복구 시 새로운 데이터로 초기화해야 복구가 완료 되도록 설정 * feat: 회고 작성 가능한 완료 목표 개수 조회 (#21) * feat: goal 생성시, goalstatus 생성자 주입으로 변경 - goalstatus 값을 변경해서 테스트 해야 할 경우들이 있다고 판단되어, 테스트 코드 편의성과 changeGoalStatus라는 setter 메서드를 제거하기 위해 작업을 진행함 * test: 테스트 작성 완료 * refactor: GoalController내 위치 변경 * application.yml 제거 * refactor: goalController 공통 URI 통일 * [Feature/#23] 하위 목표 모두 성공시 보상 제공 및 팝업 기능 구현 (#25) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * feat: 보상 제공 기능 구현 (#23) * feat: 상위 목표 달성 시 팝업 기능 구현 (#23) - 랜덤으로 보석 지급 기능 구현 - 상위 목표 리스트 조회 시 보석 enum도 조회 추가 - 보석 지급과 함께 complete 상태의 상위 목표 개수 조회 * test: 상위 목표 성공 시 기능 테스트 작성 (#23) * refactor: 상위 목표 개수 반환값 및 주석 수정 * [Feature/#24] 채움함 내 상위 목표의 종료 기간 경과 시 보관함으로 이동하는 스케쥴러 구현 (#26) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * feat: 0시 0분에 호출되는 스케쥴러 구현 (#24) * .gitignore 초기화 * test: 스케쥴러 테스트 작성 * test: 스케쥴러 테스트 작성 (#24) * feat: cron 수정 (#24) * Cicd test (#27) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * 서브 모듈 수정 * ci: redis container 설정 추가 * ci: SuperCharge의 Redis Server를 사용하도록 수정 * ci : build시 submodule을 가져오도록 설정 * ci: deploy 대상을 dev 브랜치로만 변경 * ci: deploy.yml의 submodule를 recursive로 설정 * ci: submodule 업데이트 * ci: dev profile로 빌드하도록 수정 및 submodule update 구문 추가 * [Feature/#19] 로그아웃, 회원 탈퇴 구현 및 Custom Filter 생성 후 Spring Security 적용 (#29) * feat: 로그아웃 기능 추가 (#19) * feat: Redis에 블랙 리스트 기능 추가 (#19) * refactor: BlackList 도메인에서 status 제외 * feat: 회원 탈퇴 기능 구현 (#19) * feat: reissue 시 refresh token도 새로 발급하도록 수정 * feat: Security Config 생성 및 OAuthController URI 통일 * feat: JwtFilter 구현 및 TokenProvider의 getAuthentication 작성 * feat: 인증, 인가 로직 실패 시 Exception Handler 작성 * feat: Q클래스 생성 * chore: SecurityConfig 작성 * feat: SecurityConfig 설정 추가 * test: TokenProviderTest의 멤버 호출 구문 Mocking * ci: build.yml, deploy.yml에서 submodule 자동 업데이트하도록 수정 * refactor: 토큰 유효성 검사 중복 제거 * feat: 회원 탈퇴 시 블랙 리스트에 추가 * feat: jwtFilter에서 블랙리스트 조회하는 로직 추가 * refactor: OAuthController의 함수 명칭을 일관되게 변경 * build: 라이브러리 꼬임 해결 * ci: java 실행 시 sudo 권한 추가 * docs: swagger cors에러 수정 * chore: 모든 URL 접근 가능하도록 설정 * refactor: jwtFilter에서 예외 던지지 않도록 수정 * chore: 모든 경로 접근 허용 * chore: 모든 경로 접근 허용 * refactor: JwtFilter에서 모든 Exception을 제외 * refactor: CORS 에러 해결 * chore: swagger에 authorization 인증 받을 수 있도록 수정 * chore: SwaggerConfig 수정 * build: run_new_was.sh 스크립트 들여쓰기 수정 * chore: run_new_was.sh가 동작 확인을 위한 로그 출력 * build: run_new_was.sh 에서 구동할 포트를 죽이는 명령어 수정 * feat: 회원 탈퇴 컨트롤러 URL추가 * [Feature/#31] 유저 로그인 시 fcm token을 저장하는 로직 구현 (#32) * feat: 로그인 시 fcm token을 함께 전달받도록 수정 * feat: Fcm Token 저장 및 조회 로직 추가 * [Feature/#28] 알림 요일과 시간에 따라 FCM 알림을 전송하는 기능 구현 (#35) * feat: 상위 목표 d-day 기능 구현, 테스트 작성 (#6) - 상위 목표 종료 일자 필수 입력으로 확정 후, d-day 계산 로직 plan 엔티티내 생성 후 테스트 - planService에 상위 목표 단건 조회 로직 추가 * 간격 수정 * 최신 사항 머지 * git cache 초기화 * feat: 푸시 알람 스케쥴러 구현 (#28) - 매일 30분 간격으로 작동하는 스케쥴러 구현 - FCM 서비스를 호출하는 event 구현 * feat: 요일, 시간별 알림 전송 스케쥴러 구현 (#28) * test: detailGoalQueryRepository 테스트 추가 (#28) * refactor: 공통 응답 스펙 수정 * docs: swagger 문서 수정 * docs: 코드,메세지 설명 추가 * feat: 응답 Response에 Schema 추가 (#36) * chore: 토큰의 만료시간 임의 변경 * locale (#39) * fix: locale 수정 * JsonFormat pattern 변경 (#41) * fix: localtime 형식 변경 * [Feature/#37] 회고 도메인 생성 및 저장, 조회 로직 구현 (#42) * refactor: fcmToken 조회 로직 수정, logout, withdraw에 추가 * feat: 회고 도메인 생성 (#37) * feat: 회고 도메인의 Repository 생성 * feat: 회고 저장 및 조회 로직 구현 (#37) * feat: 회고의 내용을 담는 RetroSpectContent 분리 (#37) * test: 회고 저장 및 조회 서비스 로직 테스트 * feat: 회고 저장 및 조회 컨트롤러 구현 (#37) * refactor: 의존성 관련 오류 수정 * [Refactor/#37] 회고 기능 관련 리팩토링 (#44) * LocalDate JSON 응답 형식 변경 (#45) * refactor: GoalController LocalTime 형식 변경 * chore: JPA의 ddl-auto를 create로 설정 * build: 빌드 시 워크플로우에서 secrets 불러오는 것 제외 * feat: Retrospect Response에 hasGuide 컬럼 추가 * build: build.yml 워크플로우에서 서브모듈 로직 제외 * refactor: contents의 @column 삭제 * chore: run_new_was.sh의 내용 일부 수정 * chore: config의 application-dev.yml 수정 * refactor: Retrospect와 Content를 양방향 매핑으로 변경 * refactor: retrospect content가 retrospect를 가져오지 못하는 부분 수정 * chore: ddl-auto를 create로 변경 * [Feature/#38] FCM 푸시 알림 기능 연동 후 하위 목표 알림 스케쥴러와 연결한다 (#46) * feat: FCM 알림 설정 및 연동 (#38) * refactor: GoalController LocalTime 형식 변경 * feat: FCM 알림 스케쥴링 기능 복구 * refactor: 테스트 수정 및 도메인 디렉토리 구조 변경 * refactor: DetailGoal 수정 시 locale 정보 변경 * submodule내 FCM 설정 파일 경로 수정 (#50) * fix: submodule에 fcm_key.json 경로 수정 * 하위 목표 시간 locale 응답 ko로 수정 (#51) * refactor: 하위 목표 응답 시간 locale ko로 수정 * 상위 목표 개수 카운트 쿼리 수정 (#52) - 삭제 여부 판단 로직을 쿼리의 having 부분에서 where 절로 옮김 * [Refactor/#47] 사용자 인증 필터에서 발생하는 예외 핸들러 필터 구현 (#49) * feat: 예외를 발생시키는 JwtExceptionFilter 클래스 생성 * refactor: TokenProvider의 validateToken이 JwtException을 반환하도록 수정 * refactor: 따로 처리가 필요한 인증 예외 클래스를 생성하고, Token 검증 오류 시 Throw한다. * feat: 블랙 리스트 Exception 클래스 생성, Authentication 필터 수정 * feat: 필터의 오류 핸들링 필터를 추가 (#47) * feat: 인증 필터를 핸들링하는 필터 작성 (#47) 추가로 궁금한 점 : (1) 토큰 만료 시 = reissue 요청 (2) 토큰이 없는 경우 = 로그인 요청 (3) 토큰이 잘못된 경우 = 올바르지 않다는 메시지 반환 이런 식으로 구현할려고 했는데, ErrorCode가 달라지는 것 말고는 별 다른 처리할 것이 없다고 생각해서 setErrorResponse 메소드 하나로 통일하여 예외를 처리하였다. 이렇게 획일화하고 나니 그냥 JwtException 하나로만 서로 다른 ErrorCode를 넣어서 구현해도 같은 결과를 가져올 것 같아서, Exception 클래스의 분리의 필요성을 못느꼈다. * refactor: jwt 토큰의 유효성 검증은 따로 Exception 처리 제외 * chore: config 수정 사항 반영 * 상위 목표 수정 기능 Service 파라미터 수정 및 Security Config 변경 (#53) * refactor: 상위 목표 수정 컨트롤러에서 Path Variable 사용하도록 변경 * refactor: SecurityConfig 설정 변경 * 기존에 전체 허용으로 열려있던 URL 경로 권한을 인증 URL로 제한 * Spring Security내 permitAll 동작할 수 있도록 JwtFilter 수정 (#54) * refactor: permitAll한 url은 token 예외가 발생하지 않도록 처리 * GoalResponse @jsonformat 수정 (#55) * refactor: GoalResponse의 JsonFormat 수정 * JWT 유효기간 수정 (#56) * refactor: JWT 만료 시간 수정 * 하위 목표 수정 문제 해결 및 상위 목표 페이징 커서 수정 (#57) * refactor: 페이징 커서 null에서 -1일때 전체 조회하도록 수정 * 회고 작성 시 보관함 내 목표 리마인드 기능 추가 (#58) * feat: 보관함 목표 리마인드 기능 개발 * 상위 목표 리스트 조회 시 리마인드 여부 컬럼 추가 (#59) * refactor: 상위 목표 리스트 반환 시 reminder 여부 컬럼 추가 * 보관함에 있는 목표 조회 시 d-day 0으로 계산 (#60) * 보관함에 있는 목표 d-day 계산 시 0 반환하도록 변경 * 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환 (#61) * 보관함에 있는 목표 조회 시 d-day 값을 음수로 반환 * feat: 토큰 재발급 시, 재발급된 refresh token을 redis에 저장 * refactor: SecurityConfig 에서 exception Handling 제외 * refactor: reissue 시 refresh token을 조회할 수 없는 부분 수정 * hotfix: import 시 오타 수정 * refactor: /auth 경로를 Authentication Filter를 거치지 않도록 설정 * hotfix: URI와 Request Method 확인을 위한 로깅 처리 * refactor: 허용한 URL 이외의 요청에 인증을 거치도록 설정 * feat: 상위 목표, 세부 목표 API JWT 인증 거치도록 설정 * feat: 최초 로그인 시 관련 정보를 함께 Response에 전달 * 인증 유저 정보를 사용해서 사용자 상위 목표를 식별한다 (#62) - @AuthenticationPrincipal을 통해 인증 유저 식별자 가져옴 * refactor: 재로그인 시 refresh, fcm token 삭제하는 코드 제거 * refactor: 애플리케이션 실행 시 Asia/Seoul Timezone 설정 * test: 토큰 테스트를 위해 유효 기간을 짧게 설정 * refactor: 저장되지 않은 토큰 입력 시 401 에러 반환하도록 수정 * refactor: 토큰의 유효시간 정상화 * test: 토큰 유효시간 짧게 설정 * refactor: 리프레시 토큰 유효기간 정상화 * test: reissue 테스트를 위한 로그 추가 * refactor: refresh Token 객체 timeToLive설정 * refactor: @column에 unique=true를 추가하여 해결 (#65) * refactor: 토큰 유효시간 정상화 * 목표 달성 후 보상 지급 시, 로그인한 사용자의 달성 목표만 카운트 하도록 설정한다 (#66) * refactor: 보상 지급 시 달성 목표 카운트 수정 * feat: 토큰 관리 API 추가 (#68) Co-authored-by: MingyeomKim <[email protected]> --------- Co-authored-by: Seo Jemin <[email protected]> Co-authored-by: MingyeomKim <[email protected]>
1️⃣ 작업 내용 (Contents)
resolved : #10
변경사항들이 좀 많은데, 핵심적인 것들만 요약하자면
이렇게 입니다!
설명이 더 자세히 필요한 부분은 제가 셀프 리뷰 남겨두겠습니다!
2️⃣ 링크 (Links)
3️⃣ 희망 리뷰 완료 일 (Expected due date)
8.15
4️⃣ 기타 사항 (ETC)