Skip to content
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

[Feat] 전역적 예외 및 핸들러 추가 #4

Merged
merged 10 commits into from
Feb 8, 2025

Conversation

helenason
Copy link
Collaborator

issue #2

💻 수정 사항

ErrorResponse가 불필요한 정보 없이 필요한 정보만 담도록 하다보니 돌고돌아 저번 프로젝트에서 사용하던 방식이 되었는데요, 다른 방식을 원하신다면 얼마든지 코드 리뷰 남겨주세요!

제가 의도한 사용 예시는 아래와 같습니다.

아래 클래스를 통해 비즈니스 로직에서 발생시킬 예외 코드를 도메인별로 나누어 정의합니다.

@Getter
@AllArgsConstructor
public enum XXXErrorCode implements ErrorCode {

    NOT_FOUND(BAD_REQUEST, "해당 명함이 존재하지 않습니다."),
    INVALID_MEMBER(BAD_REQUEST, "유효하지 않은 사용자입니다."),
    ;

    private final HttpStatus status;
    private final String message;

    @Override
    public ErrorResponse getResponse() {
        return new ErrorResponse(message);
    }
}

그리고 비즈니스 로직에서는 아래와 같이 예외를 발생시킵니다.

public void throwException() {
    throw new BlokException(TestErrorCode.NOT_FOUND);
}

⛳️ 고민 사항

예외 핸들러 구현과 더불어 글로벌 요청/응답 클래스 구현하기를 담당했는데요! 아직 글로벌 요청/응답 클래스를 구현해본 적이 없고, 필요성을 느끼지 못하는 상태라 구현하지 않고 먼저 PR 요청합니다. 제가 이해한 글로벌 응답 클래스는 이러한 것인데, 제가 잘 이해한 게 맞는지 궁금하고, 다른 사례가 있다면 알려주시면 감사하겠습니다 :)

Copy link

coderabbitai bot commented Jan 27, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Member

@Hoya324 Hoya324 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

연휴인데 너무너무 수고하셨습니다! 궁금한거 몇 가지 적어두고 가요~!!

import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 전 프로젝트에서 @ExceptionHandler(EntityNotFoundException.class) 이런식으로 각 Exception에 대한 예외 Handling을 따로 적용했던거 같은데 어떻게 생각하시는지 궁금합니다!

또한, 중요한 예외의 경우 log도 추가했었는데 저희 컨벤션에 warn 부터는 logging이 되어야한다는 부분이 있어서 이 부분도 고려해봐주시면 좋을거 같아요!
그래서 같은 맥락으로 exception의 이름도 추가하고, timestamp도 추가하면 나중에 logging 시 좋을거 같아서 의견 남겨요!

아래는 제가 생각하는 예시입니다.!!

	@ExceptionHandler(EntityNotFoundException.class)
	public ResponseEntity<ErrorResponse> handleEntityNotFoundException(EntityNotFoundException e) {
		String timestamp = getCurrentTimestamp();
		log.error(LOG_FORMAT, timestamp, e.getClass().getSimpleName(), e.getMessage());
		return ResponseEntity.status(NOT_FOUND)
			.body(ErrorResponse.of(e.getClass().getSimpleName(), NOT_FOUND.value(), e.getMessage()));
	}

Copy link
Collaborator Author

@helenason helenason Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1. @ExceptionHandler 파라미터 선언 관련

@ExceptionHandler의 파라미터가 존재하지 않아도 선언한 메서드의 파라미터를 통해 예외 타입을 지정할 수 있는데요! (스프링에서도 메서드 시그니처 파라미터를 통해서만 예외 타입을 지정하여 실수를 방지할 것을 추천하기도 합니다) 저도 마찬가지로 중복 코드를 선호하지 않아서, 파라미터만으로 예외 타입을 선언하도록 하였습니다 :) 이 내용을 기반으로 다시 한번 경호님의 의견을 여쭙습니다!

2. 로그 기준 및 로그에 담을 정보 관련

로그의 경우 컨벤션을 추후 확정하는 것으로 알고 있었어서 기존에는 추가하지 않았었는데요, 로그 관련하여서도 다양한 이야기를 해볼 수 있을 것 같아요! (추후 회의를 통해 명확한 기준을 정하는 것도 좋을 것 같습니다)

  1. 개인적으로 예측가능한 예외(ex. 400, 401, 404 등)는 warn보다는 info에 가깝다고 생각해요! 저희가 '대처'해야할 예외가 아닌 클라이언트에게 정보 전달을 위해 직접 '의도'한 예외니까요. 그래서 추후 filter나 interceptor를 통해 로그를 작성하면 되겠다고 생각하고 있었는데요. 이러한 기준과 방법에 대해 어떻게 생각하시는지 궁금합니다!
  2. timestamp의 경우는 로그가 발생할 때 아래와 같이 가장 상단에 기본으로 제공되어서 로그에 timestamp를 추가하는 것은 중복이라고 판단하여 제외시켰습니다! 이에 대한 의견도 궁금해요오
2024-10-10 20:35:23 [http-nio-8080-exec-4] INFO  c.z.c.l.config.LoggingInterceptor - LoggingInfoSuccessResponse[identifier=e472b64f-5b04-4ce4-ab08-0c96c43fdd45, httpMethod=GET, uri=/offerings, requestBody=, statusCode=200, latency=238ms]

3. 에러 응답 관련

저는 고민 끝에 아래와 같은 형태로 모든 비즈니스 예외에 대해 BlokException(커스텀 예외)를 반환하도록 하였는데요.

@ExceptionHandler
public ResponseEntity<ErrorResponse> handle(BlokException ex) {
    ErrorCode errorCode = ex.getErrorCode();
    return ResponseEntity
            .status(errorCode.getStatus())
            .body(errorCode.getResponse());
}

경호님이 위에서 제시해주신 예시를 기반으로 저의 의견을 소개드리고 싶어요!

  1. response의 body에 status를 포함하는 것은 불필요하다고 생각하였습니다. response의 status를 통해 충분히 제공되는 정보이기 때문에 body에 status를 추가로 포함하는 것은 중복이라고 생각해요!
  2. 저는 애플리케이션 단에서 예외를 한가지의 커스텀 예외(BlokException)로 발생시켰기 때문에 response의 body에 exception의 이름을 담는 것이 무의미하다고 판단하였어요! 모든 예외의 이름이 'BlokException'이기 때문에요. 또한, 클라이언트는 서버에서 발생한 예외의 이름을 알 필요가 없다고 생각하기도 하였습니다. 클라이언트에게는 이해하기 쉽게 저희가 예외를 가공하여 전달하는 게 좋은 것 같아요!

제가 고민했던 부분들을 경호님이 쏙쏙 짚어주셔서 적다보니 내용이 길어졌는데요 하하 (다음엔 PR description에 고민한 내용을 최대한 적어보겠습니닷..)

불필요한 중복을 최대한 쳐내기 위해 고민 끝에 내린 결론은, 예외를 반환할 때 헤더에 status를 포함하고, 바디에 에러메시지를 포함하자는 결론이었습니다. 하지만 반대로 중복된 정보는 오히려 정보를 얻기 수월하다는 장점이 있을 수 있겠어요. 따라서 애플리케이션 단에서 예외를 발생시킬 방법과, 클라이언트에게 전달할 예외 응답과 관련하여 저희 셋이 논의할 필요가 있어 보여요. 그에 따라 response의 형태도 달라질 것 같아요. 여러분들의 전반적인 의견이 궁금합니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

너무나 친절한 설명 감사드립니다!!
ExceptionHandler, log timestamp, status 모두 결국엔 중복에 대한 고민 결과라고 생각이 들어서 함께 의견 남겨요!
결론적으로는 채영님 의견을 들어보니 충분히 공감되는 부분이라서 그대로 진행해도 좋을거 같다고 생각했어요!

제가 저 exception을 명시하거나 timestamp, status를 과거에 왜 찍었는지 생각했을 때도 결국엔 좀더 관리 측면에서 직관적이라 편하다는 니즈가 있었던거 같아요.
그래서 이 부분은 저희가 진행하다가 필요하면 다시 고민해볼 문제가 맞고 지금은 불필요한 부분 같다는게 채영님의 의견을 듣고 난 후의 생각이었습니다!! 너무나 친절한 설명 조와요~~

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

두분께서 충분한 고민을 거쳐 의견을 정리해주셔서 너무 감사드립니다!!

추후 논의를 위한 고민해볼만한 몇 가지 포인트들 한 번 정리해봤어요.

  • 에러를 로깅하는 과정에서 중복된 데이터를 제거 및 꼭 필요한 데이터만 첨부

    • 제거했을 때, 응답 사이즈의 차이가 서비스에 어느정도의 영향을 주는지
    • 프론트에서 API 연동 작업을 진행할 때 불편함이 발생하지는 않을지
    • 에러 로깅의 목적 ⇒ 가볍고 중복을 방지하기는 것 보단 최대한 상세한 정보를 담고, 백/프론트 양쪽에서 이슈 트래킹을 원할하도록
  • Response Status 에만 상태값을 의지

    • 일부 프론트엔드 프레임워크에서 응답 처리 중 HTTP 상태가 손실되는 케이스 존재
  • 공통 에러 클래스를 완벽하게 통일

// 기본 에러 응답
{
  "message": "잘못된 요청 파라미터",
  "timestamp": "2025-02-03T10:30:45Z"
}

// 필드 유효성 검사 상세 에러
{
  "message": "유효성 검사 실패",
  "timestamp": "2025-02-03T10:30:45Z",
  "errors": [
    {
      "field": "email",
      "message": "유효한 이메일 주소여야 합니다",
      "value": "invalid.email"
    },
    {
      "field": "age",
      "message": "0보다 큰 값이어야 합니다",
      "value": "-5"
    }
  ]
}

// 서버 에러 (개발 환경용 디버그 정보 포함)
{
  "message": "내부 서버 오류",
  "timestamp": "2025-02-03T10:30:45Z",
  "error": {
    "code": "SERVER_001",
    "details": "데이터베이스 연결 실패",
    "debug": {
      "exception": "SQLException",
      "stackTrace": "...",
      "correlationId": "cor_abc123"
    }
  }
}

// 요청 제한 초과 에러
{
  "message": "너무 많은 요청",
  "timestamp": "2025-02-03T10:30:45Z",
  "error": {
    "code": "RATE_LIMIT_001",
    "details": "요청 제한 초과",
    "retryAfter": 60,
    "limit": 100,
    "current": 101
  }
}
  • 이렇듯 Exception 케이스별로 꼭 담고있어야할 정보가 상이하는 경우가 많고, 동일한 에러 내에서도 다른 필드값을 보고 프론트에서의 에러화면이 달라질 수 있어, 이러한 여러 케이스들을 어떻게 처리하면 좋을지 함께 고민해보면 좋을 것 같습니다!

Copy link
Collaborator Author

@helenason helenason Feb 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 좋은 의견 정말 감사해요!

응답이 많아지면 복잡도가 높아져 클라이언트 입장에서 오히려 읽기 불편할 것이라 생각했다가, 이전에 경호님 코멘트를 받고 변경에 아주 민감한 API응답은 DB 설계할 때와 같이 최대한 변경되지 않도록 세세한 정보를 담는 방향이 더 적절할 수 있다는 생각을 매일같이 하고 있었는데요 ㅋㅋㅋㅋ 찬기님이 주신 다른 근거들을 접하니 더더욱 그렇게 생각하게 되었습니다!! 특히 아래 부분이 인상적이었어요.

에러 로깅의 목적 ⇒ 가볍고 중복을 방지하기는 것 보단 최대한 상세한 정보를 담고, 백/프론트 양쪽에서 이슈 트래킹을 원할하도록

일부 프론트엔드 프레임워크에서 응답 처리 중 HTTP 상태가 손실되는 케이스 존재

이렇게 세세한 정보를 담도록 한다면 에러 응답뿐 아니라 공통 응답 클래스도 더더욱 필요해지겠네요. 첨부해주신 예시 참고해서 코드 수정해보겠습니다 👊


@ExceptionHandler
public ResponseEntity<ErrorResponse> handle(Exception ex) {
ErrorResponse response = new ErrorResponse("서버 관리자에게 문의하세요.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 공통이라 따로 관리하셨는지 궁금합니다!
그리고 ex.getMessage()로 예외 메시지를 받게 되는건 어떨지, 또는 ErrorCode를 Enum으로 관리해서 status와 message를 관리하는건 어떨지 의견 남겨봐요!

Copy link
Collaborator Author

@helenason helenason Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체 핸들러를 살펴보면 아래와 같은데요!

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler
    public ResponseEntity<ErrorResponse> handle(BlokException ex) {
        ErrorCode errorCode = ex.getErrorCode();
        return ResponseEntity
                .status(errorCode.getStatus())
                .body(errorCode.getResponse());
    }

    // 이곳에 다른 핸들러들이 차근차근 들어올 예정

    @ExceptionHandler
    public ResponseEntity<ErrorResponse> handle(Exception ex) {
        ErrorResponse response = new ErrorResponse("서버 관리자에게 문의하세요.");
        return ResponseEntity
                .internalServerError()
                .body(response);
    }
}

이 부분은 공통이라 따로 관리하셨는지 궁금합니다!

두 메서드 사이에 Validation 예외 등이 나중에 추가될 것이고, 위에서 걸러진 예외가 아닌 다른 모든 예외는 저희가 잡지 못한 예외로 판단하여 가장 아래 메서드인 Exception에서 잡힙니다! 그러한 예상 밖의 예외들은 500에러로 반환하도록 하였어요. 즉, 경호님이 언급주신 위 메서드는 예상치 못한 예외를 잡는 메서드를 의도했다고 봐주시면 됩니다!

그리고 ex.getMessage()로 예외 메시지를 받게 되는건 어떨지, 또는 ErrorCode를 Enum으로 관리해서 status와 message를 관리하는건 어떨지 의견 남겨봐요!

500 에러의 경우는 클라이언트 단이 아닌 서버 단에서 처리할 예외이기 때문에 클라이언트에게는 구체적인 정보를 제공하지 말아야 한다고 생각해요! 하지만 에러코드로 관리하자는 경호님의 의견에 너무나 동의하기 때문에 코드 수정해두었습니다 :)
refactor: 500 서버 에러 코드 추가

