안녕하세요. 꼬동입니다.
Angular로 작업 중, 평소와 같이 ElementRef를 쓰다가 어떤 코드를 봤는데, Renderer2로 DOM에 접근하여, 값을 동적으로 바꾸더라고요 ?
읭 그러면 ElementRef는 왜 있는거야 ?
라는 생각으로 글을 작성해봅니다.
Renderer2는 무엇인가요 ?
Renderer2는 DOM에 직접적으로 접근하지 않고도, Renderer2 class의 도움을 통해 app에 있는 elements를 조종할 수 있게 해주는 친구입니다.
DOM element와 component code 사이를 추상 레이어로 제공해주는 Abstraction class이며, 다양한 이유로 인해서 해당 class를 사용하는 것을 추천합니다.
element를 만들거나, text를 넣거나, child element를 넣거나, 스타일을 삭제하거나, CSS class를 넣거나 할 때도 다 사용하는 친구입니다.
그나저나 왜 Renderer2일까요.
찾아보니, Angular 4까진 Renderer였다가 이후로 Renderer2를 사용한다고 하네요.
너무 유용해보이는데요.
근데 저흰 이 때까지 사용하던 ElementRef가 있는데 얘랑은 무슨 차이일까요?
왜 ElementRef는 안되나요?
natvieElement를 사용하기 위해서 ElementRef를 사용하여 DOM을 조작했습니다.
사실 너 잘 못했어 ! 라기 보단 여러가지 이유로 사용에 대해서 충고를 하고 있는데요. 이유는 아래와 같습니다.
- DOM APIs들의 경우 data를 거를 수 없기 때문에, script를 inject할 수 있습니다. 그렇기에 app이 XSS 크로스 사이트 스크립팅 공격에 매우 취약합니다.
- DOM 조작은 Browser 안에서만 동작을 합니다. 그 말은 browser가 없는 환경에서는 사용할 수 없습니다.
- Angular는 데이터 바인딩 & 체인지 디텍션을 이용하여 Component와 View를 유지하는데, DOM을 직접 접근하면, 이를 우회하기 때문에 좋지 않습니다.
해당 이유 때문에 ElementRef를 쓰는 것을 말리는거 같네요. 심지어 Angular 공식문서에서도 말리니..
그러면 Renderer2를 써야하는 이유를 알았으니, 한 번 사용해보도록합시다.
Renderer2 사용
import {Component, Renderer2, ElementRef, ViewChild, AfterViewInit} from '@angular/core';
...
constructor(private renderer: Renderer2) {}
...
@ViewChild('hello', {static: false})
divHello: ElementRef;
...
this.renderer.setProperty(this.divHello.nativeElement, 'innerHTML', "Hello Angular")
this.renderer.setStyle(this.divHello.nativeElement, 'color', 'red');
보시다시피, ElementRef 변수를 들고와서 renderer의 메소드에 같이 넣어주면서 사용을 함을 볼 수 있습니다. 그렇기에 안전한 조작이 가능하죠.
Style을 추가하거나 삭제해보았습니다.
abstract setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void
abstract removeStyle(el: any, style: string, flags?: RendererStyleFlag2): void
...
this.renderer.setStyle(this.div.nativeElement, 'color', 'blue');
this.renderer.removeStyle(this.div.nativeElement, 'color');
CSS 클래스를 추가하거나 삭제해보았습니다.
abstract addClass(el: any, name: string): void
abstract removeClass(el: any, name: string): void
...
this.renderer.addClass(this.div.nativeElement, 'black-border');
this.renderer.removeClass(this.div.nativeElement, 'black-border');
eventListener도 등록이 가능하군요.
abstract listen(target: any, eventName: string, callback: (event: any) => boolean: void): () => void
...
this.clickListener = this.renderer.listen(this.div.nativeElement, 'click', (evt) => {
this.Count++;
});
이 경우 unsubscribe() 하는 것을 잊지 맙시다.
사실 뭘 좀 더 적어보려고 했는데, 사용 방법이 너무 간단해서 더 적을게 없네요.
https://www.tektutorialshub.com/angular/renderer2-angular/
https://www.positronx.io/using-renderer2-angular/
위의 글을 참고하여 작성했습니다.
그러니 위에서 예제 찾아보시면 더 좋을거 같은데, 다 사용방법이 비슷비슷해서 똑똑한 여러분들은 쉽게 이해 하실 수 있으실거 같습니다.
이상 Renderer2 in Angular 12 (Why not ElementRef ?) 였습니다. ^_^
'Web + APP > Angular' 카테고리의 다른 글
NGRX - Actions (0) | 2021.10.24 |
---|---|
Angular : 같은 URL에서 Refetch data (2) | 2021.10.17 |
iOS 한글 buffer 문제 (1) | 2021.09.11 |
Angular Flex-Layout using MediaObserver (2) | 2021.08.28 |
RxJS 구독해제 패턴 심화편 (3) | 2021.06.26 |