From bd66fb3610a005680f107dd01444c317816d6c11 Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Mon, 24 Aug 2026 17:25:31 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Decision=20=EB=AF=B8=EB=A6=AC=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=EA=B0=80=20=EC=97=B4=EB=A6=AC=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=EA=B3=B5=EA=B0=9C=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EB=A5=BC=20catalog=20=EC=97=90=20=EC=8B=A3?= =?UTF-8?q?=EB=8A=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decision 문서는 즉시 미리보기가 어떤 문서에서도 열리지 않았다. Decision 의 공개 주소는 자기 slug 가 아니라 `<프로젝트 경로>/decisions#` 다. 그래서 렌더 모델이 프로젝트의 공개 경로를 요구하는데, PROJECT catalog 는 그 자리를 언제나 null 로 돌려주고 있었다 — 게시된 프로젝트인지 아닌지와 무관하게 상수 null 이었다. 미리보기는 "PROJECT public path is required" 로 멈췄고, 화면에는 무엇이 모자란지 나오지 않았다. 게시된 프로젝트만 경로를 싣는다. 게시되지 않았으면 공개 주소가 실제로 없고, 없는 주소를 지어내면 미리보기가 보여 준 링크가 게시 뒤에 달라진다. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01XEHXspz4rv5pB5wiiSsVDu --- .../query/JdbcCatalogQueryAdapter.java | 20 +++++++++++-- .../ManagementPersistenceIntegrationTest.java | 30 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/query/JdbcCatalogQueryAdapter.java b/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/query/JdbcCatalogQueryAdapter.java index d7eb6c2..5b11fae 100644 --- a/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/query/JdbcCatalogQueryAdapter.java +++ b/src/adapter/outbound/persistence-jpa/src/main/java/dev/caskeleton/adapter/outbound/persistence/techlog/query/JdbcCatalogQueryAdapter.java @@ -68,11 +68,25 @@ public class JdbcCatalogQueryAdapter implements CatalogQueryPort { .list(); } + /** + * 프로젝트의 공개 경로를 함께 싣는다. + * + *

여기서 {@code publicPath} 를 늘 null 로 두었더니 Decision 의 즉시 미리보기가 어떤 문서에서도 열리지 않았다. Decision 의 공개 + * 주소는 자기 slug 가 아니라 {@code <프로젝트 경로>/decisions#} 라, 렌더 모델이 프로젝트 경로를 요구한다 — 그것이 비어 있으면 + * "PROJECT public path is required" 로 미리보기 전체가 멈춘다. 화면에는 무엇이 모자란지 나오지 않는다. + * + *

게시되지 않은 프로젝트는 여전히 null 이다. 그때는 공개 주소가 실제로 없고, 없는 주소를 지어내면 미리보기가 보여 주는 링크가 게시 뒤에 달라진다. + */ private List searchProjects(String pattern, int limit) { return jdbcClient .sql( - "SELECT id, name, updated_at FROM project " - + "WHERE lower(name) LIKE :pattern ORDER BY name LIMIT :limit") + "SELECT pr.id, pr.name, pr.updated_at, p.navigation_path" + + " FROM project pr" + + " LEFT JOIN public_resource_projection p" + + " ON p.resource_type = 'PROJECT' AND p.resource_id = pr.id" + + " AND " + + PUBLICLY_VISIBLE + + " WHERE lower(pr.name) LIKE :pattern ORDER BY pr.name LIMIT :limit") .param("pattern", pattern) .param("limit", limit) .query( @@ -82,7 +96,7 @@ public class JdbcCatalogQueryAdapter implements CatalogQueryPort { CatalogEntryType.PROJECT, rs.getString("name"), "PROJECT", - null, + rs.getString("navigation_path"), "project:" + rs.getTimestamp("updated_at").toInstant())) .list(); } diff --git a/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/management/ManagementPersistenceIntegrationTest.java b/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/management/ManagementPersistenceIntegrationTest.java index f987730..ea7d843 100644 --- a/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/management/ManagementPersistenceIntegrationTest.java +++ b/src/adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/techlog/management/ManagementPersistenceIntegrationTest.java @@ -785,4 +785,34 @@ class ManagementPersistenceIntegrationTest { .single()) .isZero(); } + + /** + * Decision 의 공개 주소는 자기 slug 가 아니라 프로젝트 주소 아래에 있다. 그래서 편집기가 Decision 을 미리 그리려면 이 목록이 프로젝트의 공개 경로를 + * 알고 있어야 한다 — 한동안 늘 null 이었고, 그동안 Decision 은 어떤 문서에서도 즉시 미리보기가 열리지 않았다. + */ + @Test + void projectCatalogCarriesThePublicPathOfPublishedProjectsOnly() { + ProjectEditView open = projects.create(new CreateProjectCommand("Catalog Published", "test")); + jdbcClient + .sql("UPDATE project SET slug = 'catalog-published' WHERE id = :id") + .param("id", open.id()) + .update(); + ProjectEditView loaded = projects.find(open.id()).orElseThrow(); + assertThat(projects.publish(loaded.id(), loaded.version(), "PUBLIC", "test")).isPresent(); + + ProjectEditView hidden = projects.create(new CreateProjectCommand("Catalog Hidden", "test")); + + var entries = catalog.search(CatalogEntryType.PROJECT, "catalog", null, 50).items(); + + assertThat(entries) + .filteredOn(entry -> entry.id().equals(open.id())) + .singleElement() + .satisfies( + entry -> assertThat(entry.publicPath()).isEqualTo("/projects/catalog-published")); + // 게시되지 않은 프로젝트는 공개 주소가 실제로 없다. 지어내면 미리보기가 보여 준 링크가 게시 뒤에 달라진다. + assertThat(entries) + .filteredOn(entry -> entry.id().equals(hidden.id())) + .singleElement() + .satisfies(entry -> assertThat(entry.publicPath()).isNull()); + } }