Skip to content

[VISION] 종 추정 정확도 및 UX 개선#16

Merged
s0ooo0k merged 1 commit into
PETTY-HUB:mainfrom
23MinL:main
Apr 22, 2025
Merged

[VISION] 종 추정 정확도 및 UX 개선#16
s0ooo0k merged 1 commit into
PETTY-HUB:mainfrom
23MinL:main

Conversation

@23MinL
Copy link
Copy Markdown
Contributor

@23MinL 23MinL commented Apr 22, 2025

📜 PR 내용 요약

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)

  • VisionService의 종(species) 추정 로직 개선 및 대응 가능 범위 확장
  • 사용자 친화적인 interim 메시지 출력 처리 보완
  • AWS Rekognition 설정 코드 (AwsConfig) 안정성 점검 및 명확화
  • Vision 기능 HTML (visionUpload.html) 리팩토링 및 UX 개선

⚒️ 작업 및 변경 내용(상세하게)

변경 내용, 업데이트 및 수정 사항을 자세하게 적어주세요

  • VisionService.java
    • 다중 라벨(예: "개 + 고양이") 상황 처리 추가
    • 매핑되지 않은 종("알 수 없음")에 대한 interim 메시지 명확화
  • VisionController.java
    • interim 및 최종 보고서 호출 로직 예외 처리 개선
  • AwsConfig.java
    • AWS Rekognition Client 빈(bean) 설정 명확화 및 코드 안정성 검증 완료
  • visionUpload.html
    • 분석 전/후 UX 개선 (로딩 스피너, 뒤로가기 버튼 추가)
    • 분석 결과 표시 UI 일관성 확보 및 메시지 명확화

📚 기타 참고 사항

리뷰 포인트, 참고 사항, 빌드 관련 내용 기타 사항을 자세히 적어주세요

  • 기능별 패키지 구조(controller, service)는 기존과 동일하게 유지
  • 타 팀원과 충돌 발생 우려되는 VectorStoreService 관련 이슈는 별도 확인 필요
  • Vision 기능의 로컬 테스트 및 예외처리 최종 점검 완료

@PETTY-HUB PETTY-HUB deleted a comment from coderabbitai Bot Apr 22, 2025
@s0ooo0k
Copy link
Copy Markdown
Member

s0ooo0k commented Apr 22, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2025

Summary by CodeRabbit

  • 신규 기능

    • 동물 이미지 분석을 위한 업로드 페이지와 결과 리포트 기능이 추가되었습니다.
    • 이미지 업로드 시 중간 메시지와 최종 분석 리포트를 받아볼 수 있습니다.
    • AWS Rekognition 및 외부 API를 활용한 종(種) 판별 및 상세 리포트 생성을 지원합니다.
  • UI 개선

    • 업로드 페이지가 현대적이고 직관적인 디자인으로 개편되었습니다.
    • 업로드 이미지 미리보기, 로딩 스피너, 오류 메시지, 결과 영역 등이 추가되었습니다.
  • 버그 수정

    • 오류 발생 시 사용자에게 적절한 안내 메시지가 표시됩니다.

Walkthrough

이 변경사항은 AWS Rekognition을 활용한 반려동물 이미지 분석 기능을 애플리케이션에 도입합니다. 새로운 Spring 설정 클래스(AwsConfig)가 추가되어 AWS 자격 증명과 리전을 기반으로 Rekognition 클라이언트를 빈으로 제공합니다. VisionController와 VisionService가 새롭게 도입되어, 이미지 업로드, 종 판별, 상세 분석 리포트 생성을 위한 엔드포인트와 비즈니스 로직을 구현합니다. 프론트엔드 템플릿(visionUpload.html)도 대폭 리뉴얼되어, 업로드, 결과 표시, 비동기 처리 및 에러 핸들링을 지원합니다.

Changes

파일/경로 변경 요약
src/main/java/io/github/petty/config/AwsConfig.java AWS Rekognition 클라이언트 생성을 위한 Spring 설정 클래스 및 빈 추가
src/main/java/io/github/petty/vision/controller/VisionController.java 이미지 업로드, 종 판별, 분석 리포트 엔드포인트 제공하는 Spring MVC 컨트롤러 신설
src/main/java/io/github/petty/vision/service/VisionService.java 이미지 기반 종 판별, 분석 리포트 생성, Gemini 및 Together Vision API 연동 서비스 클래스 신설
src/main/resources/templates/visionUpload.html 부트스트랩 기반 UI 리뉴얼, 이미지 업로드/미리보기/결과 표시, 비동기 처리 및 에러 핸들링 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend (visionUpload.html)
    participant VisionController
    participant VisionService
    participant AWS Rekognition
    participant Gemini API
    participant Together Vision API

    User->>Frontend (visionUpload.html): 이미지 업로드 및 이름 입력
    Frontend->>VisionController: POST /vision/species (파일, 이름)
    VisionController->>VisionService: getInterimMessage(파일, 이름)
    VisionService->>AWS Rekognition: detectLabels(이미지)
    AWS Rekognition-->>VisionService: 라벨 결과
    VisionService-->>VisionController: 종 판별 결과
    VisionController-->>Frontend: interim 메시지 반환

    User->>Frontend: 분석 요청 클릭
    Frontend->>VisionController: POST /vision/analyze (파일, 이름)
    VisionController->>VisionService: createFinalReport(파일, 이름)
    VisionService->>Gemini API: 이미지+프롬프트로 분석 요청
    alt Gemini 실패
        VisionService->>Together Vision API: 이미지+프롬프트로 분석 요청
        Together Vision API-->>VisionService: 분석 결과
    else Gemini 성공
        Gemini API-->>VisionService: 분석 결과
    end
    VisionService-->>VisionController: 최종 리포트
    VisionController-->>Frontend: 리포트 반환
Loading

Possibly related PRs

Poem

🐰
새싹처럼 솟아난 비전의 힘,
사진 한 장에 담긴 반려동물의 꿈.
AWS와 Gemini가 손을 맞잡고,
종을 찾고 리포트도 척척!
업로드 페이지도 새 옷을 입었네,
코드를 토끼가 뛰며 노래하네.
분석의 숲에서 우리 함께 가요!

✨ 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.
    • 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.
  • @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
Copy Markdown

@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 (3)
src/main/resources/templates/visionUpload.html (1)

73-108: 동일 이미지를 두 번 전송하여 네트워크·서버 부하가 2배 발생

/vision/species, /vision/analyze에 각각 FormData 전체(이미지 포함)를 전송하고 있습니다.
첫 호출에서 종 추정을 완료한 뒤 같은 파일을 다시 업로드하지 말고,

  1. 백엔드에서 두 로직을 한 엔드포인트로 합치거나
  2. /vision/species 응답에 서버 내 임시 경로/식별자를 반환 → 두 번째 호출에서는 파일 대신 ID만 보내는 방식이 효율적입니다.
src/main/java/io/github/petty/vision/controller/VisionController.java (1)

21-33: REST 응답 형식을 명시적으로 관리하세요

현재 두 POST 메서드가 String만 반환하여 항상 200 OK로 응답합니다.
실패 시에도 200이 전달되면 프론트엔드에서 오류를 구분하기 어렵습니다.

@PostMapping("/species")
public ResponseEntity<String> getSpeciesInterim(...) {
    try {
        return ResponseEntity.ok(visionService.getInterimMessage(file, petName));
    } catch(Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                             .body("중간 분석 실패");
    }
}

같이 ResponseEntity로 상태 코드를 명시해 주세요.

src/main/java/io/github/petty/vision/service/VisionService.java (1)

100-116: 키워드 매칭 로직 성능 개선 가능

현재 20 라벨 × 16 키워드 = 최대 320 비교가 이루어집니다.
파일당 호출 빈도가 높다면 label.name().toLowerCase() 결과를 SPECIES_KEYWORDS의 key Set 포함 여부로 한 번만 확인하도록 개선할 수 있습니다. 다만 심각한 병목은 아니므로 우선순위는 낮습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8f8419b and b202830.

📒 Files selected for processing (4)
  • src/main/java/io/github/petty/config/AwsConfig.java (1 hunks)
  • src/main/java/io/github/petty/vision/controller/VisionController.java (1 hunks)
  • src/main/java/io/github/petty/vision/service/VisionService.java (1 hunks)
  • src/main/resources/templates/visionUpload.html (1 hunks)
