Skip to content

Conversation

@seamooll
Copy link
Contributor

@seamooll seamooll commented Feb 10, 2026

🔗 Related Issue

📝 Summary

  • 외부 API 호출과 DB 트랜잭션 분리
    • 카드사 연동 로직이 클래스 레벨의 @transactional 내에 포함되어 있어, 외부 API 응답을 기다리는 동안 DB 커넥션 풀을 불필요하게 점유하는 현상 발생
    • 외부 API 호출과 데이터 저장(DB 트랜잭션) 로직을 분리하여 개선
  • 타임아웃 설정 강화 및 안정성 확보
    • 카드사 연동 시 지연 현상의 원인이 외부 API 응답 대기 시간임을 확인
    • Feign Client의 readTimeout 상향 조정 및 Nginx 프록시 타임아웃 설정 보완
  • 비동기 작업의 Graceful Shutdown 도입
    • 배포나 서버 재시작 시 실행 중인 비동기 작업(Codef 연동 등)이 강제 종료되지 않도록 ThreadPoolTaskExecutor 설정 추가
  • Codef 연동 로깅 시스템 보완

🔄 Changes

  • API 변경 (추가/수정)
  • 데이터 및 도메인 변경 (DB, 비즈니스 로직)
  • 설정 또는 인프라 관련 변경
  • 리팩토링

💬 Questions & Review Points

📸 API Test Results (Swagger)

✅ Checklist

  • API 테스트 완료
  • 테스트 결과 사진 첨부
  • 빌드 성공 확인 (./gradlew build)

@seamooll seamooll self-assigned this Feb 10, 2026
@seamooll seamooll added the ♻️ refactor 코드 구조 개선 label Feb 10, 2026
@seamooll seamooll linked an issue Feb 10, 2026 that may be closed by this pull request
2 tasks
@seamooll seamooll added 도희 도희 🔧 enhancement 기존 기능 개선 labels Feb 10, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello @seamooll, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 카드사 연동 로직의 전반적인 성능, 안정성 및 리소스 관리 효율성을 개선하기 위한 리팩토링을 포함합니다. 외부 API 호출과 데이터베이스 트랜잭션을 명확히 분리하고, 외부 서비스 연동 시 발생할 수 있는 지연 및 오류에 대비하여 타임아웃 설정을 강화했습니다. 또한, 비동기 작업의 안정적인 종료를 보장하고, 시스템 전반의 로깅을 보완하여 운영 및 디버깅 편의성을 향상시켰습니다.

Highlights

  • 외부 API 호출 및 DB 트랜잭션 분리: 카드사 연동 로직에서 외부 API 호출과 DB 트랜잭션을 분리하여, API 응답 대기 중 불필요한 DB 커넥션 점유를 방지하고 리소스 효율성을 개선했습니다. @Transactional 어노테이션을 클래스 레벨에서 제거하고, DB 저장 로직에 Propagation.REQUIRES_NEW를 사용하여 독립적인 트랜잭션을 보장합니다.
  • 타임아웃 설정 강화 및 안정성 확보: Codef API 호출 시 Feign Client의 readTimeout을 120초로 상향 조정하여 외부 API 지연으로 인한 문제를 완화하고, connectTimeout도 10초로 설정하여 연결 안정성을 높였습니다. 이는 application.yml에 OpenFeign 클라이언트 설정을 추가하여 적용되었습니다.
  • 비동기 작업의 Graceful Shutdown 도입: 비동기 자산 동기화(assetFetchExecutor) 스레드 풀에 waitForTasksToCompleteOnShutdownawaitTerminationSeconds 설정을 추가하여, 애플리케이션 종료 시 실행 중인 비동기 작업이 강제 종료되지 않고 완료될 때까지 대기하도록 개선했습니다.
  • 로깅 시스템 보완: 주요 서비스(AssetSyncService, ConnectionCommandService, CodefAccountService, CodefAssetService)에 상세한 시작/종료 로그 및 에러 로그를 추가하여, 문제 발생 시 원인 파악 및 디버깅을 용이하게 했습니다.
  • CodefCardService 제거 및 기능 통합: CodefCardService 파일을 제거하고 해당 기능을 CodefAssetService로 통합하여 코드 중복을 줄이고 관련 로직을 한 곳에서 관리하도록 리팩토링했습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/main/java/org/umc/valuedi/domain/asset/repository/bank/bankAccount/BankAccountRepository.java
    • CodefConnection으로 은행 계좌를 조회하는 findByCodefConnection 메서드를 추가했습니다.
  • src/main/java/org/umc/valuedi/domain/asset/service/command/AssetSyncService.java
    • 클래스 레벨의 @Transactional 어노테이션을 제거했습니다.
    • 외부 API 호출과 분리된 DB 저장 로직을 위한 @Transactional(propagation = Propagation.REQUIRES_NEW) 메서드들을 추가했습니다.
    • 은행 및 카드 자산 동기화 로직을 리팩토링하여 API 호출과 DB 저장을 명확히 분리했습니다.
    • ObjectMapper 의존성을 제거했습니다.
    • 상세한 로깅을 추가했습니다.
  • src/main/java/org/umc/valuedi/domain/connection/service/command/ConnectionCommandService.java
    • 연동 및 연동 해제 메서드에 시작/종료 로그를 추가했습니다.
    • 접근 거부 에러 발생 시 상세 에러 로그를 추가했습니다.
    • 은행 연결 목표 비활성화 시 디버그 로그를 추가했습니다.
  • src/main/java/org/umc/valuedi/domain/connection/service/event/ConnectionEventListener.java
    • 연동 성공 이벤트 리스너의 로깅 메시지를 간소화하고 에러 로그를 개선했습니다.
  • src/main/java/org/umc/valuedi/global/config/AsyncConfig.java
    • assetFetchExecutorwaitForTasksToCompleteOnShutdownawaitTerminationSeconds 설정을 추가하여 Graceful Shutdown을 구현했습니다.
  • src/main/java/org/umc/valuedi/global/external/codef/service/CodefAccountService.java
    • 사용되지 않는 MemberException, MemberErrorCode, MemberRepository 임포트를 제거했습니다.
    • 계정 연결 및 삭제 성공/실패 시 상세 로그를 추가했습니다.
    • deleteAccount 메서드에서 businessType을 문자열로 변환하도록 수정했습니다.
    • handleFirstCreationhandleAddition 메서드에서 중복된 에러 로깅을 제거했습니다.
  • src/main/java/org/umc/valuedi/global/external/codef/service/CodefAssetService.java
    • 사용되지 않는 Function, Collectors 임포트를 제거했습니다.
    • API 호출 실패 및 경고 로깅 메시지를 개선했습니다.
    • getCards 메서드에서 응답 데이터 처리 로직을 간소화했습니다.
    • getCardApprovals 메서드에서 불필요한 주석을 제거했습니다.
  • src/main/java/org/umc/valuedi/global/external/codef/service/CodefCardService.java
    • 파일이 제거되었습니다. 해당 기능은 CodefAssetService로 통합되었습니다.
  • src/main/resources/application.yml
    • OpenFeign 클라이언트 설정을 추가하여 CodefApiClientconnectTimeout을 10초, readTimeout을 120초로 설정했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@seamooll seamooll changed the title [REFACTOR/#94] 카드사 연동 로직 리팩토링 및 로깅 보완 [REFACTOR/#94] 카드사 연동 로직 리팩토링 및 CODEF 로깅 시스템 보완 Feb 10, 2026
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

이번 PR은 외부 API 호출과 데이터베이스 트랜잭션을 분리하여 애플리케이션의 성능과 안정성을 크게 향상시키는 훌륭한 리팩토링입니다. 비동기 작업에 대한 Graceful Shutdown 도입과 타임아웃 설정 강화 또한 운영 안정성을 높이는 좋은 개선입니다. 전반적으로 로깅이 개선되어 관측 가능성도 높아졌습니다. 리뷰 중 런타임에 예외를 발생시킬 수 있는 치명적인 문제 하나와, 코드 일관성 및 설계를 개선할 수 있는 몇 가지 제안 사항을 발견했습니다.

Comment on lines +148 to 189
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveBankAccounts(List<BankAccount> accounts) {
if (accounts.isEmpty()) return;
try {
bankAccountRepository.saveAll(accounts);
} catch (DataIntegrityViolationException e) {
for (BankAccount account : accounts) {
try {
bankAccountRepository.save(account);
} catch (DataIntegrityViolationException ex) {
// 이미 존재하는 계좌는 무시
}
}
}
}

// 전체 승인 내역 조회 (API)
// CodefAssetService 내부에서 CodefAssetConverter를 통해 매칭까지 완료된 리스트 반환
List<CardApproval> approvals = codefAssetService.getCardApprovals(connection);
if (approvals.isEmpty()) {
log.info("조회된 승인내역이 없습니다.");
return false;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveBankTransactions(List<BankTransaction> transactions) {
bankTransactionRepository.bulkInsert(transactions);
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveCards(List<Card> cards) {
if (cards.isEmpty()) return;
try {
cardRepository.saveAll(cards);
} catch (DataIntegrityViolationException e) {
for (Card card : cards) {
try {
cardRepository.save(card);
} catch (DataIntegrityViolationException ex) {
// 이미 존재하는 카드는 무시
}
}
}
}

// 저장
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveCardApprovals(List<CardApproval> approvals) {
cardApprovalRepository.bulkInsert(approvals);
log.info("카드 승인내역 Bulk Insert 완료 - {}건", approvals.size());
return true;
}
}

Choose a reason for hiding this comment

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

medium

새로운 트랜잭션을 시작하기 위해 save... 메서드들을 public으로 만들고 @Transactional(propagation = Propagation.REQUIRES_NEW)를 사용한 것은 좋은 접근입니다. 하지만 스프링의 트랜잭션 프록시를 적용하기 위해 메서드를 public으로만 만드는 것은 캡슐화를 해칠 수 있습니다. 이 메서드들이 의도치 않게 다른 서비스에서 호출될 수 있기 때문입니다. 장기적인 유지보수성을 위해 다음과 같은 대안을 고려해볼 수 있습니다.

  1. save 메서드들을 담을 새로운 컴포넌트(예: AssetPersistenceService)를 만듭니다. AssetSyncService는 이 새 컴포넌트를 주입받아 사용합니다. 이것이 가장 깔끔한 접근 방식입니다.
  2. AssetSyncService에 자기 자신을 주입하여 프록시 인스턴스를 통해 public 트랜잭션 메서드를 호출합니다. 이는 흔한 해결 방법이지만 코드가 혼란스러워질 수 있습니다.

현재 구현도 동작은 하지만, 더 나은 캡슐화를 위해 리팩토링을 권장합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

♻️ refactor 코드 구조 개선 도희 도희 🔧 enhancement 기존 기능 개선

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] 카드사 연동 로직 리팩토링

1 participant