+) 또한, 이전 리뷰에서 남겨주신 로그의 warn 레벨은 위와 같은 예상치 못한 예외가 발생하였을 때 로깅하면 좋을 것 같아요! 로그를 어떻게 구성할지 다같이 상의해보고 확정된 내용 바탕으로 추가하겠습니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 저는 항상 ErrorCode를 enum으로 관리했어서 이 ErrorCode가 interface인 이유가 궁금해요!!

Copy link
Collaborator Author

@helenason helenason Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

경호님이 언급해주신, "ErrorCode를 기본 enum 클래스로 관리한다"는 것은 아마 하나의 클래스에서 모든 에러 코드를 관리하는 것으로 이해했는데요!! 제가 ErrorCode를 interface로 선언한 이유는 도메인별로 에러 코드를 분리하자는 의도였습니다!

만약, 저희 도메인이 Card, Member 로 구성되어 있다면 CardErrorCode, MemberErrorCode, (추가로 CommonErrorCode?)로 에러 코드가 분리될 수 있을 거예요! 각 에러 코드는 ErrorCode 인터페이스를 기반으로 구현하면 됩니다!

MemberErrorCode 예시

public enum MemberErrorCode implements ErrorCode {

    INVALID_MEMBER(BAD_REQUEST, "유효하지 않은 사용자입니다."),
    // ...
    ;

    private final HttpStatus status;
    private final String message;

    @Override
    public ErrorResponse getResponse() {
        return new ErrorResponse(message);
    }
}

CommonErrorCode 추가
refactor: 500 서버 에러 코드 추가

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와 그렇네요!! 이렇게 interface로 에러코드을 추상화하는거 너무 좋습니다👍👍👍

@Lim-Changi Lim-Changi added the ✨ Feature 기능 추가 구현 label Feb 1, 2025
@Lim-Changi
Copy link
Member

너무 고생많으셨습니다!!
글로벌 응답 클래스는 이해하신 것 처럼 작업해주시면 될 것 같아요:)

사실 아직 API 가 없어서 완벽하게 Global Response 및 Error 핸들러를 구현하고 테스트해보기 어려울 것 같다는 생각이 드네요ㅠ
일단은 기본적인 부분만 작업해두고, API 에서 저희가 활용해보며 필요한 부분들을 개선해나가는 방향으로 추가 디벨롭이 이루어져도 괜찮을 것 같아요!

이후에 저희 코드상에서 어떻게 쓰이는지 예시도 추가로 만들어 주시면 감사드리겠습니다!!

추가로 Error Response 에 저희가 쓰는 Custom Code 가 있으면 좋을 것 같아요!
⇒ 프론트와 공유하여 에러 상황에 맞는 화면을 더 편하게 구분짓는 목적

Copy link
Member

@Hoya324 Hoya324 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨어요!!

@helenason
Copy link
Collaborator Author

helenason commented Feb 2, 2025

@Lim-Changi

  1. 노션 페이지에 커스텀 예외 사용 방법 공유해두었습니다! 더 보완할 부분 있으면 말씀해주세요!!

  2. 네 좋습니다! 찬기님 의견 반영하여 enum 클래스에서 정의한 이름을 code로 삽입하도록 구현하였습니다!
    feat: 에러 응답에 code 필드를 포함하도록 변경

@helenason
Copy link
Collaborator Author

helenason commented Feb 6, 2025

@Lim-Changi @Hoya324

변경사항

  1. 여러 의견 반영하여 최종적으로 공통 성공 응답과 공통 에러 응답을 정의하였습니다. (아래 기술)
  2. 기존 GlobalExceptionHandlerController에서 불필요하게 반복되던 ResponseEntity 구현 로직을 제거하기 위해 GlobalResponseHandler를 추가하였습니다.

공통 성공 응답

{
    "status": "CREATED",
    "message": "요청이 성공적으로 처리되었습니다.",
    "timestamp": "2025-02-07T02:20:33.315583",
    "data": {
        "test1": 1,
        "test2": 2,
        "test3": 3
    }
}

관련 클래스: SuccessResponse

컨트롤러에서 SuccessResponse를 반환하면 GlobalResponseHandler가 status와 body를 처리해줍니다.

공통 에러 응답

{
    "status": "BAD_REQUEST",
    "message": "유효하지 않은 사용자입니다.",
    "timestamp": "2025-02-07T01:45:32.235379"
}

관련 클래스: ErrorResponse

GlobalExceptionHandler에서 ErrorResponse를 반환하면 GlobalResponseHandler가 status와 body를 처리해줍니다.

유효성 검증 실패 에러 응답

{
    "errors": [
	  {
              "field": "email",
              "message": "유효한 이메일 주소여야 합니다",
              "value": "invalid.email"
	  },
	  {
              "field": "age",
              "message": "0보다 큰 값이어야 합니다",
              "value": "-5"
	  }
    ],
    "status": "BAD_REQUEST",
    "message": "유효하지 않은 요청값입니다.",
    "timestamp": "2025-02-07T01:46:01.139924",
}

관련 클래스: ValidationErrorResponse

서버 에러 응답

{
    "error": {
        "exception": "NullPointerException",
        "message": "Cannot invoke \"com.evenly.blok.domain.test.controller.TestDto.getTest1()\" because \"test\" is null",
        "stackTrace": "com.evenly.blok.domain.test.controller.TestController"
    },
    "status": "INTERNAL_SERVER_ERROR",
    "message": "서버 관리자에게 문의하세요.",
    "timestamp": "2025-02-07T01:51:00.403302"
}

관련 클래스: ServerErrorResponse


더 자세한 내용은 노션에 정리해두었습니다! 추가로 보완할 사항 있으면 편하게 말씀해주세요!

@Hoya324
Copy link
Member

