HOWTO · Angular

Angular의 getElementById 교체

템플릿 참조, ElementRef, Renderer2를 사용해 Angular에서 컴포넌트 요소를 찾고 입력 값을 읽습니다.

이 페이지의 내용

Angular 컴포넌트에 속한 요소를 찾으려면 그 요소에 템플릿 참조를 부여하고 @ViewChild로 그 참조를 조회하세요. 이렇게 하면 문서 전체를 ID로 검색하지 않고 컴포넌트 범위로 조회가 한정됩니다. 컴포넌트 코드에 네이티브 요소 참조가 필요할 때는 ElementRef를 사용하고, 스타일 설정과 같이 지원되는 DOM 작업에는 Renderer2를 사용하세요. 이 API들은 역할이 다릅니다. 어느 것도 getElementById의 만능 일대일 대체재는 아닙니다.

Angular에서 getElementById 대체

브라우저의 document.getElementById("name")는 id가 name인 요소를 문서에서 검색합니다. Angular 컴포넌트에서는 대상이 그 컴포넌트 자체 템플릿의 일부일 때 템플릿 참조가 보통 더 적합합니다. 예를 들어, 컴포넌트 템플릿의 입력에 #nameInput을 추가한 다음, 컴포넌트 클래스에서 @ViewChild로 nameInput을 조회하세요. 이 참조는 문서 전체 조회나 전역적으로 유일한 ID를 요구하지 않고 둘을 연결합니다.

이 패턴은 컴포넌트가 이벤트 이후 특정 컨트롤을 읽거나 업데이트해야 할 때 유용합니다. 목표가 뷰와 컴포넌트 사이에 값을 전달하는 것이라면, DOM에 직접 접근하는 것보다 Angular 템플릿 바인딩이 더 나은 선택일 수 있습니다. 네이티브 요소 참조는 작업이 실제로 요소 자체를 필요로 할 때만 사용하고, 조회는 템플릿을 소유한 컴포넌트 내부로 한정하세요.

Angular의 ElementRef

ElementRef는 네이티브 요소 참조를 감싸는 래퍼입니다. 그 nativeElement 속성은 기반 요소를 노출합니다. 그 요소에 Angular 전용 메서드를 추가하지는 않습니다. 컴포넌트 템플릿에서는 입력에 #nameInput으로 표시하고, 컴포넌트 클래스에서는 @ViewChild("nameInput") nameInput!: ElementRef<HTMLInputElement>;를 사용해 그 정확한 이름을 조회하세요. 템플릿 참조와 조회 이름은 일치해야 하며, 제네릭 타입은 네이티브 요소가 입력임을 TypeScript에 알려 줍니다.

구체적인 조합으로, 템플릿은 <input #nameInput type="text" value="Ada">를 포함할 수 있습니다. 대응하는 클래스는 @ViewChild("nameInput") nameInput!: ElementRef<HTMLInputElement>;를 선언하고, getValue(): string { return this.nameInput.nativeElement.value; }를 사용해 핸들러에서 값을 읽을 수 있습니다. Angular가 컴포넌트에 대해 조회를 해결합니다. 참조가 생성 시점에 준비되었다고 가정하지 말고, 뷰가 렌더링된 후 이벤트에서 핸들러를 호출하세요.

nativeElement를 통한 직접 접근은 코드를 플랫폼의 네이티브 DOM에 묶어 둡니다. 그것은 입력 속성을 읽는 것과 같은 좁은 작업에는 적절하지만, Angular 바인딩의 일반적인 대체재로 사용하는 것은 피하세요. 또한 서버 렌더링과 같은 환경에서는 브라우저 DOM이 존재한다고 코드가 가정해서는 안 된다는 뜻이기도 합니다. 여기에서는 어떤 Angular 버전 범위도 주장하지 않습니다. 조회 구문과 라이프사이클 세부 사항은 애플리케이션이 사용하는 버전을 기준으로 확인하세요.

Angular에서 ElementRef를 사용해 입력 값 가져오기

입력을 읽고 재설정하려면 템플릿과 클래스 부분을 함께 유지하세요. 템플릿은 <input #nameInput type="text" value="Ada"><button (click)="showValue()">Read</button><button (click)="resetValue()">Reset</button>가 될 수 있습니다. 컴포넌트 클래스에서는 @ViewChild("nameInput") nameInput!: ElementRef<HTMLInputElement>;를 사용한 다음, showValue(): void { console.log(this.nameInput.nativeElement.value); }와 resetValue(): void { this.nameInput.nativeElement.value = ""; }를 정의하세요. #nameInput 표시는 템플릿 쪽 참조입니다. @ViewChild에 전달된 문자열이 그것을 선택하고, 버튼 바인딩이 핸들러를 호출합니다.

이것은 네이티브 요소에 대한 직접 접근입니다. 값은 입력 요소에서 읽거나 입력 요소에 씁니다. 필드가 폼이나 애플리케이션 상태의 일부라면, 데이터 흐름을 더 잘 나타낼 때 폼 컨트롤이나 바인딩을 선호하세요. 그런 접근 방식은 값을 Angular의 모델 안에 유지하며 유효성 검사와 업데이트를 조율하기 쉽게 만들 수 있습니다. ElementRef는 작업이 특히 입력 요소와의 상호 작용을 요구할 때 사용하고, 작업은 작고 명확하게 유지하세요.

다음의 순수 JavaScript 예제는 그 핸들러들이 사용하는 네이티브 입력 속성 접근만을 모델링합니다. 이것은 Angular 컴포넌트가 아닙니다. 위의 템플릿 참조와 @ViewChild 조합이 프레임워크 전용 연결을 보여 줍니다.

const input = { value: "Ada" };
const component = {
  nameInput: { nativeElement: input },
  getValue() {
    return this.nameInput.nativeElement.value;
  },
  resetValue() {
    this.nameInput.nativeElement.value = "";
  }
};

console.log(component.getValue());
component.resetValue();
console.log(JSON.stringify(input.value));
Ada
""

위의 Angular 스니펫은 설명용 템플릿 및 TypeScript 조각이며, 독립적으로 실행 가능한 예제가 아닙니다. 마크업은 컴포넌트 템플릿에, 조회와 핸들러는 그 컴포넌트 클래스에 두세요. 실행 증거는 순수 JavaScript 모델에 대해서만 얻을 수 있으므로, Angular 출력은 주장하지 않습니다.

Angular Renderer2

Renderer2는 렌더링된 요소에 대한 지원 작업을 위한 Angular 추상화입니다. 이것은 ElementRef와 다릅니다. 후자는 네이티브 요소 참조에 대한 접근을 제공하고, Renderer2는 클래스 추가나 스타일 설정과 같은 작업을 수행하는 메서드를 제공합니다. 작업에 그 추상화가 필요할 때 컴포넌트에 주입하세요. 이것은 getElementById를 Angular 조회로 바꾸지 않으며, 임의의 DOM 조작을 자동으로 안전하게 만들지도 않습니다.

컴포넌트가 소유한 요소에 스타일을 설정하려면, 템플릿의 div에 #styledDiv를 추가하고 @ViewChild("styledDiv") styledDiv!: ElementRef<HTMLElement>;와 같은 조회에 연결하세요. 컴포넌트 생성자에서 Renderer2를 주입합니다. applyStyles() 핸들러에서는 this.renderer.setStyle(this.styledDiv.nativeElement, "background-color", "lightblue")를 호출한 다음, "border"와 "1px solid darkblue"로 다시 호출하세요. 템플릿 버튼은 (click)="applyStyles()"로 그 핸들러를 호출할 수 있습니다.

템플릿 마크업은 HTML 템플릿에, 조회와 주입과 핸들러는 TypeScript 클래스에 유지하세요. 두 파일을 하나의 코드 블록으로 합치면 각 부분이 어디에 속하는지 모호해질 수 있습니다. 이 호출들은 컴포넌트 맥락에서의 Angular API를 설명하는 것이며, 독립적으로 실행 가능한 예제가 아닙니다. 일반적인 표현 변경의 경우, 클래스 바인딩이나 스타일 바인딩이 더 간단할 수 있고 조건을 템플릿에 보이게 유지합니다. Renderer2는 그 렌더링 추상화가 작업에 적합할 때 사용하고, 모든 사용에서 보안이나 변경 감지 동작을 보장한다고 주장하는 것은 피하세요.

결론: Angular에서의 DOM 조작

컴포넌트가 소유한 요소에 대해서는 문서 전체를 대상으로 하는 getElementById 검색이 아니라 템플릿 참조와 @ViewChild로 시작하세요. ElementRef와 그 nativeElement는 입력 값을 읽거나 재설정하는 경우처럼 코드에 네이티브 요소가 필요할 때만 사용합니다. Renderer2는 스타일 설정과 같은 지원 작업에 사용하세요. 이들은 Angular의 컴포넌트 모델을 서로 다른 방식으로 보완합니다. 작업에 따라 선택하고, 원하는 뷰와 데이터 흐름을 더 명확하게 표현할 때는 바인딩이나 폼 컨트롤을 선호하세요.