Skip to content

fix(webview): RN WebView 홍보 탭 헤더 누락 및 검색바 너비 수정#1612

Open
oesnuj wants to merge 1 commit into
develop-fefrom
fix/#1611-rn-webview-header-layout-MOA-918
Open

fix(webview): RN WebView 홍보 탭 헤더 누락 및 검색바 너비 수정#1612
oesnuj wants to merge 1 commit into
develop-fefrom
fix/#1611-rn-webview-header-layout-MOA-918

Conversation

@oesnuj
Copy link
Copy Markdown
Member

@oesnuj oesnuj commented May 26, 2026

#️⃣연관된 이슈

#1611

📝작업 내용

RN WebView에서 발생하던 헤더 누락 및 검색바 레이아웃 문제 2가지를 수정했습니다.

1. 홍보 탭 (/webview/promotions) — 헤더 누락

Before After
Filter 탭만 렌더, 로고·검색바 없음 동아리 탭과 동일하게 로고 + 검색바 표시
  • PromotionListPage의 webview 브랜치에 SearchBarArea (로고 + 검색바) 추가
  • Containerpadding-top: 92px이 webview에서도 적용되던 문제 → $isWebview prop으로 분기해 제거

2. 검색바 너비 (/webview/main, /webview/promotions) — 끝까지 안 늘어나는 문제

Before After
SearchBoxWrappermax-width: 345px에 막혀 중간에서 끊김 로고 옆 남은 공간 전체를 검색바가 채움
  • SearchBarArea에서 & > div:last-child { flex: 1; max-width: none } 적용

변경 파일

  • PromotionListPage.tsx — webview 브랜치에 헤더 추가
  • PromotionListPage.styles.tsSearchBarArea, LogoImage, Container $isWebview 추가
  • WebviewMainPage.styles.tsSearchBarArea 검색바 너비 수정

중점적으로 리뷰받고 싶은 부분(선택)

SearchBarArea에서 & > div:last-childSearchBoxWrapper를 타겟하는 방식이 괜찮은지 봐주세요. SearchBox에 prop을 추가하는 방법도 있지만 영향 범위를 최소화하려고 이 방법을 선택했습니다.

논의하고 싶은 부분(선택)

현재 webview 진입 판별이 isInAppWebView() (UA 기반)와 pathname.startsWith('/webview') (경로 기반) 두 가지가 혼재되어 있습니다. 추후 기준을 통일하면 좋을 것 같습니다.

🫡 참고사항

isInAppWebView()는 UA의 MoadongApp 포함 여부로 판별합니다.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 모바일 앱 프로모션 페이지에 검색 기능이 추가되었습니다.
  • 개선 사항

    • 모바일 웹뷰 환경의 검색 영역 레이아웃이 개선되어 더 나은 사용자 경험을 제공합니다.

Review Change Stack

- /webview/promotions에 로고+검색바 헤더 추가 (WebviewMainPage와 동일한 구조)
- PromotionListPage Container의 padding-top을 webview에서 제거
- SearchBarArea 내 검색바가 남은 공간을 전부 차지하도록 flex: 1 적용
@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moadong Ready Ready Preview, Comment May 26, 2026 1:18pm

@github-actions github-actions Bot added 💻 FE Frontend 🛠Fix 기능이 의도한 대로 동작하지 않는 버그를 수정 labels May 26, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

프로모션 목록 페이지와 웹뷰 메인 페이지에서 모바일 웹뷰 컨텍스트용 스티키 검색 바가 추가되었습니다. Container의 padding-top이 웹뷰 플래그로 동적 조정되며, SearchBarArea와 LogoImage 스타일 컴포넌트가 새로 정의되어 검색 UI를 상단 고정하고 로고 이미지를 적절히 크기 조정합니다.

Changes

모바일 웹뷰 검색 바 UI

Layer / File(s) Summary
스타일 컴포넌트 및 웹뷰 스페이싱
frontend/src/pages/PromotionPage/PromotionListPage.styles.ts, frontend/src/pages/WebviewMainPage/WebviewMainPage.styles.ts
Container$isWebview prop을 추가하여 조건부 padding-top 설정(웹뷰: 0, 기본: 92px). SearchBarAreaLogoImage 스타일 컴포넌트를 새로 정의하여 스티키 검색 영역과 로고 크기 조정. WebviewMainPage의 SearchBarArea 마지막 자식 div에 flex 레이아웃 적용.
PromotionListPage 웹뷰 검색 바 통합
frontend/src/pages/PromotionPage/PromotionListPage.tsx
SearchBox import 추가. 웹뷰 렌더링에서 Container에 $isWebview prop 전달 및 SearchBarArea 내부에 MobileMainIcon 로고와 SearchBox 배치.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Suggested labels

💻 FE, 🛠Fix

Suggested reviewers

  • suhyun113
  • seongwon030
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 changeset의 주요 변경사항을 명확하게 반영하고 있습니다. 'RN WebView 홍보 탭 헤더 누락' 및 '검색바 너비 수정'은 제공된 파일 변경 사항과 정확히 일치합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/#1611-rn-webview-header-layout-MOA-918

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.

@github-actions
Copy link
Copy Markdown

✅ UI 변경사항 없음

구분 링크
📖 Storybook https://67904e61c16daa99a63b44a7-dgegcjzehw.chromatic.com/

전체 57개 스토리 · 22개 컴포넌트

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a search bar area (including a mobile logo and a SearchBox component) to the PromotionListPage when rendered inside an in-app webview, adjusting container padding and layout styles accordingly. The review feedback highlights two main areas for improvement: first, unifying the webview detection logic (UA-based vs. path-based) into a single custom hook to prevent layout inconsistencies; second, replacing brittle CSS selectors (like & > div:last-child) with more robust styling approaches, such as passing a className prop to the SearchBox component, to ensure the layout does not break when the DOM structure changes.

if (inAppWebView) {
return (
<Styled.Container>
<Styled.Container $isWebview>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

🌐 웹뷰 판별 기준 통일 제안

현재 inAppWebView 변수는 UA 기반의 isInAppWebView()를 사용하고 있는 반면, Filter 컴포넌트 등에서는 pathname.startsWith('/webview') 경로 기반 판별을 사용하고 있어 판별 기준이 혼재되어 있습니다.

이로 인해 일반 브라우저에서 /webview/promotions 경로로 직접 진입할 경우, inAppWebViewfalse가 되어 웹 레이아웃(헤더/푸터 포함)이 렌더링되지만, 내부 Filter 컴포넌트는 웹뷰용 필터 옵션을 보여주는 등 레이아웃과 기능의 불일치가 발생할 수 있습니다. 또한, 개발자 도구 등에서 웹뷰 화면을 디버깅하거나 테스트하기가 어려워집니다.

따라서 /webview로 시작하는 경로로 진입했을 때는 UA와 무관하게 항상 웹뷰 레이아웃을 렌더링하도록 경로 기반 판별(pathname.startsWith('/webview'))을 우선 적용하거나 이를 통합하는 커스텀 훅(예: useIsWebview)을 도입하는 것을 추천합니다.

추천하는 개선 방향:

const useIsWebview = () => {
  const { pathname } = useLocation();
  return pathname.startsWith('/webview') || isInAppWebView();
};

Comment on lines +43 to +46
& > div:last-child {
flex: 1;
max-width: none;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

⚠️ 취약한 CSS 선택자 사용 개선 제안

& > div:last-child 선택자를 사용하여 SearchBox 컴포넌트의 스타일을 제어하고 있습니다. 이 방식은 현재 구조에서는 잘 동작하지만, 다음과 같은 잠재적인 문제가 있습니다:

  1. 구조 변경에 취약: 향후 SearchBarArea 내부에 새로운 요소(예: 닫기 버튼, 알림 아이콘 등)가 추가되어 SearchBox가 더 이상 마지막 자식(:last-child)이 아니게 된다면 스타일이 깨지게 됩니다.
  2. 컴포넌트 캡슐화 위배: 부모 컴포넌트가 자식 컴포넌트의 특정 HTML 태그 구조(div)에 강하게 결합됩니다.

권장하는 개선 방향:
SearchBox 컴포넌트가 외부 스타일을 수용할 수 있도록 className 프로퍼티를 지원하도록 수정하거나, 너비를 가득 채울 수 있는 옵션(예: $fullWidth prop)을 SearchBox 자체에 추가하는 것이 안전합니다.

예시 코드:

  1. SearchBox.tsx 수정:
interface SearchBoxProps {
  className?: string;
}

const SearchBox = ({ className }: SearchBoxProps) => {
  return (
    <Styled.SearchBoxWrapper className={className}>
      {/* ... */}
    </Styled.SearchBoxWrapper>
  );
};
  1. PromotionListPage.styles.ts 수정:
export const StyledSearchBox = styled(SearchBox)`
  flex: 1;
  max-width: none;
`;

Comment on lines +18 to 21
& > div:last-child {
flex: 1;
max-width: none;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

⚠️ 취약한 CSS 선택자 사용 개선 제안

PromotionListPage.styles.ts와 마찬가지로 & > div:last-child 선택자는 SearchBarArea 내부에 새로운 요소가 추가될 경우 스타일이 깨질 위험이 있습니다.

SearchBox 컴포넌트가 className을 전달받을 수 있도록 개선하고, styled(SearchBox) 형태로 스타일을 확장하여 적용하는 방식을 권장합니다.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
frontend/src/pages/PromotionPage/PromotionListPage.styles.ts (1)

43-46: ⚡ Quick win

last-child 선택자 의존 대신 명시적 래퍼로 고정하세요.

Line 43-46은 DOM 순서/태그 타입이 바뀌면 바로 깨질 수 있습니다. SearchBoxWrapper 같은 styled 래퍼를 두고 flex: 1; max-width: none; min-width: 0;를 직접 부여하는 쪽이 안전합니다.

예시 diff
 export const SearchBarArea = styled.div`
   position: sticky;
   top: 0;
   z-index: 10;
   background-color: `#fff`;
   display: flex;
   align-items: center;
   gap: 10px;
   padding: 12px 16px 8px;
-
-  & > div:last-child {
-    flex: 1;
-    max-width: none;
-  }
 `;
+
+export const SearchBoxWrapper = styled.div`
+  flex: 1;
+  max-width: none;
+  min-width: 0;
+`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/PromotionPage/PromotionListPage.styles.ts` around lines 43
- 46, The current CSS relies on the fragile selector "& > div:last-child" —
replace that with an explicit styled wrapper component (e.g., SearchBoxWrapper)
and move the rules there: create or update SearchBoxWrapper (or similarly named
wrapper used around the search box) to include "flex: 1; max-width: none;
min-width: 0;" so layout no longer depends on DOM order or tag type; then update
JSX to wrap the search box with SearchBoxWrapper instead of relying on the
last-child selector.
frontend/src/pages/PromotionPage/PromotionListPage.tsx (1)

8-8: 🏗️ Heavy lift

공용 검색 UI는 pages가 아니라 components 경로로 승격하는 편이 맞습니다.

Line 8처럼 pages/MainPage 내부 컴포넌트를 다른 페이지가 참조하면 페이지 경계가 섞입니다. SearchBoxfrontend/src/components/로 옮겨 공용 컴포넌트로 관리하는 구조를 권장합니다.

As per coding guidelines, "React + TypeScript + Vite 기반 프론트엔드에서 공통 UI가 필요하면 frontend/src/components/에서 재사용 가능한지 먼저 확인한다".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/PromotionPage/PromotionListPage.tsx` at line 8, The import
of SearchBox in PromotionListPage.tsx indicates a page-level component is being
used as a reusable UI; move the SearchBox component file from
pages/MainPage/components/SearchBox to frontend/src/components/SearchBox (or a
suitable subfolder under components), update its default/export if needed, then
update the import in PromotionListPage.tsx to import from
'`@/components/SearchBox/SearchBox`' (and fix any other files that reference the
old path); ensure tests/exports compile after the move and update any relative
paths or index barrel exports if your project uses them.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@frontend/src/pages/PromotionPage/PromotionListPage.styles.ts`:
- Around line 43-46: The current CSS relies on the fragile selector "& >
div:last-child" — replace that with an explicit styled wrapper component (e.g.,
SearchBoxWrapper) and move the rules there: create or update SearchBoxWrapper
(or similarly named wrapper used around the search box) to include "flex: 1;
max-width: none; min-width: 0;" so layout no longer depends on DOM order or tag
type; then update JSX to wrap the search box with SearchBoxWrapper instead of
relying on the last-child selector.

In `@frontend/src/pages/PromotionPage/PromotionListPage.tsx`:
- Line 8: The import of SearchBox in PromotionListPage.tsx indicates a
page-level component is being used as a reusable UI; move the SearchBox
component file from pages/MainPage/components/SearchBox to
frontend/src/components/SearchBox (or a suitable subfolder under components),
update its default/export if needed, then update the import in
PromotionListPage.tsx to import from '`@/components/SearchBox/SearchBox`' (and fix
any other files that reference the old path); ensure tests/exports compile after
the move and update any relative paths or index barrel exports if your project
uses them.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d1e3d4d8-7ee4-4e87-877d-05551c125e53

📥 Commits

Reviewing files that changed from the base of the PR and between a082af0 and 4bb7bac.

📒 Files selected for processing (3)
  • frontend/src/pages/PromotionPage/PromotionListPage.styles.ts
  • frontend/src/pages/PromotionPage/PromotionListPage.tsx
  • frontend/src/pages/WebviewMainPage/WebviewMainPage.styles.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend 🛠Fix 기능이 의도한 대로 동작하지 않는 버그를 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant