fix(webview): RN WebView 홍보 탭 헤더 누락 및 검색바 너비 수정#1612
Conversation
- /webview/promotions에 로고+검색바 헤더 추가 (WebviewMainPage와 동일한 구조) - PromotionListPage Container의 padding-top을 webview에서 제거 - SearchBarArea 내 검색바가 남은 공간을 전부 차지하도록 flex: 1 적용
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| 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). SearchBarArea와 LogoImage 스타일 컴포넌트를 새로 정의하여 스티키 검색 영역과 로고 크기 조정. 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
- [fix] MOA-918 홍보 탭 헤더 누락 및 메인 탭 상단 빈 공간 제거 #1611: PR의 변경사항이 SearchBarArea/LogoImage 추가 및 $isWebview prop 적용을 통해 웹뷰 헤더 추가 및 상단 여백 제거 요구사항을 직접 구현합니다.
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
✅ UI 변경사항 없음
전체 57개 스토리 · 22개 컴포넌트 |
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
🌐 웹뷰 판별 기준 통일 제안
현재 inAppWebView 변수는 UA 기반의 isInAppWebView()를 사용하고 있는 반면, Filter 컴포넌트 등에서는 pathname.startsWith('/webview') 경로 기반 판별을 사용하고 있어 판별 기준이 혼재되어 있습니다.
이로 인해 일반 브라우저에서 /webview/promotions 경로로 직접 진입할 경우, inAppWebView는 false가 되어 웹 레이아웃(헤더/푸터 포함)이 렌더링되지만, 내부 Filter 컴포넌트는 웹뷰용 필터 옵션을 보여주는 등 레이아웃과 기능의 불일치가 발생할 수 있습니다. 또한, 개발자 도구 등에서 웹뷰 화면을 디버깅하거나 테스트하기가 어려워집니다.
따라서 /webview로 시작하는 경로로 진입했을 때는 UA와 무관하게 항상 웹뷰 레이아웃을 렌더링하도록 경로 기반 판별(pathname.startsWith('/webview'))을 우선 적용하거나 이를 통합하는 커스텀 훅(예: useIsWebview)을 도입하는 것을 추천합니다.
추천하는 개선 방향:
const useIsWebview = () => {
const { pathname } = useLocation();
return pathname.startsWith('/webview') || isInAppWebView();
};| & > div:last-child { | ||
| flex: 1; | ||
| max-width: none; | ||
| } |
There was a problem hiding this comment.
⚠️ 취약한 CSS 선택자 사용 개선 제안
& > div:last-child 선택자를 사용하여 SearchBox 컴포넌트의 스타일을 제어하고 있습니다. 이 방식은 현재 구조에서는 잘 동작하지만, 다음과 같은 잠재적인 문제가 있습니다:
- 구조 변경에 취약: 향후
SearchBarArea내부에 새로운 요소(예: 닫기 버튼, 알림 아이콘 등)가 추가되어SearchBox가 더 이상 마지막 자식(:last-child)이 아니게 된다면 스타일이 깨지게 됩니다. - 컴포넌트 캡슐화 위배: 부모 컴포넌트가 자식 컴포넌트의 특정 HTML 태그 구조(
div)에 강하게 결합됩니다.
권장하는 개선 방향:
SearchBox 컴포넌트가 외부 스타일을 수용할 수 있도록 className 프로퍼티를 지원하도록 수정하거나, 너비를 가득 채울 수 있는 옵션(예: $fullWidth prop)을 SearchBox 자체에 추가하는 것이 안전합니다.
예시 코드:
SearchBox.tsx수정:
interface SearchBoxProps {
className?: string;
}
const SearchBox = ({ className }: SearchBoxProps) => {
return (
<Styled.SearchBoxWrapper className={className}>
{/* ... */}
</Styled.SearchBoxWrapper>
);
};PromotionListPage.styles.ts수정:
export const StyledSearchBox = styled(SearchBox)`
flex: 1;
max-width: none;
`;| & > div:last-child { | ||
| flex: 1; | ||
| max-width: none; | ||
| } |
There was a problem hiding this comment.
🧹 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내부 컴포넌트를 다른 페이지가 참조하면 페이지 경계가 섞입니다.SearchBox를frontend/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
📒 Files selected for processing (3)
frontend/src/pages/PromotionPage/PromotionListPage.styles.tsfrontend/src/pages/PromotionPage/PromotionListPage.tsxfrontend/src/pages/WebviewMainPage/WebviewMainPage.styles.ts
#️⃣연관된 이슈
📝작업 내용
RN WebView에서 발생하던 헤더 누락 및 검색바 레이아웃 문제 2가지를 수정했습니다.
1. 홍보 탭 (
/webview/promotions) — 헤더 누락PromotionListPage의 webview 브랜치에SearchBarArea(로고 + 검색바) 추가Container의padding-top: 92px이 webview에서도 적용되던 문제 →$isWebviewprop으로 분기해 제거2. 검색바 너비 (
/webview/main,/webview/promotions) — 끝까지 안 늘어나는 문제SearchBoxWrapper의max-width: 345px에 막혀 중간에서 끊김SearchBarArea에서& > div:last-child { flex: 1; max-width: none }적용변경 파일
PromotionListPage.tsx— webview 브랜치에 헤더 추가PromotionListPage.styles.ts—SearchBarArea,LogoImage,Container $isWebview추가WebviewMainPage.styles.ts—SearchBarArea검색바 너비 수정중점적으로 리뷰받고 싶은 부분(선택)
SearchBarArea에서& > div:last-child로SearchBoxWrapper를 타겟하는 방식이 괜찮은지 봐주세요.SearchBox에 prop을 추가하는 방법도 있지만 영향 범위를 최소화하려고 이 방법을 선택했습니다.논의하고 싶은 부분(선택)
현재 webview 진입 판별이
isInAppWebView()(UA 기반)와pathname.startsWith('/webview')(경로 기반) 두 가지가 혼재되어 있습니다. 추후 기준을 통일하면 좋을 것 같습니다.🫡 참고사항
isInAppWebView()는 UA의MoadongApp포함 여부로 판별합니다.Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항