Angular 2 *ngFor 오류: Can’t bind to ’ngFor’ since it isn’t a known native property

1. 문제 정의

Angular 2에서 리스트를 반복 렌더링하기 위해 *ngFor 디렉티브를 사용하던 중, 다음과 같은 Template parse 오류가 발생합니다.

1
2
3
EXCEPTION: Template parse errors:
Can't bind to 'ngFor' since it isn't a known native property
("<div [ERROR ->]*ngFor="talk of talks">

브라우저 콘솔에 이 오류가 출력되며 컴포넌트가 정상적으로 렌더링되지 않습니다. 아래는 문제가 발생한 코드입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import {bootstrap, Component} from 'angular2/angular2'

@Component({
  selector: 'conf-talks',
  template: `<div *ngFor="talk of talks">
     {{talk.title}} by {{talk.speaker}}
     <p>{{talk.description}}
   </div>`
})
class ConfTalks {
  talks = [ {title: 't1', speaker: 'Brian', description: 'talk 1'},
            {title: 't2', speaker: 'Julie', description: 'talk 2'}];
}

핵심은 템플릿의 <div *ngFor="talk of talks"> 부분입니다. 오류 메시지가 ngFor를 “알려지지 않은 네이티브 속성"으로 지목하지만, 실제로는 디렉티브 문법이 잘못된 상황입니다.

2. 원인 탐구

브라우저는 ngFor를 알 수 없는 속성으로 보고합니다. 왜 Angular가 *ngFor 디렉티브를 인식하지 못하는 것처럼 보일까요?

관찰 결과, *ngFor 구조 디렉티브의 문법에서 talk라는 반복 변수를 선언할 때 let 키워드가 누락되어 있습니다.

  • 올바른 문법: <div *ngFor="let talk of talks">
  • 잘못된 문법: <div *ngFor="talk of talks">

*ngFor의 축약형(desugared) 구문에서 of 앞에는 반드시 “변수 선언"이 와야 합니다. 이 변수 선언은 선행 키워드(let 또는 과거의 #)가 필요한 형태입니다. 이 키워드가 없으면 파서가 talk of talks를 유효한 반복 표현식으로 해석하지 못하여 ngFor 바인딩 자체를 실패하게 됩니다.

3. 근본 원인 분석

근본 원인은 구조 디렉티브 내부의 지역 변수 선언 문법에서 선행 키워드( let )를 생략한 것입니다.

Angular 2의 * 접두사는 템플릿 문법을 축약하는 기능입니다. 예를 들어 *ngFor="let talk of talks"는 내부적으로 다음과 같이 변환됩니다.

1
2
3
<template ngFor [ngForOf]="talks" let-talk>
  ...
</template>

이 변환 과정에서 let talk 구문이 실제 바인딩을 생성합니다. 여기서 let이 없으면 ngForOf에 연결할 반복 변수(talk)가 선언되지 못하고, 결과적으로 템플릿 파서가 *ngFor 디렉티브 전체를 “알려진 네이티브 속성이 아닌” 무언가로 처리해 오류를 냅니다.

추가로, Angular 2 beta.17 버전부터 구조 디렉티브 안에서 지역 변수를 선언하는 데 사용하던 #... 문법이 deprecated(비권장) 되었습니다. 따라서 이제는 let 키워드를 사용하는 것이 표준입니다.

문법상태예시
let 변수표준 (권장)<div *ngFor="let talk of talks">
#변수deprecated (beta.17 이후)<div *ngFor="#talk of talks"> — 더 이상 권장되지 않음
변수 (키워드 없음)오류<div *ngFor="talk of talks"> — 문법 오류

4. 코드 해결책

문제는 단순합니다. *ngFor 안에서 반복 변수를 선언할 때 let 키워드를 추가하면 됩니다.

잘못된 코드:

1
2
3
4
<div *ngFor="talk of talks">
  {{talk.title}} by {{talk.speaker}}
  <p>{{talk.description}}
</div>

수정된 코드:

1
2
3
4
<div *ngFor="let talk of talks">
  {{talk.title}} by {{talk.speaker}}
  <p>{{talk.description}}
</div>

수정 후 전체 컴포넌트 코드는 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {bootstrap, Component} from 'angular2/angular2'

@Component({
  selector: 'conf-talks',
  template: `<div *ngFor="let talk of talks">
     {{talk.title}} by {{talk.speaker}}
     <p>{{talk.description}}
   </div>`
})
class ConfTalks {
  talks = [ {title: 't1', speaker: 'Brian', description: 'talk 1'},
            {title: 't2', speaker: 'Julie', description: 'talk 2'}];
}

@Component({
  selector: 'my-app',
  directives: [ConfTalks],
  template: '<conf-talks></conf-talks>'
})
class App {}

bootstrap(App, [])

만약 기존 코드가 아직 #talk 문법을 사용하고 있다면, #let으로 바꿔야 합니다.

기존 (deprecated):

1
<div *ngFor="#talk of talks">

변경 (권장):

1
<div *ngFor="let talk of talks">

구버전(베타)에서 동작하던 # 문법도 beta.17 이후로는 더 이상 표준이 아니므로, 새 코드에는 항상 let을 사용하세요.

5. 향후 예방 조치

*ngFor 관련 오류를 다시 만나지 않으려면 다음 규칙을 기억하세요.

  1. let 키워드를 습관화하라. *ngFor 안의 변수 선언에는 항상 let을 붙입니다. <div *ngFor="let item of items">
  2. # 문법을 사용하지 마라. beta.17 이후 deprecated되었습니다. 오래된 예제를 복사할 때 #talk 형태를 발견하면 let talk로 바꿉니다.
  3. 오류 메시지를 문법 관점에서 읽어라. “Can’t bind to ’ngFor’ since it isn’t a known native property” 같은 메시지는 디렉티브 자체가 없는 것이 아니라, 디렉티브의 축약 문법이 잘못됐을 때도 나타납니다.
  4. 반복 대상(컬렉션)과 반복 변수(요소) 이름을 구분하라. of 왼쪽은 “하나의 요소를 담는 변수 선언”, 오른쪽은 “컬렉션(배열)“입니다.
  5. 최신 Angular 버전에서는 *ngFor 대신 새 구조 디렉티브 문법을 확인하라. 최신 Angular에서는 @for (Angular 17+) 같은 공식 반복문이 도입되었으므로, 버전에 맞는 공식 문서를 참고하세요.

이 규칙만 지켜도 “Can’t bind to ’ngFor’” 같은 혼란스러운 템플릿 오류 대부분을 예방할 수 있습니다.


참고 출처