docs(blog): TypeScript 6 삽질기 글 정비 + 인라인 code 렌더링 수정#129
Conversation
…Node 버전 동기화 - @design-system/ui: 최상위 main/types가 tsup 시절 .js/.d.ts를 가리켜 dangling 참조였음. tsdown은 .mjs/.d.mts만 산출하므로 publishConfig.exports와 일치시킴 - CLAUDE.md: engines.node >=24 반영 (Node >=22 → >=24), pnpm 10.10.0 → 11.6.0 동기화 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baseUrl deprecation(TS5101)·types 기본값 []·rootDir 요구(TS5011)를 릴리스 노트·이슈를 넘어 실제 microsoft/TypeScript PR diff(#62509·#63054·#62418)까지 추적하는 탐구 서사로 전면 재작성. 보너스로 유지보수가 멈춘 tsup을 tsdown으로 전환한 과정까지. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scripts/build-content.ts가 prebuild/predev에서 재생성하는 public/ 산출물을 .gitignore에 추가하고 추적에서 제거. 빌드 시점에 항상 새로 생성되므로 버전 관리 불필요. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- named catalog(react19) → 기본 catalog로 react·react-dom·@types 통합 (stable 19.2.x) - apps/{react,blog-web,next.js}·@design-system/ui의 catalog:react19 → catalog: 전환 - @design-system/ui: 빌드 도구(tsdown·typescript)를 dependencies → devDependencies (동일 파일이라 함께 반영) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- @package/bundler: tsdown.config에 target: 'node24' 명시 (platform과 별개 축) - @package/core: 루트(pnpm@11.6.0)와 어긋난 packageManager(pnpm@10.4.1) 필드 제거 - blog: tsup→tsdown 보너스에 함정(platform≠target, 빌드도구 devDeps) + 체크리스트 보강 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 도입부(회사 리허설→부채→TS7 Go 청소)와 결말 수미상관 구성 - baseUrl→package.json imports 곁가지(details), tsup 5장 압축 - '정작 가장 큰 수확'을 7장으로 승격 + 정리/액션 재구성 - excerpt 압축·tags 보강 등 SEO, 6렌즈 평가 기반 구조 개선 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts: # apps/blog/posts/typescript/typescript-6-업그레이드-삽질기.md
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 PR은 TypeScript 6 마이그레이션 관련 블로그 포스트의 내용을 최신화하고, 프로젝트 내 불필요한 IDE 설정 파일을 정리하며 전반적인 문서 및 환경 설정을 정비하는 것을 목적으로 합니다. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
이번 풀 리퀘스트는 불필요한 IDE 설정 파일들을 정리하고 Node.js 버전을 24.17.0으로 업데이트하며, TypeScript 6 마이그레이션 삽질기를 다룬 기술 블로그 포스트를 추가 및 보완합니다. 리뷰어 피드백에서는 마크다운 문서 내 코드 블록 지시어의 적절한 사용(json 대신 jsonc), 인라인 코드 블록 주변의 공백 추가, 줄바꿈으로 인한 볼드체 강조 기호 분리 수정, 그리고 JSON 스니펫 내 불필요한 trailing comma 제거 등 문서의 가독성과 구문 정확성을 높이기 위한 유용한 개선 사항들이 제시되었습니다.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| `baseUrl`이 deprecated된다는 건 이미 알고 있었다. 내 코드에서 `baseUrl`을 실제로 쓰는 곳은 React 앱 하나뿐이었고, `paths`의 접두사 용도였다. | ||
|
|
||
| ```jsonc | ||
| ```json |
| ``` | ||
|
|
||
| 그냥 지웠다. `paths`는 [TypeScript 4.1부터 `baseUrl` 없이 동작](https://www.typescriptlang.org/tsconfig/baseUrl.html)한다. | ||
| 그냥 지웠다. `paths`는 [TypeScript 4.1부터`baseUrl` 없이 동작](https://www.typescriptlang.org/tsconfig/baseUrl.html)한다. |
| `baseUrl`이 6.0에서 막힌 그 이유(런타임에 안 맞는 import를 타입체커만 통과)와 정도만 다를 뿐 같은 괴리를 안는다. 그 괴리가 구조적으로 없는 대안이 * | ||
| *Node가 런타임에 직접 읽는 package.json `imports`** (`#` subpath)다 — 타입과 런타임이 같은 매핑을 보니 어긋날 수 없고, TS 핸드북도 |
| +export function usesWildcardTypes(options: CompilerOptions): options is CompilerOptions & { types: string[] } { | ||
| + return some(options.types, t => t === "*"); | ||
| +} | ||
| ```json |
| "rootDir": "./src", // ← 추가 | ||
| } |
PR Review: TypeScript 6 삽질기 글 정비 + 인라인 code 렌더링 수정이 PR은 TypeScript 6 마이그레이션 블로그 글을 draft에서 published 상태로 전환하고, 섹션 순서 재배치 및 내용 보강을 포함합니다. 동시에 MDX 렌더러에서 인라인 🔴 중요: 예약 발행 메커니즘 오류
date: '2026-07-02'
published: true오늘(2026-06-27)로부터 5일 뒤 날짜를 예약 발행이 의도라면 CLAUDE.md 정책대로 아래 형식을 사용해야 합니다: status: 'scheduled'
scheduledDate: '2026-07-02T09:00:00+09:00'🟡
|
| # | 파일 | 심각도 | 문제 |
|---|---|---|---|
| 1 | typescript-6-...삽질기.md |
🔴 | published: true + 미래 날짜 → 즉시 공개됨. status: 'scheduled' + scheduledDate 필요 |
| 2 | PostClient.tsx |
🟡 | react-markdown v10에서 node prop 제거로 tagName 체크 항상 undefined → 수정 무효 |
| 3 | admin-posts-index.json |
🟡 | 빌드 산출물 수동 커밋 → 다음 빌드 시 덮어써짐 |
| 4 | .idea/dataSources.xml |
🔵 | DB URL이 git 히스토리에 잔존 (자격증명 여부 확인 권장) |
published: true → status: scheduled + scheduledDate(2026-07-02T09:00+09:00). status가 있으면 isPostVisible은 published를 무시하므로 published 필드 제거. 매일 KST 09:00 cron 빌드에서 예약 시각 도달 시 자동 공개됩니다. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Code Review이 PR은 세 가지를 포함합니다: TypeScript 6 삽질기 블로그 포스트 개편 (draft → scheduled), 인라인 코드 렌더링 버그 수정 ( 🟡
|
| 필드 | admin-posts-index.json (커밋된 값) |
실제 frontmatter |
|---|---|---|
status |
"published" |
"scheduled" |
scheduledDate |
null |
"2026-07-02T09:00:00+09:00" |
이 파일은 scripts/generate-search-index.ts의 buildAdminPostsIndex()가 자동 생성하는 파일입니다. frontmatter를 status: 'scheduled'으로 바꾼 후 스크립트를 재실행하지 않아 커밋 시점에 이미 stale한 상태가 됐습니다. 다음 빌드에서 자동 정정되지만, PR 상태에서 admin 대시보드를 확인하면 잘못된 published 상태로 표시됩니다.
권고: PR 머지 전에 pnpm blog-web(prebuild) 혹은 빌드 스크립트를 한 번 실행해 admin-posts-index.json을 재생성하고 커밋에 포함하세요.
🟢 apps/blog/web/src/app/posts/[...slug]/PostClient.tsx:265 — isBlockElement 수정 검증 완료
// Before
const isBlockElement = (node: unknown) =>
isValidElement(node) && typeof node.type !== 'string';
// After
const isBlockElement = (node: unknown) => {
if (!isValidElement(node) || typeof node.type === 'string') {
return false;
}
const tagName = (node.props as { node?: { tagName?: string } })?.node?.tagName;
return tagName !== 'code';
};로직 검증: node.props.node?.tagName 경로가 실제로 hast 노드의 tagName에 도달하는지 확인했습니다. react-markdown은 custom 컴포넌트에 node prop으로 hast Element를 전달하므로, 이 경로는 올바릅니다. 인라인 코드(`foo`)의 경우 tagName === 'code'가 맞고, 고쳐진 버그(인라인 code가 block 취급되어 <p> → <div> 변환되던 문제)가 의도대로 해결됩니다.
한 가지 개선 가능 포인트: node.props as { node?: { tagName?: string } }는 매우 느슨한 타입 캐스트입니다. react-markdown의 hast Element 타입을 직접 import해서 사용하면 향후 API 변경을 TypeScript가 잡아줄 수 있습니다:
import type { Element } from 'hast';
// ...
const tagName = (node.props as { node?: Element })?.node?.tagName;현재는 기능상 완전히 올바르므로 blocking 이슈는 아닙니다.
🟡 .idea/dataSources.xml — 프로덕션 DB URL이 git 이력에 기록됨
이번 PR에서 .idea/ 파일들을 정리하는 것 자체는 바람직합니다. 다만 dataSources.xml에는 프로덕션 Supabase DB 호스트(aws-0-ap-northeast-2.pooler.supabase.com)가 포함되어 있었고, 이 파일은 이전에 이미 git 이력에 커밋된 상태입니다. 자격증명(credentials)은 없으므로 즉각적인 보안 위험은 아니지만, .idea/가 .gitignore에 포함되어 있지 않아 발생한 일입니다.
권고: 루트 .gitignore에 .idea/를 추가하여 재발 방지 (이번 PR 범위가 아니라면 별도 PR로).
✅ 기타
.tool-versionsNode.js 24.6.0 → 24.17.0 업데이트: 정상thumbnail: 'typescript-6-migration-thumb.png'경로 형식:resolveThumbnailUrl()이/posts/{relativeDir}/를 자동으로 prefix하므로 시리즈 폴더 없이 파일명만 쓰는 것이 올바른 형식입니다.- 포스트 frontmatter의
status: 'scheduled'+scheduledDate: '2026-07-02T09:00:00+09:00'조합: CLAUDE.md 규칙에 맞게 작성됨.
요약: admin-posts-index.json 재생성 후 재커밋을 권고합니다. PostClient.tsx 코드 수정은 검증 완료되었으며 올바릅니다.
generate-search-index.ts 생성기로 재생성하여 .md frontmatter(status: scheduled, scheduledDate)와 동기화. 손으로 두었던 status:'published', scheduledDate:null 항목을 정정. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
isBlockElement(인라인 클로저, code 태그 denylist)를 모듈 레벨 순수 함수 isBlockMarkdownChild로 교체. - fenced code(language-*)가 <p> 안에 들어올 때도 블록으로 인식해 무효 중첩(<p><div>…</div></p>) → hydration mismatch 방지 - react-markdown 내부 node prop(node.props.node.tagName) 의존 제거. 커스텀 블록 컴포넌트는 참조(identity), fenced code는 공개 prop className 으로 식별 → 라이브러리 업그레이드 시 회귀 방지 - 인라인 이미지/코드 등 phrasing 콘텐츠를 더는 <div>로 오포장하지 않음 (`& p` 마진/타이포 보존). denylist 1태그 설계 → allowlist로 전환 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Code ReviewThis PR has two distinct parts: a bug fix in The bug fix is the only code logic change, so that's where the review is focused. ✅ Fix is correct for its stated purpose
The root cause was right: This works because fenced code blocks are block-level in standard Markdown and are never parsed as children of
|
hast-util-to-jsx-runtime는 컴포넌트 type이 함수일 때(passNode:true)
hast node를 props.node로 주입한다. p/table/li 오버라이드가 이 props를
{...props}로 host 요소에 spread하면서 node="[object Object]" 속성이
렌더링됐다. 세 곳에서 node를 destructure로 걸러내 누출 제거.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
generate-search-index.ts가 prebuild/predev에서 매번 재생성하는 산출물. 형제 파일(search-index.json·sitemap.xml·rss.xml·llms-full.txt)은 이미 gitignore인데 이 파일만 추적돼 "커밋+자동생성" drift 위험이 있었다 (코드 리뷰 봇·워크플로 공통 지적). gitignore에 추가하고 추적 해제해 public/ 생성물 처리를 일관화한다. 배포 빌드가 재생성하므로 안전. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Code Review이 PR은 TypeScript 6 업그레이드 블로그 글을 draft → scheduled로 정비하고, 🔴 버그 (CONFIRMED):
|
Code Review이 PR은 [HIGH] MarkdownImage 회귀:
|
MarkdownImage는 react-medium-image-zoom <Zoom>의 블록 <div data-rmiz>를
렌더하므로 단독 이미지()가 <p><div></div></p> 무효 중첩을
만들었다. img는 closure(relativeDir)가 필요한 인라인 래퍼로 매핑돼
child.type이 래퍼 함수라 identity로 못 잡으므로(코드 리뷰 봇 제안의
Set 추가가 실제로는 매치 안 됨), code의 className 판별과 동일하게 공개
prop src로 식별하도록 보강.
- BLOCK_MARKDOWN_COMPONENTS: Set<unknown> → Set<ElementType> (컴포넌트가
아닌 값이 들어가면 컴파일 단계에서 차단)
- isValidElement<{ className?; src? }>로 props 캐스팅 제거
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR Review이 PR은 두 가지 작업을 합칩니다: (1) TypeScript 6 업그레이드 경험을 담은 블로그 글 정비 및 예약 발행 설정, (2) 마크다운 단락( Findings1.
|
함수명이 이미 전달하는 내용을 반복하던 JSDoc 제거(CLAUDE.md: 기본은 주석 없음, non-obvious WHY만). hydration mismatch 방지 의도와 identity/ 공개-prop 식별 이유만 인라인 주석으로 유지. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
isBlockMarkdownChild를 PostClient에서 markdownBlocks.ts로 분리하고 Vitest 테스트(14 케이스)를 co-located로 추가. 코드 리뷰 봇이 반복 지적한 "p 오버라이드 테스트 부재"를 해소하고, 그간 회귀가 잦던 분기를 잠근다: - 직접 매핑된 블록 컴포넌트(Callout/Figure/FileTree) identity 판정 - 이미지: 인라인 래퍼라 identity 불가 → src 공개 prop으로 판정 - inline vs fenced code: 동일 핸들러라 language-* className으로만 구분 - phrasing 네이티브 요소/문자열/숫자/null은 비블록 src/의 React 의존 테스트는 vitest 러너가 담당(node --test 글롭 밖)이라 별도 설정 변경 없이 편입된다. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Code Review for PR 129 |
|
Code Review summary: PR does three things: TypeScript 6 blog post major reorg, inline code block element misclassification rendering bug fix, .idea/ cleanup + admin-posts-index.json gitignore. Issue [Medium]: BLOCK_MARKDOWN_COMPONENTS allowlist maintenance burden - when adding new block-level custom components to the components map, forgetting to update BLOCK_MARKDOWN_COMPONENTS will silently reintroduce invalid nesting (p>div). Issue [Low]: src prop detection is somewhat broad - audio/video elements via rehype-raw could be misclassified as block. Well done: node:_node separation, admin-posts-index.json gitignore, scheduled publish settings accurate. Generated with Claude Code |
Code ReviewThis PR improves an inline Three findings worth addressing: Finding 1 (maintenance hazard):
The Set is a manually-maintained parallel of the Suggestion: define a shared Finding 2 (minor):
Finding 3 (low):
This PR adds Summary: Finding 1 is the most actionable. The sync hazard between Generated with Claude Code |
Code ReviewPR은 세 가지 일을 합니다: TypeScript 6 삽질기 블로그 글 대폭 정비, 인라인 발견된 이슈[중간]
두 곳의 동기화를 강제하는 가장 간단한 방법은 [낮음]
잘 된 부분
전반적으로 버그 수정의 의도는 명확하고 핵심 케이스(인라인 🤖 Generated with Claude Code |
개요
PR #128(TypeScript 6 + 빌드 툴체인 업데이트) 이후 작업으로, TypeScript 6 업그레이드 삽질기 블로그 글을 정비하고, 그 글을 쓰면서 발견한 마크다운 렌더링 버그를 함께 수정합니다.
변경 사항
블로그
apps/blog/posts/typescript/typescript-6-업그레이드-삽질기.md— 글 전반 정비 (489 라인 변경)baseUrl/rootDir/types기본값 변경의 "왜"를 microsoft/TypeScript PR diff까지 추적한 내용으로 재구성status: scheduled,scheduledDate: 2026-07-02T09:00:00+09:00(KST 09:00 cron 빌드에서 자동 공개)typescript-6-migration-thumb.png) 추가 및THUMBNAIL_LOG.md기록admin-posts-index.json갱신버그 수정
PostClient.tsx— 마크다운 단락(<p>) 안의 인라인code가 블록 요소로 오판되던 문제 수정.isBlockElement가node.tagName === 'code'를 명시적으로 제외하도록 변경해, 인라인 코드가 포함된 단락이 잘못 분해되지 않도록 함.기타
.idea/디렉터리 git 추적 제외 (12개 파일 삭제).tool-versions갱신발행 동작
status: scheduled이므로, 이 PR을 머지해도 즉시 공개되지 않습니다.2026-07-02 09:00 KST)이 지난 뒤 매일 KST 09:00 cron 빌드가 돌면 자동으로 공개됩니다. (isPostVisible:status가 있으면published필드는 무시)scheduledDate만 조정하면 됩니다.참고
🤖 Generated with Claude Code