Skip to content

Conversation

six-standard
Copy link
Member

@six-standard six-standard commented Aug 6, 2025

🔥 변경 사항

전체적인 뉴스레터 메일 템플릿을 수정하였습니다!
우선은 현재 나온 디자인으로 진행했는데, 여기서 더 개선할 곳이 있을까요?

🏷 관련 이슈

  • 관련 이슈: X

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

스크린샷 2025-08-06 오후 9 49 15 스크린샷 2025-08-06 오후 9 49 30 스크린샷 2025-08-06 오후 9 49 37

📌 체크리스트

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

Summary by CodeRabbit

  • 신규 디자인

    • 벨로그 대시보드 주간 리포트 이메일 및 트렌드 리포트 템플릿의 전체적인 시각 디자인이 새롭게 변경되었습니다.
    • 폰트, 색상, 레이아웃, 버튼 및 푸터 등 다양한 UI 요소가 현대적으로 개선되었습니다.
  • 스타일 개선

    • 각 섹션별로 글꼴, 배경색, 여백, 정렬 등이 통일감 있게 리뉴얼되었습니다.
    • 트렌딩 글, 트렌드 분석, 통계 등 주요 정보가 더 명확하게 구분되어 표시됩니다.
    • 박스 모델(box-sizing: border-box) 적용으로 레이아웃 안정성이 향상되었습니다.
  • 조건부 안내 강화

    • 토큰 만료, 활동 리마인더 등 안내 메시지의 시각적 강조와 설명이 보강되었습니다.
    • 토큰 만료 시 사용자명 포함 경고 메시지와 재로그인 링크가 추가되었습니다.
  • 테스트 및 검증 강화

    • 뉴스레터 이메일 제목과 내용에 대한 테스트가 한글화 및 상세화되어 검증 범위가 확대되었습니다.

@six-standard six-standard self-assigned this Aug 6, 2025
@six-standard six-standard added the enhancement New feature or request label Aug 6, 2025
Copy link

Copy link

coderabbitai bot commented Aug 6, 2025

Walkthrough

이번 변경에서는 Velog 대시보드 주간 리포트 관련 HTML 템플릿 3종이 전면적으로 리디자인 및 리팩토링되었습니다. 전반적으로 색상, 폰트, 레이아웃, 조건부 렌더링 로직, 한글화 등이 적용되었으며, 토큰 만료 안내 및 사용자별 트렌드 섹션의 조건 처리도 개선되었습니다.

Changes

Cohort / File(s) Change Summary
Velog 대시보드 메인 템플릿 리디자인
templates/insights/index.html
전체 레이아웃, 색상, 폰트, 버튼, 헤더, 푸터, 토큰 만료 안내, 조건부 렌더링 구조 전면 리디자인 및 한글화.
사용자 주간 트렌드 템플릿 개편
templates/insights/user_weekly_trend.html
시각적 요소 및 레이아웃 개선, 조건부 안내 메시지 로직 단순화 및 한글화, 스타일 일관성 강화.
주간 트렌드 리포트 템플릿 리디자인
templates/insights/weekly_trend.html
섹션별 제목, 레이아웃, 색상, 폰트, 트렌딩 글 목록 스타일, 트렌드 분석 섹션 등 시각적 리디자인 및 한글화.
템플릿 스타일 보완
templates/insights/insight_preview.html
여러 요소에 box-sizing: border-box; 스타일 추가로 박스 모델 일관성 확보.
배치 처리 로직 텍스트 조건 변경
insight/tasks/weekly_newsletter_batch.py
템플릿 렌더링 성공 조건 내 문구 변경 ("이 주의 트렌딩 글" → "이번 주의 트렌딩 글", "트렌드 분석" → "주간 트렌드 분석").
테스트 이메일 메시지 및 검증 업데이트
insight/tests/conftest.py, insight/tests/tasks/test_weekly_newsletter_batch.py, insight/tests/tasks/test_weekly_newsletter_template.py
뉴스레터 이메일 제목, 본문 내용 및 템플릿 렌더링 결과 검증 문구를 변경된 한글 텍스트와 스타일에 맞게 수정.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant EmailTemplate
  participant DataEngine

  User->EmailTemplate: 이메일 열람
  EmailTemplate->DataEngine: 주간 트렌드/사용자 데이터 조회
  DataEngine-->>EmailTemplate: 데이터 반환 (트렌드, 사용자, 토큰 상태 등)
  alt 토큰 만료
    EmailTemplate->User: 토큰 만료 안내 및 재로그인 링크 표시
  else 토큰 유효
    EmailTemplate->User: 주간 트렌드 및 사용자별 리포트 표시
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • Jihyun3478
  • Nuung

Poem

🐰
새 옷 입은 대시보드,
한글 폰트 가득 담아
토큰 만료도 친절하게,
트렌드와 통계 한눈에!
리포트 꾸미는 토끼 손길,
이메일 속 봄바람 솔솔~

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/improve_newsletter_design

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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 (4)
templates/insights/index.html (1)

8-20: @import 웹폰트는 다수 메일 클라이언트에서 차단됩니다

Gmail·Outlook Web 등 주요 클라이언트는 <style>@import 를 무시하거나 CSS 자체를 제거할 수 있습니다.
– 브랜드 폰트 유지가 중요하다면 <link rel="stylesheet"> 로 교체하거나,
– 최소한 시스템 폰트("Apple SD Gothic Neo", "맑은 고딕", sans-serif)를 첫 번째 폴백으로 지정해 주세요.

templates/insights/weekly_trend.html (2)

67-74: 외부 링크에 rel="noopener noreferrer" 추가 권장

메일에서 열리는 새 탭은 JS 접근 위험은 낮지만, 일관된 보안을 위해 target="_blank" 사용 시엔 항상 rel="noopener noreferrer" 를 함께 넣어주세요.

- <a
-   href="https://velog.io/@{{item.username}}/{{item.slug}}?utm_source=velog_dashboard_email&utm_medium=weekly_analysis"
-   target="_blank"
-   style="color: #000000; text-decoration: none"
- >
+ <a
+   href="https://velog.io/@{{item.username}}/{{item.slug}}?utm_source=velog_dashboard_email&utm_medium=weekly_analysis"
+   target="_blank"
+   rel="noopener noreferrer"
+   style="color: #000000; text-decoration: none"
+ >

1-10: 상위 <div>에 이미 color 지정이 있으므로 중첩 스타일은 중복입니다

헤더·본문 곳곳에 반복적으로 color: #000000 이 선언되어 있는데, 상위 컨테이너에서 기본값이 같다면 삭제해도 결과는 동일하며 템플릿 용량이 줄어듭니다.

templates/insights/user_weekly_trend.html (1)

186-193: target="_blank" 링크 동일 보안 보강 필요

weekly_trend.html 과 동일하게 rel="noopener noreferrer" 속성을 추가해 주세요.

- <a
-   href="https://velog.io/@{{item.username}}/{{item.slug}}?utm_source=velog_dashboard_email&utm_medium=weekly_analysis"
-   target="_blank"
-   style="color: #000000; text-decoration: none"
- >
+ <a
+   href="https://velog.io/@{{item.username}}/{{item.slug}}?utm_source=velog_dashboard_email&utm_medium=weekly_analysis"
+   target="_blank"
+   rel="noopener noreferrer"
+   style="color: #000000; text-decoration: none"
+ >
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 035a0de and 83919a8.

📒 Files selected for processing (3)
  • templates/insights/index.html (1 hunks)
  • templates/insights/user_weekly_trend.html (1 hunks)
  • templates/insights/weekly_trend.html (1 hunks)
🔇 Additional comments (1)
templates/insights/user_weekly_trend.html (1)

64-99: 메일 TIP URL에 utm_campaign 파라미터 누락 확인

다른 CTA 링크에는 utm_campaign이 포함되어 있으나, 리마인더 구간의 리더보드 링크엔 빠져 있습니다.
캠페인별 효과 측정이 필요하다면 동일한 UTM 파라미터 세트를 유지해 주세요.

Copy link
Contributor

@ooheunda ooheunda left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 👍 🔥 의견 몇 개 드립니다.

좋았던 점

  • CTA 버튼이랑 푸터가 확실히 전보다 예뻐졌네요!
  • 각 글별 키워드를 따로 두지 않고 작성자와 같은 레벨에 두는게 깔끔해보이네요!

아쉬웠던 점

  • 글꼴이 기본적으로 굵어서 가독성이 떨어지는 것 같아요.
  • 키워드를 작성자와 같은 레벨에 두는 건 좋은데, 눈에 잘 안 띄는게 아쉬워요! 그리고 이모지가 하나엔 있고 하나엔 없네요.

일단 저는 글꼴은 꼭 바뀌었으면 좋겠어요...🥲🙏
그리고 지금 있는 테스트는 직접 렌더링하고 템플릿 체크하는 테스트여서, 수정하시면서 테스트도 같이 돌려보면 좋을 것 같네요!

Comment on lines 7 to 20
<style>
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700;900&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Noto Sans KR", sans-serif;
background-color: #ebebeb;
margin: 0;
padding: 0;
}
</style>
Copy link
Contributor

Choose a reason for hiding this comment

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

메일로 보내는 HTML에 스타일은 보통 인라인으로만 넣는다고 합니다.
메일 클라이언트에서 인식을 못하는 경우가 종종 있어서라는데... 현재에 얼마나 경우가 많을지는 모르겠지만, 적용해보는게 어떨까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

반영했습니다!

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.

너무 고생 많으셨습니다! 👏
항상 예쁘게 레이아웃 구성해주셔서 정말 감사드려요 🙇‍♀️
개인적인 의견이긴 하지만, 아래 두 부분은 살짝 아쉬운 점이 있어 공유드려요:)

좋았던 점

  • 전체적으로 디자인을 통일화 해서 개선해주신 부분이 좋았습니다!
  • 트렌딩 글의 키워드가 제목 바로 하단에 위치하도록 수정해주신 부분이 좋았습니다!

아쉬운 점

  • 글꼴이 다소 굵게 느껴져서, 가독성이 조금 떨어지는 느낌이 있었어요 🥲 조금 더 얇은 서체로 테스트해보는 것도 괜찮을 것 같아요!
  • 상단의 'Velog Dashboard' 색상이 기존 연두색일 때 저희 서비스 느낌이 더 잘 살아났던 것 같아요. 기준님은 어떤 색상이 더 눈에 잘 들어오셨는지 궁금합니다!

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

🧹 Nitpick comments (6)
insight/tests/conftest.py (1)

163-166: 플레인 텍스트 본문 가독성 보강 제안

이메일 클라이언트에 따라 text_body가 표시될 수 있으니 줄바꿈/구분선 등을 넣어 가독성을 높이는 것을 권장합니다. HTML과 주요 메시지가 분리되지 않도록 핵심 CTA/제목도 포함해 주세요.

예:

text_body = (
    "벨로그 대시보드 주간 뉴스레터 #1\n"
    "Weekly Report Test content\n\n"
    "대시보드 보러가기: https://velog-dashboard.kro.kr/\n"
)
insight/tests/tasks/test_weekly_newsletter_batch.py (1)

199-201: 제목 검증을 더 명확한 패턴으로 강화하세요

현재는 부분 문자열만 검사합니다. 가능하면 newsletter_id까지 포함한 포맷을 검증하도록 사전 상태 세팅 후 정합성을 체크하세요.

예:

# 사전 준비
newsletter_batch.weekly_info["newsletter_id"] = 42

# 검증
subject = newsletters[0].email_message.subject
assert subject.startswith("벨로그 대시보드 주간 뉴스레터 #42")
insight/tests/tasks/test_weekly_newsletter_template.py (1)

150-160: 조건부 기대값 분기는 OK, 하지만 테스트를 분리하는 편이 명확합니다

days_ago 유무 케이스를 하나의 테스트 내 조건문으로 분기하기보다, 파라미터화/별도 테스트로 분리하면 의도가 선명해지고 실패 시 원인 파악이 쉬워집니다.

templates/insights/index.html (3)

68-77: user.username 컨텍스트 미전달로 사용자명 헤더가 항상 일반 문구로 출력됩니다

_get_newsletter_html 컨텍스트에는 user가 없으므로 {% if user.username %}가 항상 거짓으로 평가되어 “활동 리포트”만 노출됩니다. 만료 안내에 사용자명을 노출하려면 username을 별도 키로 넘기거나 user를 전달하세요.

예(파이썬 쪽 보완):

# insight/tasks/weekly_newsletter_batch.py 내 _get_newsletter_html 서명/호출부에 username 전달
def _get_newsletter_html(..., username: str | None = None) -> str:
    ctx = to_dict(NewsletterContext(...))
    if username:
        ctx["username"] = username
    return render_to_string("insights/index.html", ctx)

# 호출부(_build_newsletters)
html_body = self._get_newsletter_html(
    is_expired_token_user=is_expired_token_user,
    weekly_trend_html=weekly_trend_html,
    user_weekly_trend_html=user_weekly_trend_html,
    username=user.get("username"),
)

그리고 템플릿에서는 user.username 대신 username 사용:

{% if username %} {{ username }}님의 활동 리포트 {% else %} 활동 리포트 {% endif %}

46-55: CTA 링크 속성 보강 제안

이메일 클라이언트 호환에 큰 영향은 없지만, 보안/사용성 측면에서 target="_blank"rel="noopener noreferrer" 추가를 권장합니다.

- <a 
+ <a target="_blank" rel="noopener noreferrer"

6-6: 문서 타이틀과 본문 언어 일관성

<title>은 영문, 본문은 한글입니다. 미리보기/접근성 측면에서 한글 제목(예: “벨로그 대시보드 주간 뉴스레터”)로 맞추는 것을 권장합니다.
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 83919a8 and 9b5cc25.

📒 Files selected for processing (8)
  • insight/tasks/weekly_newsletter_batch.py (1 hunks)
  • insight/tests/conftest.py (1 hunks)
  • insight/tests/tasks/test_weekly_newsletter_batch.py (1 hunks)
  • insight/tests/tasks/test_weekly_newsletter_template.py (5 hunks)
  • templates/insights/index.html (1 hunks)
  • templates/insights/insight_preview.html (3 hunks)
  • templates/insights/user_weekly_trend.html (1 hunks)
  • templates/insights/weekly_trend.html (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • templates/insights/insight_preview.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • templates/insights/weekly_trend.html
  • templates/insights/user_weekly_trend.html
🔇 Additional comments (4)
insight/tests/tasks/test_weekly_newsletter_template.py (3)

65-67: 업데이트된 헤더 문구 검증 LGTM

새 템플릿 카피에 맞는 기대값으로 잘 갱신되었습니다.


128-133: 표기 일관성(‘이번 주’ vs ‘이번주’) 확인 요청

본 테스트는 “이번주에 작성한 글”, 위쪽 테스트는 “이번 주의 트렌딩 글”을 사용합니다. 의도된 차이가 아니라면 템플릿/테스트에서 띄어쓰기를 일관화해 주세요.


218-224: 만료 토큰 안내 문구 검증 LGTM

새 문구와 조건부 렌더링 의도에 부합합니다.

templates/insights/index.html (1)

102-154: 푸터 SVG 호환성 점검 필요

여러 메일 클라이언트(특히 Gmail/Outlook)에서 인라인 SVG가 표시되지 않을 수 있습니다. PNG 대체(또는 서버 호스팅된 이미지)로 교체/백업을 고려하세요.

테스트 가이드:

  • Gmail Web/모바일, Outlook(Windows/웹), iOS Mail에서 수신 확인
  • 보이지 않을 경우 <img alt="Velog Dashboard" src="...png">로 대체

Comment on lines +60 to +66
{% if weekly_trend_html %}
{{weekly_trend_html}}
{% endif %}

{% if not is_expired_token_user and user_weekly_trend_html %}
{{user_weekly_trend_html}}
{% endif %}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

크리티컬: 사전 렌더된 HTML을 안전하게 삽입하기 위해 |safe 필터가 필요합니다

현재 {{weekly_trend_html}}, {{user_weekly_trend_html}}는 이스케이프되어 태그가 그대로 노출될 수 있습니다. 이메일 레이아웃이 붕괴하고 text_body 추출에도 악영향을 줍니다. 반드시 |safe를 적용하세요.

다음 변경을 적용해 주세요:

-                  {% if weekly_trend_html %} 
-                    {{weekly_trend_html}}
+                  {% if weekly_trend_html %} 
+                    {{weekly_trend_html|safe}}
                   {% endif %} 
                   
-                  {% if not is_expired_token_user and user_weekly_trend_html %} 
-                    {{user_weekly_trend_html}} 
+                  {% if not is_expired_token_user and user_weekly_trend_html %} 
+                    {{user_weekly_trend_html|safe}} 
                   {% endif %} 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{% if weekly_trend_html %}
{{weekly_trend_html}}
{% endif %}
{% if not is_expired_token_user and user_weekly_trend_html %}
{{user_weekly_trend_html}}
{% endif %}
{% if weekly_trend_html %}
{{ weekly_trend_html|safe }}
{% endif %}
{% if not is_expired_token_user and user_weekly_trend_html %}
{{ user_weekly_trend_html|safe }}
{% endif %}
🤖 Prompt for AI Agents
In templates/insights/index.html around lines 60 to 66, the variables
weekly_trend_html and user_weekly_trend_html are rendered without the |safe
filter, causing their HTML content to be escaped and displayed as plain text. To
fix this, add the |safe filter to both variables in the template expressions to
ensure the pre-rendered HTML is inserted safely and correctly without escaping.

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.

(퀵하게 닫기위해 리뷰잉 형식을 단일화 했어요!)

  • 밀도있게 디자인 톤앤 매너, 기본 폰트까지 전반적으로 너무 고생많으셨습니다. 사실 in/out data 들때문에 실제 적용하시는데 읽는 비용이 많으셨을 것 같아요! 너무 고생하셨어요~
  • safe 는 사실 무조건 넣긴 합니다만, 이 경우는 우리가 직접 잘 만들어진 html 으로 우리가 직접 원하는 위치에 넣기 때문에 필수는 아닌 것으로 보입니다~
  • 테스트 코드에서 언급한 "문자열만을 기반으로 한 테스팅" 은 지향하는게 맞으나, 이는 기준님 선택에 맡기도록 하겠습니다!
  • 앞으로 메일링 보내보면서 다양한 output, 출력 형식에 대해 더블 체크하며 점진적 업데이트를 하면 좋을 것 같아요!

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.

확인했습니다 고생하셨습니다~!!

Copy link
Contributor

@ooheunda ooheunda left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 테스트 개선해주신 부분까지 눈에 띄네요. 👍

@six-standard six-standard merged commit 5cc9018 into main Aug 10, 2025
2 checks passed
@six-standard six-standard deleted the refactor/improve_newsletter_design branch August 10, 2025 16:34
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