🔇 Additional comments (1)
src/main/java/io/github/petty/vision/service/VisionService.java (1)

24-27: RestTemplate 빈 정의 여부 확인 필요

RestTemplate를 생성자 주입 받고 있지만, 프로젝트 전역에 @Bean RestTemplate 정의가 없으면 애플리케이션이 시작되지 않습니다. 존재 여부를 재확인해 주세요.

Comment on lines +23 to +30
@Bean
public RekognitionClient rekognitionClient() {
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
return RekognitionClient.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(Region.of(region))
.build();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

RekognitionClient 자원 해제 누락

RekognitionClientAutoCloseable을 구현합니다. 빈이 싱글턴으로 유지되더라도 애플리케이션 종료 시 close()를 호출하지 않으면 채널/스레드 풀 누수가 발생합니다.

@PreDestroy
public void shutdown() {
    rekognitionClient().close();
}

같은 @Bean(destroyMethod = "close") 혹은 별도 @PreDestroy 메서드를 추가해주세요.

Comment on lines +14 to +22
@Value("${aws.accessKeyId}")
private String accessKeyId;

@Value("${aws.secretAccessKey}")
private String secretAccessKey;

@Value("${aws.region}")
private String region;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

애플리케이션 프로퍼티에 정적 자격 증명 사용은 보안 취약점을 초래할 수 있습니다.

@Value("${aws.accessKeyId}"), @Value("${aws.secretAccessKey}") 방식으로 코드에 접근 키를 주입하면

  1. git 커밋 실수로 키가 노출될 위험이 높고
  2. 운영/개발 환경 전환 시 별도 관리 포인트가 늘어납니다.

AWS SDK v2는 DefaultCredentialsProvider(환경 변수, EC2/컨테이너 메타데이터, IAM Role 등)를 자동 탐색하므로 이를 우선 사용하고, 로컬 개발만 별도 프로퍼티 파일을 읽도록 분리하는 편이 안전합니다.

-@Value("${aws.accessKeyId}")
-private String accessKeyId;
-@Value("${aws.secretAccessKey}")
-private String secretAccessKey;
...
-        AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
-        return RekognitionClient.builder()
-                .credentialsProvider(StaticCredentialsProvider.create(credentials))
+        return RekognitionClient.builder()
+                .credentialsProvider(DefaultCredentialsProvider.create())
                 .region(Region.of(region))
                 .build();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Value("${aws.accessKeyId}")
private String accessKeyId;
@Value("${aws.secretAccessKey}")
private String secretAccessKey;
@Value("${aws.region}")
private String region;
// only keep the region from properties
@Value("${aws.region}")
private String region;
@Bean
public RekognitionClient rekognitionClient() {
return RekognitionClient.builder()
// use the SDK’s default provider chain instead of static creds
.credentialsProvider(DefaultCredentialsProvider.create())
.region(Region.of(region))
.build();
}

Comment on lines +86 to 95
try {
const res1 = await fetch('/vision/species', { method: 'POST', body: fd });
const text1 = await res1.text();
interim.textContent = text1;
result.style.display = 'block';
} catch (e) {
interim.textContent = 'AWS 분석 중 오류가 발생했습니다…';
console.error(e);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

HTTP 오류 코드 미처리

fetch() 결과를 await res.text()로 바로 읽고 있는데, 4xx/5xx 상태도 텍스트로 처리해 버립니다.
response.ok를 확인하여 사용자에게 정확한 오류 메시지를 전달해 주세요.

-const text1 = await res1.text();
-if (!res1.ok) throw new Error(text1);
+if (!res1.ok) {
+    const err = await res1.text();
+    throw new Error(err || res1.status);
+}
+const text1 = await res1.text();

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +18 to +19
@Autowired
private VisionService visionService;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

필드 주입 대신 생성자 주입 권장

@Autowired 필드 주입은

  • final 불가 → 불변성 약화
  • 순환 참조 감지가 늦어짐
  • 테스트 시 목 객체 주입이 번거로움

@RequiredArgsConstructor를 사용한 생성자 주입으로 전환하면 개선됩니다.

Comment on lines +184 to +206
private String callTogetherVision(byte[] imageData, String petName) {
Map<String, Object> payload = createTogetherPayload(imageData, petName);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(togetherApiKey);

HttpEntity<Map<String, Object>> req = new HttpEntity<>(payload, headers);
ResponseEntity<JsonNode> res = restTemplate.exchange(
togetherApiUrl,
HttpMethod.POST,
req,
JsonNode.class
);

if (res.getStatusCode() == HttpStatus.OK && res.getBody() != null) {
return res.getBody()
.path("choices").get(0)
.path("message").path("content")
.asText();
}
throw new RuntimeException("Together API 비정상 응답: " + res.getStatusCode());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Together API 응답 파싱 시 Null/빈 배열 예외 가능

choices.get(0) 호출 전 배열 크기를 확인하지 않으면 API 변경·오류 시 IndexOutOfBoundsException이 발생합니다.

- if (res.getStatusCode() == HttpStatus.OK && res.getBody() != null) {
-     return res.getBody()
-             .path("choices").get(0)
-             .path("message").path("content")
-             .asText();
- }
+ if (res.getStatusCode() == HttpStatus.OK && res.getBody() != null) {
+     JsonNode choices = res.getBody().path("choices");
+     if (choices.isArray() && choices.size() > 0) {
+         return choices.get(0).path("message").path("content").asText();
+     }
+     log.error("Together 응답에 choices가 없습니다: {}", res.getBody());
+ }
 throw new RuntimeException("Together API 비정상 응답: " + res.getStatusCode());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private String callTogetherVision(byte[] imageData, String petName) {
Map<String, Object> payload = createTogetherPayload(imageData, petName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(togetherApiKey);
HttpEntity<Map<String, Object>> req = new HttpEntity<>(payload, headers);
ResponseEntity<JsonNode> res = restTemplate.exchange(
togetherApiUrl,
HttpMethod.POST,
req,
JsonNode.class
);
if (res.getStatusCode() == HttpStatus.OK && res.getBody() != null) {
return res.getBody()
.path("choices").get(0)
.path("message").path("content")
.asText();
}
throw new RuntimeException("Together API 비정상 응답: " + res.getStatusCode());
}
private String callTogetherVision(byte[] imageData, String petName) {
Map<String, Object> payload = createTogetherPayload(imageData, petName);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(togetherApiKey);
HttpEntity<Map<String, Object>> req = new HttpEntity<>(payload, headers);
ResponseEntity<JsonNode> res = restTemplate.exchange(
togetherApiUrl,
HttpMethod.POST,
req,
JsonNode.class
);
if (res.getStatusCode() == HttpStatus.OK && res.getBody() != null) {
JsonNode choices = res.getBody().path("choices");
if (choices.isArray() && choices.size() > 0) {
return choices.get(0)
.path("message")
.path("content")
.asText();
}
log.error("Together 응답에 choices가 없습니다: {}", res.getBody());
}
throw new RuntimeException("Together API 비정상 응답: " + res.getStatusCode());
}

Comment on lines +133 to +152
private String callGemini(byte[] imageData, String petName, String species) {
String prompt = createEnhancedPromptForReport(petName, species);
String base64Image = Base64.getEncoder().encodeToString(imageData);

Map<String,Object> payload = Map.of(
"contents", List.of(Map.of(
"parts", List.of(
Map.of("text", prompt),
Map.of("inline_data", Map.of(
"mime_type", "image/jpeg",
"data", base64Image
))
)
))
);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String url = geminiApiUrl + "?key=" + geminiApiKey;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Gemini API 호출 Payload에 model 누락

공식 문서에 따르면 contents 외에 model 필드(예: "gemini-pro-vision")가 필요합니다.
누락 시 400 Bad Request가 반환됩니다.

 Map<String,Object> payload = Map.of(
-        "contents", List.of(Map.of(
+        "model", "gemini-pro-vision",
+        "contents", List.of(Map.of(
             "parts", List.of(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private String callGemini(byte[] imageData, String petName, String species) {
String prompt = createEnhancedPromptForReport(petName, species);
String base64Image = Base64.getEncoder().encodeToString(imageData);
Map<String,Object> payload = Map.of(
"contents", List.of(Map.of(
"parts", List.of(
Map.of("text", prompt),
Map.of("inline_data", Map.of(
"mime_type", "image/jpeg",
"data", base64Image
))
)
))
);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String url = geminiApiUrl + "?key=" + geminiApiKey;
Map<String,Object> payload = Map.of(
"model", "gemini-pro-vision",
"contents", List.of(Map.of(
"parts", List.of(
Map.of("text", prompt),
Map.of("inline_data", Map.of(
"mime_type", "image/jpeg",
"data", base64Image
))
)
))
);

@s0ooo0k
Copy link
Copy Markdown
Member

s0ooo0k commented Apr 22, 2025

타 팀원과 충돌 발생 우려되는 VectorStoreService 관련 이슈는 별도 확인 필요

VectorStoreService 관련하여 어떤 이슈가 예상되는지 궁금합니다
답변 주시면 논의 후 참고하겠습니다

==> 논의 예정

@s0ooo0k
Copy link
Copy Markdown
Member

s0ooo0k commented Apr 22, 2025

✅ 리뷰

  • 코드 확인했습니다! 1차 프로젝트와 달리 AWS Rekognition을 도입하신 점이 인상깊었습니다. 분석 결과에 맞게 기준을 세워 구현한 부분에서 API를 잘 활용하신 거 같습니다.
  • 예외 처리 및 예외 발생 시 메세지 제공 등, 기능 구현 단계임에도 테스터, 사용자가 결과를 파악할 수 있는 설계가 인상깊었습니다.
  • 추후 PIPELINE 파트와 통합이 잘 이루어진다면 좋은 결과를 얻어낼 수 있을 거 같습니다.

🔧 제안 및 아이디어

  • 현재 VisionService에서 수행하는 로직이 많아보이는데, 추후 가능하다면 역할을 나누어 메서드를 분리하는 것도 좋을 듯 합니다.
  • @Value를 사용하는 파트에서 어떤 방법이 더 보안적으로 적합한지 확인 후 선택하면 될 거 같습니다.
  • 여러 번 테스트를 통해 API의 정확도나 분석 시도 나타내면 좋을 듯합니다. 고생하셨습니다!

@usn757
Copy link
Copy Markdown
Contributor

usn757 commented Apr 22, 2025

리뷰

  • Vision 기능 구현과 AWS 설정 안정화 작업 고생 많으셨습니다!
  • 특히 AWS Rekognition 연동 및 결과 처리 로직 구현이 인상적이네요.
  • AwsConfig를 통해 설정을 명확히 분리하신 점 좋아 보입니다.

제안

  • 혹시 코드 내에 API URL, 모델 이름("gemini-pro-vision"), 또는 특정 프롬프트 문자열 등이 직접 작성되어 있다면, 나중에 변경이 용이하도록 application.yml 같은 설정 파일이나 상수 클래스로 분리하는 것을 고려해보시면 유지보수에 도움이 될 것 같습니다.
  • 외부 API 요청 본문(payload)을 Map으로 구성하거나 JsonNode로 응답을 처리하는 대신, 각 요청/응답 구조에 맞는 전용 DTO(Data Transfer Object) 클래스를 정의해서 사용하면 타입 안정성이 높아지고, 코드의 의도를 더 명확하게 표현할 수 있습니다.
  • 현재도 예외 처리가 잘 되어 있지만, 나중에 운영 환경에서 문제 발생 시 원인 파악을 쉽게 하려면 외부 API 호출 전후나 중요한 분기점에서 조금 더 상세한 로그(예: 호출 대상 API, 주요 파라미터 일부, 응답 상태 코드 등)를 남겨두면 큰 도움이 될 것 같습니다.

@s0ooo0k s0ooo0k merged commit bd39ea0 into PETTY-HUB:main Apr 22, 2025
2 checks passed
23MinL pushed a commit to 23MinL/PETTY-BACK-VISION that referenced this pull request Apr 23, 2025
[VISION] 종 추정 정확도 및 UX 개선
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants