Skip to content

5. 프로퍼티 바인딩


프로퍼티 바인딩을 활용하면 HTML 엘리먼트나 디렉티브의 프로퍼티 값을 지정할 수 있다. 이 문법을 활용하면 버튼을 비활성화할 수 있고, 이동할 주소를 프로그램 로직으로 할당할 수 있으며, 컴포넌트에 데이터를 전달할 수 있다.


Note


1. 사전지식

프로퍼티 바인딩을 제대로 이해하려면 이런 내용을 먼저 알고 있는 것이 좋다:



2. 데이터 흐름 이해하기

프로퍼티 바인딩에서 데이터는 컴포넌트 프로퍼티에서 대상 엘리먼트 프로퍼티로, 한 방향으로만 움직인다.


Note

  • 이벤트를 감지하는 방법에 대해 자세하게 알아보려면 이벤트 바인딩 문서를 참고한다.


2. 프로퍼티에 바인딩하기

엘리먼트 프로퍼티를 바인딩하려면 대상 프로퍼티를 대괄호로 감싸는 문법([])을 사용한다. 이 때 대상 프로퍼티는 값을 지정하려고 하는 DOM 프로퍼티이다. 아래 예제에서는 <img> 엘리먼트의 src 프로퍼티가 대상 프로퍼티이다.


src/app/app.component.html
<img [src]="itemImageUrl" />


헷갈릴 수 있지만 대상이 되는 이름은 어트리뷰트가 아니라 프로퍼티 이름이다. 위 예제에서도 src<img> 엘리먼트의 프로퍼티이다.


대괄호([])가 사용되면 Angular는 프로퍼티 바인딩 표현식의 등호 오른쪽에 있는 표현식을 평가한다. 그리고 대괄호를 사용하지 않으면 등호 오른쪽에 있는 문자열은 단순한 문자열 리터럴로 사용되어 프로퍼티에 바인딩된다.


src/app.component.html
<app-item-detail childItem="parentItem"></app-item-detail>


위 예제에서 대상 프로퍼티에 바인딩 되는 값은 parentItem 프로퍼티의 값이 아니라 parentItem이라는 문자열이다.


3. 엘리먼트 프로퍼티 설정하기

<img> 엘리먼트의 src 프로퍼티를 컴포넌트 itemImageUrl 프로퍼티의 값으로 바인딩하려면 대괄호를 사용해서 이렇게 작성하면 된다.


src/app/app.component.html
<img [src]="itemImageUrl" />


이 예제에서 itemImageUrl 프로퍼티는 AppComponent에 정의되어 있다.


src/app/app.component.ts
itemImageUrl = "../assets/phone.png";


1) colspancolSpan

가장 헷갈리는 부분은 colspan 어트리뷰트와 colSpan 프로퍼티 같이, 바인딩하는 대상이 어트리뷰트인지 프로퍼티인지 혼동이 된다는 것이다. 두 단어의 철자는 같지만 엄연히 다르다.


이렇게 작성했다고 하자:


<tr>
  <td colspan="{{1 + 1}}">Three-Four</td>
</tr>


그러면 이런 에러가 표시된다:


Template parse errors:
Can't bind to 'colspan' since it isn't a known native property


이 메시지에서 알 수 있듯이, <td> 엘리먼트에는 colspan이라는 프로퍼티가 없다. 왜냐하면 colspan은 프로퍼티가 아니라 어트리뷰트이며, 관련된 프로퍼티는 대문자가 들어간 colSpan이다. 문자열 바인딩(Interpolation)이나 프로퍼티 바인딩은 모두 프로퍼티를 대상으로 동작한다. 어트리뷰트가 아니다.


프로퍼티 바인딩은 이렇게 사용한다:


src/app/app.component.html
<!-- colSpan 프로퍼티는 캐멀 케이스입니다. -->
<tr>
  <td [colSpan]="1 + 1">Three-Four</td>
</tr>


그리고 컴포넌트에 있는 isUnchanged 프로퍼티 값으로 버튼을 비활성화하려면 이렇게 구현하면 된다:


src/app/app.component.html
<!-- 버튼의 활성화 여부를 `isUnchanged` 프로퍼티와 바인딩합니다. -->
<button [disabled]="isUnchanged">Disabled Button</button>


디렉티브의 프로퍼티 값은 이렇게 설정한다:


src/app/app.component.html
<p [ngClass]="classes">
  [ngClass] binding to the classes property making this blue
</p>


커스텀 컴포넌트에 값을 전달할 수도 있다. 부모/자식 컴포넌트끼리는 이렇게 데이터를 전달한다:


src/app/app.component.html
<app-item-detail [childItem]="parentItem"></app-item-detail>


4. 버튼 비활성화하기

버튼을 비활성화하려면 불리언 값으로 DOM disabled 프로퍼티 값을 지정하면 된다.


src/app/app.component.html
<!-- 버튼의 활성화 여부를 `isUnchanged` 프로퍼티와 바인딩합니다. -->
<button [disabled]="isUnchanged">Disabled Button</button>


그러면 AppComponentisUnchanged 프로퍼티 값이 true일 때 Angular가 버튼을 비활성화한다.


src/app/app.component.ts
isUnchanged = true;


5. 디렉티브 프로퍼티 값 지정하기

디렉티브의 프로퍼티 값을 지정하려면 대괄호를 사용해서 [ngClass]와 같이 대상 프로퍼티를 지정하고 그 오른쪽에 등호를 붙여 표현식을 연결하면 된다. classes 프로퍼티를 바인딩하려면 이렇게 구현하면 된다.


src/app/app.component.html
<p [ngClass]="classes">
  [ngClass] binding to the classes property making this blue
</p>


프로퍼티를 바인딩하려면 반드시 이 프로퍼티를 컴포넌트 클래스에 선언해야 하며, 예제의 경우에는 AppComponent가 컴포넌트 클래스이다. classes 프로퍼티의 값은 special이다.


src/app/app.component.ts
classes = "special";


그러면 Angular가 <p> 엘리먼트의 CSS 클래스를 special로 지정하며, special 클래스에 맞는 CSS 스타일이 적용된다.


6. 컴포넌트끼리 프로퍼티 바인딩하기

커스텀 컴포넌트의 프로퍼티 값을 설정하려면 대상 컴포넌트의 프로퍼티를 대괄호로 감싸면 된다. 아래 예제는 부모 컴포넌트에 있는 parentItem을 자식 컴포넌트의 childItem 프로퍼티로 바인딩하는 예제 코드이다.


src/app/app.component.html
<app-item-detail [childItem]="parentItem"></app-item-detail>


바인딩하려는 프로퍼티와 바인딩 대상이 되는 프로퍼티는 반드시 컴포넌트 클래스에 선언되어 있어야 한다. childItemItemDetailComponent에 선언된 프로퍼티이다.


그리고 이 프로퍼티에 @Input() 데코레이터를 지정하면 데이터가 이 프로퍼티로 전달될 수 있다.


src/app/item-detail/item-detail.component.ts
@Input() childItem = '';


그리고 바인딩 대상이 되는 프로퍼티 parentItemAppComponent에 선언되어 있다. 이 예제에서 childItem 프로퍼티의 타입은 string이기 때문에 parentItem 프로퍼티도 문자열 타입이어야 한다. 그래서 parentItem 프로퍼티에도 lamp라는 문자열 값이 할당되어 있다.


src/app/app.component.ts
parentItem = "lamp";


이렇게 구현하면 <app-item-detail>childItem으로 lamp 값을 받는다.


7. 프로퍼티 바인딩과 보안

프로퍼티 바인딩을 활용하면 보안에도 도움이 된다. 예를 들어 이런 악성 코드가 있다고 하자.


src/app/app.component.ts
evilTitle = 'Template <script>alert("evil never sleeps")</script> Syntax';


이 컴포넌트의 문자열이 바인딩되면 이런 내용이 된다:


src/app/app.component.html
<p>
  <span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span>
</p>


브라우저는 이 악성코드를 그대로 실행하지 않고 이런 메시지를 출력한다.


"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.


Angular는 문자열 바인딩과 프로퍼티 바인딩 문법에서 <script> 태그를 허용하지 않기 때문에 악성 JavaScript 코드가 실행되는 것도 막는다.


Anuglar는 아래 예제처럼 악성 코드를 무력화(sanitize)한다.


src/app/app.component.html
<!--
 Angular가 아래와 같이 위험한 코드를 발견하면 경고를 표시합니다.
 WARNING: 안전성 검사를 우회하는 방법은 http://g.co/ng/security#xss 를 참고하세요.
-->
<p>
  "<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil
  title.
</p>


문자열 바인딩과 프로퍼티 바인딩은 <script> 태그를 처리하는 방식이 조금 다르지만, 결국 위험하지 않은 내용만 화면에 렌더링된다. evilTitle이 프로퍼티 바인딩에 사용되면 이런 에러 메시지가 브라우저 콘솔에 출력된다.


"Template Syntax" is the property bound evil title.


8. 프로퍼티 바인딩과 문자열 바인딩

문자열 바인딩과 프로퍼티 바인딩은 보통 같은 결과를 낸다. 아래 예제에서도 문자열 바인딩과 프로퍼티 바인딩의 결과는 같다.


src/app/app.component.html
<p><img src="{{itemImageUrl}}" /> is the <i>interpolated</i> image.</p>
<p><img [src]="itemImageUrl" /> is the <i>property bound</i> image.</p>

<p>
  <span>"{{interpolationTitle}}" is the <i>interpolated</i> title.</span>
</p>
<p>
  "<span [innerHTML]="propertyTitle"></span>" is the
  <i>property bound</i> title.
</p>


문자열 같은 데이터를 화면에 렌더링하는 용도라면 어느 방식을 써도 되지만, 가독성 때문에 문자열 바인딩이 더 선호되곤 한다. 하지만 문자열이 아닌 데이터를 엘리먼트 프로퍼티에 바인딩하려면 반드시 프로퍼티 바인딩을 활용해야 한다.


References