feat: 홈과 주제의 최근 기록이 게시된 Open Question 을 담는다

질문을 게시해도 홈 최근 기록에 나오지 않았다. 백엔드가 담지 않은 것이 아니라 담을 수
없었다 — 계약의 `LatestEntry.entryType` 이 CASE/REFERENCE/PROJECT_ACTIVITY/RELEASE 넷만
허용했고, 계약 밖 값을 응답 매퍼에 넘기면 500 이 되어 홈 화면 전체를 못 쓰게 만들기 때문에
질의가 먼저 걸러 내고 있었다.

계약을 넓혔으므로(design-package ef49d3a) 걸러 낼 이유가 사라졌다. `LATEST_ENTRY_TYPES` 에
`QUESTION` 을 더한다. `pathOf` 는 이미 `/questions/{slug}` 를 만들고 있었고, projection 에도
질문 행이 `ACTIVE`/`PUBLIC` 으로 `navigation_path` 까지 채워진 채 들어 있었다 — 막고 있던
것은 이 `IN` 목록 하나였다.

`LATEST_ENTRY_TYPES` 는 홈과 주제 상세가 함께 쓴다. 두 목록의 의미가 같으므로 한 곳만
넓히면 둘 다 따라오고, 그것이 의도다. 두 화면 각각에 "게시한 Open Question 이 목록에
나온다"는 단언을 세워 둔다 — 유형 허용 목록만 검사하면 담기지 않아도 통과한다.

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:43:56 +09:00
co-authored by Claude Opus 5
parent c6d9d2d675
commit edb0890dc8
5 changed files with 26 additions and 10 deletions
@@ -180,8 +180,8 @@ public class JdbcPublicSiteQueryAdapter implements PublicSiteQueryPort {
}
/**
* 계약 {@code LatestEntry.entryType} 은 {@code CASE / REFERENCE / PROJECT_ACTIVITY / RELEASE} 네 값만
* 허용한다. projection 에는 {@code QUESTION}·{@code PROJECT}·{@code PROJECT_DECISION}·{@code PROFILE} 도
* 계약 {@code LatestEntry.entryType} 은 {@code CASE / REFERENCE / QUESTION / PROJECT_ACTIVITY /
* RELEASE} 다섯 값을 허용한다. projection 에는 {@code PROJECT}·{@code PROJECT_DECISION}·{@code PROFILE} 도
* 들어 있으므로 여기서 걸러야 한다 — 거르지 않으면 응답 매퍼가 계약 밖 값을 만나 500 이 되고, 그 500 은 홈 화면 전체를 못 쓰게 만든다.
*
* <p>{@code RELEASE} 가 결과에 없는 것은 누락이 아니다. 릴리스는 Publication 파이프라인을 거치지 않고 자체 {@code
@@ -16,7 +16,7 @@ final class PublicSql {
* 조건도 한 곳에서 정의한다.
*/
static final String LATEST_ENTRY_TYPES =
" p.resource_type IN ('CASE', 'REFERENCE', 'PROJECT_ACTIVITY') ";
" p.resource_type IN ('CASE', 'REFERENCE', 'QUESTION', 'PROJECT_ACTIVITY') ";
private PublicSql() {}
@@ -206,12 +206,21 @@ class PublicSitePersistenceIntegrationTest {
.noneMatch(entry -> entry.title().contains("숨김"));
assertThat(view.latestEntries())
.as(
"계약 LatestEntry.entryType 은 네 값만 허용한다 — projection 의 QUESTION/PROJECT 등이 섞이면"
+ " 응답 매퍼가 계약 밖 값을 만나 500 이 ")
"계약 LatestEntry.entryType 이 허용하는 값만 나와야 한다 — projection 의 PROJECT/PROJECT_DECISION"
+ " 등이 섞이면 응답 매퍼가 계약 밖 값을 만나 500 이 되고, 그 500 은 홈 화면 전체를 못 쓰게 만든")
.extracting("entryType")
.containsAnyOf("CASE", "REFERENCE", "PROJECT_ACTIVITY")
.allSatisfy(
type -> assertThat(type).isIn("CASE", "REFERENCE", "PROJECT_ACTIVITY", "RELEASE"));
type ->
assertThat(type)
.isIn("CASE", "REFERENCE", "QUESTION", "PROJECT_ACTIVITY", "RELEASE"));
assertThat(view.latestEntries())
.as("게시한 Open Question 도 최근 기록에 나와야 한다 — 목록에서 빠지면 게시한 사실이 어디에도 보이지 않는다")
.anySatisfy(
entry -> {
assertThat(entry.entryType()).isEqualTo("QUESTION");
assertThat(entry.path()).isEqualTo("/questions/reprocessing-latency");
});
}
/**
@@ -397,10 +406,16 @@ class PublicSitePersistenceIntegrationTest {
assertThat(view.relatedProjects()).extracting("title").contains("Tech Log");
assertThat(view.latestRecords()).isNotEmpty();
assertThat(view.latestRecords())
.as("주제 상세의 최신 기록도 계약의 entryType 네 값을 벗어나면 안 된다")
.as("주제 상세의 최신 기록도 계약의 entryType 을 벗어나면 안 된다")
.extracting("entryType")
.allSatisfy(
type -> assertThat(type).isIn("CASE", "REFERENCE", "PROJECT_ACTIVITY", "RELEASE"));
type ->
assertThat(type)
.isIn("CASE", "REFERENCE", "QUESTION", "PROJECT_ACTIVITY", "RELEASE"));
assertThat(view.latestRecords())
.as("주제와 홈은 같은 목록 의미를 쓴다 — 홈에 나오는 Open Question 이 여기서 빠지면 두 화면이 어긋난다")
.extracting("entryType")
.contains("QUESTION");
}
@Test
+2 -2
View File
@@ -1,6 +1,6 @@
# source: tech-log-design-package contracts/openapi/studio-v1.yaml @ 0ffbc28 (master)
18dd46898be64b07f7e826409d19347512613ee2e22420028a4a0644f50f37dd studio-v1.yaml
# source: tech-log-design-package contracts/openapi/public-v1.yaml @ 0ffbc28 (master)
79949b286e2b4d28333d3376945960a319d247b675b23a73f50b75ce10994c5e public-v1.yaml
# source: tech-log-design-package contracts/openapi/public-v1.yaml @ ef49d3a (master)
7eb668e39e279e49767306dd36e1dd51302071c39d78495d21307bbd9676220e public-v1.yaml
# source: tech-log-design-package contracts/openapi/studio-management-v1.yaml @ 0ffbc28 (master)
72650735061fde627f5037571eb986cb758f44a546f065c88408399f8eec4a55 studio-management-v1.yaml
+1
View File
@@ -1022,6 +1022,7 @@ components:
enum:
- CASE
- REFERENCE
- QUESTION
- PROJECT_ACTIVITY
- RELEASE
title: