Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - zzoe2346/MyCodingTest_BACKEND: ✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중) · GitHub
Skip to content

Repository files navigation


MyCodingTest
MY CODING TEST

백준 문제 풀이 기록을 자동 수집하고 복습을 도와주는 서비스

JavaSpring BootMySQLAWS

Data Collection & Review PipelineMulti-Module ArchitectureModule StructureDomain ModelGetting StartedRelated Repositories


Deployment Architecture

image

CI/CD Pipeline

image

Data Collection & Review Pipeline

image

Multi-Module Architecture

본 프로젝트는 DDD(Domain-Driven Design)계층형 아키텍처를 적용한 멀티 모듈 구조로 설계되었습니다.

⭐️ 리팩토링 과정에대한 글

image

의존성 규칙

  • 상위 레이어 → 하위 레이어 방향으로만 의존
  • Domain Layer는 어떤 모듈에도 의존하지 않음
  • Infrastructure Layer는 Domain의 Repository 인터페이스를 구현

Module Structure

📦 module-api

Presentation Layer - REST API 엔드포인트

api/
├── SwaggerConfig.java # Swagger API 문서 설정
├── auth/ # 인증 관련 API
├── collector/ # 외부 플랫폼 데이터 수집 API
├── judgment/ # 채점 결과 조회 API
└── review/ # 오답노트 CRUD API
# 각 패키지 내부 구성은 다음과 같습니다.
├── ReviewCommandController.java
├── ReviewQueryController.java
└── dto/

Dependencies: module-application, module-domain, module-security


📦 module-application

Application Layer - 비즈니스 로직의 응집 및 트랜잭션 경계 설정, 도메인 객체들을 조합하여 비즈니스 유스케이스를 완성

application/
├── config/
│ └── AsyncConfig.java # 비동기 처리 설정
├── collector/ # 데이터 수집 서비스(Orchestration)
│ ├── BojIngestionService.java
│ └── dto/
├── judgment/ # 채점 처리 서비스
│ ├── command/
│ │ ├── JudgmentCommandService.java
│ │ ├── CreateBojJudgmentCommand.java
│ │ └── DeleteJudgmentCommand.java
│ ├── query/
│ │ ├── JudgmentQueryService.java
│ │ └── JudgmentInfo.java
│ └── support/
├── problem/ # 문제 정보 서비스
│ └── command/
├── review/ # 복습 관리 서비스
│ ├── command/
│ │ ├── ReviewCommandService.java
│ │ ├── CreateReviewCommand.java
│ │ ├── UpdateReviewCommand.java
│ │ └── UpdateReviewResult.java
│ └── query/
│ ├── ReviewQueryService.java
│ ├── ReviewInfo.java
│ ├── ReviewSummary.java
│ └── ReviewSummaryPage.java
└── user/ # 사용자 관리 서비스
├── command/
│ ├── UserCommandService.java
│ ├── SyncUserCommand.java
│ └── WelcomeService.java # 신규 사용자 온보딩
└── event/
└── UserCreatedEventListener.java # 비동기 이벤트 리스너

Dependencies: module-domain, module-infra-rdb


📦 module-domain

Domain Layer - 핵심 비즈니스 로직 (순수 도메인)

domain/
├── common/ # 공통
│ ├── DomainPage.java # 페이지네이션 VO
│ ├── Platform.java # 플랫폼 Enum
│ └── exception/ # 도메인 예외
│ ├── ResourceNotFoundException.java
│ ├── InvalidOwnershipException.java
│ └── NotOurUserException.java
├── judgment/ # ⭐️채점 도메인
│ ├── Judgment.java # Entity (Aggregate Root)
│ ├── JudgmentRepository.java # Repository Interface
│ ├── JudgmentStatus.java # Enum
│ ├── SubmissionInfo.java # Value Object (제출 정보)
│ ├── MetaData.java # Value Object (플랫폼별 메타데이터 인터페이스)
│ └── BojMetaData.java # BOJ 플랫폼 메타데이터 구현체
├── problem/ # 문제 도메인
│ ├── Problem.java
│ └── ProblemRepository.java
├── review/ # ⭐️리뷰 도메인
│ ├── Review.java # Entity (Aggregate Root)
│ ├── ReviewRepository.java # Repository Interface
│ └── ReviewStatus.java # Enum (TO_DO, IN_PROGRESS, COMPLETED)
└── user/ # 사용자 도메인
├── User.java
├── UserRepository.java
└── UserCreatedEvent.java # 사용자 신규 생성 시 이벤트

Dependencies: 없음 (Spring Context, Validation만 사용)


📦 module-infra-rdb

Infrastructure Layer - JPA 기반 영속성 구현

infra/
├── BaseEntity.java # 공통 엔티티 (생성/수정 시간)
├── judgment/
│ ├── JudgmentEntity.java # JPA Entity
│ ├── JpaJudgmentRepository.java # Spring Data JPA
│ ├── JudgmentRepositoryImpl.java # Repository 구현체
│ └── MetaDataConverter.java # MetaData JSON 변환기
├── problem/
│ ├── ProblemEntity.java
│ ├── JpaProblemRepository.java
│ └── ProblemRepositoryImpl.java
├── review/
│ ├── ReviewEntity.java
│ ├── JpaReviewRepository.java
│ └── ReviewRepositoryImpl.java
└── user/
├── UserEntity.java
├── JpaUserRepository.java
└── UserRepositoryImpl.java

Dependencies: module-domain


📦 module-security

Security Layer - 인증/인가

security/
├── SecurityConfig.java # Spring Security 설정
├── CustomOAuth2SuccessHandler.java # OAuth2 성공 핸들러
├── CustomUserDetails.java # UserDetails 구현
├── JwtFilter.java # JWT 인증 필터
├── JwtUtil.java # JWT 유틸리티
├── CookieUtil.java # 쿠키 관리
└── GlobalExceptionHandler.java # 예외 핸들러

Dependencies: module-domain, module-application


Domain Model

erDiagram
USER {
Long id PK
String name
String email
String picture
String oauthProvider
String oauthId
LocalDateTime createdAt
}
PROBLEM {
Long id PK
Integer problemNumber
String problemTitle
Platform platform
LocalDateTime createdAt
LocalDateTime updatedAt
}
JUDGMENT {
Long id PK
Long problemId FK
Long userId FK
SubmissionInfo submissionInfo "VO (submissionId, status, platform, metaData, sourceCode)"
LocalDateTime createdAt
LocalDateTime updatedAt
}
REVIEW {
Long id PK
Long problemId FK
Long userId FK
String content
Integer difficultyLevel
Integer importanceLevel
String revisedCode
LocalDateTime reviewedAt
ReviewStatus status
boolean favorited
LocalDateTime recentSubmitAt
String recentResult
LocalDateTime createdAt
LocalDateTime updatedAt
}
USER ||--o{ JUDGMENT : "owns"
USER ||--o{ REVIEW : "owns"
PROBLEM ||--o{ JUDGMENT : "has"
PROBLEM ||--o{ REVIEW : "has"
Loading

Getting Started

Prerequisites

  • Java 21
  • MySQL 8.0+
  • Gradle 8.x

Run Locally

./gradlew bootRun

Run Tests

./gradlew test

Build

./gradlew :module-api:bootJar

Related Repositories

RepositoryDescription
MyCodingTest_FEReact 프론트엔드
MyCodingTest_ConnectorChrome Extension

About

✏️ 코딩 문제 풀이와 복습에만 집중할 수 있도록 도와드립니다(서비스 중)

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages