Skip to content

[25.07.09 / TASK-215] Feature - 뉴스레터 배치 이슈 대응 & 리마인더 추가 #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 13, 2025

Conversation

ooheunda
Copy link
Contributor

@ooheunda ooheunda commented Jul 9, 2025

🔥 변경 사항

  • 주간 통계 이슈 픽스
    • 일주일 간의 누적값 전부 Sum -> 오늘 통계/일주일 전 통계 누적값을 각각 구한뒤 차이 계산
    • 오늘자 통계를 확인해 판단했던 토큰 만료 확인 메서드(_get_expired_token_user_ids)를 주간 통계 함수(_get_users_weekly_stats_chunk)로 통합
    • => 해당사항 분석 배치로 이동 (25.07.13)
  • 글 미작성 유저에 대한 리마인더 추가
    • 토큰이 정상인 유저이면, 개인 트렌드/개인 통계 요약/리마인더 셋 중 하나만 있어도 개인 리포트 표시
    • 토큰이 만료된 유저이면, 셋 다 있어도 skip됩니다! (아래 차트 참고)
    • => 해당사항 분석 배치로 이동 (25.07.13)
  • env를 직접 로드하는 대신 Django settings를 통해 로드하도록 수정

25.07.13 회의 후 수정된 내용

  • user_weekly_trend 레코드가 없는 경우 토큰 만료 유저로 간주
  • 데이터 세팅은 모두 분석 배치에서 실행
  • 주간 통계 / 리마인더(최근 글 정보 get) 로직 삭제
  • 관련한 context 스키마 삭제 => models.py에 정의된 데이터클래스 하나로 관리

유저별 포함 내용 차트

flowchart TD
    A[배치 시작] --> B{Target Users 존재?}
    B -->|No| C[배치 종료]
    
    B -->|Yes| D{WeeklyTrend 존재?}
    D -->|No| E[배치 종료]
    
    D --> |Yes| F[유저 청크별 처리]
    F --> G{토큰 만료?}
    
    G -->|No| H{개인 트렌드 존재?}
    G -->|Yes| I{개인 트렌드 존재?}
    
    H -->|Yes| J[case1: 글 작성 정상 유저]
    H -->|No| K[case2: 글 미작성 정상 유저]
    
    I -->|Yes| L[case3: 글 작성 비정상 유저]
    I -->|No| M[case4: 글 미작성 비정상 유저]
    
    J --> J1[주간 공통 트렌드]
    J1 --> J2[개인 주간 통계]
    J2 --> J3[개인 트렌드]
    J3 --> N[종료]
    
    K --> K1[주간 공통 트렌드]
    K1 --> K2[개인 주간 통계]
    K2 --> K3[글 작성 리마인드]
    K3 --> N
    
    L --> L1[토큰 만료 박스]
    L1 --> L2[주간 공통 트렌드]
    L2 --> N
    
    M --> L1[토큰 만료 박스]
    
    style A fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style B fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style C fill:#e53e3e,stroke:#c53030,stroke-width:2px,color:#ffffff
    style D fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style E fill:#e53e3e,stroke:#c53030,stroke-width:2px,color:#ffffff
    style F fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style G fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style H fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style I fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
    style J fill:#38a169,stroke:#2f855a,stroke-width:2px,color:#ffffff
    style K fill:#38a169,stroke:#2f855a,stroke-width:2px,color:#ffffff
    style L fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#ffffff
    style M fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#ffffff
    style J1 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style J2 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style J3 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style K1 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style K2 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style K3 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style L1 fill:#ed8936,stroke:#dd6b20,stroke-width:2px,color:#ffffff
    style L2 fill:#3182ce,stroke:#2c5aa0,stroke-width:2px,color:#ffffff
    style N fill:#2d3748,stroke:#4a5568,stroke-width:2px,color:#ffffff
Loading

🏷 관련 이슈

  • 이슈 내용은 노션에서 참고하실 수 있습니다!

📸 스크린샷 (UI 변경 시 필수)

image
(*위 통계 요약 박스와는 무관)
user_weekly_trend 데이터가 없는 사용자인 경우 위 리마인더 박스가 표시됩니다!

📌 체크리스트

  • 기능이 정상적으로 동작하는지 테스트 완료
  • 코드 스타일 가이드 준수 여부 확인
  • 관련 문서 업데이트 완료 (필요 시)

Summary by CodeRabbit

Summary by CodeRabbit

  • 신규 기능

    • 주간 뉴스레터에 리마인더(최근 게시글 정보 및 작성 권장 메시지) 안내가 추가되었습니다.
    • 이메일 발송 관련 환경설정이 추가되어, 기본 발신 이메일 주소가 지정되었습니다.
  • 버그 수정

    • 만료된 토큰 안내 메시지의 색상이 더 읽기 쉽게 개선되었습니다.
  • 스타일

    • 주간 통계 및 리마인더 안내 영역의 디자인이 개선되어 가독성이 향상되었습니다.
  • 기타

    • 주간 트렌드 리포트 제목이 더 다양한 조건에서 표시됩니다.

@ooheunda ooheunda self-assigned this Jul 9, 2025
@ooheunda ooheunda added the enhancement New feature or request label Jul 9, 2025
Copy link

Copy link

coderabbitai bot commented Jul 9, 2025

"""

Walkthrough

이 변경사항은 뉴스레터 배치 프로세스와 관련된 환경 변수, 데이터 스키마, 템플릿 렌더링 로직을 확장 및 리팩토링합니다. AWS 및 이메일 발송 환경 변수 설정이 추가되었고, 사용자 주간 통계 및 리마인더 데이터 처리가 개선되었으며, 관련 템플릿에서 조건부 렌더링과 스타일이 변경되었습니다.

Changes

파일/경로 요약 변경 내용 요약
backoffice/settings/base.py AWS 접근 키, 시크릿 키, 리전, 기본 이메일 주소 환경 변수 설정 추가
insight/schemas.py WeeklyTrendInsight import 제거, NewsletterContext 내 weekly_trend_html 필드 non-optional 변경, WeeklyTrendContext 및 UserWeeklyTrendContext 클래스 삭제
insight/tasks/weekly_newsletter_batch.py 환경 변수 참조를 environ에서 settings로 변경, get_local_date() 사용, 주간 통계 및 만료 토큰 처리 로직 단순화, 개인화 뉴스레터 HTML 렌더링 분리 및 조건부 처리, 메서드 시그니처 및 내부 구현 변경
templates/insights/index.html 만료 토큰 경고 텍스트 색상 변경 (#574202 → #51441b)
templates/insights/user_weekly_trend.html 주간 통계 및 리마인더 조건부 렌더링 추가, 스타일 및 문구 변경, 리마인더 블록 신설
templates/insights/weekly_trend.html 트렌드 리포트 헤딩 조건부 렌더링 범위 확대 (trending_summary 또는 trend_analysis 존재 시 표시)
utils/utils.py 현재 로컬 날짜 반환 함수 get_local_date() 추가, get_previous_week_range() 함수 내 timezone.make_aware() 포맷팅 변경
insight/models.py WeeklyTrendInsight 데이터클래스 내 사용자 트렌드 관련 필드에 대한 상세 주석 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WeeklyNewsletterBatch
    participant DB
    participant Template

    User->>WeeklyNewsletterBatch: 뉴스레터 배치 실행
    WeeklyNewsletterBatch->>DB: 사용자 주간 통계 및 리마인더 데이터 조회
    WeeklyNewsletterBatch->>Template: 개인화 뉴스레터 HTML 렌더링 (user, weekly_trend_html, user_weekly_trend_html, 만료 토큰 여부)
    Template-->>WeeklyNewsletterBatch: 렌더링된 HTML 반환
    WeeklyNewsletterBatch-->>User: 뉴스레터 발송
Loading

Possibly related PRs

Suggested reviewers

  • Jihyun3478
  • six-standard

Poem

🐰
새로운 환경 변수와 리마인더,
뉴스레터에 담긴 따뜻한 인사.
토끼는 코를 실룩이며
"이번 주도 글을 써볼까요?"
초록빛 응원과 함께
벨로그 트렌드, 구독자에게 hop hop!

"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b5ea68 and 04a10fb.

📒 Files selected for processing (1)
  • insight/tasks/weekly_newsletter_batch.py (14 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • insight/tasks/weekly_newsletter_batch.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test-ci
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/weekly-newsletter-batch

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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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

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: 2

🧹 Nitpick comments (2)
insight/tasks/weekly_newsletter_batch.py (2)

170-207: 대용량 데이터 처리 시 성능을 고려하세요.

두 개의 별도 쿼리로 인해 성능이 저하될 수 있습니다. 사용자가 많을 경우 쿼리 최적화를 고려하세요.

다음과 같은 최적화 방안을 고려해보세요:

  • 두 날짜의 데이터를 한 번의 쿼리로 가져오기
  • 데이터베이스 인덱스 추가 (user_id, date)
  • 쿼리 결과 캐싱

238-241: 에러 처리 시 부분적 실패를 고려하세요.

현재 에러 발생 시 모든 사용자의 통계가 누락됩니다. 개별 사용자 단위로 에러를 처리하는 것이 더 안전합니다.

        except Exception as e:
            # 개인 통계 조회 실패 시에도 계속 진행
            logger.error(f"Failed to get users weekly stats: {e}")
-            return {}, set()
+            # 부분적으로 성공한 데이터라도 반환
+            return users_weekly_stats_dict, expired_user_ids
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f952e5e and 9864c13.

📒 Files selected for processing (6)
  • backoffice/settings/base.py (1 hunks)
  • insight/schemas.py (2 hunks)
  • insight/tasks/weekly_newsletter_batch.py (11 hunks)
  • templates/insights/index.html (1 hunks)
  • templates/insights/user_weekly_trend.html (2 hunks)
  • templates/insights/weekly_trend.html (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
backoffice/settings/base.py (1)
Learnt from: Nuung
PR: Check-Data-Out/velog-dashboard-v2-back-office#24
File: backoffice/settings/base.py:19-22
Timestamp: 2025-03-25T15:31:20.445Z
Learning: Sentry SDK 설정 시 `environment` 파라미터를 사용하면 로컬 개발 환경과 운영 환경에서 발생한 에러를 구분할 수 있어 디버깅이 더 효율적입니다.
insight/tasks/weekly_newsletter_batch.py (1)
Learnt from: ooheunda
PR: Check-Data-Out/velog-dashboard-v2-back-office#30
File: modules/mail/schemas.py:21-25
Timestamp: 2025-06-08T15:02:11.518Z
Learning: AWSSESCredentials dataclass에서 clear_credentials 메서드는 SESClient의 싱글톤 + lazy init 패턴과 충돌하여 실용적이지 않음. credentials가 reset_client() 후 재초기화에 필요하기 때문.
🧬 Code Graph Analysis (2)
insight/schemas.py (1)
insight/models.py (1)
  • WeeklyTrendInsight (31-33)
insight/tasks/weekly_newsletter_batch.py (5)
posts/models.py (1)
  • PostDailyStatistics (50-88)
utils/utils.py (3)
  • get_local_now (17-24)
  • to_dict (68-77)
  • parse_json (27-36)
insight/tests/conftest.py (1)
  • user_weekly_trend (117-138)
insight/models.py (1)
  • UserWeeklyTrend (72-112)
insight/schemas.py (1)
  • UserWeeklyTrendContext (25-31)
🔇 Additional comments (12)
backoffice/settings/base.py (1)

29-34: AWS 및 이메일 설정이 올바르게 구성되었습니다.

AWS SES 통합을 위한 설정이 적절하게 추가되었습니다. 기본 리전이 한국에 적합하고, 기본 이메일 주소도 no-reply 패턴을 따라 좋은 관례입니다.

templates/insights/index.html (1)

30-30: 만료된 토큰 경고 메시지의 색상이 개선되었습니다.

텍스트 색상이 더 어두운 색상으로 변경되어 가독성이 향상되었습니다.

templates/insights/weekly_trend.html (1)

2-2: 조건부 렌더링 로직이 개선되었습니다.

제목이 trending_summary 또는 trend_analysis 중 하나가 존재할 때 표시되도록 변경되어 더 유연한 콘텐츠 표시가 가능합니다.

insight/schemas.py (2)

13-13: weekly_trend_html 필드가 필수로 변경되었습니다.

이 변경사항이 의도된 것인지 확인해주세요. 만약 글로벌 트렌드가 항상 표시되어야 한다면 적절한 변경이지만, 데이터가 없는 경우를 고려해야 할 수도 있습니다.


27-31: 리마인더 기능을 위한 스키마 변경이 잘 구성되었습니다.

user_weekly_stats를 선택적으로 만들고 reminder 필드를 추가한 것은 PR 목표와 일치합니다. 토큰 만료 사용자와 일반 사용자를 다르게 처리할 수 있도록 유연성이 제공됩니다.

templates/insights/user_weekly_trend.html (3)

2-2: 조건부 렌더링이 리마인더 기능을 포함하도록 확장되었습니다.

reminder 조건이 추가되어 리마인더가 있는 경우에도 활동 리포트 섹션이 표시되도록 개선되었습니다.


16-38: 사용자 통계 블록의 스타일과 텍스트가 개선되었습니다.

"이번 주에는"에서 "저번 주에는"으로 변경된 것은 주간 통계의 의미상 더 정확합니다. 스타일링 개선(box-shadow, 여백 조정 등)도 UI를 향상시킵니다.


40-53: 리마인더 기능이 적절하게 구현되었습니다.

새로운 리마인더 블록이 잘 디자인되었고, 사용자에게 도움이 되는 정보(마지막 글 제목, 경과 일수, 리더보드 링크 등)를 제공합니다. 스타일링도 일관성 있게 적용되었습니다.

insight/tasks/weekly_newsletter_batch.py (4)

184-187: 토큰 만료 감지 로직의 정확성을 검증하세요.

오늘자 통계가 없다고 해서 항상 토큰이 만료된 것은 아닙니다. 사용자가 단순히 오늘 글을 작성하지 않았을 수도 있습니다.

토큰 만료 여부를 더 정확하게 판단할 수 있는 방법이 있는지 확인해주세요. 예를 들어:

  • User 모델에 토큰 만료 필드가 있는지
  • 토큰 유효성을 직접 검증하는 API가 있는지

17-17: 환경 변수 처리가 Django settings로 일관되게 변경되었습니다.

environ.Env()에서 django.conf.settings로의 변경이 파일 전체에 일관되게 적용되었습니다.

Also applies to: 411-411, 567-568, 637-639


322-336: 리마인더 기능이 PR 목표에 따라 올바르게 구현되었습니다.

토큰이 만료되지 않은 사용자 중 주간 트렌드가 없는 경우에만 리마인더를 제공하는 로직이 적절히 구현되었습니다.

Also applies to: 375-381, 389-394


292-294: 타임존 일관성 검증 완료

get_local_now()가 Django의 timezone.localtime을 사용해 timezone-aware datetime을 반환하며, released_at도 USE_TZ=True 환경에서 ORM이 timezone-aware datetime으로 로드하기 때문에 두 값 간 뺄셈으로 올바른 일수 차이가 계산됩니다. 추가 조치가 필요 없습니다.

Copy link
Member

@Nuung Nuung left a comment

Choose a reason for hiding this comment

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

좋았던 점

  • 전체적으로 디버깅을 위한 로깅, 계층형, 함수로 분리해서 최대한 클린하게 만드시려고 한게 이해가 되어서 너무 좋았습니다!

아쉬운 점

  • ORM 쿼리의 최적화 (n+1), 디테일한 부분에서의 약간 코멘트가 있습니다! 확인해주세요 :)

Comment on lines 636 to 640
aws_credentials = AWSSESCredentials(
aws_access_key_id=env("AWS_ACCESS_KEY_ID"),
aws_secret_access_key=env("AWS_SECRET_ACCESS_KEY"),
aws_region_name=env("AWS_REGION"),
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
aws_region_name=settings.AWS_REGION,
)
Copy link
Member

Choose a reason for hiding this comment

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

bbb

Copy link
Member

Choose a reason for hiding this comment

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

이 부분은 어떤 목적으로 남기신 코멘트일까요..? @Nuung

Copy link
Member

Choose a reason for hiding this comment

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

ㅋㅋㅋㅋ 참고로 bb = 👍 이겁니다! 환경변수를 런타임에서 중복해서 메모리에 올리는 이슈가 있었는데 이게 해결되었어요!

Copy link
Member

@six-standard six-standard left a comment

Choose a reason for hiding this comment

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

코드 잘 읽었습니다!
현우님이 리뷰를 잘 남겨주셔서 제가 별도로 확인한 이슈는 크게 없습니다.

좋았던 점

  • 이전에 있었던 뉴스레터 관련 문제 (모든 글을 이번 주에 작성한 것으로 인식하는 문제) 해결을 위해 넣으신 것 같은데, 괜찮은 방식인 것 같아 좋네요.
  • env 형태 변경과 같은 사소한 수정들에 눈에 띕니다!

Copy link
Contributor

@Jihyun3478 Jihyun3478 left a comment

Choose a reason for hiding this comment

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

코드 잘 읽었습니다 고생하셨습니다!!
발생했던 이슈 모두 꼼꼼히 적용해주신 것 같습니다!

좋았던 점

  • None 처리를 세심하게 명시해주신 부분이 좋았습니다!
  • 뉴스레터 항상 예쁘게 개선해주시는 부분이 좋은 것 같습니다!👍
  • 플로우차트 정말 꼼꼼하게 그려주신 것 같아요! 고민하신 흔적이 보이네요 저도 배워갑니다:)

ooheunda added 2 commits July 11, 2025 14:46
PostDailyStatistics로부터의 3중 조인 -> Post로부터의 2중 조인
@ooheunda ooheunda requested a review from Nuung July 11, 2025 06:15
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: 0

🧹 Nitpick comments (1)
insight/tasks/weekly_newsletter_batch.py (1)

164-242: 주간 통계 계산 로직 대폭 개선

기존 누적 방식에서 차이값 계산 방식으로 변경한 것이 정확한 주간 변동량 계산을 위한 올바른 접근입니다. 토큰 만료 사용자 감지 기능도 잘 통합되었습니다.

다음 최적화를 고려해보세요:

# 성능 최적화를 위해 select_related나 prefetch_related 사용 고려
            stats = (
                Post.objects.filter(
                    user_id__in=user_ids,
                    daily_statistics__date__in=[
                        self.today,
                        self.before_a_week,
                    ],
                    is_active=True,
                )
+               .select_related('daily_statistics')
                .values("user_id", "daily_statistics__date")
                .annotate(
                    posts=Count("id", distinct=True),
                    views=Sum("daily_statistics__daily_view_count"),
                    likes=Sum("daily_statistics__daily_like_count"),
                )
            )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 036016d and 7fd730d.

📒 Files selected for processing (1)
  • insight/tasks/weekly_newsletter_batch.py (14 hunks)
🧰 Additional context used
🧠 Learnings (1)
insight/tasks/weekly_newsletter_batch.py (1)
Learnt from: ooheunda
PR: Check-Data-Out/velog-dashboard-v2-back-office#30
File: modules/mail/schemas.py:21-25
Timestamp: 2025-06-08T15:02:11.518Z
Learning: AWSSESCredentials dataclass에서 clear_credentials 메서드는 SESClient의 싱글톤 + lazy init 패턴과 충돌하여 실용적이지 않음. credentials가 reset_client() 후 재초기화에 필요하기 때문.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test-ci
🔇 Additional comments (7)
insight/tasks/weekly_newsletter_batch.py (7)

16-16: Django settings 사용으로 환경변수 접근 방식 개선

environ.Env()에서 Django settings 사용으로 변경한 것이 좋습니다. 이는 Django 프로젝트에서 일관성 있는 설정 관리를 위한 모범 사례입니다.

Also applies to: 31-31, 34-34


69-70: 날짜 초기화 로직 개선

get_local_date() 사용으로 일관된 로컬 날짜 처리가 가능해졌습니다. 이전 timezone 이슈를 해결하는 좋은 개선사항입니다.


309-363: 렌더링 로직 분리가 코드 구조 개선에 기여

기존 단일 메서드에서 _get_user_weekly_trend_html_get_newsletter_html로 분리한 것이 책임 분리 원칙에 부합하고 가독성을 향상시켰습니다.


377-420: 배치 빌드 로직의 토큰 만료 처리 개선

토큰 만료 사용자와 리마인더 기능을 통합한 로직이 잘 구현되었습니다. 조건부 렌더링으로 성능도 고려되었습니다.


428-428: Django settings 활용 일관성 확보

DEFAULT_FROM_EMAIL, DEBUG 등 Django settings 직접 사용으로 환경변수 접근 방식이 일관되게 개선되었습니다.

Also applies to: 552-553, 585-585


655-658: AWS 자격증명 설정 방식 개선

Environment variables에서 Django settings로 변경하여 설정 관리가 일관되게 개선되었습니다. 과거 학습 내용과 일치하는 AWSSESCredentials 사용법입니다.


275-307: 리마인더 기능 추가 잘 구현됨

새로운 리마인더 기능이 잘 구현되었지만, 성능 최적화를 위한 개선이 필요합니다.

# N+1 쿼리 방지를 위한 최적화
            reminders = (
                Post.objects.filter(
                    user_id__in=user_ids,
                    is_active=True,
                )
+               .select_related('user')
                .values("user_id", "title", "released_at")
                .order_by("user_id", "-released_at")
                .distinct("user_id")
            )

또한 get_local_now() 호출을 루프 밖으로 이동하는 것이 좋습니다:

+           now = get_local_now()
            users_reminder_dict = {
                reminder["user_id"]: {
                    "title": reminder["title"],
-                   "days_ago": (get_local_now() - reminder["released_at"]).days,
+                   "days_ago": (now - reminder["released_at"]).days,
                }
                for reminder in reminders
            }

Likely an incorrect or invalid review comment.

Comment on lines +399 to 401
is_expired_token_user = (
user["id"] in expired_token_user_ids
)
Copy link
Member

Choose a reason for hiding this comment

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

이게 사실 for loop 랑 같아서요
DP 는 어떠실까요? 메모이제이션이 넉넉하다면,
expired_token_user_ids[유저ID의 index] = 0 또는 1 / 또는 boolean

is_expired_token_user = bool(expired_token_user_ids[user["id"]])

제 과정이 정답이 아니라서요, 메모이제이션 vs 반복 for loop 중 고민을 해주시면 더 좋을 것 같아요! 아니면 hash 로 접근하는 것도 좋구요. -> 마스킹

좋은 알고리즘 시간..!

ooheunda added 2 commits July 13, 2025 12:55
모든 데이터 세팅은 분석 배치에서 실행됨
이에 따른 주간 통계 / 리마인더 함수 삭제 및 관련 스키마, 로직 수정
@Nuung Nuung merged commit b5886a7 into main Jul 13, 2025
2 checks passed
@Nuung Nuung deleted the feature/weekly-newsletter-batch branch July 13, 2025 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants