Skip to content

Fix/#168 타임라인 상세조회 - comparisonPeriodType 추가#169

Merged
kingmingyu merged 2 commits into
developfrom
fix/#168
Jul 7, 2026
Merged

Fix/#168 타임라인 상세조회 - comparisonPeriodType 추가#169
kingmingyu merged 2 commits into
developfrom
fix/#168

Conversation

@kingmingyu

@kingmingyu kingmingyu commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

📌 관련 이슈

🚀 개요

이번 PR에서 변경된 핵심 내용을 요약해주세요.

  • 타임라인 상세 조회 시 응답 값에 comparisonPeriodType 추가

📄 작업 내용

구체적인 작업 내용을 설명해주세요.

  • 타임라인 엔티티에 comparisonPeriodType 필드 추가
  • 타임라인 상세조회 응답에 comparisonPeriodType 추

📸 스크린샷 / 테스트 결과 (선택)

결과물 확인을 위한 사진이나 테스트 로그를 첨부해주세요.

타임라인 상세 조회

image

✅ 체크리스트

  • 브랜치 전략(GitHub Flow)을 준수했나요?
  • 메서드 단위로 코드가 잘 쪼개져 있나요?
  • 테스트 통과 확인
  • 서버 실행 확인
  • API 동작 확인

🔍 리뷰 포인트 (Review Points)

리뷰어가 중점적으로 확인했으면 하는 부분을 적어주세요. (P1~P4 적용 가이드)

  • 타임라인 엔티티에 comparisonPeriodType 추가했습니다.
  • 변경이 크지 않아 코드레빗 리뷰 받고 바로 머지하겠습니다!

💬 리뷰어 가이드 (P-Rules)
P1: 필수 반영 (Critical) - 버그 가능성, 컨벤션 위반. 해결 전 머지 불가.
P2: 적극 권장 (Recommended) - 더 나은 대안 제시. 가급적 반영 권장.
P3: 제안 (Suggestion) - 아이디어 공유. 반영 여부는 드라이버 자율.
P4: 단순 확인/칭찬 (Nit) - 사소한 오타, 칭찬 등 피드백.

Summary by CodeRabbit

  • New Features

    • 타임라인에 비교 기간 유형 정보가 추가되어, 생성·수정·조회 응답에서 해당 값을 확인할 수 있게 되었습니다.
    • 타임라인 상세 정보에 비교 기간 타입이 함께 노출됩니다.
  • Bug Fixes

    • 타임라인 저장 및 업데이트 시 비교 기간 유형이 누락되지 않도록 반영되었습니다.

@kingmingyu kingmingyu self-assigned this Jul 7, 2026
@kingmingyu kingmingyu added the 🐛 Bug 버그 수정 label Jul 7, 2026
@kingmingyu kingmingyu linked an issue Jul 7, 2026 that may be closed by this pull request
1 task
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Timeline 엔티티에 comparisonPeriodType 필드를 추가하고, EnumType.STRING으로 DB 컬럼에 매핑했습니다. update 메서드 시그니처를 확장하고, TimelineConverter와 TimelineServiceImpl, TimelineResponse의 TimelineDetailDTO에 comparisonPeriodType 값을 전파하여 생성 및 상세 조회 응답에서 노출되도록 변경했습니다.

Changes

comparisonPeriodType 전파

Layer / File(s) Summary
Timeline 엔티티 필드 및 update 메서드 확장
.../persistence/entity/Timeline.java
comparisonPeriodType 필드를 EnumType.STRING, nullable = false로 매핑 추가하고, update(...) 메서드 파라미터와 본문에 해당 값 반영 로직을 추가했습니다.
서비스 계층 update 호출 인자 반영
.../domain/service/TimelineServiceImpl.java
updateTimeline에서 timeline.update(...) 호출 시 dto.comparisonPeriodType()을 인자로 전달하도록 변경했습니다.
응답 DTO에 comparisonPeriodType 필드 추가
.../application/dto/response/TimelineResponse.java
TimelineDetailDTO 레코드에 ComparisonPeriodType 필드와 관련 import를 추가했습니다.
TimelineConverter 매핑 확장
.../application/mapper/TimelineConverter.java
toTimeline 빌더와 toTimelineDetailDTO 생성자에 comparisonPeriodType 값 매핑을 추가했습니다.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant TimelineController
    participant TimelineServiceImpl
    participant Timeline
    participant TimelineConverter

    Client->>TimelineController: 타임라인 상세 조회 요청
    TimelineController->>TimelineServiceImpl: getTimelineDetail(...)
    TimelineServiceImpl->>Timeline: getComparisonPeriodType()
    Timeline-->>TimelineServiceImpl: comparisonPeriodType 값 반환
    TimelineServiceImpl->>TimelineConverter: toTimelineDetailDTO(timeline)
    TimelineConverter-->>TimelineServiceImpl: TimelineDetailDTO(comparisonPeriodType 포함)
    TimelineServiceImpl-->>TimelineController: TimelineDetailDTO
    TimelineController-->>Client: 응답(comparisonPeriodType 포함)
Loading

Possibly related PRs

  • WhereYouAd/WhereYouAd-Backend#130: 동일하게 comparisonPeriodTypeTimelineRequest, Timeline, TimelineConverter, TimelineResponse에 걸쳐 도입한 PR로 본 PR의 전파 로직과 직접적으로 겹칩니다.

Suggested reviewers: ojy0903, jinnieusLab


시니어 개발자 입장에서 리뷰해보면, 이번 PR은 딱 필요한 부분만 깔끔하게 건드린 좋은 예시예요! 👍

  • 좋은 점: Timeline.update(...)nullable = false 제약을 걸어둔 부분이 마음에 듭니다. 이렇게 하면 comparisonPeriodType 없이 저장되는 실수를 DB 레벨에서 막아주거든요.
  • 확인해볼 점: 기존에 이미 저장된 Timeline 레코드들은 comparisonPeriodType 컬럼이 없었을 텐데, nullable = false로 바로 적용하면 마이그레이션 시점에 기존 데이터에 대한 기본값 처리(예: 마이그레이션 스크립트)가 필요할 수 있어요. 예를 들어 ALTER TABLE timeline ADD COLUMN comparison_period_type VARCHAR(255) NOT NULL DEFAULT 'XXX' 같은 처리가 되어 있는지 한번 확인해보면 좋을 것 같습니다!
  • 작은 팁: TimelineServiceImpl의 인자 순서 재정렬은 가독성 면에서도 좋네요. 이런 사소한 포맷팅도 코드 품질에 은근히 도움이 됩니다.

전반적으로 스코프가 명확하고 변경 범위가 작아서 리뷰 부담이 크지 않은 PR입니다. 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed 타임라인 엔티티와 상세 응답에 comparisonPeriodType을 추가해 #168의 상세조회 누락 문제를 해결했습니다.
Out of Scope Changes check ✅ Passed 요구사항과 무관한 별도 기능 추가는 보이지 않고, 변경은 comparisonPeriodType 전달과 노출에만 한정됩니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed 제목이 issue #168의 핵심 변경점인 타임라인 상세조회에 comparisonPeriodType 추가를 명확히 요약합니다.
Description check ✅ Passed 필수 섹션(관련 이슈, 개요, 작업 내용, 스크린샷, 체크리스트, 리뷰 포인트)이 포함되어 템플릿 요구를 대부분 충족합니다.
✨ 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 fix/#168

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.

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

🧹 Nitpick comments (1)
src/main/java/com/whereyouad/WhereYouAd/domains/timeline/application/dto/response/TimelineResponse.java (1)

16-26: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

CreateResponseDTO에도 comparisonPeriodType을 포함하는 게 어떨까요?

TimelineDetailDTO에는 comparisonPeriodType이 잘 추가됐는데, CreateResponseDTO(Line 16-26)는 comparisonStartDate/comparisonEndDate는 갖고 있으면서 정작 그 기준이 되는 comparisonPeriodType은 빠져있어요. 생성/수정 응답에서 클라이언트가 "어떤 기준으로 비교 기간이 계산됐는지" 바로 알 수 없는 비일관성이 생깁니다. 이번 이슈(#168) 범위는 상세 조회에 한정되어 있어 필수 수정은 아니지만, 응답 일관성 측면에서 함께 추가하면 좋을 것 같습니다.

💡 제안 diff
     public record CreateResponseDTO(
             Long timelineId,
             String name,
             LocalDate startDate,
             LocalDate endDate,
             List<MetricType> metrics,
             LocalDate comparisonStartDate,
             LocalDate comparisonEndDate,
+            ComparisonPeriodType comparisonPeriodType,
             PerformanceStatus performanceStatus,
             LocalDateTime createdAt
     ) {}

Also applies to: 42-42

🤖 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/whereyouad/WhereYouAd/domains/timeline/application/dto/response/TimelineResponse.java`
around lines 16 - 26, `CreateResponseDTO` is missing `comparisonPeriodType`,
which makes the create/update response inconsistent with `TimelineDetailDTO`
even though it already returns the derived comparison dates. Update the
`CreateResponseDTO` record in `TimelineResponse` to include
`comparisonPeriodType`, and make sure the mapping code that builds this DTO
populates it from the timeline entity or request-derived comparison settings so
clients can see the basis for the comparison period.
🤖 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/whereyouad/WhereYouAd/domains/timeline/persistence/entity/Timeline.java`:
- Around line 57-60: The new comparison_period_type column in Timeline should
not be introduced as NOT NULL immediately because existing timeline rows may
cause schema update failures. Update the Timeline entity and migration flow so
comparisonPeriodType is added with a temporary default or nullable state first,
backfill existing data, and only then enforce NOT NULL; use the Timeline and
comparisonPeriodType symbols to locate the field and related schema handling.

---

Nitpick comments:
In
`@src/main/java/com/whereyouad/WhereYouAd/domains/timeline/application/dto/response/TimelineResponse.java`:
- Around line 16-26: `CreateResponseDTO` is missing `comparisonPeriodType`,
which makes the create/update response inconsistent with `TimelineDetailDTO`
even though it already returns the derived comparison dates. Update the
`CreateResponseDTO` record in `TimelineResponse` to include
`comparisonPeriodType`, and make sure the mapping code that builds this DTO
populates it from the timeline entity or request-derived comparison settings so
clients can see the basis for the comparison period.
🪄 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

Run ID: 7df0bd07-08ab-49bc-96d3-02773de981a5

📥 Commits

Reviewing files that changed from the base of the PR and between 2a603b5 and 028399f.

📒 Files selected for processing (4)
  • src/main/java/com/whereyouad/WhereYouAd/domains/timeline/application/dto/response/TimelineResponse.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/timeline/application/mapper/TimelineConverter.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/timeline/domain/service/TimelineServiceImpl.java
  • src/main/java/com/whereyouad/WhereYouAd/domains/timeline/persistence/entity/Timeline.java

Comment on lines +57 to +60
@Enumerated(EnumType.STRING)
@Column(name = "comparison_period_type", nullable = false)
private ComparisonPeriodType comparisonPeriodType;

@coderabbitai coderabbitai Bot Jul 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# comparison_period_type 관련 DB 마이그레이션 스크립트 존재 여부 확인
fd -e sql -e yml -e yaml . | xargs rg -l 'comparison_period_type' 2>/dev/null
fd -t d migration

Repository: WhereYouAd/WhereYouAd-Backend

Length of output: 167


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n[1] timeline entity and references\n'
rg -n "comparison_period_type|comparisonPeriodType" src/main/java src/main/resources db . 2>/dev/null || true

printf '\n[2] locate migration directories/files\n'
fd -t d migration .
fd -t f . src/main/resources db . | sed -n '1,200p'

Repository: WhereYouAd/WhereYouAd-Backend

Length of output: 23325


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== tracked migration/config files ==="
git ls-files | rg '(^|/)(migration|migrations|db/migration|flyway|liquibase|V[0-9].*\.sql|.*\.sql|.*\.yml|.*\.yaml)$' || true

echo
echo "=== comparison_period_type occurrences ==="
rg -n "comparison_period_type|comparisonPeriodType" --glob '!target/**' --glob '!build/**' . || true

echo
echo "=== Timeline.java context ==="
sed -n '1,140p' src/main/java/com/whereyouad/WhereYouAd/domains/timeline/persistence/entity/Timeline.java

Repository: WhereYouAd/WhereYouAd-Backend

Length of output: 5574


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== top-level tracked paths that look like migrations ==="
git ls-files | rg '(^|/)(db/migration|migration|migrations|flyway|liquibase)(/|$)|(^|/)V[0-9].*\.sql$|(^|/)R__.*\.sql$' || true

echo
echo "=== files mentioning timeline table or comparison period ==="
git ls-files | while read -r f; do
  case "$f" in
    *.java|*.sql|*.yml|*.yaml|*.xml|*.properties) rg -n "timeline|comparison_period_type|comparisonPeriodType" "$f" && echo "--- $f" ;;
  esac
done

echo
echo "=== Timeline.java excerpt ==="
nl -ba src/main/java/com/whereyouad/WhereYouAd/domains/timeline/persistence/entity/Timeline.java | sed -n '45,75p'

Repository: WhereYouAd/WhereYouAd-Backend

Length of output: 18748


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== application.yml ==="
nl -ba src/main/resources/application.yml | sed -n '1,220p'

echo
echo "=== build.gradle migration-related deps ==="
rg -n "flyway|liquibase|ddl-auto|hibernate\.hbm2ddl|schema" build.gradle src/main/resources/application.yml .github/workflows -n || true

Repository: WhereYouAd/WhereYouAd-Backend

Length of output: 231


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== application.yml ==="
sed -n '1,220p' src/main/resources/application.yml

echo
echo "=== build.gradle migration-related deps/config ==="
rg -n "flyway|liquibase|ddl-auto|hibernate\.hbm2ddl|schema|jakarta\.persistence|org\.flywaydb|liquibase" build.gradle src/main/resources/application.yml .github/workflows || true

Repository: WhereYouAd/WhereYouAd-Backend

Length of output: 5500


Timeline.java:58-59 — comparison_period_type는 백필 후 NOT NULL로 전환해야 합니다.
spring.jpa.hibernate.ddl-auto: update만으로 스키마를 맞추는 구조라서, 기존 timeline 데이터가 있는 상태에서 이 컬럼을 바로 nullable = false로 추가하면 반영 단계에서 실패할 수 있습니다. DEFAULT를 두거나, 먼저 nullable로 추가한 뒤 기존 row를 채우고 NOT NULL로 올려 주세요.

🤖 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/whereyouad/WhereYouAd/domains/timeline/persistence/entity/Timeline.java`
around lines 57 - 60, The new comparison_period_type column in Timeline should
not be introduced as NOT NULL immediately because existing timeline rows may
cause schema update failures. Update the Timeline entity and migration flow so
comparisonPeriodType is added with a temporary default or nullable state first,
backfill existing data, and only then enforce NOT NULL; use the Timeline and
comparisonPeriodType symbols to locate the field and related schema handling.

@kingmingyu kingmingyu Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@coderabbitai 배포 DB에 타임라인 데이터가 없는 경우는 괜찮아?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The PR description image shows an API documentation panel with Code: 200 and Details: Response body. It displays a JSON response with a dark-themed code block:

{
  "status": "OK",
  "data": {
    "timelineId": 1,
    "name": "지난주 광고 성과 요약",
    "startDate": "2026-05-13",
    "endDate": "2026-05-13",
    "performanceStatus": null,
    "comparisonPeriodType": "LAST_MONTH",
    "metrics": ["CLICK"],
    "summary": null,
    "dailyTrend": [
      {
        "date": "2026-05-13",
        "clicks": 0,
        "conversions": null,
        "impressions": null,
        "roas": null
      }
    ],
    "platformContributions": [],
    "budgetHistories": []
  }
}

There's a "Copy" icon and a "Download" button in the bottom-right of the panel.

@kingmingyu 네, 배포 DB의 timeline 테이블에 기존 row가 하나도 없다면 문제없습니다.

이유:
spring.jpa.hibernate.ddl-auto: update는 새 컬럼을 추가할 때 대략 아래와 같은 DDL을 생성합니다.

ALTER TABLE timeline ADD COLUMN comparison_period_type VARCHAR(255) NOT NULL;

NOT NULL 제약이 문제가 되는 이유는 기존 row에는 새 컬럼 값이 없어서 ALTER 시점에 제약 조건을 위반하기 때문입니다. 하지만 테이블에 row 자체가 없다면 위반할 데이터가 없으므로 이 ALTER는 그대로 성공합니다.

다만 확인하고 넘어가면 좋은 부분:

  1. 배포 직전에 실제로 row 수를 확인하는 게 안전합니다 (SELECT COUNT(*) FROM timeline;). "괜찮을 것 같다"는 가정보다 실측이 낫습니다.
  2. 운영 DB는 비어있어도, 스테이징/QA 등 다른 환경에 이미 데이터가 쌓여있다면 그 환경에서는 동일한 배포 시 실패할 수 있습니다. 다른 환경도 함께 점검해 주세요.
  3. 지금은 운영 DB가 비어있어 넘어가더라도, 다음에 유사하게 nullable 컬럼을 NOT NULL로 추가할 일이 생기면 이번처럼 "데이터 없음"을 가정하기보다 nullable로 추가 → 백필 → NOT NULL 전환의 패턴을 기본값으로 가져가는 게 안전합니다.

결론적으로 지금 배포 시점에 운영 DB의 timeline 테이블이 비어 있는 게 확인된다면, 현재 코드 그대로 배포해도 괜찮습니다. 👍


🧠 Learnings used
Learnt from: ojy0903
Repo: WhereYouAd/WhereYouAd-Backend PR: 163
File: src/main/java/com/whereyouad/WhereYouAd/domains/notification/domain/service/NotificationServiceImpl.java:160-201
Timestamp: 2026-07-04T07:01:43.103Z
Learning: For Spring-managed services, remember that a class-level `Transactional` applies to all methods unless overridden at the method level. Removing a method-level `Transactional(readOnly = true)` does not eliminate the transaction boundary—it will fall back to the class-level default (typically a non-readOnly transaction). If you need a specific method to run with *no* active transaction (e.g., to avoid holding a DB connection during synchronous outbound HTTP calls such as Slack/Discord webhook dispatch), explicitly annotate that method with `Transactional(propagation = Propagation.NOT_SUPPORTED)` to suspend any active transaction and override the class-level `Transactional`.

@kingmingyu kingmingyu changed the title Fix/#168 Fix/#168 타임라인 상세조회 - comparisonPeriodType 추가 Jul 7, 2026
@kingmingyu kingmingyu merged commit 98dff56 into develop Jul 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 Bug 버그 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: 타임라인 상세조회 - comparisonPeriodType추가

1 participant