From 263285032270fd9ce60b5477864bcae12c08065a Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Wed, 26 Aug 2026 23:44:20 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=B5=9C=EA=B7=BC=20=EA=B8=B0=EB=A1=9D?= =?UTF-8?q?=EC=97=90=20Open=20Question=20=EC=9D=84=20=EC=8B=A3=EA=B3=A0,?= =?UTF-8?q?=20=EC=A3=BC=EC=A0=9C=20=EB=A7=81=ED=81=AC=EB=A5=BC=20=ED=83=90?= =?UTF-8?q?=EC=83=89=20=ED=95=84=ED=84=B0=EB=A1=9C=20=EB=8F=8C=EB=A6=B0?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게시한 질문이 홈 최근 기록에 나오지 않았다. 계약의 `LatestEntry.entryType` 이 네 값만 허용해 백엔드가 담을 수 없었다 — design-package ef49d3a 에서 `QUESTION` 을 더했고 여기서 계약을 다시 생성한다. 포트의 `LatestRecordEntry.entryType` 도 같이 넓히고, 홈의 표기는 목록의 다른 이름들과 같은 규칙(대문자에 공백)을 따라 `OPEN QUESTION` 으로 적는다. 문서 머리말의 주제 링크는 `/topics/:slug` 로 가고 있었는데, 그 화면은 `jpa`/`authentication` /`redis` 세 개를 하드코딩해 두고 있어 실제 주제는 무엇이든 404 가 됐다. 게시한 모든 문서의 주제 링크가 거기로 갔다. 주제 페이지를 채우는 대신 링크를 탐색 필터로 돌린다. 지금 그 페이지만 줄 수 있는 것 — 설명, 범위, 선별한 대표 기록 — 이 전부 비어 있고, Studio 의 주제 만들기는 `{name, slug}` 만 보내므로 설명을 쓸 칸조차 없다. 독자가 거기서 기대하는 것은 같은 주제의 기록 목록이고, 그것은 `/explore?topic=` 이 그대로 준다. 주제가 여러 개가 되고 설명을 쓸 수 있게 되면 그때 페이지를 만드는 것이 순서다. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_0189NzCryfeqDzS81EWidnBx --- public/release-manifest.json | 10 +++++----- .../application/ports/public-content-queries.ts | 2 +- .../contracts/management/canonical-source.json | 2 +- .../tech-log/contracts/public/canonical-source.json | 4 ++-- src/features/tech-log/contracts/public/generated.ts | 2 +- .../tech-log/contracts/public/public-api.openapi.yaml | 1 + .../tech-log/contracts/studio/canonical-source.json | 2 +- .../public/components/public-document-header.tsx | 8 +++++++- .../tech-log/presentation/public/pages/home-page.tsx | 8 +++++++- 9 files changed, 26 insertions(+), 13 deletions(-) diff --git a/public/release-manifest.json b/public/release-manifest.json index 0627d5f..faab20d 100644 --- a/public/release-manifest.json +++ b/public/release-manifest.json @@ -38,28 +38,28 @@ }, "contractSet": { "setAlgorithm": "CA_CONTRACT_SET_V1", - "setDigest": "sha256:104bab24221f6d1a4c5fa7df68f5d027d227325a88fa507ebfcccebb439eb7c4", + "setDigest": "sha256:cdcfb628a502d71596f1162726eb395aad0f5f92cf05fd77d304f8e51c81b2fc", "packages": [ { "packageId": "@tech-log/management-contract", "version": "1.0.0", "digest": "sha256:72650735061fde627f5037571eb986cb758f44a546f065c88408399f8eec4a55", "runtimeProtocolVersion": 1, - "sourceRevision": "0ffbc28" + "sourceRevision": "ef49d3a" }, { "packageId": "@tech-log/public-contract", "version": "2.1.0", - "digest": "sha256:79949b286e2b4d28333d3376945960a319d247b675b23a73f50b75ce10994c5e", + "digest": "sha256:7eb668e39e279e49767306dd36e1dd51302071c39d78495d21307bbd9676220e", "runtimeProtocolVersion": 1, - "sourceRevision": "0ffbc28" + "sourceRevision": "ef49d3a" }, { "packageId": "@tech-log/studio-contract", "version": "3.1.0", "digest": "sha256:18dd46898be64b07f7e826409d19347512613ee2e22420028a4a0644f50f37dd", "runtimeProtocolVersion": 1, - "sourceRevision": "0ffbc28" + "sourceRevision": "ef49d3a" } ] } diff --git a/src/features/tech-log/application/ports/public-content-queries.ts b/src/features/tech-log/application/ports/public-content-queries.ts index 375f986..5028a52 100644 --- a/src/features/tech-log/application/ports/public-content-queries.ts +++ b/src/features/tech-log/application/ports/public-content-queries.ts @@ -173,7 +173,7 @@ export type PublicTopic = { */ export type LatestRecordEntry = { id: string; - entryType: "CASE" | "REFERENCE" | "PROJECT_ACTIVITY" | "RELEASE"; + entryType: "CASE" | "REFERENCE" | "QUESTION" | "PROJECT_ACTIVITY" | "RELEASE"; title: string; summary: string; path: string; diff --git a/src/features/tech-log/contracts/management/canonical-source.json b/src/features/tech-log/contracts/management/canonical-source.json index 05f7eff..4642375 100644 --- a/src/features/tech-log/contracts/management/canonical-source.json +++ b/src/features/tech-log/contracts/management/canonical-source.json @@ -2,7 +2,7 @@ "packageId": "@tech-log/management-contract", "version": "1.0.0", "digest": "sha256:72650735061fde627f5037571eb986cb758f44a546f065c88408399f8eec4a55", - "sourceRevision": "0ffbc28", + "sourceRevision": "ef49d3a", "operationIds": [ "createCaseDraft", "getCaseForEdit", diff --git a/src/features/tech-log/contracts/public/canonical-source.json b/src/features/tech-log/contracts/public/canonical-source.json index 538cf49..61433d0 100644 --- a/src/features/tech-log/contracts/public/canonical-source.json +++ b/src/features/tech-log/contracts/public/canonical-source.json @@ -1,8 +1,8 @@ { "packageId": "@tech-log/public-contract", "version": "2.1.0", - "digest": "sha256:79949b286e2b4d28333d3376945960a319d247b675b23a73f50b75ce10994c5e", - "sourceRevision": "0ffbc28", + "digest": "sha256:7eb668e39e279e49767306dd36e1dd51302071c39d78495d21307bbd9676220e", + "sourceRevision": "ef49d3a", "operationIds": [ "getPublicSite", "getPublicHome", diff --git a/src/features/tech-log/contracts/public/generated.ts b/src/features/tech-log/contracts/public/generated.ts index 321c040..1c7f5a1 100644 --- a/src/features/tech-log/contracts/public/generated.ts +++ b/src/features/tech-log/contracts/public/generated.ts @@ -454,7 +454,7 @@ export interface components { }; LatestEntry: { /** @enum {string} */ - entryType: "CASE" | "REFERENCE" | "PROJECT_ACTIVITY" | "RELEASE"; + entryType: "CASE" | "REFERENCE" | "QUESTION" | "PROJECT_ACTIVITY" | "RELEASE"; title: string; summary: string; path: string; diff --git a/src/features/tech-log/contracts/public/public-api.openapi.yaml b/src/features/tech-log/contracts/public/public-api.openapi.yaml index 28dd4f5..1631d17 100644 --- a/src/features/tech-log/contracts/public/public-api.openapi.yaml +++ b/src/features/tech-log/contracts/public/public-api.openapi.yaml @@ -1022,6 +1022,7 @@ components: enum: - CASE - REFERENCE + - QUESTION - PROJECT_ACTIVITY - RELEASE title: diff --git a/src/features/tech-log/contracts/studio/canonical-source.json b/src/features/tech-log/contracts/studio/canonical-source.json index 6ae8885..c014d8b 100644 --- a/src/features/tech-log/contracts/studio/canonical-source.json +++ b/src/features/tech-log/contracts/studio/canonical-source.json @@ -2,7 +2,7 @@ "packageId": "@tech-log/studio-contract", "version": "3.1.0", "digest": "sha256:18dd46898be64b07f7e826409d19347512613ee2e22420028a4a0644f50f37dd", - "sourceRevision": "0ffbc28", + "sourceRevision": "ef49d3a", "operationIds": [ "getStudioSession", "getStudioDashboard", diff --git a/src/features/tech-log/presentation/public/components/public-document-header.tsx b/src/features/tech-log/presentation/public/components/public-document-header.tsx index e988cad..ed98b68 100644 --- a/src/features/tech-log/presentation/public/components/public-document-header.tsx +++ b/src/features/tech-log/presentation/public/components/public-document-header.tsx @@ -19,7 +19,13 @@ export function PublicDocumentHeader({ record }: { record: PublicRecord }) { {kindLabels[record.kind]} - {record.topic} + {/* + 주제 페이지가 아니라 그 주제로 거른 탐색으로 보낸다. `/topics/:slug` 는 세 개를 + 하드코딩해 두고 있어 실제 주제는 무엇이든 404 가 되고, 설명·범위·대표 기록이 전부 + 비어 있어 지금 채울 내용도 없다. 독자가 여기서 기대하는 것 — 같은 주제의 기록 목록 — + 은 탐색 필터가 그대로 준다. + */} + {record.topic} {record.projectTitle} diff --git a/src/features/tech-log/presentation/public/pages/home-page.tsx b/src/features/tech-log/presentation/public/pages/home-page.tsx index 1569dd7..c4a3f5d 100644 --- a/src/features/tech-log/presentation/public/pages/home-page.tsx +++ b/src/features/tech-log/presentation/public/pages/home-page.tsx @@ -50,6 +50,11 @@ function optionalString(value: unknown): string | undefined { * 릴리스는 Publication 파이프라인을 거치지 않아 그 투영에 행이 없다. 그래서 릴리스만 따로 읽어 * 시간순으로 합친다. */ +const latestTypeLabels: Readonly> = { + PROJECT_ACTIVITY: "PROJECT ACTIVITY", + QUESTION: "OPEN QUESTION", +}; + async function getLatestEntries( publicContent: PublicContentQueries, ): Promise { @@ -60,7 +65,8 @@ async function getLatestEntries( const recordTimeline: LatestEntry[] = records.map((entry) => ({ id: entry.id, - typeLabel: entry.entryType === "PROJECT_ACTIVITY" ? "PROJECT ACTIVITY" : entry.entryType, + // 목록의 다른 이름들과 같은 자리에 놓이므로 표기도 같은 규칙을 쓴다 — 대문자에 공백. + typeLabel: latestTypeLabels[entry.entryType] ?? entry.entryType, title: entry.title, summary: entry.summary, date: dateLabel(entry.publishedAt),