Hoya324 commented Feb 7, 2025

너무너무 수고하셨습니다👍👍☺️
고민한 흔적이 많이 있는 작업이었네요!!
저는 친절하게 설명해주신 덕에 더 남길 의견은 없습니다!

@Lim-Changi
Copy link
Member

고생하셨어요!! PR 머지해주시면 될 것 같아요 감사합니다:)

@helenason helenason merged commit c76d43f into feat/2-initial-setup Feb 8, 2025
1 check passed
@helenason helenason deleted the feat/2-global-class branch February 8, 2025 03:08
Lim-Changi added a commit that referenced this pull request Feb 18, 2025
* feat: ✨initial setup

* [Feat] test container 환경 적용 (#3)

* chore: TestContainers 의존성 추가

* chore: Testcontainers MySQL 데이터소스 및 Hibernate 설정 추가

* chore: MySQL Testcontainer 설정 추가

* test: 테스트 환경용 @activeprofiles("test") 추가

* test: 테스트 전용 SpringApplication 구성 및 TestcontainersConfig 추가

* chore: test 환경 ddl-auto 수정

* chore: EOL 추가

* [Feat] security config 설정 (#6)

* chore: Spring Security 의존성 추가

* chore: Spring Security 설정 init

* chore: Spring Security 설정 수정

불필요한 swagger 설정 제거 및 default filter 위치 수정

* chore: private 메서드 코드 컨벤션 적용

* chore: HealthCheck 라우터 추가

* chore: 불필요한 swagger security 제거

* [Feat] DB 세팅 및 배포 플로우 자동화 기본 작업 (#5)

* feat: resource 환경변수 .env 활용 & DB RDS MySQL Datasource JPA & Docker 컨테이너화 및 로컬 빌드 테스트용 compose 파일 생성

* feat: Dev 이미지 빌드 및 ECR 업로드 후, EC2 자동 배포 GitAction 플로우 생성

* test: GitAction 배포 테스트

* feat: Devlopment 자동배포 workflow 테스트 완료

* fix: EOL (맨 밑 개행) 추가안된 파일 수정

* [Feat] swagger config setup (#8)

* chore: Swagger 의존성 추가

* chore: Swagger 설정 init

* feat: 현재 Spring Profile을 반환하는 유틸리티

* feat: 환경 상수 정의 추가

* feat: URL 상수 정의 추가

* chore: 환경별 Swagger 설정

* feat: 헬스 체크 API 문서화 적용

* feat: 헬스 체크 API 추가

* refac: 첫줄 공백 추가

(컨벤션)

* chore: private 메서드 코드 컨벤션 적용 및 EOL 추가

* chore: 프로필 상태 util 클래스명 변경

SpringEnvironmentUtil -> ProfileResolver

* chore: JWT Authorization Bearer 추가

* refac: EnvironmentConstants enum 제거

* [Feat] 전역적 예외 및 핸들러 추가 (#4)

* feat: 전역적 예외 및 핸들러 추가

* refactor: 500 서버 에러 코드 추가

* feat: 에러 응답에 code 필드를 포함하도록 변경

* feat: ErrorResponse 필드 보완 및 유효성 검사 실패 에러 응답 추가

* feat: 공통 성공 응답 클래스 정의

* refactor: 예외 및 성공 응답 반환 공통 로직 추출

* feat: 서버 에러 응답 구체화

* feat: 성공 응답시 다양한 status 응답할 수 있도록 변경

* feat: 유효성 예외 발생 시 상태코드 400 반환

* feat: 유효하지 않은 API 경로 예외 핸들러 추가

* [Feat] 테스트 통합 환경 구축 (#9)

* chore: Testcontainers의 JDBC URL 인식 설정

* refac: test 환경 변수 추가

* test: 테스트 통합 환경 구축

* test: Health Check 통합 테스트 추가

* refac: EOL 해결

* chore: datasource 관련 설정들을 모두 제거

TestcontainersConfig 파일 기준의 이미지로 Test 환경을 구축을 위함

* chore: amd64 호환성 경고 해결

* chore: application dev 파일 수정

* chore: dialect 중복 제거

* fix: test시 swagger config 오류 해결

* chore: IntegrationTest와 ControllerTest 분리

IntegrationTest -> RestAssured
ControllerTest -> MockMVC

* test: HealthCheck IntegrationTest, ControllerTest

* refac: EOL 해결

* [Feat] Private RDS 로컬 EC2 인스턴스 터널링 작업 (#10)

* feat: 로컬 환경에서 Private RDS 터널링 셋업

* chore: 불필요한 annotation 제거 및 변수명 수정

* [Refactor] 프로젝트명 변경 (#11)

* refactor: 프로젝트명 변경 및 코드 스타일 통일

* docs: README 프로젝트명 변경

* refactor: 불필요한 설정 필드 제거

* refactor: 머지된 클래스에 대해 프로젝트명 변경

* refactor: 불필요한 설정 필드 제거

* [Feat] GitAction CI workflow 구현 (#13)

* test: ci gitaction workflow

* test: use v4 artifact

* feat: gitaction 자동 CI flow 구현

* feat: CODEOWNERS 추가

* refactor: @ignore -> @disabled

junit5에서 @ignore이 deprecated 되었으므로 변경

* chore: PR 크기 라벨링 전체PR 작업 기준으로 작동하도록 변경

---------

Co-authored-by: 나경호 <[email protected]>
Co-authored-by: SCY <[email protected]>
Lim-Changi added a commit that referenced this pull request Apr 1, 2025
* docs: 이슈 템플릿 설정

* chore: PR 크기 자동 라벨링 workflow

* [Feat] 초기 세팅 작업 완료 (#14)

* feat: ✨initial setup

* [Feat] test container 환경 적용 (#3)

* chore: TestContainers 의존성 추가

* chore: Testcontainers MySQL 데이터소스 및 Hibernate 설정 추가

* chore: MySQL Testcontainer 설정 추가

* test: 테스트 환경용 @activeprofiles("test") 추가

* test: 테스트 전용 SpringApplication 구성 및 TestcontainersConfig 추가

* chore: test 환경 ddl-auto 수정

* chore: EOL 추가

* [Feat] security config 설정 (#6)

* chore: Spring Security 의존성 추가

* chore: Spring Security 설정 init

* chore: Spring Security 설정 수정

불필요한 swagger 설정 제거 및 default filter 위치 수정

* chore: private 메서드 코드 컨벤션 적용

* chore: HealthCheck 라우터 추가

* chore: 불필요한 swagger security 제거

* [Feat] DB 세팅 및 배포 플로우 자동화 기본 작업 (#5)

* feat: resource 환경변수 .env 활용 & DB RDS MySQL Datasource JPA & Docker 컨테이너화 및 로컬 빌드 테스트용 compose 파일 생성

* feat: Dev 이미지 빌드 및 ECR 업로드 후, EC2 자동 배포 GitAction 플로우 생성

* test: GitAction 배포 테스트

* feat: Devlopment 자동배포 workflow 테스트 완료

* fix: EOL (맨 밑 개행) 추가안된 파일 수정

* [Feat] swagger config setup (#8)

* chore: Swagger 의존성 추가

* chore: Swagger 설정 init

* feat: 현재 Spring Profile을 반환하는 유틸리티

* feat: 환경 상수 정의 추가

* feat: URL 상수 정의 추가

* chore: 환경별 Swagger 설정

* feat: 헬스 체크 API 문서화 적용

* feat: 헬스 체크 API 추가

* refac: 첫줄 공백 추가

(컨벤션)

* chore: private 메서드 코드 컨벤션 적용 및 EOL 추가

* chore: 프로필 상태 util 클래스명 변경

SpringEnvironmentUtil -> ProfileResolver

* chore: JWT Authorization Bearer 추가

* refac: EnvironmentConstants enum 제거

* [Feat] 전역적 예외 및 핸들러 추가 (#4)

* feat: 전역적 예외 및 핸들러 추가

* refactor: 500 서버 에러 코드 추가

* feat: 에러 응답에 code 필드를 포함하도록 변경

* feat: ErrorResponse 필드 보완 및 유효성 검사 실패 에러 응답 추가

* feat: 공통 성공 응답 클래스 정의

* refactor: 예외 및 성공 응답 반환 공통 로직 추출

* feat: 서버 에러 응답 구체화

* feat: 성공 응답시 다양한 status 응답할 수 있도록 변경

* feat: 유효성 예외 발생 시 상태코드 400 반환

* feat: 유효하지 않은 API 경로 예외 핸들러 추가

* [Feat] 테스트 통합 환경 구축 (#9)

* chore: Testcontainers의 JDBC URL 인식 설정

* refac: test 환경 변수 추가

* test: 테스트 통합 환경 구축

* test: Health Check 통합 테스트 추가

* refac: EOL 해결

* chore: datasource 관련 설정들을 모두 제거

TestcontainersConfig 파일 기준의 이미지로 Test 환경을 구축을 위함

* chore: amd64 호환성 경고 해결

* chore: application dev 파일 수정

* chore: dialect 중복 제거

* fix: test시 swagger config 오류 해결

* chore: IntegrationTest와 ControllerTest 분리

IntegrationTest -> RestAssured
ControllerTest -> MockMVC

* test: HealthCheck IntegrationTest, ControllerTest

* refac: EOL 해결

* [Feat] Private RDS 로컬 EC2 인스턴스 터널링 작업 (#10)

* feat: 로컬 환경에서 Private RDS 터널링 셋업

* chore: 불필요한 annotation 제거 및 변수명 수정

* [Refactor] 프로젝트명 변경 (#11)

* refactor: 프로젝트명 변경 및 코드 스타일 통일

* docs: README 프로젝트명 변경

* refactor: 불필요한 설정 필드 제거

* refactor: 머지된 클래스에 대해 프로젝트명 변경

* refactor: 불필요한 설정 필드 제거

* [Feat] GitAction CI workflow 구현 (#13)

* test: ci gitaction workflow

* test: use v4 artifact

* feat: gitaction 자동 CI flow 구현

* feat: CODEOWNERS 추가

* refactor: @ignore -> @disabled

junit5에서 @ignore이 deprecated 되었으므로 변경

* chore: PR 크기 라벨링 전체PR 작업 기준으로 작동하도록 변경

---------

Co-authored-by: 나경호 <[email protected]>
Co-authored-by: SCY <[email protected]>

* [Fix] Swagger 환경별 url 설정 수정 (#16)

* fix: swagger 환경별 url 설정방법 변경

* chore: swagger 환경별 url 설정

junit5에서 @ignore이 deprecated 되었으므로 변경

* chore: 환경별 url 설정법 변경으로 인한 test 환경 설정 수정

junit5에서 @ignore이 deprecated 되었으므로 변경

* [Feat] PR 플로우 개선 작업 (#19)

* chore: PR 크기 라벨링 워크플로우 수정 & 코드래빗 설정 YAML 파일 추가

* fix: EOL (맨 밑 개행) 추가안된 파일 수정

* fix: 잘못들어간 문자 제거

* [Feat] OAuth 및 JWT 인증 기능 구현 및 Composite 패턴 적용 (#20)

* feat: OAuth 인가 코드 요청 기능 구현

* feat: OAuth 타입 관련 예외 처리 추가

* feat: OAuth 인증 후 사용자 정보를 조회하는 UserClient 인터페이스 및 Composite 구현

* feat: JWT 발급 및 validation 기능 추가

* feat: JWT 발급 및 validation filter

* feat: OAuth 인증 처리 및 JWT 토큰 발급 service

* feat: OAuth 컨트롤러 추가

- OAuth 인가 요청 URL 리다이렉트 API 추가
- OAuth 로그인 후 JWT 발급 API 추가
- API 문서화를 위한 Swagger 설정 포함

* feat: User/OAuth 관련 domain 추가

* feat: User Repository 추가

* chore: RestClient 설정

* chore: jwt 변수 properties 및 의존성 추가

* feat: jwt 예외코드 및 response dto 추가

* feat: 공통 time entity 추가

* chore: Jpa Auditing 설정

* chore: jwt properties 설정 방식 변경

* test: AuthCode Request Url Provider Composite 동작 test

* test: access token 생성/validate test

* test: User Client Composite 동작 Test

* test: 공통 Mock User Factory 추가

* chore: oauth controller swagger 적용 및 security path 추가

* [Feat] PR 플로우 개선 작업 (#19)

* chore: PR 크기 라벨링 워크플로우 수정 & 코드래빗 설정 YAML 파일 추가

* fix: EOL (맨 밑 개행) 추가안된 파일 수정

* fix: 잘못들어간 문자 제거

* feat: OAuth 인가 코드 요청 기능 구현

* feat: OAuth 타입 관련 예외 처리 추가

* feat: OAuth 인증 후 사용자 정보를 조회하는 UserClient 인터페이스 및 Composite 구현

* feat: JWT 발급 및 validation 기능 추가

* feat: JWT 발급 및 validation filter

* feat: OAuth 인증 처리 및 JWT 토큰 발급 service

* feat: OAuth 컨트롤러 추가

- OAuth 인가 요청 URL 리다이렉트 API 추가
- OAuth 로그인 후 JWT 발급 API 추가
- API 문서화를 위한 Swagger 설정 포함

* feat: User/OAuth 관련 domain 추가

* feat: User Repository 추가

* chore: RestClient 설정

* chore: jwt 변수 properties 및 의존성 추가

* feat: jwt 예외코드 및 response dto 추가

* feat: 공통 time entity 추가

* chore: Jpa Auditing 설정

* chore: jwt properties 설정 방식 변경

* test: AuthCode Request Url Provider Composite 동작 test

* test: access token 생성/validate test

* test: User Client Composite 동작 Test

* test: 공통 Mock User Factory 추가

* chore: oauth controller swagger 적용 및 security path 추가

* refac: nullable=false -> @NotNull

* refac: 불필요 컬럼 제거

* refac: OAuthId -> OAuthIdentifier

* refac: mapp -> 불변 mapp

* refac: jwt 불필요한 반환 제거

* refac: jwt accessToken 변수 추출

* refac: jwt 유효성 검증에 예외처리 추가

* test: jwt 유효성 검증 예외처리 테스트

* rename: mock -> stub으로 네이밍 변경

* refac: jwt 예외 추가

* refac: 토큰 응답 방식 변경

---------

Co-authored-by: 찬기 <[email protected]>

* refac: 폴더 구조 변경 (#22)

* [Feat] Redis 환경 구성 및 테스트 플로우 구축 (#23)

* feat: Redis Lettuce Client 세팅 및 RedisService 구현 & Docker Compose Redis 연동 실행환경 구성

* feat: Redis TestContainer 가상 환경 테스트 환경 구성

* refac: Docker Build 시, test 결과 무시 & 로컬에서 .env 통해 개별적으로 Redis 환경 구축

* fix: Convention 적용 & 테스트 코드 형식 통일

* [Feat] refresh token으로 로그인 상태 유지 (#24)

* feat: 로그인 시 refresh token 발급 및 헤더에 응답

* feat: 매 요청에서 token 검증 및 재발급

* test: OAuthService 로그인 로직

* refac: refresh token 만료 환경 변수 추출

* test: UuidTokenProvider 클래스

* fix: 인증 로직 통합 테스트하면서 잘못된 로직 수정

* refac: 인증 필터 이름 변경

* test: mock user 추출

* test: ServiceTest 추출

* refac: 패키지 구조 기존 구조랑 통일

* refac: 스웨거 문서 수정

* refac: 불필요한 생성자 제거

* refac: 레디스 데이터 초기화 메서드 테스트로 이동

* refac: 로그인 시 응답 토큰 위치 헤더 -> 바디

* refac: oauth url API 응답 형식 통일

* test: 응답 형태 변경에 따른 테스트 코드 수정

* feat: 응답 DTO 스웨거 설명 추가

* refac: 공통 응답 클래스 data 필드 타입 변경 Object -> 제네릭

* refac: refresh token 발급 방식 변경

- 기존: AT 만료 시 함께 보낸 RT로 갱신
- 수정: AT 만료 시 /refresh API를 통해 갱신

* refac: 서비스 계층의 책임 분리를 위해 TokenProvider 추가

* refac: Auth 에러 코드 통합 및 static import 제거

* refac: 커밋 7ad1105 보완

* refac: filter 에러 응답 형태 통일

* refac: 인증 도메인 용어 통일 oauth -> auth

* refac: 패키지 위치 통일

- 기존: global > exception > [feature]
- 개선: [feature] > exception

* refac: 불필요한 커스텀 예외 제거

- 기존: 여러개의 커스텀 예외 사용
- 개선: 하나의 커스텀 예외 사용

* refac: 인증 관련 클래스 auth feature 패키지로 이동

* docs: 스웨거 문서 정리

* refac: 인증 필터에서 상황에 따른 예외 반환

* refac: login API HTTP method GET -> POST

* [Feat] 카카오 로그인 구현 (#31)

* chore: 각 서버 환경별 변수 보완

* refac: 토큰 프로퍼티 네이밍 수정

* feat: 카카오 인증 코드 발급 경로 제공

* feat: 요청 파라미터가 유효하지 않은 경우 400 예외 반환

* feat: 카카오 토큰 발급 및 사용자 정보 조회

* refac: 커스텀 예외 메시지 추가

* refac: client > kakao 패키지 추가 및 관련 클래스 이동

* refac: 각 카카오 외부 API 접근 클래스 책임 분리

* refac: EnableConfigurationProperties Config 클래스로 이동

* feat: 해당 요청을 수행하는 핸들러가 없을 때 400 예외 반환

* refac: 유효하지 않은 카카오 인증 코드 예외 메시지 수정

* refac: 올바른 예외를 반환하도록 수정

* refac: mock server 초기화 로직 위치 변경

* refac: response body 재사용 가능하도록

* feat: 카카오 인증 코드 유효하지 않을 경우 반환 상태 코드 변경

* refac: client > kakao 하위 패키지 통일

* chore: dev 및 prod 서버 환경변수 업데이트

* refac: 카카오 리프레시 토큰 유효기간 응답 타입 올바르게 수정

* feat: 응답 바디 형식에 따른 예외 처리

* [Feat] 구글 로그인 구현 (#27)

* chore: dev, prod 환경 env 변수명 갱신

* refac: auth token properties 폴더 구조 및 네이밍 변경

* feat: 구글 인증 코드 요청 Provider

* feat: 구글 유저 조회 client

* feat: 구글 oauth 예외코드 추가

* chore: 구글 oauth env 설정

* chore: CORS origin url pattern 을 통한 유연성 추가

원활한 작업을 위한 임시 추가이므로 추후에 변경되어야함

* refac: Google client 에서 token 발급과 정보 조회 분리

* feat: token 발급과 정보 조회 dto 추가

* feat: 예외 handler 추가 및 예러 코드 추가

* test: google 소셜 로그인 mock test

* test: 구글 provider test 공통 Mock 클래스 추가

* refac: 애매한 예외 변수명 변경

* refac: 예외 메시지를 테스트에서 검증을 위한 수정

* test: 예외 발생 시점 수정

* refac: 환경변수 properties 공통 적용 방식으로 수정

* refac: 토큰 요청 시 request dto 추가

* refac: 폴더 구조 변경

* [Feat] 애플 로그인 구현 (#33)

* feat: Apple 로그인 구현 및 디버깅 완료

* feat: Apple 로그인 테스트 코드 작성

* fix: 간단한 PR 이슈 수정

* fix: ErrorHandler InputStream 객체 중복사용 제거

* fix: 테스트 코드 conflict 해결

* [Refactor] 환경변수 개선 및 프로퍼티 관련 패키지 이동 (#35)

* refac: 환경별 공통으로 사용되는 환경변수 추출

* refac: 인증 피처 프로퍼티 클래스 위치 이동

* refac: `@ConfigurationPropertiesScan`으로 감지하고 있으므로 프로퍼티를 빈으로 등록하는 클래스 제거

* refac: spring.datasource.url 베이스 데이터 수정

* fix: 클래스별 restClient 분리를 위해 restClientBuilder 빈 복사 후 빌드 (#37)

* [Feat] 소셜 로그인 정보 추가 (#41)

* feat: 사용자 엔티티에 이메일 필드 추가

* feat: 카카오 소셜 로그인 시 사용자 이름 및 이메일 정보 가져오기

* feat: 애플 소셜 로그인 시 사용자 이름 및 이메일 정보 가져오기

* feat: 구글 소셜 로그인 시 사용자 이름 및 이메일 정보 가져오기

* [Feat] S3 서비스 구현

feat: S3 서비스 구현 및 테스트 케이스 작성 (#42)

* [Docs] 명함 Swagger Open API (#43)

* docs: 명함 Swagger Open API init

* feat: 썸네일 명함에 대표로 보여줄 정보 타입

* docs: 내 명함 목록 조회 api

* feat: 내 명함 목록 조회 dto 추가

* docs: 링크 스크랩 및 직군 조회 스웨거 API 추가

* docs: 직군 조회 응답에 id 추가

* feat: SnsType 추가

* feat: SnsType 추가

* docs: 스크랩 대상 타입 String -> LinkType

* docs: 명함 추가 API docs

* docs: 특정 명함의 모든 상세 정보를 조회 swagger api 추가

* feat: 특정 명함의 모든 상세 정보를 조회 dto 추가

* refac: 직군 클래스명 CardJob -> Job

* docs: Swagger 명세 Mapping URL 제거 & 기본 created Response 추가

* fix: conflict 해결

* feat: 쿼리 파라미터 없는 경우 예외 처리

* refac: LinkType 이넘 형식 통일

* refac: Job Type 추가

* feat: MultiPart Request Object 변환 Converter 구현 및 명함 추가 API docs

* feat: MultiPart Request Object 변환 Converter 구현 및 명함 추가 API docs

* docs: swagger 불필요한 어노테이션 제거

* fix: EOL 추가

---------

Co-authored-by: SCY <[email protected]>
Co-authored-by: 찬기 <[email protected]>

* [Feat] 명함에 필요한 Entity 추가 (#47)

* chore: swagger Authorization header 설정 추가

* feat: Card Entity 추가

* feat: Career Entity 추가

* feat: User Entity Column 추가

* feat: Not Null 조건 추가

* refac: 불필요한 생성자 제거

* refac: 정적팩토리 위치 변경 vo -> dto

* [Deploy] nginx 무중단 배포 작업 완료 (#48)

* [Feat] 사용자 정보를 컨트롤러 메서드에 주입하는 LoginUserArgumentResolver 구현 (#51)

* feat: 사용자 정보를 컨트롤러 메서드에 주입하는 LoginUserArgumentResolver 구현

* feat: 사용자 정보를 컨트롤러 메서드에 주입하는 LoginUserArgumentResolver 구현

* refac: EOL 추가

* [Feat] 블로그 및 프로젝트 페이지 크롤링 (#52)

* feat: 블로그 및 프로젝트 페이지 크롤링

* refac: 빈 문자열 상수화

* feat: og 링크 필드명 수정

* [Feat] 명함 커리어 전체 조회 API (#54)

* feat: 전체 커리어 조회 API

* refac: 합의된 메서드 네이밍 컨벤션 적용

* refac: 엔티티와 DTO 간 변환 로직 MapStruct 활용

* feat: Career 클래스에서 BaseTimeEntity 제거 및 컬럼명 케이스 통일

* test: 테스트 컨테이너 생성 후 career 데이터 추가

* test: 데이터베이스 초기화 시 테스트간 간섭 제거

* [Feat] 현재 로그인한 사용자가 소유한 모든 명함 목록을 조회 API (#55)

* feat: 현재 로그인한 사용자가 소유한 모든 명함 목록을 조회 API

* chore: MapStruct 설정

* refac: 불필요한 메서드 제거

* test: CardMapper Test

* feat: Card Test용 Factory 추가

* test: IntegrationTest에서 JWT filter mocking

* chore: Card Test용 Factory 수정

* test: 내 명함 목록 integrationTest 추가

* test: Jwt Mocking 용 integrationTest

* test: 테스크명 수정

* feat: merge [Feat] 명함 커리어 전체 조회 API

* refac: MapStruct MyCardListResponse 반환 Mapper 추가

* [Feat] 특정 명함의 모든 상세 정보를 조회  (#57)

* feat: 특정 명함의 모든 상세 정보를 조회 API

* test: 특정 명함의 모든 상세 정보를 조회 test

* refac: Service Layer 메서드명 컨벤션 적용

* test: 테스크명 수정

* feat: request dto valid 추가

* test: 오류 수정

* refac: MapStruct mapper 사용

* refac: LazyLoading으로 인한 Transaction 추가

* [Feat] Docker 배포 환경 KST 적용 #60

* [Feat] 명함 추가 API 구현 (#53)

* fix: header 불필요 보안 체크 제거

* feat: 명함 생성 API 구현

* feat: 필드 유효성 검증 로직 추가 & 테스트 케이스 작성

* fix: controller, service 네이밍 컨벤션

* fix: develop 브랜치 파일 이동 반영

* fix: 테스트 코드 conflict 해결

* fix: PR Comment 반영

* [Feat] 링크 스크랩 API 연결 및 크롤러 기능 보완 (#58)

* feat: 링크 스크랩 API 연결

* feat: API 요청 형식 변경 및 MapStruct 도입

* feat: 네이버 블로그 크롤러 추가

* refac: 크롤러 코드 형식 통일

* refac: 링크의 호스트 서버에서 파싱하도록 수정

* feat: 비핸스 크롤링 로직 구현

* chore: WebDriverManager 버전 업그레이드

* refac: WebDriver 빈 등록 제거

* refac: toResponse 메서드명 구체화

* test: 실행시간 측정 로직 추가

* test: careers 초기 데이터 삽입 방식 변경 및 데이터 Fixture 도입

* test: 통합테스트에서 모킹 제거

* refac: 크롤러 예외 처리 책임 이동

* feat: 서버에서 동작하도록 크롬 드라이버 추가

* chore: Dockerfile 명령어 위치 수정

* docs: 스웨거 쿼리 파라미터 요청 형태 JSON -> 개별 필드

* [Fix] Docker chrome driver 위치 설정 변경 (#61)

* fix: docker chrome driver 위치 설정 변경

* fix: downgrade chrome browser version

* fix: Multipart String Request 데이터 Converter 예외 케이스 처리 추가

* [Fix] 동적 크롤링 시 서버 메모리 부족 문제 해결 (#64)

* refac: 웹 드라이버 관리 클래스 이름 변경

* fix: 서버에서 /dev/shm 공간 사용하지 않도록 옵션 추가

* chore: 서버 테스트를 위한 스크립트 트리거 변경

* fix: disable dev shm 옵션 제거

* fix: 크롬 드라이버 버전 설정 코드 제거

* chore: 크롬 드라이버 설치 로직 제거

* chore: 크롬 브라우저 설치 로직 추가

* feat: 크롬 드라이버 설치 시 캐싱 활용하여 속도 개선

* feat: 크롬 드라이버 설치 시 캐싱 활용하지 않도록

* chore: 크롬 브라우저 경로 지정

* chore: 크롬 브라우저 종류 변경

* chore: 크롬 브라우저 종류 변경

* chore: 현 브랜치 코드로 재배포

* chore: 캐시 제거 및 최신 chromium 설치

* chore: 캐시 제거 및 최신 chromium 설치

* chore: chromium 대신 google chrome 설치

* chore: wget 의존성 추가

* chore: 크롬 브라우저 경로 변경

* refac: resolutionCache 재적용

* refac: binary path 옵션 제거

* refac: driver cache 재적용

* refac: WebDriverManager 의존성 제거

* WebDriverManager 없이 Selenium의 최신 버전에서 제공하는 SeleniumManager 활용하도록

* chore: CI/CD 스크립트 원상복구

* chore: 명함생성 제한 임시 해제(프론트 작업 편의 목적)

* [Feat] FCM 푸시알림 초기 설계 (#66)

* feat: FCM 푸시알림 초기 설계

* feat: FCM 서버 연결 후 테스트 환경에서의 외부 의존 제거 및 import 정리

* [Fix] FCM 키 파일 읽기 방식 변경 (#70)

* fix: 배포 환경에서 JSON 인식 불가하여 경로 기반 관리로 변경

* chore: 배포 환경에서의 테스트를 위한 트리거 변경

* refac: 리소스 파일이 아닌 파일 시스템 경로 직접 사용

* chore: CI/CD 트리거 원상복구

* [Test] 테스트 데이터 삽입 환경 개선 (#73)

* refac: UserFixture 및 UserFactory 도입

* refac: CardFixture 및 CardFactory 도입 (+ Career)

* refac: 메서드명과 필드명 통일

* [Feat] 폴더 기본 CRUD API 추가 (#72)

* fix: 크롤링 API 더미데이터 응답하도록

* [Fix] 애플 인증키 파일 경로 관리되도록 수정 (#79)

* fix: 애플 인증키 파일 경로 관리되도록 수정

* fix: 테스트 케이스 파일 읽어오도록 mocking 수정 & 인증키 파싱 로직 수정

* [Feat] 명함 공유 및 폴더 설정 CRUD 기능 작업 (#75)

* feat: 폴더 기본 CRUD API 추가

* feat: 명함 공유 API 명세 작업 & 외부 공유용 명함 정보 조회 API 작업 완료

* feat: 명함 공유 CRUD & 명함 폴더설정 API 작업 완료

* fix: Swagger Description 수정

* feat: 명함&폴더 테스트 케이스 Base Factory Fixture 클래스 생성

* [Feat] 로그아웃 및 회원탈퇴 기능 구현 (#77)

* feat: 폴더 기본 CRUD API 추가

* feat: 명함 공유 API 명세 작업 & 외부 공유용 명함 정보 조회 API 작업 완료

* feat: 명함 공유 CRUD & 명함 폴더설정 API 작업 완료

* feat: auth logout 기능 추가

* feat: auth 회원탈퇴 기능 추가

* test: 로그인, 회원탈퇴 test

* fix: Swagger Description 수정

* fix: Auth Swagger Security 수정

* feat: 명함&폴더 테스트 케이스 Base Factory Fixture 클래스 생성

* fix: WithdrawService에서 같은 레벨의 의존성을 갖도록 수정

* fix: 화이트리스트 annotation 추가

* test: 회원탈퇴, 로그아웃 테스트 추가

---------

Co-authored-by: 찬기 <[email protected]>

* [Feat] 카카오 로그인 보안 강화 작업 (#82)

* feat: 회원탈퇴 시 OAuth 정보 삭제

* feat: 카카오 소셜로그인 client secret 도입

* [Test] 공유 받은 명함 및 폴더 관리 테스트 (#86)

* feat: 폴더 기본 CRUD API 추가

* feat: 명함 공유 API 명세 작업 & 외부 공유용 명함 정보 조회 API 작업 완료

* feat: 명함 공유 CRUD & 명함 폴더설정 API 작업 완료

* fix: Swagger Description 수정

* feat: 명함&폴더 테스트 케이스 Base Factory Fixture 클래스 생성

* feat: 받은명함 CRUD 테스트 케이스 작성중

* test: 카드 통합테스트 전체적인 given절 보완

* test: fixture 생성 시 필수 필드 없을 경우 예외 처리

---------

Co-authored-by: 찬기 <[email protected]>

* feat: 크롤링 API 재활성화

* [Feat] 로깅 시스템 구축 및 IP 차단 메커니즘 구현 (#87)

* feat: IP 기반 Rate Limiting 및 차단 시스템 구현

- 초당 요청 수 기반 IP 차단 필터 추가
- 차단된 IP 데이터베이스 영구 저장 구현
- IP별 요청 카운터 메모리 캐싱 및 관리
- 차단된 IP 로깅 시스템 추가

* chore: 로깅 설정 및 환경 구성 최적화

- 로그 종류별 파일 분리 및 롤링 정책 설정
- 요청/응답, 차단 IP 로그 전용 어펜더 구성
- IP 차단 관련 설정 값 application.yml에 추가
- 로그 보관 기간 및 용량 제한 설정

* feat: 개인정보 민감 API 로깅 제어 어노테이션 구현

- PrivacySensitiveLogging 어노테이션 정의
- 컨트롤러/메서드 수준의 로깅 제어 기능 추가
- 개인정보가 포함된 API에 어노테이션 적용
- 요청/응답 본문의 선택적 로깅 기능 구현

* feat: 로깅 기본 인프라 구축

* feat: 요청 응답 logging 설정

* test: 블랙리스트 test

* fix: auth api에 @PrivacySensitiveLogging 추가

* test: 필요한 경우만 테스트를 실행하도록 변경

* fix: logs 경로 절대 경로로 변경

* feat: FCM 서버 연결 주석 처리

* chore: 람다 관련 임시 주석처리

* [Deploy] 프로덕션 배포 환경 구축 (#84)

* test: 프로덕션 배포 테스트

* deploy: 프로덕션 배포 환경 구축 완료

---------

Co-authored-by: 나경호 <[email protected]>
Co-authored-by: SCY <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ Feature 기능 추가 구현
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants