fix: 최근 기록에 Open Question 을 싣고, 주제 링크를 탐색 필터로 돌린다

게시한 질문이 홈 최근 기록에 나오지 않았다. 계약의 `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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0189NzCryfeqDzS81EWidnBx
This commit is contained in:
DongHyeonka
2026-08-26 23:44:20 +09:00
co-authored by Claude Opus 5
parent ad8f322b43
commit 2632850322
9 changed files with 26 additions and 13 deletions
+5 -5
View File
@@ -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"
}
]
}
@@ -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;
@@ -2,7 +2,7 @@
"packageId": "@tech-log/management-contract",
"version": "1.0.0",
"digest": "sha256:72650735061fde627f5037571eb986cb758f44a546f065c88408399f8eec4a55",
"sourceRevision": "0ffbc28",
"sourceRevision": "ef49d3a",
"operationIds": [
"createCaseDraft",
"getCaseForEdit",
@@ -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",
@@ -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;
@@ -1022,6 +1022,7 @@ components:
enum:
- CASE
- REFERENCE
- QUESTION
- PROJECT_ACTIVITY
- RELEASE
title:
@@ -2,7 +2,7 @@
"packageId": "@tech-log/studio-contract",
"version": "3.1.0",
"digest": "sha256:18dd46898be64b07f7e826409d19347512613ee2e22420028a4a0644f50f37dd",
"sourceRevision": "0ffbc28",
"sourceRevision": "ef49d3a",
"operationIds": [
"getStudioSession",
"getStudioDashboard",
@@ -19,7 +19,13 @@ export function PublicDocumentHeader({ record }: { record: PublicRecord }) {
{kindLabels[record.kind]}
</Link>
<span aria-hidden="true">/</span>
<Link to={`/topics/${record.topicSlug}`}>{record.topic}</Link>
{/*
주제 페이지가 아니라 그 주제로 거른 탐색으로 보낸다. `/topics/:slug` 는 세 개를
하드코딩해 두고 있어 실제 주제는 무엇이든 404 가 되고, 설명·범위·대표 기록이 전부
비어 있어 지금 채울 내용도 없다. 독자가 여기서 기대하는 것 — 같은 주제의 기록 목록 —
은 탐색 필터가 그대로 준다.
*/}
<Link to={`/explore?topic=${encodeURIComponent(record.topicSlug)}`}>{record.topic}</Link>
<span aria-hidden="true">/</span>
<Link to={`/projects/${record.projectSlug}`}>
{record.projectTitle}
@@ -50,6 +50,11 @@ function optionalString(value: unknown): string | undefined {
* 릴리스는 Publication 파이프라인을 거치지 않아 그 투영에 행이 없다. 그래서 릴리스만 따로 읽어
* 시간순으로 합친다.
*/
const latestTypeLabels: Readonly<Record<string, string>> = {
PROJECT_ACTIVITY: "PROJECT ACTIVITY",
QUESTION: "OPEN QUESTION",
};
async function getLatestEntries(
publicContent: PublicContentQueries,
): Promise<LatestEntry[]> {
@@ -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),