Skip to content

[feat] SEO 최적화 - #235

Merged
blueiz920 merged 17 commits into
devfrom
feat/#225/seo-setting
Apr 16, 2026
Merged

[feat] SEO 최적화#235
blueiz920 merged 17 commits into
devfrom
feat/#225/seo-setting

Conversation

@blueiz920

@blueiz920 blueiz920 commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

📌 Summary

프로젝트 전반의 SEO 기본기를 정비했습니다.

++핫픽스 사항들 PR에 반영중입니다. (완료)

  • 모임 유형별 구분 아이콘 추가
  • 모바일 레이아웃 깨짐 수정
  • 모임 상세 페이지 - 비로그인 유저에게 모집중인 모임도 모집 마감이라 뜨던 버그 수정

관련 있는 Issue를 태그해주세요. (e.g. > - #1)

기본 metadata, robots.txt, sitemap.xml을 추가하고, 공개 페이지와 비공개/개인화 페이지를 검색엔진 관점에서 구분하도록 정책을 정리했습니다.
또한 /, /search, /moim-detail/[meetingId]에 전용 metadata를 적용해 페이지 목적에 맞는 title/description/canonical이 내려가도록 보완했습니다.

📄 Tasks

  • 루트 metadata 기본값 정리

    • src/wep/app/layout.tsx에 기본 메타데이터 정의
    • 사이트 기본 title/description/metadataBase를 공통 설정으로 분리
    • title.template 적용으로 페이지별 title 체인 일관화
  • robots.ts / sitemap.ts 추가

    • robots.ts
      • 검색엔진 크롤러가 어떤 경로를 크롤링해도 되는지, 어떤 경로를 제외해야 하는지 확인할 수 있습니다.
    • sitemap.ts
      • 검색엔진 크롤러가 현재 사이트에서 인덱싱 대상이 되는 공개 URL 목록을 확인할 수 있습니다.
      • Next.js App Router의 내장 기능을 통해 빌드 시점에 자동으로 sitemap.xml과 robots.txt 파일이 생성됩니다.
      • 크롤러는 sitemap.xml과 robots.txt에 접근하여 사이트 정보를 얻어가게 됩니다.
    • App Router metadata route 방식으로 robots.ts, sitemap.ts 추가
    • /robots.txt, /sitemap.xml이 proxy 인증 로직에 막히지 않도록 예외 처리
  • disallownoindex를 역할에 맞게 분리 적용

    • Disallow는 크롤링 자체를 허용하지 않는 목적의 경로에 적용 -> 접근에 인증이 필요한 페이지 or login, signup
    • 현재 적용 경로: /api/, /oauth/, /mypage, /spaces, /moim-create, /moim-edit
    • 이유: 위 경로들은 기계용 엔드포인트이거나 인증되지 않았다면 접근자체가 막히는 경로이므로, 검색 유입 가치보다 크롤러의 불필요한 요청을 줄이는 쪽이 더 적절하다고 판단했습니다.
    • noindex는 HTML 페이지의 검색 결과 노출을 직접 제어하는 용도로 적용
    • 인증 페이지(/login, /signup)는 공통 auth layout에서 noindex 처리했습니다.
    • /search는 기본 URL만 index 허용하고, 필터/키워드가 붙은 내부 탐색 상태는 canonical을 /search로 고정하면서 noindex 처리했습니다.
  • 동적 meetingId sitemap 수집 추가

    • /moim-detail/[meetingId]는 공개된 상세 페이지이므로 sitemap 대상에 포함했습니다.
    • 정적 /moim-detail 경로만 넣는 경우 실제 존재하지 않는 URL을 index 대상으로 내보낼 수 있어, meetings 목록 API를 순회해 실제 meetingId를 수집한 뒤 /moim-detail/{id} URL을 생성하도록 수정했습니다.
    • 이 로직은 shared/seo/get-moim-detail-urls.ts로 분리해 sitemap.ts는 정적 URL 조합과 merge만 담당하도록 정리했습니다.
    • revalidate를 적용해 크롤러가 sitemap 요청 시마다 전체 목록을 매번 다시 순회하지 않도록 했습니다.
  • 전용 metadata 적용 페이지

    • 메인 랜딩 페이지

      • 이유: 서비스 대표 진입점이라 루트 기본값만 사용하는 것보다, 랜딩 목적에 맞는 문구를 직접 내려주는 것이 더 적절했습니다.
      • _pages/landing/lib/에 메타데이터 landing-metadata.ts 파일을 생성했습니다.
    • /search

      • 이유: 공개 탐색 페이지이며, 기본 검색 URL과 쿼리 상태 URL의 SEO 정책을 분리할 필요가 있었습니다.
      • 적용 내용: title/description/openGraph, canonical /search, 쿼리 상태 noindex
      • _pages/space-search-/lib/ 에 get-search-metadata.ts 파일을 생성했습니다.
    • /moim-detail/[meetingId]

      • 이유: 공개 상세 페이지로서 개별 title/description/OG 이미지 가치가 높아 전용 metadata 적용이 필요했습니다.
      • 적용 내용: meeting 상세 데이터를 기반으로 title/description 생성, fallback 설명 처리, canonical, openGraph 이미지 연결
      • _pages/moim-detail/lib/에 메타데이터 get-moim-detail-metadata.ts파일을 생성했습니다.
  • 메타데이터 로직 위치 정리

    • 전용 metadata 로직을 한 군데에 모으는 대신, 각 페이지의 책임과 맥락이 보이도록 페이지별 lib 폴더에 분리했습니다.
    • 이유: /search는 검색 상태 기반 canonical/noindex 정책이 핵심이고, /moim-detail/[meetingId]는 상세 데이터 기반 title/description/OG 생성이 핵심이라 성격이 달라 공통 추상화보다 페이지 근처에서 관리하는 쪽이 더 읽기 쉽고 유지보수하기 적절하다고 판단했습니다.

  • 기타 HOTFIX

    • 배너 문구 SEO 맥락에 맞게 소폭 수정
    • 모임찾기 페이지에서 각 스페이스 카드별 종류 구분 아이콘 추가했습니다.
      • online | offline -> 헤드셋 | 기존locationPin
      • 스터디 | 프로젝트 -> 책 | 모니터
    • 모바일 구간에서 각 모임별 카드 레이아웃이 잘리는 현상 수정했습니다.
    • lg~xl 사이 아슬아슬한 구간에서, 마감표시 태그와 참여하기 버튼이 겹쳐 레이아웃 깨지는 현상 수정했습니다.
    • 모임상세페이지에서 모집 중인 모임도 비로그인 유저에겐 모집 마감이라고 보이던 현상 수정했습니다.

👀 To Reviewer

📸 Screenshot

  • /robots.txt 출력 화면 (disallow 위주)
    • 검색엔진 크롤러가 어떤 경로를 크롤링해도 되는지, 어떤 경로를 제외해야 하는지 확인할 수 있습니다.
    • 또한 크롤러가 접속할 수 있도록 공개된 경로가 나와있는 표지판의 격인 sitemap.xml의 주소를 안내합니다.
image
  • /sitemap.xml 출력 화면 (allow 위주)
    • 검색엔진 크롤러가 현재 사이트에서 인덱싱 대상이 되는 공개 URL 목록을 확인할 수 있습니다.
image
  • 기본 head
image
  • 메인 랜딩 페이지 head
image
  • /search head
image
  • /moim-detail/[meetingId] head (모임별 title | 기본 head)
image
  • 모임 종류 아이콘 추가
image

Summary by CodeRabbit

  • 새로운 기능

    • 사이트맵 제공 및 robots 규칙 추가로 검색 엔진 제어 강화
    • 랜딩/검색/상세 페이지용 동적 메타데이터(OG 포함) 도입으로 공유·검색성 개선
    • 상세 페이지 및 검색 페이지의 메타 생성 로직 추가
  • Chores

    • 사이트 메타데이터 중앙화(SITE_URL 등) 및 기본값 설정
    • 인증 영역에 검색 인덱스 차단 메타 추가
    • 프록시에서 robots.txt·sitemap.xml 제외 처리, 검색 문구·입력.placeholder 문구 일부 수정
  • 기타

    • .gitignore 항목에 /plan/ 추가

@blueiz920 blueiz920 self-assigned this Apr 16, 2026
@blueiz920
blueiz920 requested a review from a team as a code owner April 16, 2026 01:41
@blueiz920
blueiz920 requested review from eojindesu and removed request for a team April 16, 2026 01:41
@blueiz920 blueiz920 added ✨ Feature 새로운 기능 추가 / 퍼블리싱 🚀 Deploy 배포 관련 작업 labels Apr 16, 2026
@blueiz920 blueiz920 linked an issue Apr 16, 2026 that may be closed by this pull request
7 tasks
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

루트 메타데이터·robots·sitemap 추가, 랜딩·검색·모임상세 전용 메타데이터 도입, 검색 기본 상태 기반 robots 제어, 동적 모임 상세 URL 수집 로직 및 일부 텍스트·레이아웃·환경설정 정리가 적용되었습니다.

Changes

Cohort / File(s) Summary
환경·설정
\.gitignore, apps/web/src/shared/config/env.ts, apps/web/src/shared/config/site.ts
.gitignore 주석 수정 및 /plan/ 추가. SITE_URL 환경값 추가 및 사이트 메타데이터 상수(SITE_NAME, DEFAULT_SITE_*, METADATA_BASE, RESOLVED_SITE_URL) 중앙화.
랜딩 메타데이터 / 홈
apps/web/src/_pages/landing/lib/landing-metadata.ts, apps/web/src/app/(main)/page.tsx
랜딩 전용 landingMetadata 추가 및 홈 페이지 metadata를 해당 상수로 설정(한국어 title/description, canonical, OG).
모임 상세 메타데이터, 라우트 유효성
apps/web/src/_pages/moim-detail/lib/get-moim-detail-metadata.ts, apps/web/src/app/(main)/moim-detail/[meetingId]/page.tsx
getMoimDetailMetadata(meetingId) 추가(API 조회, 페일백, 설명 생성, OG 이미지 포함). 라우트에 generateMetadata 추가 및 parseMeetingId로 id 유효성 검사(notFound() 호출).
검색 메타데이터 / 검색 페이지
apps/web/src/_pages/space-search/lib/get-search-metadata.ts, apps/web/src/app/(main)/search/page.tsx, apps/web/src/features/space-search/model/search-params.ts, apps/web/src/_pages/space-search/constants.ts
getSearchMetadata 추가: 허용 쿼리키 검사·정규화로 기본 검색 상태 판정해 robots.index 제어. 검색 관련 텍스트(히어로/플레이스홀더)와 SEARCH_QUERY_PARAM_KEYS 상수 추가/업데이트.
루트 레이아웃 및 OG
apps/web/src/app/layout.tsx
루트 metadata를 중앙 상수로 변경(타이틀 템플릿, 기본 설명, metadataBase, openGraph 설정 추가).
인증 레이아웃 noindex
apps/web/src/app/(main)/(auth)/layout.tsx
인증 하위 레이아웃에 metadata.robots = { index: false, follow: false } 추가 및 기본 AuthLayout 컴포넌트 추가.
robots·sitemap·SEO 유틸
apps/web/src/app/robots.ts, apps/web/src/app/sitemap.ts, apps/web/src/shared/seo/get-moim-detail-urls.ts
robots() 라우트 추가(비허용 경로 목록 및 sitemap URL). sitemap() 라우트 추가: 정적 경로 + getMoimDetailUrls()로 동적 상세 URL 수집(커서 페이징, 중복 제거, 페이지 한도, 에러 로깅).
프록시 예외 및 정적 파일
apps/web/src/proxy.ts
미들웨어 예외 목록에 /robots.txt, /sitemap.xml 추가(해당 경로에서 미들웨어 우회).
UI 텍스트·레이아웃 조정
apps/web/src/features/space-search/ui/*, apps/web/src/features/space-search/ui/space-card.tsx, apps/web/src/features/space-search/ui/space-card-skeleton.tsx, apps/web/src/_pages/space-search/constants.ts
검색 관련 문구(스페이스→모임)·플레이스홀더 업데이트, 일부 레이아웃/클래스 변경, SpaceCard에 카테고리 기반 아이콘 및 categoryId 읽기 추가.
모임 액션 상태 로직
apps/web/src/entities/moim-detail/model/mapper.ts, apps/web/src/_pages/moim-detail/ui/information-container.tsx
isJoinActionAvailable 도입으로 canJoin·requiresAuth 계산 조정. 정보 컨테이너에서 requiresAuth를 신청 버튼 조건에 포함.
기타 소소 변경
\.gitignore
Codex 주석 문구 변경(Codex subagent artifactsCodex run artifacts) 및 /plan/ 추가.

Sequence Diagram(s)

sequenceDiagram
  participant Client as "Client"
  participant SitemapRoute as "app/sitemap"
  participant SEOUtil as "getMoimDetailUrls()"
  participant API as "api.meetings"
  participant Router as "ROUTES / RESOLVED_SITE_URL"

  Client->>SitemapRoute: GET /sitemap.xml
  SitemapRoute->>SEOUtil: 호출 (getMoimDetailUrls)
  SEOUtil->>API: getList(size=100, cursor)
  API-->>SEOUtil: 페이지 응답 (items, nextCursor, hasMore)
  SEOUtil->>SEOUtil: meeting.id → 절대 URL 생성 (RESOLVED_SITE_URL + ROUTES.moimDetail)
  alt 다음 페이지 존재
    SEOUtil->>API: 다음 페이지 요청 (nextCursor)
  end
  SEOUtil-->>SitemapRoute: URL 목록 반환
  SitemapRoute->>Router: 정적 경로 결합 (RESOLVED_SITE_URL + ROUTES)
  SitemapRoute-->>Client: sitemap entries (static + dynamic)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • eojindesu
  • miloupark

Poem

🐰 깡충깡충 SEO 다듬었네,
메타와 로봇 길에 표지를 세우고,
모임 주소 하나씩 모아 담으니,
검색봇도 춤추며 길을 찾아오네,
당근으로 축하해요 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed PR implements all coded objectives from issue #225: root metadata with site defaults [layout.tsx], robots.ts with Disallow paths, sitemap.ts with dynamic MOIM details, noindex for auth pages, dedicated metadata for landing/search/moim-detail, and API-based meeting URL collection.
Out of Scope Changes check ✅ Passed All changes align with SEO optimization objectives. Layout adjustments in space-search components support responsive design for SEO-related UI; mapper/information-container updates support join-action logic tied to auth/metadata context; placeholder/constant updates reflect SEO messaging changes.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/_pages/space-search/constants.ts`:
- Around line 2-3: The title/description pair in constants (the description and
title properties) use inconsistent product terms ("스페이스" vs "모임"); update them
to the same approved term from the product terminology (e.g., change title from
"지금 모임에 참여해보세요" to "지금 스페이스에 참여해보세요" or adjust description to use "모임") so both
description and title use the same word and align with the space-search context;
apply the chosen term consistently in the description and title values and
verify it matches the product term policy.

In `@apps/web/src/_pages/space-search/lib/get-search-metadata.ts`:
- Around line 13-17: isDefaultSearchPage currently treats unknown query keys
(and multi-valued arrays) as harmless because parseSearchQueryState ignores
them; update isDefaultSearchPage to reject such cases by (1) building the set of
allowed keys from the parsed queryState (const queryState =
parseSearchQueryState(searchParams); const allowed = new
Set(Object.keys(queryState))) and then comparing against the raw searchParams
keys: if any key in searchParams is not in allowed, return false; and (2) if any
searchParams value is an array (Array.isArray) with length > 1 treat it as
non-default and return false; only if no unknown keys and no multi-valued arrays
proceed to compare buildSearchHref(ROUTES.search, queryState) === ROUTES.search.
Ensure you reference isDefaultSearchPage, parseSearchQueryState,
buildSearchHref, and ROUTES.search when making the change.

In `@apps/web/src/app/`(main)/moim-detail/[meetingId]/page.tsx:
- Around line 29-37: parseMeetingId currently permits numeric strings with
exponents, leading zeros or surrounding whitespace because it uses
Number(value); instead validate the raw path segment against a strict decimal
regex like /^[1-9]\d*$/ and call notFound() if it doesn't match, then safely
convert to Number (or parseInt) and return it; update the parseMeetingId
function to perform this regex check before any Number.isInteger/<=0 checks so
only pure non-zero-leading decimal IDs (e.g. "1","10","123") are accepted.

In `@apps/web/src/shared/seo/get-moim-detail-urls.ts`:
- Around line 45-47: The catch block that currently swallows errors in
getMoimDetailUrls should log the caught error before returning an empty array;
modify the catch to catch the error (e) and emit a minimal log or metric (e.g.,
console.error or the project logger like logger.error) with context such as
"getMoimDetailUrls failed" and the error, then return []; ensure you do not
change the return behavior—only add the single-line log and keep the function
name getMoimDetailUrls referenced for locating the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: af8c47a5-847f-4663-8b15-6b58313f4f3c

📥 Commits

Reviewing files that changed from the base of the PR and between c51b286 and 6d6f2e2.

📒 Files selected for processing (16)
  • .gitignore
  • apps/web/src/_pages/landing/lib/landing-metadata.ts
  • apps/web/src/_pages/moim-detail/lib/get-moim-detail-metadata.ts
  • apps/web/src/_pages/space-search/constants.ts
  • apps/web/src/_pages/space-search/lib/get-search-metadata.ts
  • apps/web/src/app/(main)/(auth)/layout.tsx
  • apps/web/src/app/(main)/moim-detail/[meetingId]/page.tsx
  • apps/web/src/app/(main)/page.tsx
  • apps/web/src/app/(main)/search/page.tsx
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/robots.ts
  • apps/web/src/app/sitemap.ts
  • apps/web/src/proxy.ts
  • apps/web/src/shared/config/env.ts
  • apps/web/src/shared/config/site.ts
  • apps/web/src/shared/seo/get-moim-detail-urls.ts

Comment thread apps/web/src/_pages/space-search/constants.ts
Comment thread apps/web/src/_pages/space-search/lib/get-search-metadata.ts
Comment thread apps/web/src/app/(main)/moim-detail/[meetingId]/page.tsx
Comment thread apps/web/src/shared/seo/get-moim-detail-urls.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/_pages/space-search/lib/get-search-metadata.ts`:
- Around line 25-27: The current index check relies on normalized state so URLs
with invalid/empty query params (e.g., /search?category=invalid or
/search?keyword=) can be treated as the default; change get-search-metadata.ts
so it only returns index: true when the normalized href equals ROUTES.search AND
the original raw searchParams contains no query entries (i.e.,
searchParams.toString() === '' or URLSearchParams has no keys). Keep references
to parseSearchQueryState and buildSearchHref but add this additional guard on
the original searchParams to prevent false positives.

In `@apps/web/src/shared/seo/get-moim-detail-urls.ts`:
- Around line 28-42: The pagination loop using
visitedCursors/getMeetingsPage/buildMoimDetailUrl may run unbounded if an
upstream API keeps returning hasMore and new nextCursor values; add a hard cap
(e.g., maxPages or maxIterations) and increment a counter each iteration,
breaking the loop when the counter exceeds the cap (and optionally log a
warning) to prevent excessive calls; keep the existing loop logic
(visitedCursors, cursor assignment, meetingDetailUrls population) but insert the
counter check before continuing to the next getMeetingsPage call.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 623268ec-806f-4b42-8735-e0ff510f645d

📥 Commits

Reviewing files that changed from the base of the PR and between 6d6f2e2 and 432fa32.

📒 Files selected for processing (4)
  • apps/web/src/_pages/space-search/lib/get-search-metadata.ts
  • apps/web/src/app/(main)/moim-detail/[meetingId]/page.tsx
  • apps/web/src/app/(main)/search/page.tsx
  • apps/web/src/shared/seo/get-moim-detail-urls.ts

Comment thread apps/web/src/_pages/space-search/lib/get-search-metadata.ts Outdated
Comment thread apps/web/src/shared/seo/get-moim-detail-urls.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx (1)

59-64: ⚠️ Potential issue | 🟡 Minor

접근성 라벨이 placeholder와 불일치합니다

Line 60, Line 87의 aria-label이 아직 “스페이스 검색어 입력”이라, Line 63/Line 90의 “모임 …” 문구와 의미가 어긋납니다. 스크린리더 사용자에게 혼동을 줄 수 있어 동일 용어로 맞춰주세요.

수정 예시
-              aria-label="스페이스 검색어 입력"
+              aria-label="모임 검색어 입력"
...
-            aria-label="스페이스 검색어 입력"
+            aria-label="모임 검색어 입력"

Also applies to: 86-90

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx` around
lines 59 - 64, The aria-label on the search input ("스페이스 검색어 입력") does not match
the placeholder ("모임명, 설명, 카테고리, 종류 검색"); update the aria-label to the same
descriptive text as the placeholder (or vice versa) so screen readers get
consistent wording for the input that uses onChange/onKeywordChange; apply the
same change to the other instance of this input (the repeated block referenced
around the second occurrence) to keep both inputs consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/_pages/space-search/lib/get-search-metadata.ts`:
- Line 12: Replace the locally defined ALLOWED_SEARCH_PARAM_KEYS with a single
exported source: import and use the allowed-keys export from the module that
defines parseSearchQueryState (e.g., export the Set/array from the
parseSearchQueryState module and consume it here) so both the parser and
get-search-metadata use the same canonical allowed keys; update the import to
reference that exported symbol and remove the local const
ALLOWED_SEARCH_PARAM_KEYS.

In `@apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx`:
- Around line 82-83: The form's Tailwind classes in the SpaceSearchKeywordBar
component conflict: using min-w-80 together with sm:w-[15.5rem] prevents the
small breakpoint width from taking effect. Update the class list on the <form>
(in SpaceSearchKeywordBar / the element using handleSubmit) to remove the
conflicting min-w-80 or replace it with a responsive min-width (e.g., min-w-0 or
sm:min-w-[15.5rem]) and keep w-full sm:w-[15.5rem] so the intended sm breakpoint
width is honored; ensure any references to className prop are preserved.

In `@apps/web/src/shared/seo/get-moim-detail-urls.ts`:
- Around line 53-55: The catch block in getMoimDetailUrls currently logs the
entire error object which may contain sensitive request metadata; change the
catch to log a minimal, non-sensitive message (e.g., "getMoimDetailUrls failed"
plus error.message or a sanitized error code) instead of the full error object,
or call a sanitization utility before logging; update the console.error(...)
call in the getMoimDetailUrls catch block to only include safe fields
(error.message or a short identifier) and/or use an existing logging helper that
strips headers and stack traces.

---

Outside diff comments:
In `@apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx`:
- Around line 59-64: The aria-label on the search input ("스페이스 검색어 입력") does not
match the placeholder ("모임명, 설명, 카테고리, 종류 검색"); update the aria-label to the
same descriptive text as the placeholder (or vice versa) so screen readers get
consistent wording for the input that uses onChange/onKeywordChange; apply the
same change to the other instance of this input (the repeated block referenced
around the second occurrence) to keep both inputs consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 53e7a4e6-1094-4dc8-aa4a-4ffa6ca89961

📥 Commits

Reviewing files that changed from the base of the PR and between 432fa32 and 091fe7c.

📒 Files selected for processing (3)
  • apps/web/src/_pages/space-search/lib/get-search-metadata.ts
  • apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx
  • apps/web/src/shared/seo/get-moim-detail-urls.ts

Comment thread apps/web/src/_pages/space-search/lib/get-search-metadata.ts Outdated
Comment thread apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx Outdated
Comment thread apps/web/src/shared/seo/get-moim-detail-urls.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx`:
- Line 63: The placeholder text in the input was changed to "모임..." but the
aria-label still uses "스페이스", causing inconsistent screen reader text; update
the aria-label to match the placeholder wording (use "모임" instead of "스페이스") in
the input elements within the SpaceSearchKeywordBar component (look for the JSX
input/combobox elements that set placeholder and aria-label) and apply the same
change for the other occurrence noted (the second input around the other
instance mentioned).

In `@apps/web/src/shared/seo/get-moim-detail-urls.ts`:
- Line 52: Return value ordering is unstable; sort the meetingDetailUrls before
returning to make sitemap output deterministic by replacing the current spread
return of meetingDetailUrls with a sorted array (e.g., call .sort() on the array
produced from meetingDetailUrls) in the get-moim-detail-urls function so the
output order is stable across API responses and caches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 91b77531-8042-40de-b3c7-10cadf71e777

📥 Commits

Reviewing files that changed from the base of the PR and between 091fe7c and 48e88ee.

📒 Files selected for processing (7)
  • apps/web/src/_pages/space-search/lib/get-search-metadata.ts
  • apps/web/src/app/(main)/page.tsx
  • apps/web/src/app/layout.tsx
  • apps/web/src/features/space-search/model/search-params.ts
  • apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx
  • apps/web/src/proxy.ts
  • apps/web/src/shared/seo/get-moim-detail-urls.ts

Comment thread apps/web/src/features/space-search/ui/space-search-keyword-bar.tsx
cursor = page.nextCursor;
}

return [...meetingDetailUrls];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

sitemap 결과 정렬로 출력 안정성을 높여주세요.

현재는 API 응답 순서에 따라 URL 배열 순서가 달라질 수 있어, 캐시/스냅샷 비교 시 불필요한 변동이 생길 수 있습니다. 반환 전에 정렬하면 출력이 더 안정적입니다.

정렬 적용 제안
-    return [...meetingDetailUrls];
+    return [...meetingDetailUrls].sort();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return [...meetingDetailUrls];
return [...meetingDetailUrls].sort();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/shared/seo/get-moim-detail-urls.ts` at line 52, Return value
ordering is unstable; sort the meetingDetailUrls before returning to make
sitemap output deterministic by replacing the current spread return of
meetingDetailUrls with a sorted array (e.g., call .sort() on the array produced
from meetingDetailUrls) in the get-moim-detail-urls function so the output order
is stable across API responses and caches.

@blueiz920 blueiz920 added the 🚨 HOTFIX 긴급 수정 label Apr 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/space-search/ui/space-search-toolbar.tsx`:
- Line 107: 컨테이너의 현재 클래스 조합("flex-nowrap" + "overflow-hidden") 때문에 모바일(≈320px)에서
마지막 필터가 잘릴 수 있으니, 공간 검색 툴바의 컨테이너 in space-search-toolbar.tsx에서 "flex-nowrap"를
제거하거나 기본을 "flex-wrap"으로 바꾸고 "overflow-hidden"을 삭제(또는 기본을 "overflow-visible"로
변경)하여 작은 화면에서 항목이 줄바꿈되게 하세요; 또한 필요하면 packages/ui/src/components/ui/filter.tsx의
Filter 컴포넌트에서 "whitespace-nowrap"를 제거하거나 좁은 화면용으로 반응형으로 바꿔(예:
sm:whitespace-nowrap 대신 기본은 normal, sm:whitespace-nowrap) 모바일 320px에서 긴 옵션 조합으로도
레이블이 잘리지 않는지 확인해 주세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d2ccc3af-b8b5-4f9b-b3d0-0db8ad546f8d

📥 Commits

Reviewing files that changed from the base of the PR and between 48e88ee and be08d96.

📒 Files selected for processing (7)
  • apps/web/src/_pages/moim-detail/ui/information-container.tsx
  • apps/web/src/_pages/space-search/ui/space-search-hero.tsx
  • apps/web/src/entities/moim-detail/model/mapper.ts
  • apps/web/src/features/space-search/ui/space-card-skeleton.tsx
  • apps/web/src/features/space-search/ui/space-card.tsx
  • apps/web/src/features/space-search/ui/space-search-sections.tsx
  • apps/web/src/features/space-search/ui/space-search-toolbar.tsx

Comment thread apps/web/src/features/space-search/ui/space-search-toolbar.tsx
@blueiz920
blueiz920 merged commit b314c42 into dev Apr 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚀 Deploy 배포 관련 작업 ✨ Feature 새로운 기능 추가 / 퍼블리싱 🚨 HOTFIX 긴급 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] SEO 기본기 정비

1 participant