Skip to content

20260223 #239 qr코드 url 반환 및 라운드 상태 업데이트#240

Merged
discipline24 merged 3 commits intomainfrom
20260223-#239-qr코드-url-반환-및-라운드-상태-업데이트
Feb 23, 2026

Hidden character warning

The head ref may contain hidden characters: "20260223-#239-qr\ucf54\ub4dc-url-\ubc18\ud658-\ubc0f-\ub77c\uc6b4\ub4dc-\uc0c1\ud0dc-\uc5c5\ub370\uc774\ud2b8"
Merged

20260223 #239 qr코드 url 반환 및 라운드 상태 업데이트#240
discipline24 merged 3 commits intomainfrom
20260223-#239-qr코드-url-반환-및-라운드-상태-업데이트

Conversation

@nayoung04
Copy link
Contributor

@nayoung04 nayoung04 commented Feb 22, 2026

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • QR 토큰 생성 시 완전한 QR URL을 반환하도록 개선되었습니다.
    • 환경(운영/개발)에 따라 적절한 URL이 자동으로 선택됩니다.
  • 개선사항

    • 출석 상태 유지 관리 작업이 트랜잭션 격리 수준을 개선했습니다.

@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

Warning

Rate limit exceeded

@nayoung04 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 59 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

출석 관리 시스템의 QR 토큰 생성 및 배포 로직을 개선합니다. QR URL 생성 기능을 새로 추가하고, 환경별로 프론트엔드 URL을 동적으로 선택하도록 수정합니다. 또한 스케줄러 작업의 트랜잭션 격리 정책과 실행 주기를 조정합니다.

Changes

Cohort / File(s) Summary
Quartz 스케줄링 설정
backend/src/main/.../attendance/config/AttendanceQuartzConfig.java
출석 상태 유지보수 작업의 cron 표현식을 변경하여 매시간 30분 간격 실행에서 매시간 0분(정각)에만 실행되도록 조정
데이터 무결성 제약조건
backend/src/main/.../attendance/entity/Attendance.java
(round_id, device_id) 복합 고유 제약조건 제거; (round_id, user_id) 제약조건은 유지
QR 토큰 서비스 레이어
backend/src/main/.../attendance/service/QrTokenStreamService.java
환경별 프론트엔드 URL 설정 추가(프로덕션/개발); 새로운 createQrUrl() 메서드로 완전한 QR URL 생성; 응답 페이로드를 원본 토큰에서 생성된 QR URL로 변경
출석 라운드 비즈니스 로직
backend/src/main/.../attendance/service/AttendanceRoundService.java
QrTokenStreamService 의존성 주입 추가; issueQrToken() 메서드를 qrTokenStreamService.createQrUrl()을 통해 QR URL 생성하도록 수정; runRoundStatusMaintenance() 메서드에 @Transactional(propagation = Propagation.REQUIRES_NEW) 추가
컨트롤러 포맷팅
backend/src/main/.../attendance/controller/AttendanceRoundController.java
issueQrToken() 반환문 이후 빈 줄 추가(순수 포맷팅 변경)

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client/Controller
    participant RoundService as AttendanceRoundService
    participant QrService as QrTokenStreamService
    participant Env as Environment Config

    Client->>RoundService: issueQrToken(roundId)
    RoundService->>RoundService: 토큰 생성 (RoundQrTokenUtil)
    RoundService->>QrService: createQrUrl(roundId, token)
    QrService->>Env: 활성 프로필 확인 (prod/dev)
    Env-->>QrService: 프론트엔드 URL 반환
    QrService->>QrService: QR URL 구성<br/>(baseUrl + path + params)
    QrService-->>RoundService: qrUrl 반환
    RoundService-->>Client: AttendanceRoundQrTokenResponse<br/>(qrUrl 포함)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • discipline24
  • Yooonjeong

Poem

🐰 토큰에서 QR로, 꼬리 흔들며 춤을 춰요
환경 따라 URL 달라지니, 똑똑해졌네요!
매정각 실행, 제약도 빼고,
출석 관리는 이제 더 우아하게! 🎯✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 풀 리퀘스트 제목은 변경 사항의 주요 내용을 정확하게 반영합니다. QR 코드 URL 반환 기능 추가와 라운드 상태 업데이트 스케줄링 변경이라는 핵심 변경을 명확하게 요약합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 20260223-#239-qr코드-url-반환-및-라운드-상태-업데이트

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 and usage tips.

Copy link

@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: 1

Caution

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

⚠️ Outside diff range comments (1)
backend/src/main/java/org/sejongisc/backend/attendance/service/AttendanceRoundService.java (1)

189-201: ⚠️ Potential issue | 🟡 Minor

주석이 현재 크론 스케줄과 불일치

Line 192의 (cron: 0분, 30분마다 실행) 주석이 AttendanceQuartzConfig에서 변경된 크론 표현식 "0 * * * * ?" (매분 실행)과 일치하지 않습니다.

📝 주석 수정 제안
-   * (cron: 0분, 30분마다 실행)
+   * (cron: 매분 실행)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@backend/src/main/java/org/sejongisc/backend/attendance/service/AttendanceRoundService.java`
around lines 189 - 201, The javadoc on runRoundStatusMaintenance incorrectly
states "(cron: 0분, 30분마다 실행)"; update this comment to reflect the actual
schedule used in AttendanceQuartzConfig (cron "0 * * * * ?" — every minute) or
make the comment dynamic by referencing AttendanceQuartzConfig so they stay in
sync; modify the comment above the runRoundStatusMaintenance method to
accurately describe the cron expression or mention that the schedule is defined
in AttendanceQuartzConfig.
🧹 Nitpick comments (2)
backend/src/main/java/org/sejongisc/backend/attendance/service/QrTokenStreamService.java (2)

111-123: QR 토큰의 URL 인코딩 누락 가능성

token 값에는 :(콜론) 등의 특수 문자가 포함됩니다 (roundId:expiresAt:signature 형식). RFC 3986상 쿼리 파라미터에서 :는 허용되지만, 일부 프론트엔드 URL 파서나 QR 스캐너에서 예기치 않게 동작할 수 있습니다. URLEncoder를 사용해 token 값을 인코딩하면 더 안전합니다.

♻️ 제안하는 수정
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 ...
   public String createQrUrl(UUID roundId, String token) {
     String baseUrl = devFrontendUrl;
 
     for (String profile : environment.getActiveProfiles()) {
       if ("prod".equalsIgnoreCase(profile)) {
         baseUrl = prodFrontendUrl;
         break;
       }
     }
 
-    return String.format("%s%s?roundId=%s&token=%s", baseUrl, ATTENDANCE_PATH, roundId, token);
+    return String.format("%s%s?roundId=%s&token=%s", baseUrl, ATTENDANCE_PATH, roundId,
+        URLEncoder.encode(token, StandardCharsets.UTF_8));
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@backend/src/main/java/org/sejongisc/backend/attendance/service/QrTokenStreamService.java`
around lines 111 - 123, createQrUrl builds the QR URL using a raw token that can
contain special chars (token format: roundId:expiresAt:signature); update
createQrUrl to URL-encode the token before inserting into the query string (use
URLEncoder with UTF-8) while keeping the same baseUrl selection logic
(devFrontendUrl/prodFrontendUrl via environment.getActiveProfiles()) and the
same ATTENDANCE_PATH; ensure you only encode the token (UUID roundId can remain
as-is) and handle/propagate the checked UnsupportedEncodingException or use
StandardCharsets.UTF_8 to avoid checked exceptions.

43-49: 두 환경의 URL이 모든 프로필에 정의되어야 함 — 설정 누락 시 기동 실패

@Value("${app.prod-frontend-url}")@Value("${app.dev-frontend-url}")가 모두 주입되므로, dev 환경에서도 app.prod-frontend-url이 정의되어야 하고 그 반대도 마찬가지입니다. 누락 시 BeanCreationException으로 기동이 실패합니다.

기본값을 지정하거나, 프로필별로 하나의 프로퍼티(app.frontend-url)만 사용하는 방식이 더 간결합니다.

♻️ 대안 1: 기본값 지정
-  `@Value`("${app.prod-frontend-url}")
-  private String prodFrontendUrl;
+  `@Value`("${app.prod-frontend-url:}")
+  private String prodFrontendUrl;

-  `@Value`("${app.dev-frontend-url}")
-  private String devFrontendUrl;
+  `@Value`("${app.dev-frontend-url:}")
+  private String devFrontendUrl;
♻️ 대안 2: 프로필별 단일 프로퍼티

각 프로필의 application-{profile}.yml에서 app.frontend-url을 정의하고, 서비스에서는 하나만 주입:

`@Value`("${app.frontend-url}")
private String frontendUrl;

이렇게 하면 Environment 주입과 프로필 루프가 불필요해집니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@backend/src/main/java/org/sejongisc/backend/attendance/service/QrTokenStreamService.java`
around lines 43 - 49, QrTokenStreamService currently injects both
prodFrontendUrl and devFrontendUrl which forces both app.prod-frontend-url and
app.dev-frontend-url to be defined for any profile; replace the two `@Value`
fields with a single `@Value`("${app.frontend-url}") private String frontendUrl
(remove prodFrontendUrl, devFrontendUrl and the Environment loop) and update
application-{profile}.yml files to define app.frontend-url per profile, or
alternatively provide safe defaults in the existing `@Value` annotations if you
prefer to keep two fields; ensure all references in QrTokenStreamService use the
new frontendUrl field.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@backend/src/main/java/org/sejongisc/backend/attendance/config/AttendanceQuartzConfig.java`:
- Line 19: ROUND_STATE_CRON was changed to "0 * * * * ?" which runs every
minute; confirm intended schedule and either revert the constant in
AttendanceQuartzConfig (ROUND_STATE_CRON) to the 30-minute cron (e.g. "0 0/30 *
* * ?" or the previous value) or, if the every-minute behavior is intended,
update the comment in AttendanceRoundService (the comment near line ~192 that
currently says "(cron: 0분, 30분마다 실행)") to reflect the new schedule; make the
change only in one place (constant or comment) so code and documentation stay
consistent.

---

Outside diff comments:
In
`@backend/src/main/java/org/sejongisc/backend/attendance/service/AttendanceRoundService.java`:
- Around line 189-201: The javadoc on runRoundStatusMaintenance incorrectly
states "(cron: 0분, 30분마다 실행)"; update this comment to reflect the actual
schedule used in AttendanceQuartzConfig (cron "0 * * * * ?" — every minute) or
make the comment dynamic by referencing AttendanceQuartzConfig so they stay in
sync; modify the comment above the runRoundStatusMaintenance method to
accurately describe the cron expression or mention that the schedule is defined
in AttendanceQuartzConfig.

---

Nitpick comments:
In
`@backend/src/main/java/org/sejongisc/backend/attendance/service/QrTokenStreamService.java`:
- Around line 111-123: createQrUrl builds the QR URL using a raw token that can
contain special chars (token format: roundId:expiresAt:signature); update
createQrUrl to URL-encode the token before inserting into the query string (use
URLEncoder with UTF-8) while keeping the same baseUrl selection logic
(devFrontendUrl/prodFrontendUrl via environment.getActiveProfiles()) and the
same ATTENDANCE_PATH; ensure you only encode the token (UUID roundId can remain
as-is) and handle/propagate the checked UnsupportedEncodingException or use
StandardCharsets.UTF_8 to avoid checked exceptions.
- Around line 43-49: QrTokenStreamService currently injects both prodFrontendUrl
and devFrontendUrl which forces both app.prod-frontend-url and
app.dev-frontend-url to be defined for any profile; replace the two `@Value`
fields with a single `@Value`("${app.frontend-url}") private String frontendUrl
(remove prodFrontendUrl, devFrontendUrl and the Environment loop) and update
application-{profile}.yml files to define app.frontend-url per profile, or
alternatively provide safe defaults in the existing `@Value` annotations if you
prefer to keep two fields; ensure all references in QrTokenStreamService use the
new frontendUrl field.

Copy link
Contributor

@discipline24 discipline24 left a comment

Choose a reason for hiding this comment

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

고생하셨습니다

@discipline24 discipline24 merged commit 4546176 into main Feb 23, 2026
1 check passed
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.

⚙️ [기능추가][출석체크] QR 코드 URL 반환 및 라운드 상태 업데이트

2 participants