{{ product.name }}
{{ product.price | currency:'USD' }}
@if (product.inStock) { } @else { Out of Stock }# Angular 면접 질문 TOP 25: 성공을 위한 완벽 가이드 > 2026년 가장 많이 묻는 Angular 면접 질문 25선. 상세한 답변과 코드 예시, Angular 개발자 포지션을 잡기 위한 팁을 제공합니다. - Published: 2026-02-04 - Updated: 2026-04-27 - Author: SharpSkill - Tags: angular interview, frontend interview, angular questions, typescript, technical interview - Reading time: 16 min --- Angular 기술 면접은 프레임워크의 아키텍처에 대한 이해, TypeScript 숙련도, 프런트엔드 개발 모범 사례를 평가합니다. 이 가이드는 가장 자주 묻는 25개의 질문을 자세한 답변과 코드 예시와 함께 정리하여 효율적인 준비를 돕습니다. > **준비 팁** > > 이 질문들은 Signals, 스탠드얼론 컴포넌트, 새로운 컨트롤 플로우 등 최신 Angular 버전(16+)을 다룹니다. 이러한 모던한 개념을 익혀 두면 기술 트렌드를 적극적으로 따라가고 있다는 점을 어필할 수 있습니다. ## Angular 기본기 ### 1. Angular와 AngularJS의 차이는 무엇인가요? Angular(버전 2 이상)는 AngularJS를 완전히 다시 작성한 프레임워크입니다. 주요 차이점은 아키텍처, 언어, 성능에 있습니다. AngularJS는 JavaScript와 MVC 패턴, 양방향 바인딩 시스템을 사용했으며 이로 인해 성능 문제가 발생할 수 있었습니다. Angular는 TypeScript와 컴포넌트 기반 아키텍처, 최적화된 변경 감지 시스템을 사용합니다. ```typescript // AngularJS (1.x) - Controller-based // angular.module('app').controller('UserController', function($scope) { // $scope.user = { name: 'Alice' }; // }); // Angular (2+) - Component-based // user.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-user', standalone: true, template: `
{{ user.email }}
{{ product.price | currency:'USD' }}
@if (product.inStock) { } @else { Out of Stock }{{ data }}
` }) export class LifecycleDemoComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy { @Input() data = ''; // 1. Called when an @Input changes (before ngOnInit) ngOnChanges(changes: SimpleChanges) { console.log('ngOnChanges', changes); } // 2. Called once after the first ngOnChanges // Ideal for initializations ngOnInit() { console.log('ngOnInit - Component initialization'); } // 3. Called on every change detection cycle // Use with caution (performance) ngDoCheck() { console.log('ngDoCheck'); } // 4. After content projection (ng-content) ngAfterContentInit() { console.log('ngAfterContentInit'); } // 5. After each projected content check ngAfterContentChecked() { console.log('ngAfterContentChecked'); } // 6. After component view initialization // @ViewChild references are available here ngAfterViewInit() { console.log('ngAfterViewInit - View initialized'); } // 7. After each view check ngAfterViewChecked() { console.log('ngAfterViewChecked'); } // 8. Just before component destruction // Cleanup: unsubscribe, clearInterval, etc. ngOnDestroy() { console.log('ngOnDestroy - Cleanup'); } } ``` 가장 자주 사용되는 훅은 초기화를 위한 `ngOnInit`, 입력 변경에 반응하는 `ngOnChanges`, 리소스를 정리하는 `ngOnDestroy`입니다. ### 4. Angular의 Data Binding이란 무엇인가요? Data binding은 컴포넌트의 데이터를 템플릿에 연결합니다. Angular는 네 가지 형태의 바인딩을 제공합니다. ```typescript // data-binding.component.ts import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-data-binding', standalone: true, imports: [FormsModule], template: `{{ getFullName() }}
Hello, {{ username }}
` }) export class DataBindingComponent { // Properties for interpolation title = 'My Application'; firstName = 'John'; lastName = 'Doe'; // Properties for property binding imageUrl = '/assets/logo.png'; imageAlt = 'Application logo'; isLoading = false; // Property for two-way binding username = ''; getFullName(): string { return `${this.firstName} ${this.lastName}`; } handleClick(): void { console.log('Button clicked'); } onEnter(event: KeyboardEvent): void { const target = event.target as HTMLInputElement; console.log('Entered value:', target.value); } } ``` 양방향 바인딩 `[(ngModel)]`은 프로퍼티 바인딩과 이벤트 바인딩이 결합된 형태로, 모델과 뷰를 자동으로 동기화합니다. ### 5. Module과 Standalone Component의 차이는 무엇인가요? NgModules는 관련된 컴포넌트, 디렉티브, 서비스를 묶어 줍니다. 스탠드얼론 컴포넌트(Angular 14+)는 모듈 없이도 독립적인 컴포넌트를 만들 수 있게 합니다. ```typescript // Traditional approach with NgModule // products.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ProductListComponent } from './product-list.component'; import { ProductCardComponent } from './product-card.component'; import { ProductService } from './product.service'; @NgModule({ // Components belonging to this module declarations: [ ProductListComponent, ProductCardComponent ], // Modules needed imports: [CommonModule], // Components usable outside exports: [ProductListComponent], // Services with module scope providers: [ProductService] }) export class ProductsModule {} // Modern approach with Standalone Components // product-list.component.ts import { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ProductCardComponent } from './product-card.component'; import { ProductService } from './product.service'; @Component({ selector: 'app-product-list', // No NgModule needed standalone: true, // Direct dependency imports imports: [CommonModule, ProductCardComponent], template: ` @for (product of products(); track product.id) {{{ user.email }}
} ` }) export class UserProfileComponent implements OnInit { // Injection via inject() (recommended) private userService = inject(UserService); user$!: ObservableDouble: {{ doubleCount() }}
Message: {{ message() }}
No users found
}{{ data }}
` }) export class DefaultStrategyComponent { data = 'Hello'; } // OnPush strategy: checks only if inputs change // or if an event is triggered within the component @Component({ selector: 'app-onpush-strategy', changeDetection: ChangeDetectionStrategy.OnPush, template: `{{ data().name }}
` }) export class OnPushStrategyComponent { private cdr = inject(ChangeDetectorRef); // Signal: automatically triggers detection data = signal({ name: 'Alice' }); update() { // With signal, update is automatic this.data.set({ name: 'Bob' }); } // For cases where manual detection is needed manualUpdate() { // Mark component for checking this.cdr.markForCheck(); // Or force immediate detection this.cdr.detectChanges(); } } // Practical example: optimized list @Component({ selector: 'app-optimized-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` @for (item of items(); track item.id) {{{ message() }}
` }) export class ChildComponent { message = input.required{{ message$ | async }}
` }) export class ComponentB implements OnDestroy { private messageService = inject(MessageService); private destroy$ = new SubjectYour cart is empty
} @else { @for (item of cartStore.items(); track item.id) {{itemCount, plural, =0 {No items} =1 {One item} other {{{itemCount}} items} }
` }) export class AppComponent { itemCount = 5; } // 2. ngx-translate (runtime language switching) // app.config.ts import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, './assets/i18n/', '.json'); } // Configuration provideTranslateService({ defaultLanguage: 'en', loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient] } }) // language-switcher.component.ts @Component({ selector: 'app-language-switcher', standalone: true, imports: [TranslateModule], template: `{{ 'HOME.WELCOME' | translate:{ name: userName } }}
` }) export class LanguageSwitcherComponent { private translate = inject(TranslateService); userName = 'Alice'; changeLanguage(event: Event) { const lang = (event.target as HTMLSelectElement).value; this.translate.use(lang); } } // assets/i18n/en.json { "HOME": { "TITLE": "Welcome", "WELCOME": "Hello {{name}}!" } } // assets/i18n/fr.json { "HOME": { "TITLE": "Bienvenue", "WELCOME": "Bonjour {{name}} !" } } ``` 내장 i18n과 ngx-translate 중 무엇을 선택할지는 요구 사항에 따라 다릅니다. 최고의 성능을 위해서는 별도 컴파일을, 더 큰 유연성을 원할 때는 동적 전환을 선택할 수 있습니다. ### 25. Angular 프로젝트를 구성하는 모범 사례는 무엇인가요? 잘 구성된 구조는 프로젝트의 유지 관리와 확장성을 쉽게 만들어 줍니다. ``` src/ ├── app/ │ ├── core/ # Singleton services, guards, interceptors │ │ ├── guards/ │ │ │ └── auth.guard.ts │ │ ├── interceptors/ │ │ │ └── auth.interceptor.ts │ │ ├── services/ │ │ │ ├── auth.service.ts │ │ │ └── api.service.ts │ │ └── core.provider.ts # Provider configuration │ │ │ ├── shared/ # Reusable components, pipes, directives │ │ ├── components/ │ │ │ ├── button/ │ │ │ └── modal/ │ │ ├── directives/ │ │ ├── pipes/ │ │ └── index.ts # Barrel exports │ │ │ ├── features/ # Feature modules (lazy-loaded) │ │ ├── products/ │ │ │ ├── components/ │ │ │ ├── services/ │ │ │ ├── models/ │ │ │ ├── products.routes.ts │ │ │ └── products.component.ts │ │ ├── cart/ │ │ └── checkout/ │ │ │ ├── layouts/ # Page layouts │ │ ├── main-layout/ │ │ └── auth-layout/ │ │ │ ├── app.component.ts │ ├── app.config.ts │ └── app.routes.ts │ ├── assets/ ├── environments/ └── styles/ ``` ```typescript // Best code practices // 1. Barrel exports to simplify imports // shared/index.ts export * from './components/button/button.component'; export * from './components/modal/modal.component'; export * from './pipes/format-date.pipe'; // 2. Centralized provider configuration // core/core.provider.ts import { provideHttpClient, withInterceptors } from '@angular/common/http'; import { authInterceptor } from './interceptors/auth.interceptor'; export const coreProviders = [ provideHttpClient( withInterceptors([authInterceptor]) ), // Other global providers ]; // 3. Typed models // features/products/models/product.model.ts export interface Product { id: number; name: string; price: number; category: ProductCategory; createdAt: Date; } export type ProductCategory = 'electronics' | 'clothing' | 'books'; export interface CreateProductDto { name: string; price: number; category: ProductCategory; } // 4. Functional interceptor // core/interceptors/auth.interceptor.ts import { HttpInterceptorFn } from '@angular/common/http'; import { inject } from '@angular/core'; export const authInterceptor: HttpInterceptorFn = (req, next) => { const authService = inject(AuthService); const token = authService.getToken(); if (token) { req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next(req); }; ``` 이러한 컨벤션은 코드 내 직관적인 탐색을 가능하게 하고 팀 협업을 수월하게 만듭니다. ## 결론 이 25개의 질문은 면접에서 자주 다뤄지는 Angular의 핵심 개념을 모두 다룹니다. 마스터해야 할 핵심 포인트: - ✅ **기본기**: 컴포넌트, 데이터 바인딩, 라이프사이클, DI - ✅ **모던 Angular**: Signals, 스탠드얼론 컴포넌트, 새로운 control flow - ✅ **리액티비티**: RxJS, Observable, Signals 기반 상태 관리 - ✅ **폼**: Template-driven vs Reactive, 커스텀 검증 - ✅ **라우팅**: Guards, 지연 로딩, 데이터 전달 - ✅ **성능**: OnPush, defer, 가상 스크롤 - ✅ **테스트**: 단위 테스트, 모킹, HttpTestingController Angular 면접 준비에는 꾸준한 연습이 필요합니다. 개인 프로젝트를 만들어 보면 이 지식을 다지는 데 도움이 되고, 면접에서도 자연스럽게 설명할 수 있게 됩니다. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/ko/blog/angular/top-25-angular-interview-questions