심화 가이드
접근성 지원

자동 완성

개요

사용자가 입력할 때 옵션을 필터링하고 추천해서 목록에서 값을 찾고 선택하도록 돕는 접근성 있는 입력 필드입니다.

사용법

자동 완성은 옵션이 많아 스크롤보다 입력해서 선택하는 것이 빠를 때 적합합니다. 다음과 같은 경우에 자동 완성 사용을 고려하세요.

  • 옵션 목록이 긴 경우(20개 초과): 드롭다운을 스크롤하는 것보다 입력해서 후보를 좁히는 것이 빠릅니다.
  • 사용자가 찾는 값을 알고 있는 경우: 주 이름, 제품, 사용자 이름처럼 예상하는 값의 일부를 입력할 수 있습니다.
  • 옵션에 예측 가능한 패턴이 있는 경우: 국가 코드, 이메일 도메인, 범주처럼 일부 문자열을 추측해서 일치하는 항목을 찾을 수 있습니다.
  • 속도가 중요한 경우: 복잡한 탐색 없이 빠르게 선택할 수 있으면 폼 사용이 편리해집니다.

다음과 같은 경우에는 자동 완성을 피하세요.

  • 목록의 옵션이 10개보다 적은 경우: 일반 드롭다운이나 라디오 그룹이 옵션을 더 잘 보여줍니다.
  • 사용자가 옵션을 둘러봐야 하는 경우: 어떤 옵션이 있는지 알아보는 것이 중요하다면 처음부터 모든 옵션을 표시하세요.
  • 옵션이 생소한 경우: 사용자가 목록에 어떤 항목이 있는지 모르면 입력할 수 없습니다.

주요 기능

Angular의 자동 완성은 다음과 같이 접근성을 갖춘 콤보박스 구현을 제공합니다.

  • 키보드 탐색: 방향키로 옵션을 탐색하고 Enter로 선택하며 Escape로 닫습니다.
  • 스크린 리더 지원: 보조 기술을 위한 ARIA 어트리뷰트를 기본 제공합니다.
  • 동적 강조 동작: 인라인 선택 추천을 기본 지원합니다.
  • 시그널 기반 반응성: Angular 시그널로 상태를 반응형으로 관리합니다.
  • Popover API 통합: 네이티브 HTML Popover API를 활용해서 적절한 위치에 표시합니다.
  • 양방향 텍스트 지원: 오른쪽에서 왼쪽으로 쓰는 언어(RTL)를 자동으로 처리합니다.

예제

자동 선택 모드

텍스트 일부를 입력하는 사용자는 입력값과 일치하는 옵션이 있는지 바로 확인하기를 기대합니다. 자동 선택 모드는 사용자가 입력할 때 필터링된 첫 번째 옵션에 맞춰 입력값을 변경합니다. 필요한 키 입력 횟수를 줄이고 검색이 올바르게 진행되고 있다는 사실을 바로 보여줍니다.

수동 선택 모드

수동 선택 모드는 사용자가 추천 목록을 탐색하는 동안 입력한 텍스트를 그대로 유지해서 자동 변경으로 인한 혼란을 방지합니다. 사용자가 Enter를 누르거나 클릭해서 명시적으로 선택을 확정할 때만 입력값이 바뀝니다.

강조 모드

강조 모드에서는 사용자가 방향키로 옵션을 탐색하는 동안 입력값이 바뀌지 않습니다. Enter를 누르거나 클릭해서 새 옵션을 명시적으로 선택할 때 입력값이 바뀝니다.

시그널 폼 통합

Angular Aria는 시그널 기반 시그널 폼 API와 자연스럽게 통합됩니다. FormValueControl을 구현해서 복잡한 입력 UI를 재사용 가능한 커스텀 컨트롤 컴포넌트로 캡슐화할 수 있습니다.

다음 예제는 FormValueControl<string>을 구현한 국가 선택기 컴포넌트입니다. [formField]로 부모 폼에 바인딩하고 스키마의 유효성 검사 규칙으로 값을 검사합니다.

테스트

자동 완성 패턴은 @angular/aria/combobox/testing의 ComboboxHarness와 @angular/aria/listbox/testing의 ListboxHarness를 함께 사용해서 테스트할 수 있습니다. 하네스로 자동 완성 컴포넌트를 테스트하는 예제는 다음과 같습니다.

import {ComponentFixture, TestBed} from '@angular/core/testing';
import {HarnessLoader} from '@angular/cdk/testing';
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {ComboboxHarness} from '@angular/aria/combobox/testing';
import {ListboxHarness} from '@angular/aria/listbox/testing';
import {MyAutocompleteComponent} from './my-autocomplete'; // 테스트할 컴포넌트

describe('MyAutocompleteComponent', () => {
  let fixture: ComponentFixture<MyAutocompleteComponent>;
  let loader: HarnessLoader;

  beforeEach(async () => {
    TestBed.configureTestingModule({
      imports: [MyAutocompleteComponent],
    });

    fixture = TestBed.createComponent(MyAutocompleteComponent);
    await fixture.whenStable();
    loader = TestbedHarnessEnvironment.loader(fixture);
  });

  it('should filter options based on input', async () => {
    const combobox = await loader.getHarness(ComboboxHarness);

    // 입력란에 텍스트를 입력해서 필터링을 실행합니다.
    await combobox.setValue('ap');
    expect(await combobox.isOpen()).toBe(true);

    // 팝업에서 리스트박스 하네스를 가져옵니다.
    const listbox = await combobox.getPopupWidget(ListboxHarness);
    const options = await listbox.getOptions();

    // 옵션이 필터링되었는지 확인합니다(예: 'Apple', 'Apricot').
    expect(options.length).toBe(2);
    expect(await options[0].getText()).toBe('Apple');

    // 첫 번째 옵션을 선택합니다.
    await options[0].click();

    // 입력값이 변경되고 팝업이 닫혔는지 확인합니다.
    expect(await combobox.isOpen()).toBe(false);
    expect(await combobox.getValue()).toBe('Apple');
  });
});

API 레퍼런스

자세한 API 문서는 다음 API 레퍼런스를 참고하세요.