Skip to content

Conversation

@Kimminu7
Copy link
Collaborator

@Kimminu7 Kimminu7 commented Jun 25, 2025


작업 내용

  • 문제 등록시 문제 이미지 추가 ( S3 )
  • prefix로 Enum으로 문제이미지면 problem, 프로필 이미지면 profile로 설정
  • 문제 이미지 예외처리 ( jpg, jpeg, png 등 이미지 파일만 업로드 가능 )
  • ProblemImage 엔티티 삭제 > Problem 컬럼(imageUrl)으로 관리 -> @ElementCollection 사용
  • Problem 컬럼 ( 총 제출 횟수, 성공한 제출 횟수 ) 추가

변경 사항


트러블 슈팅


해결해야 할 문제

  • 수정과 삭제는 아직 되지 않음
  • 이게 확실한 이미지 파일인지 검증할 로직 필요.

참고 사항

  • ⭐ postman에서만 사용 가능
    image

  • Swagger에서는 request를 json, image를 form data로 따로따로 지원해주지 않음.

  • 그래서, 한다고해도 record 클래스 방식을 다 뜯어 고쳐나가야 하기 해서, postman으로 해야함.


코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

Summary by CodeRabbit

  • 신규 기능

    • 문제 생성 시 이미지 파일 업로드 기능이 추가되었습니다.
    • 문제에 여러 이미지 URL과 제출 통계(총 제출 수, 정답 제출 수) 필드가 추가되었습니다.
    • AWS S3와 연동하여 이미지 파일을 저장하고 관리할 수 있습니다.
  • 버그 수정

    • 문제 이미지와 관련된 불필요한 엔티티 및 저장소가 제거되었습니다.
  • 환경설정

    • AWS S3 연동을 위한 설정 및 의존성이 추가되었습니다.

Kimminu7 added 27 commits June 22, 2025 06:42
@Kimminu7 Kimminu7 requested review from pokerbearkr and thezz9 June 25, 2025 04:16
@Kimminu7 Kimminu7 self-assigned this Jun 25, 2025
@Kimminu7 Kimminu7 added the enhancement New feature or request label Jun 25, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 25, 2025

"""

Walkthrough

이 변경사항은 AWS S3를 이용한 이미지 업로드 기능을 문제 등록 과정에 통합하는 데 초점을 맞추고 있습니다. S3 연동을 위한 의존성, 설정, 예외 처리, 업로더 클래스 및 관련 엔티티/컨트롤러/서비스의 수정이 포함되어 있습니다. 기존 문제 이미지 엔티티 및 저장소는 삭제되었습니다.

Changes

파일/경로 그룹 변경 요약
build.gradle, src/main/resources/application.properties S3 연동을 위한 Spring Cloud AWS 의존성 및 AWS 관련 프로퍼티 추가
.../infrastructure/s3/S3Uploader.java, .../s3/S3Directory.java, .../s3/config/S3Config.java S3 업로더 클래스, S3 디렉토리 enum, S3 설정 클래스 신규 추가
.../infrastructure/s3/exception/S3Exception.java, .../exception/code/S3ExceptionCode.java S3 관련 예외 및 예외코드 enum 신규 추가
.../domain/problem/model/entity/Problem.java 이미지 URL 리스트, 제출/정답 수 필드 및 이미지 추가 메서드 추가
.../application/problem/service/ProblemService.java 이미지 파일 파라미터 추가, S3 업로드 및 이미지 URL 저장 로직 반영
.../presentation/problemmanagement/problem/ProblemAdminController.java 문제 등록 API에서 multipart/form-data 및 이미지 파일 파라미터 지원
.../domain/problem/model/entity/ProblemImage.java, .../repository/ProblemImageRepository.java, .../repository/problem/ProblemImageJpaRepository.java 문제 이미지 엔티티 및 관련 저장소/레포지토리 파일 삭제

Sequence Diagram(s)

sequenceDiagram
    participant Admin as Admin
    participant Controller as ProblemAdminController
    participant Service as ProblemService
    participant S3 as S3Uploader
    participant DB as Database

    Admin->>Controller: POST /problems (multipart/form-data: request, image)
    Controller->>Service: createProblem(request, image, user)
    Service->>DB: 문제 엔티티 저장
    alt 이미지 파일 존재
        Service->>S3: upload(image, "problem")
        S3-->>Service: 이미지 URL 반환
        Service->>DB: 문제 엔티티에 이미지 URL 추가
    end
    Service-->>Controller: ProblemDetailResponse 반환
    Controller-->>Admin: 응답 반환
Loading

Possibly related PRs

Suggested reviewers

  • minjee2758
  • pokerbearkr
  • thezz9

Poem

🐰
S3에 토끼가 점프를 해,
문제 이미지 척척 업로드해!
새 디렉토리, 예외도 챙기고,
컨트롤러, 서비스 모두 바뀌고,
오래된 엔티티는 안녕~
구름 위에 문제 사진,
EZ코드엔 오늘도 변화의 바람!
☁️🖼️
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (8)
src/main/resources/application.properties (1)

115-124: 하드코드된 S3 설정을 환경 변수로 변경 권장

보안상 AWS 크리덴셜을 환경 변수로 관리하는 것은 좋은 접근입니다. 하지만 버킷 이름과 리전이 하드코드되어 있어 다른 환경(개발/스테이징/프로덕션)에서의 유연성이 떨어집니다.

다음과 같이 환경 변수로 변경하는 것을 고려해보세요:

-cloud.aws.s3.bucket=ezcode-s3
-cloud.aws.region.static=ap-northeast-2
+cloud.aws.s3.bucket=${AWS_S3_BUCKET:ezcode-s3}
+cloud.aws.region.static=${AWS_REGION:ap-northeast-2}
src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java (1)

81-82: ElementCollection 사용 시 성능 고려사항

이미지 URL 저장을 위해 @ElementCollection을 사용하는 것은 적절하지만, 대량의 이미지가 있을 경우 성능 문제가 발생할 수 있습니다. FetchType.LAZY 사용은 좋은 선택입니다.

다음 개선사항을 고려해보세요:

  • 이미지 개수 제한 추가
  • 별도의 테이블로 분리하여 더 나은 인덱싱과 쿼리 최적화 가능
@Size(max = 10, message = "이미지는 최대 10개까지 등록 가능합니다")
@ElementCollection(fetch = FetchType.LAZY)
private List<String> imageUrl = new ArrayList<>();
src/main/java/org/ezcode/codetest/infrastructure/s3/config/S3Config.java (3)

12-12: 불필요한 어노테이션 제거

@RequiredArgsConstructor 어노테이션이 있지만 생성자 주입이 필요한 final 필드가 없습니다.

-@RequiredArgsConstructor

Also applies to: 18-18


22-29: AWS 자격증명 보안 강화 권장

하드코딩된 자격증명 방식 대신 더 안전한 방법을 고려해보세요.

AWS SDK는 다음과 같은 자격증명 순서로 작동합니다:

  1. IAM Role (EC2/ECS에서 권장)
  2. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 환경변수
  3. ~/.aws/credentials 파일
  4. 하드코딩된 자격증명 (현재 방식, 권장하지 않음)

프로덕션 환경에서는 IAM Role 사용을 권장합니다.


18-18: 불필요한 @requiredargsconstructor 어노테이션 제거 필요

클래스에 생성자 주입이 필요한 final 필드가 없으므로 @requiredargsconstructor 어노테이션이 불필요합니다.

-@RequiredArgsConstructor
src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java (3)

40-41: 파일명 생성 로직 개선 권장

현재 파일명 생성 방식에 잠재적 문제가 있습니다.

개선 방안:

private String generateFileName(String dirName, String originalFilename) {
    if (originalFilename == null || originalFilename.trim().isEmpty()) {
        originalFilename = "unknown";
    }
    
    // 파일명에서 확장자 추출
    String extension = "";
    int dotIndex = originalFilename.lastIndexOf(".");
    if (dotIndex > 0) {
        extension = originalFilename.substring(dotIndex);
    }
    
    // 안전한 파일명 생성 (특수문자 제거)
    String safeName = originalFilename.replaceAll("[^a-zA-Z0-9.-]", "_");
    
    return String.format("%s/%s-%s", dirName, UUID.randomUUID(), safeName);
}

이유:

  • 원본 파일명이 null일 경우 처리
  • 특수문자로 인한 S3 키 오류 방지
  • 파일명 길이 제한 고려

30-38: MIME 타입 검증 로직 개선 권장

현재 contentType.startsWith("image/")로만 검증하고 있지만, 주석에서 언급한 특정 이미지 형식(png, jpeg, jpg, webp)에 대한 더 엄격한 검증을 고려해보세요.

-if (contentType == null || !contentType.startsWith("image/")) {
+private static final Set<String> ALLOWED_CONTENT_TYPES = Set.of(
+    "image/jpeg", "image/jpg", "image/png", "image/webp"
+);
+
+if (contentType == null || !ALLOWED_CONTENT_TYPES.contains(contentType)) {

47-48: 파일 크기 제한 검증 추가 고려

현재 구현에는 업로드 파일 크기 제한이 없습니다. 대용량 파일 업로드를 방지하기 위해 파일 크기 검증을 추가하는 것을 고려해보세요.

+private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
+
+if (multipartFile.getSize() > MAX_FILE_SIZE) {
+    throw new S3Exception(
+        S3ExceptionCode.S3_INVALID_FILE_TYPE,
+        S3ExceptionCode.S3_INVALID_FILE_TYPE.getStatus(),
+        "파일 크기가 너무 큽니다. 최대 10MB까지 업로드 가능합니다."
+    );
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ce16d7 and 7ebd0ff.

📒 Files selected for processing (13)
  • build.gradle (1 hunks)
  • src/main/java/org/ezcode/codetest/application/problem/service/ProblemService.java (2 hunks)
  • src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java (4 hunks)
  • src/main/java/org/ezcode/codetest/domain/problem/model/entity/ProblemImage.java (0 hunks)
  • src/main/java/org/ezcode/codetest/domain/problem/repository/ProblemImageRepository.java (0 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemImageJpaRepository.java (0 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/S3Directory.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/config/S3Config.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/exception/S3Exception.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/exception/code/S3ExceptionCode.java (1 hunks)
  • src/main/java/org/ezcode/codetest/presentation/problemmanagement/problem/ProblemAdminController.java (3 hunks)
  • src/main/resources/application.properties (1 hunks)
💤 Files with no reviewable changes (3)
  • src/main/java/org/ezcode/codetest/domain/problem/repository/ProblemImageRepository.java
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/problem/ProblemImageJpaRepository.java
  • src/main/java/org/ezcode/codetest/domain/problem/model/entity/ProblemImage.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (16)
build.gradle (1)

113-114: Spring Cloud AWS 버전 호환성 검증 필요

Spring Boot 3.5.0과 Spring Cloud AWS 2.2.6.RELEASE 간의 호환성 문제가 있을 수 있습니다. 이 버전은 Spring Boot 2.x용으로 설계되었으며 javax 네임스페이스를 사용하지만, Spring Boot 3.x는 Jakarta EE를 사용합니다.

최신 호환 버전 확인을 위해 다음 웹 검색을 실행해주세요:

Spring Boot 3.x compatible Spring Cloud AWS version latest
src/main/java/org/ezcode/codetest/infrastructure/s3/S3Directory.java (1)

1-21: 깔끔한 enum 구현입니다

S3 디렉터리 관리를 위한 enum이 잘 구현되었습니다. 불변성과 명확한 네이밍 컨벤션을 따르고 있으며, 코드가 간결하고 이해하기 쉽습니다.

src/main/java/org/ezcode/codetest/infrastructure/s3/exception/S3Exception.java (1)

18-22: 아래 스크립트를 실행하여 BaseException.java 클래스의 위치와 생성자 선언부를 확인해주세요.

#!/bin/bash
# BaseException.java 파일 위치 검색 및 내용 출력
file=$(fd BaseException.java)
echo "Found BaseException.java at: $file"
sed -n '1,200p' "$file"
src/main/java/org/ezcode/codetest/domain/problem/model/entity/Problem.java (1)

72-76: 제출 통계 필드 추가 승인

문제별 제출 횟수와 정답 횟수를 추적하는 필드가 적절히 추가되었습니다. null 제약조건과 기본값 초기화가 올바르게 구현되어 있습니다.

src/main/java/org/ezcode/codetest/infrastructure/s3/config/S3Config.java (2)

31-38: Bean 설정 구현 승인

AmazonS3 클라이언트 설정이 올바르게 구현되었습니다.


22-29: 전체 설정 파일(.properties, .yml, .yaml)에서 AWS 자격증명 키 사용 여부를 확인하겠습니다:

#!/bin/bash
# 전체 설정 파일에서 AWS 자격증명 확인
fd -e properties -e yml -e yaml --exec grep -H "cloud.aws.credentials" {}
src/main/java/org/ezcode/codetest/infrastructure/s3/exception/code/S3ExceptionCode.java (1)

14-14: 파일 타입 검증 에러 코드 승인

잘못된 파일 타입에 대한 BAD_REQUEST 상태 코드 사용이 적절합니다.

src/main/java/org/ezcode/codetest/application/problem/service/ProblemService.java (3)

13-14: S3 관련 의존성 추가 승인

S3 업로드 기능을 위한 import와 의존성 주입이 적절합니다.

Also applies to: 29-29


33-33: 메서드 시그니처 변경 승인

이미지 업로드를 위한 MultipartFile 파라미터 추가가 적절합니다.


33-47: 이미지 업로드 로직 구현이 적절합니다

문제 생성 후 이미지 업로드를 처리하는 로직이 올바르게 구현되었습니다. null/empty 체크와 트랜잭션 경계 설정이 적절하며, S3Uploader를 통한 업로드 후 엔티티에 URL을 추가하는 흐름이 정확합니다.

src/main/java/org/ezcode/codetest/presentation/problemmanagement/problem/ProblemAdminController.java (3)

9-9: 멀티파트 지원을 위한 import 추가 승인

멀티파트 폼 데이터 처리를 위한 필요한 import들이 적절히 추가되었습니다.

Also applies to: 18-18, 20-20


36-47: 멀티파트 폼 데이터 처리 구현 승인

@RequestPart를 사용한 멀티파트 데이터 처리와 선택적 이미지 파라미터 구현이 적절합니다.

구현이 올바른 이유:

  • consumes = MediaType.MULTIPART_FORM_DATA_VALUE로 명시적 컨텐츠 타입 지정
  • @RequestPart로 각 파트를 별도 처리
  • required = false로 이미지를 선택사항으로 설정
  • 기존 유효성 검증(@Valid) 유지

36-48: 멀티파트 폼 데이터 처리 구현이 정확합니다

컨트롤러에서 @RequestPart를 사용한 멀티파트 폼 데이터 처리가 올바르게 구현되었습니다. 이미지 파일을 선택적 매개변수로 처리하고, 검증 어노테이션도 적절히 유지되었습니다.

src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java (3)

18-26: 컴포넌트 설정 승인

S3Uploader 컴포넌트의 기본 설정과 의존성 주입이 적절합니다.


43-48: S3 업로드 구현 승인

ObjectMetadata 설정과 S3 업로드 로직이 적절하게 구현되었습니다.

구현이 우수한 점:

  • ContentLength와 ContentType 메타데이터 설정
  • 업로드 후 URL 반환
  • 적절한 로깅

28-61: S3 업로드 구현이 전반적으로 우수합니다

파일 업로드 로직이 잘 구현되었습니다. UUID를 사용한 파일명 생성, 적절한 메타데이터 설정, 예외 처리, 그리고 로깅이 모두 적절합니다.

Comment on lines +37 to +44
Problem problem = ProblemCreateRequest.toEntity(requestDto, user);
Problem savedProblem = problemDomainService.createProblem(problem);

// 문제 이미지 있다면?
if (image != null && !image.isEmpty()) {
String imageUrl = s3Uploader.upload(image, S3Directory.PROBLEM.getDir());
savedProblem.addImage(imageUrl);
}
Copy link

@coderabbitai coderabbitai bot Jun 25, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

트랜잭션 범위 내 외부 서비스 호출 검토 필요

S3 업로드가 트랜잭션 내에서 실행되고 있습니다. 이는 다음과 같은 문제를 야기할 수 있습니다.

문제점:

  1. S3 업로드 실패 시 DB 트랜잭션도 롤백됨
  2. S3 업로드 성공 후 DB 저장 실패 시 S3에 불필요한 파일 남음
  3. 트랜잭션이 오래 지속됨

개선 방안:

@Transactional
public ProblemDetailResponse createProblem(ProblemCreateRequest requestDto, MultipartFile image, AuthUser authUser) {
    User user = userDomainService.getUserById(authUser.getId());
    Problem problem = ProblemCreateRequest.toEntity(requestDto, user);
    Problem savedProblem = problemDomainService.createProblem(problem);
    
    // 트랜잭션 완료 후 S3 업로드 수행
    if (image != null && !image.isEmpty()) {
        String imageUrl = uploadImageAfterTransaction(image, savedProblem.getId());
        updateProblemWithImage(savedProblem.getId(), imageUrl);
    }
    
    return ProblemDetailResponse.from(savedProblem);
}

@Transactional
public void updateProblemWithImage(Long problemId, String imageUrl) {
    Problem problem = problemDomainService.getProblem(problemId);
    problem.addImage(imageUrl);
}

private String uploadImageAfterTransaction(MultipartFile image, Long problemId) {
    try {
        return s3Uploader.upload(image, S3Directory.PROBLEM.getDir());
    } catch (Exception e) {
        // 업로드 실패 시 로깅하고 기본값 반환 또는 재시도 로직
        log.error("Problem {} 이미지 업로드 실패", problemId, e);
        throw e;
    }
}
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/problem/service/ProblemService.java
around lines 37 to 44, the S3 upload is performed inside the transaction, which
can cause rollback issues and leave orphan files on S3. To fix this, refactor
the code to perform the S3 upload after the transaction commits by first saving
the Problem entity within the transaction, then uploading the image outside the
transaction, and finally updating the Problem entity with the image URL in a
separate transactional method.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED); 이렇게 커스텀 예외처리 해보는게 좋을거같아 적용해봐

Copy link

Choose a reason for hiding this comment

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

@Kimminu7 좋은 제안이네요! 커스텀 예외를 사용하면 일관성 있는 예외 처리가 가능하겠어요. 제안하신 방식으로 개선해보겠습니다:

@Transactional
public ProblemDetailResponse createProblem(ProblemCreateRequest requestDto, MultipartFile image, AuthUser authUser) {
    User user = userDomainService.getUserById(authUser.getId());
    Problem problem = ProblemCreateRequest.toEntity(requestDto, user);
    Problem savedProblem = problemDomainService.createProblem(problem);
    
    // 트랜잭션 완료 후 S3 업로드 수행
    if (image != null && !image.isEmpty()) {
        String imageUrl = uploadImageAfterTransaction(image, savedProblem.getId());
        updateProblemWithImage(savedProblem.getId(), imageUrl);
    }
    
    return ProblemDetailResponse.from(savedProblem);
}

@Transactional
public void updateProblemWithImage(Long problemId, String imageUrl) {
    Problem problem = problemDomainService.getProblem(problemId);
    problem.addImage(imageUrl);
}

private String uploadImageAfterTransaction(MultipartFile image, Long problemId) {
    try {
        return s3Uploader.upload(image, S3Directory.PROBLEM.getDir());
    } catch (Exception e) {
        // 커스텀 예외로 일관성 있는 예외 처리
        log.error("Problem {} 이미지 업로드 실패", problemId, e);
        throw new S3Exception(S3ExceptionCode.S3_UPLOAD_FAILED);
    }
}

이렇게 하면 S3Uploader 내부의 예외 처리와 동일한 패턴을 유지하면서 일관성 있는 예외 처리가 가능하겠네요!

   (\   /)
  ( ._. )
 o_(")(")

Copy link
Collaborator Author

@Kimminu7 Kimminu7 Jun 25, 2025

Choose a reason for hiding this comment

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

안되는데? S3ExceptionCode.S3_UPLOAD_FAILED 생성자 생성하라고하네

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

@Kimminu7 어떤 부분이 안 되는지 구체적으로 알려주실 수 있을까요?

컴파일 에러인지, 실행 시 에러인지, 아니면 다른 문제인지 확인해보고 싶어요. 현재 코드베이스 구조를 더 자세히 살펴보고 정확한 해결책을 제공해드리겠습니다.

구체적인 에러 메시지나 문제 상황을 알려주시면 더 정확한 도움을 드릴 수 있어요!

   (>.<)
  o_(")(")

🏁 Script executed:

#!/bin/bash
# S3Exception과 관련 import들이 올바른지 확인
echo "=== S3Exception 클래스 확인 ==="
cat "src/main/java/org/ezcode/codetest/infrastructure/s3/exception/S3Exception.java"

echo -e "\n=== S3ExceptionCode 확인 ==="
cat "src/main/java/org/ezcode/codetest/infrastructure/s3/exception/code/S3ExceptionCode.java"

echo -e "\n=== ProblemService 현재 import 확인 ==="
head -20 "src/main/java/org/ezcode/codetest/application/problem/service/ProblemService.java"

echo -e "\n=== 로깅 관련 import나 annotation 확인 ==="
rg "import.*log|@Slf4j" "src/main/java/org/ezcode/codetest/application/problem/service/ProblemService.java"

Length of output: 3056


@Kimminu7 아, 문제를 찾았어요! 몇 가지 이슈가 있었네요:

  1. S3Exception 생성자 문제: S3Exception은 3개의 파라미터가 필요한데 1개만 전달했어요
  2. 로깅 import 누락: log 객체가 없는데 사용하려고 했어요
  3. 필요한 import 누락

다음과 같이 수정하면 됩니다:

// 필요한 import 추가
import org.ezcode.codetest.infrastructure.s3.exception.S3Exception;
import org.ezcode.codetest.infrastructure.s3.exception.code.S3ExceptionCode;
import lombok.extern.slf4j.Slf4j;

@Slf4j  // 로깅을 위한 어노테이션 추가
@Service
@RequiredArgsConstructor
public class ProblemService {
    // ... 기존 코드 ...

    private String uploadImageAfterTransaction(MultipartFile image, Long problemId) {
        try {
            return s3Uploader.upload(image, S3Directory.PROBLEM.getDir());
        } catch (Exception e) {
            log.error("Problem {} 이미지 업로드 실패", problemId, e);
            // S3Exception 생성자에 필요한 모든 파라미터 전달
            throw new S3Exception(
                S3ExceptionCode.S3_UPLOAD_FAILED,
                S3ExceptionCode.S3_UPLOAD_FAILED.getStatus(),
                S3ExceptionCode.S3_UPLOAD_FAILED.getMessage()
            );
        }
    }
}

또는 더 간단하게 S3ExceptionCode의 정보를 직접 사용할 수도 있어요:

throw new S3Exception(
    S3ExceptionCode.S3_UPLOAD_FAILED,
    S3ExceptionCode.S3_UPLOAD_FAILED.getStatus(),
    S3ExceptionCode.S3_UPLOAD_FAILED.getMessage()
);

이제 제대로 작동할 거예요!

   (\   /)
  ( ^.^ )
 o_(")(")

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/java/org/ezcode/codetest/infrastructure/s3/exception/S3Exception.java (1)

13-17: 필드 중복성 검토

responseCode에서 이미 httpStatusmessage 정보를 추출할 수 있는데 별도 필드로 저장하고 있습니다. 메모리 효율성을 고려하면 getter 메서드에서 동적으로 반환하는 방식도 검토해볼 수 있습니다.

현재 구조가 성능상 이점이 있다면 유지하되, 필드 중복성에 대한 검토를 권장합니다:

  @Getter
  public class S3Exception extends BaseException {
  
    private final S3ExceptionCode responseCode;
  
-   private final ResponseCode responseCode;
-   private final HttpStatus httpStatus;
-   private final String message;
  
    public S3Exception(S3ExceptionCode responseCode) {
+       Objects.requireNonNull(responseCode, "S3ExceptionCode cannot be null");
        this.responseCode = responseCode;
-       this.httpStatus = responseCode.getStatus();
-       this.message = responseCode.getMessage();
    }
+   
+   public HttpStatus getHttpStatus() {
+       return responseCode.getStatus();
+   }
+   
+   public String getMessage() {
+       return responseCode.getMessage();
+   }
  }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00cea6c and 1912347.

📒 Files selected for processing (3)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/exception/S3Exception.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/exception/code/S3ExceptionCode.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/org/ezcode/codetest/infrastructure/s3/S3Uploader.java
  • src/main/java/org/ezcode/codetest/infrastructure/s3/exception/code/S3ExceptionCode.java

@Kimminu7 Kimminu7 merged commit d7ecc3a into dev Jun 25, 2025
2 checks passed
@Kimminu7 Kimminu7 deleted the feature/problemS3 branch June 25, 2025 13:01
@Kimminu7 Kimminu7 changed the title feature : 문제 이미지 기능 ( S3, 업로드 만 가능 ) feat : 문제 이미지 기능 ( S3, 업로드 만 가능 ) Jun 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants