Frontend에서 불필요한 UI 탭 숨김 처리 방법
Frontend 개발 중 불필요한 UI 탭을 숨기지 못해 3시간을 헤맸습니다. 원인과 해결 방법을 공개합니다.
이미지 스튜디오에서 '인물 보존 편집' 탭이 떡하니 보이는데, 실제로는 사용하지 않거나 곧 사용하지 않을 기능이었다. 이런 불필요한 UI 요소는 사용자 경험을 해치고 혼란만 줄 뿐인데, 이걸 어떻게 숨길지 고민하다가 결국 해결했다.
시도와 함정
처음에는 단순히 해당 탭의 렌더링 로직을 막아버리면 되지 않을까 싶었다. 그래서 컴포넌트 마운트 시점에 특정 조건이 만족되지 않으면 렌더링을 건너뛰도록 코드를 수정해 봤다.
// App.js
import React, { useState, useEffect } from 'react';
import FeatureTab from './FeatureTab';
function App() {
const [showEditTab, setShowEditTab] = useState(false);
useEffect(() => {
// 실제로는 백엔드 API 호출 등으로 기능 활성화 여부 판단
const isFeatureEnabled = checkFeatureStatus('인물 보존 편집');
setShowEditTab(isFeatureEnabled);
}, []);
return (
<div>
{/* 다른 UI 요소들 */}
{showEditTab && <FeatureTab title="인물 보존 편집" />}
{/* 다른 UI 요소들 */}
</div>
);
}
function checkFeatureStatus(featureName) {
// 임시 로직: 실제로는 동적으로 결정되어야 함
// 예를 들어, 현재 사용자 권한, 서비스 설정 등에 따라 달라짐
// 여기서는 일단 false로 고정하여 탭이 안 보이도록 테스트
console.log(`Checking status for: ${featureName}`);
return false; // 항상 false로 설정하여 탭 숨김 테스트
}
export default App;
그런데 아무리 setShowEditTab(false)로 설정해도 탭이 사라지지 않는 것이었다. 콘솔에는 Checking status for: 인물 보존 편집이라고 잘 찍히는데, UI에는 그대로 노출되는 황당한 상황. 3시간을 디버깅해도 원인을 못 찾다가, 결국 다른 곳에서 이 탭을 직접적으로 제어하고 있다는 사실을 발견했다.
원인
문제는 App.js에서 상태를 관리하고 렌더링을 제어하는 것 외에, 다른 컴포넌트에서 해당 탭을 직접적으로 visible 속성을 이용해 제어하고 있었다는 점이었다. 마치 부모가 "안 돼"라고 했는데, 아이가 자기 마음대로 "돼"라고 하는 격이었다.
// SomeOtherComponent.js (문제의 컴포넌트)
import React from 'react';
function SomeOtherComponent() {
return (
<div>
{/* ... */}
<div style={{ visibility: 'visible' }}> {/* <-- 여기가 문제! */}
{/* 인물 보존 편집 탭 내용 */}
<h1>인물 보존 편집</h1>
<p>이 탭은 항상 보여야 합니다.</p>
</div>
{/* ... */}
</div>
);
}
export default SomeOtherComponent;
App.js에서 showEditTab 상태를 false로 설정해도, SomeOtherComponent.js의 style={{ visibility: 'visible' }} 때문에 강제로 노출되고 있었던 것이다.
해결
가장 간단하고 명확한 해결책은 SomeOtherComponent.js에서 해당 탭의 visibility 속성을 제거하고, App.js에서 관리하는 showEditTab 상태에 따라 렌더링되도록 로직을 통일하는 것이었다.
// App.js (수정 후) import React, { useState, useEffect } from 'react'; import FeatureTab from './FeatureTab'; import SomeOtherComponent from './SomeOtherComponent'; // SomeOtherComponent 임포트function App() { const [showEditTab, setShowEditTab] = useState(false);
useEffect(() => { // 실제로는 백엔드 API 호출 등으로 기능 활성화 여부 판단 const isFeatureEnabled = checkFeatureStatus('인물 보존 편집'); setShowEditTab(isFeatureEnabled); }, []);
return ( <div> {/* 다른 UI 요소들 /} {showEditTab && <FeatureTab title="인물 보존 편집" />} {/ SomeOtherComponent 에서 탭 렌더링 로직 제거 /} <SomeOtherComponent /> {/ 다른 UI 요소들 */} </div> ); }
function checkFeatureStatus(featureName) { // 임시 로직: 실제로는 동적으로 결정되어야 함 console.log(
Checking status for: ${featureName}); return false; // 항상 false로 설정하여 탭 숨김 테스트 }
export default App;
// SomeOtherComponent.js (수정 후)
import React from 'react';
function SomeOtherComponent() {
return (
<div>
{/* ... */}
{/* visibility: 'visible' 속성 제거 */}
<div>
{/* 인물 보존 편집 탭 내용 */}
<h1>인물 보존 편집</h1>
<p>이 탭은 App.js 에서 제어됩니다.</p>
</div>
{/* ... */}
</div>
);
}
export default SomeOtherComponent;
이제 App.js의 showEditTab 상태가 false이면 '인물 보존 편집' 탭은 UI에서 완전히 사라진다.
결과
- UI에서 '인물 보존 편집' 탭이 더 이상 노출되지 않음.
- 코드의 렌더링 로직이
App.js로 일원화되어 관리 용이성이 향상됨. - 사용자 혼란 감소.
정리 — 같은 함정 안 빠지려면
- [ ] 특정 UI 요소의 노출 여부를 제어할 때, 여러 컴포넌트에서 독립적으로 제어하지 않는지 확인한다.
- [ ] 상태 관리 로직은 가능한 한 상위 컴포넌트나 중앙 집중식 상태 관리 라이브러리에서 일관되게 처리한다.
- [ ]
visibility,display등의 CSS 속성이 의도치 않게 UI 노출을 강제하는지 코드 리뷰 시 꼼꼼히 확인한다. - [ ] 기능의 활성화/비활성화 상태는 백엔드 API나 명확한 설정 값을 통해 동적으로 결정되도록 설계한다.
태그