Angular 개요
Angular란?
Angular는 구글에서 개발하고 유지보수하는 TypeScript 기반의 오픈소스 웹 애플리케이션 프레임워크입니다. 엔터프라이즈급 애플리케이션 개발을 위한 완전한 기능을 갖춘 프레임워크로, 단일 페이지 애플리케이션(SPA) 개발을 위한 강력한 도구입니다.
목차
Angular의 역사
1. AngularJS (Angular 1.x)
- 2010년: 구글의 Miško Hevery와 Adam Abrons가 AngularJS 개발 시작
- 2012년: AngularJS 1.0 릴리즈
- 특징: JavaScript 기반, 양방향 데이터 바인딩, DI(Dependency Injection) 도입
- 문제점: 성능 이슈, 복잡한 구조, 스케일링 어려움
2. Angular 2 (완전한 재작성)
- 2016년 9월: Angular 2.0 릴리즈
- 주요 변화:
- TypeScript 기반으로 전환
- 컴포넌트 기반 아키텍처
- 성능 대폭 개선 (Zone.js, AOT 컴파일)
- 모바일 우선 설계
- Breaking Changes: AngularJS와 호환되지 않음
3. Angular 4~8 (점진적 개선)
- 2017년 3월: Angular 4.0 (버전 3 생략)
- 주요 기능:
- Angular CLI 강화
- Ivy 렌더러 (렌더링 엔진) 개발 시작
- 서버 사이드 렌더링 (Angular Universal)
- 동적 컴포넌트 로딩
4. Angular 9~15 (Ivy 렌더러)
- 2020년 2월: Angular 9.0, Ivy 렌더러 기본 활성화
- 주요 개선사항:
- 번들 크기 감소 (최대 40% 감소)
- 빌드 시간 단축
- 트리 셰이킹 개선
- 컴포넌트 테스트 쉬워짐
5. Angular 16+ (최신 버전)
- 2023년 5월: Angular 16.0
- 주요 기능:
- Signals (반응형 상태 관리)
- 서버 사이드 렌더링 개선
- 하이드레이션 지원
- 독립형 컴포넌트 (Standalone Components)
버전 관리 전략
- 6개월 주기: 새로운 주요 버전 릴리즈
- LTS (Long Term Support): 12개월 지원 기간
- 하위 호환성: 주요 버전 간 마이그레이션 가이드 제공
장단점
장점
1. 완전한 프레임워크
- 의존성 주입 (DI): 내장된 강력한 DI 시스템
- 라우팅: Angular Router 제공
- HTTP 클라이언트: HttpClient 모듈 내장
- 폼 관리: Reactive Forms와 Template-driven Forms 지원
- 애니메이션: Angular Animations API 제공
- 테스트: Karma와 Jasmine 통합 지원
2. TypeScript 기반
- 타입 안정성: 컴파일 타임 오류 검출
- IDE 지원: 자동완성, 리팩토링 강화
- 코드 품질: 대규모 프로젝트에 적합
- 유지보수성: 코드 가독성 향상
3. 엔터프라이즈급 기능
- 모듈화: NgModules를 통한 코드 구조화
- 지연 로딩 (Lazy Loading): 성능 최적화
- AOT 컴파일: Ahead-of-Time 컴파일로 런타임 성능 향상
- 서버 사이드 렌더링: Angular Universal 지원
4. 강력한 CLI 도구
- 프로젝트 생성:
ng new명령어로 빠른 시작 - 코드 생성: 컴포넌트, 서비스, 모듈 자동 생성
- 빌드 및 배포: 프로덕션 빌드 최적화
- 테스트 실행: 유닛 테스트 및 E2E 테스트 지원
5. 풍부한 생태계
- Material Design: Angular Material UI 컴포넌트 라이브러리
- PrimeNG, NgBootstrap: 다양한 UI 라이브러리
- NgRx: 상태 관리 라이브러리 (Redux 패턴)
- RxJS: 반응형 프로그래밍 지원
6. 대규모 팀 협업
- 명확한 구조: 컨벤션과 베스트 프랙티스 제공
- 코드 스타일: TypeScript와 ESLint 통합
- 문서화: 공식 문서가 매우 상세함
단점
1. 높은 학습 곡선
- 복잡한 개념: 모듈, 컴포넌트, 서비스, 의존성 주입 등
- TypeScript 필요: JavaScript만으로는 부족
- RxJS 학습: Observable, Operator 개념 이해 필요
- 초기 학습 시간: 다른 프레임워크 대비 더 많은 시간 소요
2. 번들 크기
- 큰 초기 번들: 프레임워크 자체가 큼
- 최적화 필요: 트리 셰이킹, 코드 분할 필요
- 느린 초기 로딩: 작은 프로젝트에는 과할 수 있음
3. 보일러플레이트 코드
- 많은 설정: 컴포넌트 생성 시 많은 코드 필요
- 반복적인 코드: 데코레이터, 임포트 등
- 설정 복잡도: 모듈, 라우팅, 서비스 설정 등
4. 업데이트 복잡도
- Breaking Changes: 버전 업데이트 시 마이그레이션 필요
- 의존성 관리: 많은 패키지 의존성 관리 어려움
- 업그레이드 시간: 프로젝트 규모에 따라 오래 걸림
5. 성능
- 초기 렌더링: 큰 애플리케이션에서 느릴 수 있음
- 변경 감지: 기본 Change Detection이 모든 컴포넌트 체크
- 최적화 필요: OnPush 전략 등 수동 최적화 필요
6. 커뮤니티
- React 대비 작음: React에 비해 커뮤니티 규모 작음
- 라이브러리 선택: 특정 라이브러리의 Angular 버전 부족 가능
폴더 구조
기본 Angular 프로젝트 구조
my-angular-app/
├── e2e/ # E2E 테스트 파일
│ ├── src/
│ └── protractor.conf.js
├── node_modules/ # 의존성 패키지
├── src/ # 소스 코드
│ ├── app/ # 애플리케이션 코드
│ │ ├── core/ # 핵심 기능 (싱글톤 서비스)
│ │ │ ├── services/
│ │ │ ├── guards/
│ │ │ ├── interceptors/
│ │ │ └── models/
│ │ ├── shared/ # 공유 모듈 및 컴포넌트
│ │ │ ├── components/
│ │ │ ├── directives/
│ │ │ ├── pipes/
│ │ │ └── shared.module.ts
│ │ ├── features/ # 기능 모듈
│ │ │ ├── users/
│ │ │ │ ├── components/
│ │ │ │ ├── services/
│ │ │ │ ├── models/
│ │ │ │ └── users.module.ts
│ │ │ ├── products/
│ │ │ └── orders/
│ │ ├── layout/ # 레이아웃 컴포넌트
│ │ │ ├── header/
│ │ │ ├── footer/
│ │ │ └── sidebar/
│ │ ├── app.component.ts # 루트 컴포넌트
│ │ ├── app.component.html
│ │ ├── app.component.scss
│ │ ├── app.module.ts # 루트 모듈
│ │ └── app-routing.module.ts # 라우팅 설정
│ ├── assets/ # 정적 파일
│ │ ├── images/
│ │ ├── fonts/
│ │ └── styles/
│ ├── environments/ # 환경 설정
│ │ ├── environment.ts
│ │ └── environment.prod.ts
│ ├── styles.scss # 전역 스타일
│ ├── main.ts # 애플리케이션 진입점
│ ├── index.html # HTML 템플릿
│ └── polyfills.ts # 폴리필
├── angular.json # Angular CLI 설정
├── package.json # 프로젝트 의존성
├── tsconfig.json # TypeScript 설정
├── tsconfig.app.json
├── tsconfig.spec.json
└── README.md
주요 폴더 설명
1. app/core/
- 목적: 애플리케이션 전역에서 사용하는 싱글톤 서비스
- 포함: 인증 서비스, HTTP 인터셉터, 가드, 유틸리티 함수
- 규칙: AppModule에서만 임포트, 한 번만 제공
2. app/shared/
- 목적: 여러 기능 모듈에서 재사용하는 컴포넌트, 디렉티브, 파이프
- 포함: 버튼, 입력, 모달, 공용 컴포넌트
- 규칙: SharedModule로 구성하여 다른 모듈에 공유
3. app/features/
- 목적: 기능별 모듈 분리 (Feature Module)
- 구조: 각 기능은 독립적인 폴더로 구성
- 예시: 사용자 관리, 제품 관리, 주문 관리 등
4. app/layout/
- 목적: 애플리케이션 레이아웃 컴포넌트
- 포함: 헤더, 푸터, 사이드바, 네비게이션
- 특징: 여러 페이지에서 공통으로 사용
기능 모듈 상세 구조
features/users/
├── components/
│ ├── user-list/
│ │ ├── user-list.component.ts
│ │ ├── user-list.component.html
│ │ └── user-list.component.scss
│ ├── user-detail/
│ └── user-form/
├── services/
│ └── user.service.ts
├── models/
│ └── user.model.ts
├── guards/
│ └── user.guard.ts
├── users-routing.module.ts # 기능별 라우팅
└── users.module.ts # 기능 모듈
폴더 구조 베스트 프랙티스
1. Flat Structure (평면 구조)
components/
├── user-list.component.ts
├── user-detail.component.ts
└── user-form.component.ts
2. Grouped Structure (그룹 구조) - 권장
components/
├── user-list/
│ ├── user-list.component.ts
│ ├── user-list.component.html
│ └── user-list.component.scss
└── user-detail/
├── user-detail.component.ts
└── ...
3. Feature-based Structure (기능 기반 구조)
features/
├── users/
│ ├── components/
│ ├── services/
│ └── models/
└── products/
├── components/
└── services/
기본적으로 알아야 할 것
1. 핵심 개념
컴포넌트 (Component)
- 역할: UI를 구성하는 기본 단위
- 구성: TypeScript 클래스 + HTML 템플릿 + CSS 스타일
- 생명주기: ngOnInit, ngOnChanges, ngOnDestroy 등
import { Component } from '@angular/core';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.scss']
})
export class UserComponent {
title = 'User Component';
}모듈 (Module)
- 역할: 관련된 컴포넌트, 서비스, 디렉티브를 그룹화
- NgModule: @NgModule 데코레이터로 정의
- 의존성: imports, declarations, providers, bootstrap
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }서비스 (Service)
- 역할: 비즈니스 로직과 데이터 처리
- 의존성 주입: @Injectable 데코레이터로 제공
- 싱글톤: 기본적으로 애플리케이션 전체에서 하나의 인스턴스
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('/api/users');
}
}디렉티브 (Directive)
- 구조 디렉티브: DOM 구조를 변경 (*ngIf, *ngFor, *ngSwitch)
- 속성 디렉티브: 요소의 동작이나 모양 변경 ([ngClass], [ngStyle])
- 커스텀 디렉티브: 직접 만드는 디렉티브
<div *ngIf="isVisible">Visible Content</div>
<div *ngFor="let item of items">{{ item.name }}</div>
<div [ngClass]="{'active': isActive}">Content</div>파이프 (Pipe)
- 역할: 데이터 변환 및 포맷팅
- 내장 파이프: DatePipe, CurrencyPipe, JsonPipe 등
- 커스텀 파이프: @Pipe 데코레이터로 정의
{{ date | date:'short' }}
{{ price | currency:'KRW' }}
{{ user | json }}2. 데이터 바인딩
문자열 보간 (Interpolation)
// TypeScript
title = 'Angular';
// Template
<h1>{{ title }}</h1>속성 바인딩 (Property Binding)
// TypeScript
imageUrl = 'https://example.com/image.jpg';
isDisabled = false;
// Template
<img [src]="imageUrl">
<button [disabled]="isDisabled">Click</button>이벤트 바인딩 (Event Binding)
// TypeScript
onClick() {
console.log('Clicked!');
}
// Template
<button (click)="onClick()">Click</button>양방향 바인딩 (Two-way Binding)
// TypeScript
name = '';
// Template
<input [(ngModel)]="name">
<p>{{ name }}</p>3. 의존성 주입 (Dependency Injection)
기본 사용
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root' // 싱글톤으로 제공
})
export class DataService {
getData() {
return 'Data';
}
}
// 컴포넌트에서 사용
export class MyComponent {
constructor(private dataService: DataService) { }
ngOnInit() {
const data = this.dataService.getData();
}
}Provider 설정
// 모듈 레벨
@NgModule({
providers: [DataService]
})
// 컴포넌트 레벨
@Component({
providers: [DataService] // 컴포넌트별 인스턴스
})4. 라우팅 (Routing)
기본 설정
// app-routing.module.ts
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: '**', redirectTo: '' } // 404 처리
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }라우터 링크
<a routerLink="/about">About</a>
<a [routerLink]="['/user', userId]">User</a>라우트 파라미터
// 라우트 정의
{ path: 'user/:id', component: UserComponent }
// 컴포넌트에서 받기
import { ActivatedRoute } from '@angular/router';
constructor(private route: ActivatedRoute) { }
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
// 또는 Observable 사용
this.route.paramMap.subscribe(params => {
const id = params.get('id');
});
}5. 폼 처리
템플릿 기반 폼 (Template-driven Forms)
// app.module.ts에 FormsModule 추가
import { FormsModule } from '@angular/forms';
// Template
<form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
<input name="name" ngModel required>
<input name="email" ngModel email>
<button type="submit" [disabled]="!userForm.valid">Submit</button>
</form>반응형 폼 (Reactive Forms)
// app.module.ts에 ReactiveFormsModule 추가
import { ReactiveFormsModule } from '@angular/forms';
// Component
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
export class UserFormComponent {
userForm: FormGroup;
constructor(private fb: FormBuilder) {
this.userForm = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
}
onSubmit() {
if (this.userForm.valid) {
console.log(this.userForm.value);
}
}
}
// Template
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<input formControlName="name">
<input formControlName="email">
<button type="submit" [disabled]="!userForm.valid">Submit</button>
</form>6. HTTP 통신
HttpClient 사용
// app.module.ts
import { HttpClientModule } from '@angular/common/http';
// Service
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) { }
getUsers(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
createUser(user: User): Observable<User> {
return this.http.post<User>('/api/users', user);
}
updateUser(id: number, user: User): Observable<User> {
return this.http.put<User>(`/api/users/${id}`, user);
}
deleteUser(id: number): Observable<void> {
return this.http.delete<void>(`/api/users/${id}`);
}
}7. RxJS 기본
Observable과 Subscribe
import { Observable } from 'rxjs';
// 서비스에서 Observable 반환
getData(): Observable<Data> {
return this.http.get<Data>('/api/data');
}
// 컴포넌트에서 구독
ngOnInit() {
this.apiService.getData().subscribe(
data => {
console.log('Success:', data);
},
error => {
console.error('Error:', error);
}
);
}주요 Operators
import { map, filter, catchError } from 'rxjs/operators';
import { of } from 'rxjs';
this.apiService.getUsers().pipe(
map(users => users.filter(user => user.active)),
catchError(error => {
console.error(error);
return of([]);
})
).subscribe(users => {
this.users = users;
});8. 생명주기 훅 (Lifecycle Hooks)
import {
OnInit, OnDestroy, OnChanges,
AfterViewInit, AfterContentInit
} from '@angular/core';
export class MyComponent implements OnInit, OnDestroy {
ngOnInit() {
// 컴포넌트 초기화 시 실행 (한 번)
// 데이터 로딩, 구독 시작
}
ngOnDestroy() {
// 컴포넌트 파괴 시 실행
// 구독 해제, 타이머 정리
}
ngOnChanges(changes: SimpleChanges) {
// 입력 속성 변경 시 실행
}
ngAfterViewInit() {
// 뷰 초기화 완료 후 실행
}
}9. 변경 감지 전략 (Change Detection)
기본 전략
- Default: 모든 컴포넌트를 매번 체크
- 성능: 작은 앱에서는 문제없음, 큰 앱에서는 느림
OnPush 전략
import { ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-user',
changeDetection: ChangeDetectionStrategy.OnPush,
// ...
})
export class UserComponent {
// 참조가 변경될 때만 감지
}10. 테스트
컴포넌트 테스트
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { UserComponent } from './user.component';
describe('UserComponent', () => {
let component: UserComponent;
let fixture: ComponentFixture<UserComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [UserComponent]
});
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
});
it('should create', () => {
expect(component).toBeTruthy();
});
});11. Angular CLI 주요 명령어
# 프로젝트 생성
ng new my-app
# 개발 서버 실행
ng serve
# 프로덕션 빌드
ng build --prod
# 컴포넌트 생성
ng generate component user
# 서비스 생성
ng generate service user
# 모듈 생성
ng generate module users
# 테스트 실행
ng test
# E2E 테스트
ng e2e
# 라이브러리 생성
ng generate library my-lib학습 순서 추천
- 기초 개념: 컴포넌트, 모듈, 서비스
- 데이터 바인딩: 보간, 속성, 이벤트, 양방향
- 디렉티브: 구조 디렉티브, 속성 디렉티브
- 의존성 주입: 서비스 생성 및 주입
- 라우팅: 라우터 설정 및 네비게이션
- 폼 처리: 템플릿 기반 폼, 반응형 폼
- HTTP 통신: HttpClient 사용
- RxJS: Observable, Operators
- 고급 주제: 모듈 지연 로딩, 가드, 인터셉터
- 상태 관리: NgRx 또는 서비스 기반 상태 관리
참고 자료
참고
- Angular는 대규모 엔터프라이즈 애플리케이션에 적합한 프레임워크입니다
- TypeScript와 RxJS 학습이 필수입니다
- 모듈 기반 구조를 이해하면 프로젝트 관리가 쉬워집니다
- 공식 문서가 매우 상세하므로 참고하세요
- 정기적인 업데이트에 주의하며 마이그레이션 가이드를 확인하세요