Skip to content

Comments

prod : 프로덕션과 테스트 서버 파이프라인 분리#225

Merged
polyglot-k merged 841 commits intoprodfrom
develop
Aug 7, 2025
Merged

prod : 프로덕션과 테스트 서버 파이프라인 분리#225
polyglot-k merged 841 commits intoprodfrom
develop

Conversation

@polyglot-k
Copy link
Contributor

✨ 구현한 기능

📢 논의하고 싶은 내용

🎸 기타

chominju02 and others added 30 commits August 3, 2025 02:57
MOSU-153 refactor: 신청 조회시 신청 상태 구조 변경
MOSU-184 refactor: notify 과정 중 에러 발생 시 discord 알림 전송 구현
Quartz 를 통한 Application내에 실패한 객체를 Failure Log 로 이동 및 일정 주기에 따라서 삭제 하도록 구성
Fix#187: Cross Domain 쿠키 설정 변경
Fix: 쿠키 도메인 설정 주석 처리
polyglot-k and others added 26 commits August 6, 2025 21:42
MOSU-216 feat: 카카오 심사 성공에 따른 필드 추가
비회원 신청 및 가상 계좌 신청에 따른 시험 인원 수 갱신
MOSU-205 feature: 관리자 시험 마감 기능 구현
MOSU-218 내 문의글 조회 내역 기능 구현
@coderabbitai
Copy link

coderabbitai bot commented Aug 7, 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.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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.
  • 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.

Support

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

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 generate unit tests to generate unit tests 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.

@polyglot-k polyglot-k merged commit bf3089a into prod Aug 7, 2025
3 checks passed
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.

Summary of Changes

Hello @polyglot-k, 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!

My primary goal with this pull request was to establish a clear separation between our production and test server pipelines, enabling more controlled and reliable deployments. Beyond that, I've undertaken a significant architectural overhaul, refactoring numerous core modules to adopt a more robust, event-driven design. This includes a complete rewrite of key functionalities like payment processing, application submissions, and refund management, alongside the introduction of several new features to enhance the platform's capabilities.

Highlights

  • Deployment Strategy: I've implemented a robust Blue/Green deployment strategy using Docker Compose and Caddy, enabling seamless transitions between production and test environments with minimal downtime.
  • Application Packaging and Runtime: I've migrated the application's packaging from JAR to WAR and updated the base JDK to Amazon Corretto, aligning with modern deployment practices and improving compatibility with servlet containers.
  • Transactional Event-Driven Architecture: I've introduced a comprehensive transactional event-driven architecture across core business domains like payments, applications, refunds, inquiries, and user profiles, significantly enhancing system reliability and maintainability.
  • Real-time Quota Management with Caching: I've integrated Redis-based atomic caching for managing exam quotas, ensuring real-time accuracy and preventing over-subscription, complete with robust recovery mechanisms.
  • New Feature Development: I've developed a suite of new features, including extensive admin functionalities, event and form management, a recommendation system, virtual account payment processing, and a sophisticated notification system for various user interactions.
  • Enhanced Testing Infrastructure: I've incorporated Testcontainers into the build process, which will greatly improve the reliability and consistency of our integration tests by providing disposable, real service containers.
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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

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 issue 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 or fill out our survey to provide feedback.

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.

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

This pull request introduces a significant refactoring to separate production and test pipelines, including a blue-green deployment strategy. The changes are extensive, touching build configurations, deployment scripts, and a major overhaul of application services. The refactoring of services into smaller, more focused components is a great improvement for maintainability. However, there are several critical and high-severity issues that need to be addressed, such as a build-breaking typo in build.gradle, risky in-place file modifications in the deployment script, and potential data integrity issues in the OAuth user handling logic. I've provided detailed comments and suggestions for these points.

testImplementation 'org.springframework.boot:spring-boot-testcontainers:3.3.5'
testImplementation 'org.testcontainers:testcontainers:1.19.3'
testImplementation 'org.testcontainers:junit-jupiter:1.19.3'
testImplementation 'org.testcoscntainers:mysql:1.20.0'

Choose a reason for hiding this comment

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

critical

There is a typo in the Testcontainers dependency. It should be org.testcontainers instead of org.testcoscntainers. This will cause a build failure.

    testImplementation 'org.testcontainers:mysql:1.20.0'


echo "✅ 새 컨테이너 헬스 체크 성공."

sudo sed -i -E "s|(reverse_proxy /api/v1/\* localhost:)[0-9]+|\1${TARGET_PORT}|" /etc/caddy/Caddyfile

Choose a reason for hiding this comment

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

high

Modifying the Caddyfile in-place using sed is risky. If the file format changes, this command might fail silently or corrupt the configuration. A more robust approach would be to use a template for your Caddyfile and generate the final configuration with the correct port before reloading Caddy. You can use environment variables directly in Caddyfiles with the env global option.

Comment on lines 63 to 77
final UserJpaEntity newUser = UserJpaEntity.builder()
.loginId(info.email())
.gender(Gender.MALE)
.name(info.name())
.password("")
.birth(LocalDate.now())
.userRole(UserRole.ROLE_USER)
//TODO kakao 정보 null일 경우 후처리 필요, ServiceTerm 승인 시 처리 구현
.loginId(info.email() != null ? info.email() : "NA")
.gender(info.gender() != null ? info.gender() : Gender.MALE)
.name(info.name() != null ? info.name() : "NA")
.birth(info.birthDay() != null ? info.birthDay()
: LocalDate.EPOCH)
.phoneNumber(info.phoneNumber() != null ? info.phoneNumber()
: "010-0000-0000")
.userRole(UserRole.ROLE_PENDING)
.provider(AuthProvider.KAKAO)
.agreedToTermsOfService(true)
.agreedToPrivacyPolicy(true)
.agreedToMarketing(false)
.build();

Choose a reason for hiding this comment

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

high

Using placeholder values like "NA" or LocalDate.EPOCH for user information that might be missing from the OAuth provider can lead to data integrity issues and unexpected behavior later. It would be more robust to either:

  1. Throw an exception if essential information is missing, forcing the user to provide it.
  2. Redirect the user to a profile completion page where they can fill in the missing details.

The TODO comment indicates you are aware of this, but this is a significant issue that should be addressed.

ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-Duser.timezone=GMT+9", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"] No newline at end of file
FROM amazoncorretto:21
COPY build/libs/*SNAPSHOT.war app.war

Choose a reason for hiding this comment

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

medium

The pattern *SNAPSHOT.war is brittle as it will fail if you build a release version (which typically doesn't contain 'SNAPSHOT' in its name). Consider using a more generic pattern like *.war if you are sure there will be only one WAR file. An even more robust approach would be to rename the artifact to a fixed name (e.g., app.war) in your build.gradle file.

COPY build/libs/*.war app.war


dependencies {

implementation fileTree(dir: 'libs', include: ['*.jar'])

Choose a reason for hiding this comment

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

medium

Including JARs from a local libs directory is generally discouraged. It makes dependency management harder and the build less reproducible. It's better to publish these artifacts to a Maven repository (like Nexus, Artifactory, or even a local one) and declare them as regular dependencies.

Comment on lines +52 to +58
public void deleteByBannerId(Long bannerId) {
try {
bannerJpaRepository.deleteById(bannerId);
} catch (Exception e) {
throw new CustomRuntimeException(ErrorCode.BANNER_DELETE_FAILURE);
}
}

Choose a reason for hiding this comment

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

medium

Catching a generic Exception is a bad practice as it can hide underlying issues. deleteById does not throw an exception if the entity is not found. It's better to check for the existence of the banner first and throw a specific exception if it's not found. This provides clearer error handling.

    public void deleteByBannerId(Long bannerId) {
        if (!bannerJpaRepository.existsById(bannerId)) {
            throw new CustomRuntimeException(ErrorCode.BANNER_NOT_FOUND);
        }
        bannerJpaRepository.deleteById(bannerId);
    }

Comment on lines +74 to +87
public void examDateNotPassed(List<ExamJpaEntity> exams) {
boolean hasPassedExam = false;

for (ExamJpaEntity exam : exams) {
if (exam.getDeadlineTime().isBefore(LocalDateTime.now())) {
exam.close();
hasPassedExam = true;
}
}

if (hasPassedExam) {
throw new CustomRuntimeException(ErrorCode.EXAM_DATE_PASSED);
}
}

Choose a reason for hiding this comment

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

medium

This validation method has a side effect of modifying the state of ExamJpaEntity by calling exam.close(). Validators should be idempotent and free of side effects. The state modification should be handled in a service layer method after validation has passed. This separation makes the code easier to understand and test.

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.

5 participants