ADR-0007: 적응형 UI의 판정 축과 구현 패턴을 고정하고 네이티브 위임을 기각한다
상태
Accepted
날짜
2026-08-10
맥락
웹 애플리케이션이 데스크탑과 모바일에서 모두 사용됩니다. 레이아웃만 바뀌는 것으로는 부족한 경우가 있습니다. 셀렉트박스가 데스크탑에서는 앵커 드롭다운으로 뜨지만 모바일에서는 액션시트로 떠야 조작이 가능합니다.
이 영역을 라이브러리가 해결해 주지 않습니다. shadcn은 Dialog와 Drawer를 조합하는 방법을 문서에 예시로 싣고 useMediaQuery("(min-width: 768px)")로 분기하라고 안내할 뿐이며, 이 공백을 메우려는 서드파티 래퍼가 별도로 존재합니다.
그 레시피의 판정 축에 결함이 있습니다. 액션시트가 필요한 이유는 화면이 작아서가 아니라 손가락으로 조작하고 호버가 없기 때문입니다. 너비로 판정하면 터치 노트북, 태블릿 가로, 좁게 줄인 데스크탑 창이 모두 오판됩니다.
결정
판정 축
| 미디어 쿼리 | 역할 |
|---|---|
(pointer: coarse) |
1차 축 |
(hover: none) |
1차 축 |
(min-width: ...) |
2차 축. 레이아웃 배치에만 사용 |
두 1차 축이 모두 참일 때 touch, 그 외에는 pointer로 판정합니다.
컴포넌트가 미디어 쿼리 문자열을 직접 갖는 것을 금지하고, shared/lib/adaptive/의 의미 신호(injectInteractionMode())만 사용합니다. 판정 기준이 바뀌면 그 파일 하나만 고칩니다. 구현에는 이미 의존성에 있는 CDK BreakpointObserver를 사용합니다.
구현 패턴과 판정 순서
위에서부터 판정하고 먼저 해당하는 항목에서 멈춥니다.
| 순서 | 패턴 | 조건 |
|---|---|---|
| 1 | 오버레이 위치 전략 교체 | 표시 위치만 다름 |
| 2 | 표현 컴포넌트 교체 | 상호작용 모델이 다름 |
| 3 | 2번에 @defer 추가 |
번들 문제가 측정으로 확인됨 |
표현 컴포넌트는 슬라이스 공개 API로 내보내지 않으며, 두 표현은 동일한 입출력 계약을 갖습니다.
세부 규칙은 적응형 UI가 원본입니다.
검토한 대안
화면 너비(min-width)로 판정
| 구분 | 내용 |
|---|---|
| 장점 | 널리 쓰이는 방식이라 참고 자료가 많고 구현이 단순합니다 |
| 단점 | 입력 방식과 화면 크기는 독립적인 축입니다. 터치 노트북과 태블릿 가로가 오판됩니다 |
| 기각 사유 | 판정하려는 대상이 화면 크기가 아니라 조작 방식입니다. 상관관계가 있을 뿐 인과관계가 아닙니다 |
네이티브 위임 — 터치 환경에서 OS 기본 UI 사용
| 구분 | 내용 |
|---|---|
| 장점 | 접근성·현지화·제스처를 OS가 처리합니다. 날짜 선택기처럼 접근성 결함이 자주 나오는 컴포넌트의 구현 부담이 사라집니다 |
| 단점 | OS와 브라우저마다 외형이 달라집니다. 디자인 토큰이 적용되지 않습니다 |
| 기각 사유 | 화면 통제를 포기하는 것이며, 같은 화면이 기기마다 다르게 보이는 것을 허용할 수 없습니다 |
패턴을 고정하지 않고 사례마다 판단
| 구분 | 내용 |
|---|---|
| 장점 | 각 상황에 최적인 방식을 선택할 수 있습니다 |
| 단점 | 같은 성격의 컴포넌트가 서로 다른 방식으로 구현됩니다 |
| 기각 사유 | 1순위 품질 목표가 예측 가능성입니다. 판정 순서가 없으면 구현 방식이 작성자마다 갈립니다 |
결과
기기 판정 기준이 한 파일에 모이고, 구현 방식이 판정 순서로 결정됩니다. 표현 컴포넌트를 비공개로 두므로 상위 계층은 적응형 여부를 알지 못하며, 나중에 패턴을 바꿔도 사용처를 수정하지 않습니다.
감수하는 사항은 다음과 같습니다.
- 날짜 선택기의 표현을 직접 만들어야 합니다. 네이티브 위임을 기각한 직접적 결과입니다. 다만 접근성 부담은 확인 결과 크지 않습니다. brain의 캘린더가 방향키·
Home·End·PageUp·PageDown이동, 로빙 탭인덱스,role="grid"와 셀 단위 ARIA를 제공하므로 직접 만드는 것은 마크업과 두 표현이며 키보드 모델이 아닙니다. 남는 몫은 라벨의 한국어화입니다. - 적응형 컴포넌트마다 두 표현을 유지합니다. 패턴 2를 적용하면 파일 수와 테스트 수가 두 배가 됩니다.
- 정적 생성 경로에서 적응형 컴포넌트를 사용할 수 없습니다. 서버에는 포인터가 없어 하이드레이션 불일치가 발생합니다. 자동 강제 수단이 없어 코드 리뷰에서 확인합니다.
- 두 모드 테스트가 자동 강제되지 않습니다. 코드 리뷰에서 존재를 확인합니다.
개정
2026-08-11: 판정 순서의 전제 세 건을 확인했습니다. 결정은 바뀌지 않습니다.
@spartan-ng/brain이 위치 전략 교체를 허용합니다.BrnOverlay의positionStrategy입력이 기본 전략보다 우선하고, 주입 범위 전체에는provideBrnOverlayDefaultOptions()를 씁니다. 패턴 1을 유지하며 판정 순서를 그대로 둡니다.- brain의 캘린더가 APG 그리드의 키보드 모델과 ARIA를 제공합니다. 결과 절의 날짜 선택기 항목을 이에 맞게 완화했습니다.
- CDK
BreakpointObserver가 서버에서 예외 없이matches: false를 즉시 방출합니다. 정적 생성 경로의 오용이 예외로 드러나지 않으므로 결과 절의 코드 리뷰 확인 항목이 그대로 필요합니다.