1. 문제 상황
Ionic과 Angular를 활용한 프로젝트에서, Sidebar와 Popover를 함께 구현했을 때 Popover가 Sidebar 뒤에 렌더링되는 문제가 발생했습니다. 문제는 Popover가 제대로 동작하지 않으며, 클릭 또한 불가능하다는 것이었습니다.
이 문제는 특히 ion-popover와 ion-app의 구조 및 동작 방식에 대한 이해가 부족하면 쉽게 놓칠 수 있는 부분입니다.
2. 문제 원인
Sidebar 디렉티브가 Angular의 동적 DOM 조작을 통해 body에 직접 추가되었고, 이로 인해 Ionic의 ion-app 컨텍스트 외부에 위치하게 되었습니다. 하지만, Ionic의 ion-popover는 기본적으로 ion-app 내부에서 동작하도록 설계되어 있습니다.
이로 인해 다음과 같은 문제가 발생했습니다:
- z-index 충돌 문제: Popover가 Sidebar 뒤에 렌더링되어 보이지 않음.
- 이벤트 전파 문제: Popover가 Sidebar 뒤에 숨겨져 클릭 이벤트를 받을 수 없음.
3. 해결 방법
문제는 Sidebar의 append 위치를 body에서 ion-app으로 변경하는 것만으로 해결되었습니다. 이 변경을 통해 Popover와 Sidebar가 같은 컨텍스트에서 렌더링되었고, Ionic의 기본 스타일 및 동작이 정상적으로 적용되었습니다.
코드 수정 전
document.body.appendChild(this.sidebarElement); // Sidebar를 body에 추가
코드 수정 후
const ionApp = document.querySelector('ion-app'); // ion-app 요소를 가져오기
if (ionApp) {
ionApp.appendChild(this.sidebarElement); // Sidebar를 ion-app에 추가
} else {
console.error('ion-app not found');
}
위 코드를 통해 Sidebar 디렉티브의 DOM 위치를 ion-app 내부로 변경하였습니다.
4. 적용된 Sidebar 디렉티브 코드
다음은 수정된 Sidebar 디렉티브의 showSidebar 메서드입니다:
showSidebar(): void {
this.isTransitioning = true;
// Embed the sidebar template
this.embeddedViewRef = this.content.createEmbeddedView({});
this.appRef.attachView(this.embeddedViewRef);
// Get the root element of the embedded view
this.sidebarElement = this.embeddedViewRef.rootNodes[0] as HTMLElement;
// Append the sidebar to the ion-app instead of body
const ionApp = document.querySelector('ion-app');
if (ionApp) {
ionApp.appendChild(this.sidebarElement);
} else {
console.error('ion-app not found');
}
// Set sidebar mode (popup or fixed)
this.setSidebarMode();
// Attach drag event to the header
const headerElement = this.sidebarElement.querySelector('.sidebar-header') as HTMLElement;
if (headerElement) {
this.renderer.listen(headerElement, 'mousedown', this.onDragStart.bind(this));
}
}
5. CSS 및 추가 작업
위 코드를 수정한 이후, Popover와 Sidebar는 같은 DOM 컨텍스트에서 정상적으로 렌더링되었고 z-index 충돌 문제도 자연스럽게 해결되었습니다. 따라서, 이전에 시도했던 z-index 조정이나 Shadow DOM 스타일링 같은 추가 작업은 더 이상 필요하지 않았습니다.
6. 해결 후 결과
문제를 해결한 결과:
- Popover가 Sidebar 위에 정상적으로 렌더링되었습니다.
- Popover의 클릭 이벤트가 제대로 작동하게 되었습니다.
- Ionic의 기본 동작을 활용한 깔끔한 해결책이 되었습니다.
7. 배운 점
- Ionic의 ion-app 컨텍스트:
- Ionic의 대부분의 UI 컴포넌트(ion-popover, ion-modal 등)는 ion-app 내부에서 동작하도록 설계되어 있습니다. 따라서 DOM 조작 시 ion-app을 기준으로 해야 합니다.
- DOM 조작 시 위치에 대한 중요성:
- Angular에서 동적 DOM 조작을 수행할 때, 적절한 부모 컨텍스트를 선택하지 않으면 UI 충돌이 발생할 수 있습니다.
- 최대한 Ionic의 기본 동작 활용:
- 문제를 해결하기 위해 복잡한 z-index 조정이나 Shadow DOM 스타일링을 시도하기 전에, Ionic의 기본 동작 원리를 이해하고 이를 활용하는 것이 중요합니다.
8. 결론
이번 사례는 DOM 위치와 Ionic 컴포넌트의 동작 방식을 이해하는 것이 얼마나 중요한지 보여줍니다. 문제를 해결하기 위해 다양한 삽질을 했지만, 근본적인 해결책은 매우 단순한 append 위치 변경이었습니다.
Tip: 앞으로는 DOM 조작이 필요한 경우, 컴포넌트의 컨텍스트와 Ionic의 구조를 먼저 파악하세요. 이로 인해 복잡한 스타일 수정 없이 문제를 간단히 해결할 수 있습니다.
'FE > Angular' 카테고리의 다른 글
[Angular] Renderer2를 사용한 동적 사이드바 및 팝업 전환 Directive 구현 (0) | 2024.11.15 |
---|---|
[Angular] GraphQL과 gql을 사용한 서버 요청 (0) | 2024.11.12 |
[Angular] RxJS에서 Observables와 Subjects 사용하기 (0) | 2024.11.09 |
[Angular] @ViewChild 알아보기 (0) | 2024.11.08 |
[Angular] ngComponentOutlet과 ngSwitchCase로 동적 컴포넌트 표시 (0) | 2024.11.07 |