Skip to content

[FEAT] 학습 도메인 api 기본 구현#46

Merged
on1yoneprivate merged 13 commits into
developfrom
feat/#32-learning-status-api
Jul 24, 2026
Merged

[FEAT] 학습 도메인 api 기본 구현#46
on1yoneprivate merged 13 commits into
developfrom
feat/#32-learning-status-api

Conversation

@rkdehdrbs7885-oss

@rkdehdrbs7885-oss rkdehdrbs7885-oss commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

📍 개요

학습 도메인 api 기본 구현

⛓️‍💥 관련 이슈


🛠️ 작업 내용

  • 학습 결과 저장 api, 학습 진행률 조회 api

🔥 리뷰 요청 사항

리뷰어가 중점적으로 확인해주었으면 하는 내용을 작성해주세요.

  • 예외 코드 처리 방식

✅ 체크리스트

  • 코드 컨벤션을 준수했습니다.
  • 불필요한 코드 및 import를 제거했습니다.
  • 예외 처리를 적용했습니다.
  • 테스트를 완료했습니다.
  • 관련 Issue를 연결했습니다.

📎 참고 사항

Summary by CodeRabbit

  • 새 기능
    • /api/learnings/{learningId}/result로 학습 결과(점수·완료 정보)를 저장하고 결과(상태 포함)를 확인할 수 있습니다.
    • /api/learnings/{learningId}/progress로 해당 학습의 진행률을 조회할 수 있습니다.
    • 점수(0~100)와 학습 단계 ID 입력값에 대한 검증이 추가되었습니다.
  • 오류 처리 개선
    • 학습/학습 단계/사용자 존재 여부에 따라 더 명확한 오류 응답을 제공합니다.
  • 기타
    • 완료 상태 산정 로직이 추가/정리되어 진행률 계산이 안정화되었습니다.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

학습 결과 저장 및 사용자별 진행률 조회 API가 추가되었습니다. 요청·응답 DTO, 사용자 연관 진행 엔터티, JPA 저장소, 서비스 검증·계산 로직, REST 컨트롤러와 오류 코드가 구현되었습니다.

Changes

학습 진행 기능

Layer / File(s) Summary
도메인 계약과 진행 상태 모델
src/main/java/com/mr/domain/learning/dto/..., src/main/java/com/mr/domain/learning/entity/UserLearningProgress.java, src/main/java/com/mr/domain/*/exception/...
결과 저장 요청 검증과 결과·진행률 응답 DTO를 추가하고, UserLearningProgressUser 연관관계로 변경했습니다. 점수에 따라 NOT_STARTED, COMPLETED, RETRY 상태를 반환합니다.
학습 데이터 접근 계층
src/main/java/com/mr/domain/learning/repository/..., src/main/java/com/mr/domain/user/repository/UserRepository.java
학습·학습 단계·사용자·사용자별 진행 정보를 위한 JPA 저장소와 완료 단계 집계 쿼리를 추가했습니다.
결과 저장과 진행률 계산
src/main/java/com/mr/domain/learning/service/LearningService.java, src/main/java/com/mr/domain/learning/entity/LearningStep.java
사용자·학습·단계 존재 여부와 학습 단계 소속을 검증한 뒤 결과를 갱신 또는 생성하고, 전체 단계 대비 완료 단계 비율을 계산합니다.
학습 REST API 연결
src/main/java/com/mr/domain/learning/controller/LearningController.java
인증 사용자 정보를 사용해 POST /api/learnings/{learningId}/resultGET /api/learnings/{learningId}/progress를 호출하고 서비스 결과를 ApiResponse로 반환합니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant LearningController
  participant LearningService
  participant LearningRepositories
  Client->>LearningController: POST /api/learnings/{learningId}/result
  LearningController->>LearningService: saveResult(userId, learningId, request)
  LearningService->>LearningRepositories: 사용자·학습·단계·진행 정보 조회
  LearningRepositories-->>LearningService: 검증된 데이터
  LearningService-->>LearningController: SaveResultResultDTO
  LearningController-->>Client: ApiResponse

  Client->>LearningController: GET /api/learnings/{learningId}/progress
  LearningController->>LearningService: getLearningProgress(userId, learningId)
  LearningService->>LearningRepositories: 전체 단계 및 완료 단계 집계
  LearningRepositories-->>LearningService: 단계 수
  LearningService-->>LearningController: ProgressResultDTO
  LearningController-->>Client: ApiResponse
Loading

Possibly related PRs

  • Musereview/BE#45: 동일한 학습 API·서비스·DTO·엔터티·저장소 흐름과 직접 연결됩니다.
  • Musereview/BE#24: UserLearningProgress의 사용자 매핑과 진행 상태 로직이 연관됩니다.
  • Musereview/BE#31: 학습 단계 소속 검증과 LearningErrorStatus 처리 흐름이 연결됩니다.

Poem

점수는 저장되고 단계는 세어져
진행률이 둥글게 피어나네
RETRY를 지나 COMPLETED로
API가 결과를 건네주니
학습의 길도 한 칸 밝아지네 ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning 결과 저장 API는 부합하지만, 진행률 API가 이슈의 PATCH 요구와 달리 조회형 GET으로 구현되어 있어 요구사항을 완전히 충족하지 않습니다. 진행률 API의 HTTP 메서드와 요청/응답 DTO를 이슈 #32 기준으로 맞추고, 저장/업데이트 흐름이 실제 요구와 일치하도록 정리하세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 학습 도메인 API 기본 구현이라는 변경의 핵심을 간결하게 잘 담고 있습니다.
Out of Scope Changes check ✅ Passed DTO, 서비스, 레포지토리, 예외, 엔티티 변경이 모두 학습 결과 저장과 진행률 처리에 필요한 범위 안에 있습니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#32-learning-status-api

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

Comment @coderabbitai help to get the list of available commands.

@on1yoneprivate on1yoneprivate changed the title [Feat] 학습 도메인 api 기본 구현 [FEAT] 학습 도메인 api 기본 구현 Jul 24, 2026
Comment thread src/main/java/com/mr/domain/learning/service/LearningService.java Outdated
Comment thread src/main/java/com/mr/domain/learning/service/LearningService.java
Comment thread src/main/java/com/mr/domain/learning/dto/req/LearningResultSaveRequestDTO.java Outdated
Comment thread src/main/java/com/mr/domain/learning/dto/res/LearningResultResponseDTO.java Outdated

@on1yoneprivate on1yoneprivate left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

수고하셨습니다~
코멘트 확인해 주세요!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/com/mr/domain/learning/controller/LearningController.java`:
- Around line 36-42: Update the getLearningProgress endpoint mapping to match
the agreed API contract: use `@PatchMapping` for PATCH /{learningId}/progress if
this endpoint performs progress updates, or retain `@GetMapping` only when it is
strictly read-only and revise the API documentation accordingly.

In
`@src/main/java/com/mr/domain/learning/repository/UserLearningProgressRepository.java`:
- Line 12: The progress lookup must include both user and learning step. In
src/main/java/com/mr/domain/learning/repository/UserLearningProgressRepository.java:12-12,
replace findByUser_UserIdAndLearningId with a user-and-learningStepId query
method; in
src/main/java/com/mr/domain/learning/service/LearningService.java:51-58, update
saveResult() to pass learningStep.getId() and verify the existing progress-count
query remains aligned with the requested learning ID.

In `@src/main/java/com/mr/domain/learning/service/LearningService.java`:
- Around line 48-60: Validate in the learning-step lookup flow before querying
or updating UserLearningProgress that learningStep.getLearning().getId() matches
learning.getId(); when it does not, throw or return the existing
INVALID_LEARNING_STEP error. Keep the existing not-found handling and progress
creation/update behavior unchanged for valid steps.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f9675bec-d82f-4ba4-8362-c8b11b2a1607

📥 Commits

Reviewing files that changed from the base of the PR and between 274468e and 15b0fb4.

📒 Files selected for processing (12)
  • src/main/java/com/mr/domain/learning/controller/LearningController.java
  • src/main/java/com/mr/domain/learning/dto/req/LearningResultSaveRequestDTO.java
  • src/main/java/com/mr/domain/learning/dto/res/LearningProgressResponseDTO.java
  • src/main/java/com/mr/domain/learning/dto/res/LearningResultResponseDTO.java
  • src/main/java/com/mr/domain/learning/entity/UserLearningProgress.java
  • src/main/java/com/mr/domain/learning/exception/LearningErrorStatus.java
  • src/main/java/com/mr/domain/learning/repository/LearningRepository.java
  • src/main/java/com/mr/domain/learning/repository/LearningStepRepository.java
  • src/main/java/com/mr/domain/learning/repository/UserLearningProgressRepository.java
  • src/main/java/com/mr/domain/learning/service/LearningService.java
  • src/main/java/com/mr/domain/user/exception/UserErrorStatus.java
  • src/main/java/com/mr/domain/user/repository/UserRepository.java

Comment thread src/main/java/com/mr/domain/learning/service/LearningService.java

@p1001q p1001q left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 사소한 수정 제안 사항

  • LearningController/LearningService// 임시 주석 2곳
  • LearningErrorStatus에 세미콜론 두 개(;;) 오타 있어요(컴파일은 되지만 지저분함)
  • UserErrorStatus.java 파일 끝에 개행 문자 빠짐

요런 것들은 나중에 리팩토링 때나 다음 피알 때 고쳐도 되니까...
고생 많으셨습니다!!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/mr/domain/learning/service/LearningService.java (1)

52-61: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

중등 생성 경쟁을 원자로 처리해 주세요.

UserLearningProgress(user_id, learning_step_id) 유니크 인덱스가 있으니 데이터 중복은 막지만, findBy... 조회 후 save()로 분기하는 check-then-act 구조가 @Transactional 하더라도 동시 요청 두 트랜잭션이 동시에 “없음”을 보고 INSERT 경쟁을 유발합니다. 이 경기는 트랜잭션이 커밋 시점에 실패로 바뀌어 500 응답을 만들 수 있으니, @Transactional(isolation = Isolation.SERIALIZABLE)/PessimisticLock lock 기반 read, 또는 save() 실패 후 getOrCreate retry처럼 유니크 제약 위반을 우회하지 않는 전략으로 조회-생성을 묶으면 좋습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/mr/domain/learning/service/LearningService.java` around
lines 52 - 61, Update the UserLearningProgress lookup-and-create flow in the
surrounding service method to make concurrent creation for the (user_id,
learning_step_id) pair atomic, using SERIALIZABLE isolation, a pessimistic-lock
read, or a save-failure retry with get-or-create behavior. Preserve the unique
constraint and ensure concurrent requests resolve to the existing progress
instead of propagating a uniqueness violation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/main/java/com/mr/domain/learning/service/LearningService.java`:
- Around line 52-61: Update the UserLearningProgress lookup-and-create flow in
the surrounding service method to make concurrent creation for the (user_id,
learning_step_id) pair atomic, using SERIALIZABLE isolation, a pessimistic-lock
read, or a save-failure retry with get-or-create behavior. Preserve the unique
constraint and ensure concurrent requests resolve to the existing progress
instead of propagating a uniqueness violation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b0318f2e-b9c5-43a5-8722-fa842c4377da

📥 Commits

Reviewing files that changed from the base of the PR and between ed2975d and 47f7de2.

📒 Files selected for processing (4)
  • src/main/java/com/mr/domain/learning/controller/LearningController.java
  • src/main/java/com/mr/domain/learning/exception/LearningErrorStatus.java
  • src/main/java/com/mr/domain/learning/service/LearningService.java
  • src/main/java/com/mr/domain/user/exception/UserErrorStatus.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/mr/domain/learning/exception/LearningErrorStatus.java
  • src/main/java/com/mr/domain/user/exception/UserErrorStatus.java

@on1yoneprivate on1yoneprivate left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

코드래빗 제안 사항 추후에 고려해 보면 좋을 것 같습니다~
수고 많으셨어요

@on1yoneprivate
on1yoneprivate merged commit cacec75 into develop Jul 24, 2026
2 checks passed
@on1yoneprivate
on1yoneprivate deleted the feat/#32-learning-status-api branch July 24, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Feature - 학습 진행 상태 및 결과 저장 API 구현

3 participants