mgechev/angularjs-style-guide
mgechev/angularjs-style-guide has 4,909 GitHub stars and 632 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-08 13:49 UTC. Last push 2019-01-09.
์ด ์์น๋ฅผ ์ธก์ ํ๋ ๋ฐฉ๋ฒ
๐ Community-driven set of best practices for AngularJS application development
์ธก์ ๋ ์คํ ์ฆ๊ฐ
- in 24h
- 0
- in 7 days
- ๊ธฐ๋ก ์์ง ์ค
- in 15 days
- ๊ธฐ๋ก ์์ง ์ค
- in 1 month
- ๊ธฐ๋ก ์์ง ์ค
์๋ก ๊ฒน์น๋ ๊ธฐ๊ฐ์ ์์ฆ๊ฐ๋์ด๋ฉฐ ์ผ๋ณ ํฉ๊ณ๊ฐ ์๋๋๋ค. ์ธก์ ๊ฐ์ด ์์ผ๋ฉด ๋น์ ๋ก๋๋ค. ์คํ๋ ๊ด์ฌ๋๋ฅผ ๋ํ๋ด๋ฉฐ ํ์ง์ ๋ณด์ฅํ์ง ์์ต๋๋ค.
README-ko-kr.md
Original์๊ฐ
์ด ๋ฌธ์์ ๋ชฉํ๋ AngularJS ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ํ ๋ ์ฐธ๊ณ ํ ์ ์๋ ๋ชจ๋ฒ ์ฌ๋ก(best practice)์ ๊ฐ์ด๋๋ผ์ธ์ ์ ์ํ๋ ๊ฒ์ ๋๋ค. ์ด ๋ชจ๋ฒ ์ฌ๋ก๋ค์ ์๋์์ ์ฐธ๊ณ ํ์ต๋๋ค.
- AngularJS ์์ค ์ฝ๋
- ๋ณธ์ธ์ด ์ฝ์ด๋ณธ ์์ค ์ฝ๋์ ๋ฌธ์๋ค
- ๋ณธ์ธ์ ๊ฒฝํ
์ฃผ์ 1: ์ด ์คํ์ผ ๊ฐ์ด๋๋ ์์ง ์์ฑ ์ค์ ๋๋ค. ์ด ๋ฌธ์๋ community-driven์ผ๋ก ์ ์งํ๋ ๊ฒ ๋ชฉํ์ด๋ฉฐ, ์ฌ๊ธฐ์ ๊ธฐ์ฌ๋ฅผ ํด์ฃผ์ ๋ค๋ฉด ์ปค๋ฎค๋ํฐ ์ ์ฒด๊ฐ ํฌ๊ฒ ๊ฐ์ฌํ ๊ฒ์ ๋๋ค.
์ฃผ์ 2: ์ด ํ๊ตญ์ด ๋ฒ์ญ๋ณธ์ ๋ฐ๋ฅด๊ธฐ ์ด์ ์, ์ต์ ํ์ด ๋ง๋์ง ํ์ธํ์ญ์์ค. AngularJS ์คํ์ผ ๊ฐ์ด๋์ ์ต์ ๋ฒ์ ์ ์๋ฌธ ๋ฌธ์์ ๋๋ค.
์ด ์คํ์ผ ๊ฐ์ด๋์์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ ๊ฐ์ด๋๋ผ์ธ์ ์ ๊ณตํ์ง ์์ต๋๋ค. ์ฌ๊ธฐ์ ๊ด๋ จํด์๋ ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
- Google ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋
- Mozilla ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋
- Douglas Crockford's ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋
- Airbnb ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋
- Idiomatic ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋
AngularJS ๊ฐ๋ฐ์ ๋ํด์๋ Google ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ผ ๊ฐ์ด๋๋ฅผ ์ถ์ฒํฉ๋๋ค.
AngularJS GitHub ์ํค์ ProLoser๊ฐ ์์ฑํ ๋น์ทํ ํญ๋ชฉ์ด ์์ต๋๋ค. ์ฌ๊ธฐ์์ ํ์ธํ ์ ์์ต๋๋ค.
๋ฒ์ญ๋ณธ
- ์์ด(์๋ฌธ)
- ๋ ์ผ์ด
- ์คํ์ธ์ด
- ํ๋์ค์ด
- ์ธ๋๋ค์์์ด
- ์ดํ๋ฆฌ์์ด
- ์ผ๋ณธ์ด
- ํด๋๋์ด
- ํฌ๋ฅดํฌ๊ฐ์ด
- ๋ฌ์์์ด
- ์ธ๋ฅด๋น์์ด
- ์ธ๋ฅด๋น์์ด(๋ผํด ๋ฌธ์)
- ์ค๊ตญ์ด
- ํฐํค์ด
๋ชฉ์ฐจ
- ์ผ๋ฐ
- ๋ชจ๋
- ์ปจํธ๋กค๋ฌ
- ๋๋ ํฐ๋ธ
- ํํฐ
- ์๋น์ค
- ํ ํ๋ฆฟ
- ๋ผ์ฐํ
- ๊ตญ์ ํ
- ์ฑ๋ฅ
- ๊ธฐ์ฌ
- ๊ธฐ์ฌ์ ๋ช ๋จ
์ผ๋ฐ
๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ
๊ท๋ชจ๊ฐ ํฐ AngularJS ์ ํ๋ฆฌ์ผ์ด์ ์๋ ๋ง์ ์ปดํฌ๋ํธ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ณ์ธต์ ์ผ๋ก ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ก๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฃผ๋ก ๋ ๊ฐ์ง ์ ๊ทผ๋ฒ์ด ์ฌ์ฉ๋ฉ๋๋ค.
- ์ปดํฌ๋ํธ ํ์ ๋ณ๋ก ์์ ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ , ๊ธฐ๋ฅ๋ณ๋ก ํ์ ๋๋ ํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑ.
์ด๋ฌํ ์ ๊ทผ๋ฒ์ ๋ฐ๋ฅด๋ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
.
โโโ app
โ โโโ app.js
โ โโโ controllers
โ โ โโโ page1
โ โ โ โโโ FirstCtrl.js
โ โ โ โโโ SecondCtrl.js
โ โ โโโ page2
โ โ โโโ ThirdCtrl.js
โ โโโ directives
โ โ โโโ page1
โ โ โ โโโ directive1.js
โ โ โโโ page2
โ โ โโโ directive2.js
โ โ โโโ directive3.js
โ โโโ filters
โ โ โโโ page1
โ โ โโโ page2
โ โโโ services
โ โโโ CommonService.js
โ โโโ cache
โ โ โโโ Cache1.js
โ โ โโโ Cache2.js
โ โโโ models
โ โโโ Model1.js
โ โโโ Model2.js
โโโ partials
โโโ lib
โโโ test
- ๊ธฐ๋ฅ ๋ณ๋ก ์์ ๋๋ ํ ๋ฆฌ๋ฅผ ๋๋๊ณ , ์ปดํฌ๋ํธ ํ์ ๋ณ๋ก ํ์ ๋๋ ํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑ.
๋ค์๊ณผ ๊ฐ์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๊ฐ ๋ฉ๋๋ค.
.
โโโ app
โ โโโ app.js
โ โโโ common
โ โ โโโ controllers
โ โ โโโ directives
โ โ โโโ filters
โ โ โโโ services
โ โโโ page1
โ โ โโโ controllers
โ โ โ โโโ FirstCtrl.js
โ โ โ โโโ SecondCtrl.js
โ โ โโโ directives
โ โ โ โโโ directive1.js
โ โ โโโ filters
โ โ โ โโโ filter1.js
โ โ โ โโโ filter2.js
โ โ โโโ services
โ โ โโโ service1.js
โ โ โโโ service2.js
โ โโโ page2
โ โโโ controllers
โ โ โโโ ThirdCtrl.js
โ โโโ directives
โ โ โโโ directive2.js
โ โ โโโ directive3.js
โ โโโ filters
โ โ โโโ filter3.js
โ โโโ services
โ โโโ service3.js
โโโ partials
โโโ lib
โโโ test
- ๋๋ ํ ๋ฆฌ ์ด๋ฆ์ด ์ฌ๋ฌ ๋จ์ด๋ก ์ด๋ฃจ์ด์ ธ ์์ผ๋ฉด, lisp-case๋ฅผ ์ฌ์ฉํฉ๋๋ค.
app
โโโ app.js
โโโ my-complex-module
โโโ controllers
โโโ directives
โโโ filters
โโโ services
- ๋๋ ํฐ๋ธ์ ๊ด๋ จ๋ ๋ชจ๋ ํ์ผ(ํ ํ๋ฆฟ, CSS/SASS ํ์ผ, ์๋ฐ์คํฌ๋ฆฝํธ)์ ํ ํด๋์ ๋ชจ์๋์ธ์. ์ด๋ฐ ์คํ์ผ๋ก ํ๊ธฐ๋ฅผ ๋ง์๋จน์๋ค๋ฉด, ํ๋ก์ ํธ ๋ชจ๋ ๊ณณ์์ ์ด ๊ตฌ์กฐ๋ฅผ ์ผ๊ด์ ์ผ๋ก ์ ์งํ์๊ธฐ ๋ฐ๋๋๋ค.
app
โโโ directives
โโโ directive1
โ โโโ directive1.html
โ โโโ directive1.js
โ โโโ directive1.sass
โโโ directive2
โโโ directive2.html
โโโ directive2.js
โโโ directive2.sass
์ด ๋ฐฉ์์ ์์ ์ ์ํ ๋ ๊ฐ์ง ๋๋ ํ ๋ฆฌ ๊ตฌ์ฑ๋ฒ ๋ชจ๋์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ ๋ ํ ์คํธ ํ์ผ์ ์ปดํฌ๋ํธ์ ๊ฐ์ ๋๋ ํ ๋ฆฌ์ ์์ด์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ปดํฌ๋ํธ๋ฅผ ์์ ํ์ ๋ ํ ์คํธ ํ์ผ์ ์ฐพ๊ธฐ ์ฝ๊ฒ ๋ฉ๋๋ค. ๋ํ, ํ ์คํธ ํ์ผ์ ๊ทธ ์์ฒด๋ก ์ปดํฌ๋ํธ์ ์ฐธ๊ณ ๋ฌธ์๋ ์ฌ์ฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ์ญํ ๋ ํฉ๋๋ค.
services
โโโ cache
โ โโโ cache1.js
โ โโโ cache1.spec.js
โโโ models
โโโ model1.js
โโโ model1.spec.js
app.jsํ์ผ์๋ ๋ผ์ฐํธ ์ ์์ ์ค์ ์ด ํฌํจ๋์ด์ผ ํ๋ฉฐ, ํ์ํ ๊ฒฝ์ฐ ์ด๊ธฐํ ์์ ๋ ํฌํจํฉ๋๋ค.- ํ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ๋จ ํ๋์ ์ปดํฌ๋ํธ๋ง์ ํฌํจํด์ผ ํฉ๋๋ค. ํ์ผ ์ด๋ฆ์ ์ปดํฌ๋ํธ์ ์ด๋ฆ๊ณผ ๊ฐ์ ์์ผ๋ก ์ง์ด์ผ ํฉ๋๋ค.
- Yeoman์ด๋ ng-boilerplate์ ๊ฐ์ Angular ํ๋ก์ ํธ ๊ตฌ์กฐ ํ ํ๋ฆฟ์ ์ฌ์ฉํฉ๋๋ค.
์ปดํฌ๋ํธ์ ๋ช ๋ช ๊ท์น์ ๊ฐ ์ปดํฌ๋ํธ ์ ์์ ์ค๋ช ํฉ๋๋ค.
๋งํฌ์
TLDR; ์คํฌ๋ฆฝํธ ํ์ผ์ html ๋ฌธ์ ํ๋จ์ ๋ฃ์ผ์ธ์.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>MyApp</title>
</head>
<body>
<div ng-app="myApp">
<div ng-view></div>
</div>
<script src="angular.js"></script>
<script src="app.js"></script>
</body>
</html>
AngularJS ๋๋ ํฐ๋ธ๋ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค๊ณ , ํ์ค ์์ฑ(attribute)๋ณด๋ค ๋ค์ ์์น์ํต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๋ฅผ ์ฝ๊ธฐ๊ธฐ ์ฝ๊ณ ์ ์ง ๋ณด์๋ ์ฌ์์ง๋๋ค. ์๋ํ๋ฉด ์ถ๊ฐ์ ์ธ ์์ฑ๋ค์ด ์ผ๊ด๋ ์์น(์ฆ, ๊ฐ์ฅ ๋ง์ง๋ง)์ ๋ชจ์ฌ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
<form class="frm" ng-submit="login.authenticate()">
<div>
<input class="ipt" type="text" placeholder="name" require ng-model="user.name">
</div>
</form>
๋ค๋ฅธ HTML ์์ฑ๋ค์ ์ด ์ฝ๋ ๊ฐ์ด๋์ ์ถ์ฒ ๋ฐฉ๋ฒ์ ๋ฐ๋ฆ ๋๋ค.
๋ช ๋ช ๊ท์น
๋ชจ๋ ์์์ ๋ํ ๋ช ๋ช ๊ท์น์ด ์๋ ํ์ ๋์์์ต๋๋ค.
| ์์ | ๋ช ๋ช ์คํ์ผ | ์์ | ์ฉ๋ฒ |
|---|---|---|---|
| ๋ชจ๋ | lowerCamelCase | angularApp | |
| ์ปจํธ๋กค๋ฌ | Functionality + 'Ctrl' | AdminCtrl | |
| ๋๋ ํฐ๋ธ | lowerCamelCase | userInfo | |
| ํํฐ | lowerCamelCase | userFilter | |
| ์๋น์ค | UpperCamelCase | User | ์์ฑ์ |
| ํฉํ ๋ฆฌ | lowerCamelCase | dataFactory | ๊ธฐํ |
๊ธฐํ
- ๋ค์์ ๊ถ์ฅํฉ๋๋ค.
setTimeout๋์$timeoutsetInterval๋์$intervalwindow๋์$windowdocument๋์$document$.ajax๋์$httpwindow.location๋$window.location๋์$locationdocument.cookie๋์$cookies
์ด๋ ๊ฒ ํ๋ฉด ํ
์คํธ๊ฐ ์ฌ์์ง๊ณ , ์์์น ๋ชปํ ๋์๋ ๋ฐฉ์งํ ์ ์์ต๋๋ค (์๋ฅผ ๋ค๋ฉด setTimeout์์ $scope.$apply๋ฅผ ์๋ ๋ค๋ ๊ฐ).
์๋์ ํด์ ์ฌ์ฉํด ์์ ํ๋ฆ์ ์๋ํํ์ธ์.
์ฝ๋ฐฑ ๋์ ์ promises (
$q)๋ฅผ ์ฌ์ฉํ์ธ์. $q๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๊ฐ ์ฐ์ํ๊ณ ๊น๋ํด์ง๊ณ , ์ฌ๋ฌ๋ถ์ ์ฝ๋ฐฑ ์ง์ฅ์์ ๊ตฌ์ํด์ค ๊ฒ์ ๋๋ค.๊ฐ๋ฅํ
$http๋ณด๋ค๋$resource๋ฅผ ์ฌ์ฉํ์ธ์. ๋์ ์์ค์ ์ถ์ํ๋ ์์ง๊ตฌ๋ ํ ์์ ์ผ๋ก๋ถํฐ ํด๋ฐฉ์์ผ์ค๋๋ค.AngularJS pre-minifier (ng-annotate)๋ฅผ ์ฌ์ฉํด minification ์์ ๋ฌธ์ ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐฉ์งํฉ๋๋ค.
์ ์ญ ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ๋ง์ธ์. ๋ชจ๋ ์์กด์ฑ์ ์์กด์ฑ ์ฃผ์ ์ผ๋ก ํด๊ฒฐํ์๊ธฐ ๋ฐ๋๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ ์คํธ์์ ๋ฐ์ํ๋ ๋ฒ๊ทธ์ monkey patching์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
Grunt๋ Gulp๋ก ๋น์ ์ ์ฝ๋๋ฅผ ์ฆ์์คํํจ์(IIFE)๋ก ๊ฐ์ธ ์ ์ญ ๋ณ์๋ฅผ ์์ ์ฃผ์ธ์. ์ด ๋ชฉ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ํ๋ฌ๊ทธ์ธ์ grunt-wrap๋ gulp-wrap๊ฐ ์์ต๋๋ค. ๋ค์์ Gulp๋ฅผ ์ฌ์ฉํ ์์์ ๋๋ค.
gulp.src("./src/*.js") .pipe(wrap('(function(){\n"use strict";\n<%= contents %>\n})();')) .pipe(gulp.dest("./dist"));$scope๋ฅผ ์ค์ผ์ํค์ง ๋ง์ธ์. ์ค์ง ํ ํ๋ฆฟ์์ ์ฌ์ฉํ๋ ํจ์์ ๋ณ์๋ค๋ง ์ถ๊ฐํ์ธ์.nginit๋์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ์ธ์.ngInit๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ํฉ์ ์์ฃผ ํน์ํ ๊ฒฝ์ฐ ๋ฟ์ ๋๋ค. ์ฆ,ngRepeat์ ํน๋ณํ ํ๋กํผํฐ์ ๋ณ์นญ์ ๋ง๋ค ๋๋, ํน์ ์๋ฒ ์ฌ์ด๋ ์คํฌ๋ฆฝํธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๋ ๊ฒฝ์ฐ๋ฅผ ๋งํฉ๋๋ค. ์ด ๋๊ฐ์ง๊ฐ ์๋ ๋ค๋ฅธ ๋ชจ๋ ์ํฉ์๋,ngInit๋์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. The expression passed tongInitshould go through lexing, parsing and evaluation by the Angular interpreter implemented inside the$parseservice. This leads to:- Performance impact, because the interpreter is implemented in JavaScript
- The caching of the parsed expressions inside the
$parseservice doesn't make a lot of sense in most cases, sincengInitexpressions are often evaluated only once - Is error-prone, since you're writing strings inside your templates, there's no syntax highlighting and further support by your editor
- No run-time errors are thrown
๋ณ์, ํ๋กํผํฐ, ๋ฉ์๋ ์ด๋ฆ์
$์ ๋์ด๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.$๋ก ์์ํ๋ ๋ช ๋ช ๋ฒ์ AngularJS ์์ฒด์์๋ง ์ฌ์ฉํ๋๋ก ์ ํ๋์ด ์์ต๋๋ค.์ ํ๋ฆฌ์ผ์ด์ ๋ด์์
JQUERY๋ฅผ ์ฌ์ฉํ์ง ๋ง์ธ์. ๊ผญ ํ์ํ๋ค๋ฉดangular.elementํจ์๋กJQLite๋ฅผ ์ฌ์ฉํ์๊ธฐ ๋ฐ๋๋๋ค.Angular JS์ ์์กด์ฑ์ฃผ์ (DI) ๋ฉ์ปค๋์ฆ์ผ๋ก ์์กด์ฑ์ ์ฒ๋ฆฌํ ๋์๋, ์์กด์ฑ๋ค์ ์ข ๋ฅ๋ณ๋ก ์ ๋ ฌํ์ธ์. AngularJS ๋ด์ฅ ์์กด์ฑ์ ๊ฐ์ฅ ๋จผ์ , ๊ทธ ๋ค์ ์ปค์คํ ์์กด์ฑ์ ๋์ดํฉ๋๋ค.
module.factory('Service', function ($rootScope, $timeout, MyCustomDependency1, MyCustomDependency2) {
return {
//Something
};
});
๋ชจ๋
๋ชจ๋์ ์ด๋ฆ์ lowerCamelCase๋ก ๋ช ๋ช ๋์ด์ผ ํฉ๋๋ค. ๋ชจ๋
a์ ํ์ ๋ชจ๋b๋ฅผ ๊ฐ๋ฆฌํค๋ ค๋ฉดa.b์ ๊ฐ์ด ๋ค์์คํ์ด์ค๋ฅผ ์ค์ฒฉ์ํฌ ์ ์์ต๋๋ค.์ผ๋ฐ์ ์ผ๋ก ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๋ชจ๋์ ๊ตฌ์กฐํํ ์ ์์ต๋๋ค.
- ๊ธฐ๋ฅ์ ์ผ๋ก
- ์ปดํฌ๋ํธ ํ์ ๋ณ๋ก
๋ ๋ฐฉ๋ฒ์๋ ํฐ ์ฐจ์ด๊ฐ ์์ง๋ง, ์ฒซ ๋ฒ์งธ๊ฐ ์ข ๋ ๋ช ํํฉ๋๋ค. ๋ํ, ๋ชจ๋์ ์ง์ฐ ๋ก๋ฉ(lazy-loading)์ด ์ง์๋๋ค๋ฉด (์์ง AngularJS ๋ก๋๋งต์ ์์ต๋๋ค), ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์ปจํธ๋กค๋ฌ
์ปจํธ๋กค๋ฌ์์ DOM์ ์กฐ์ํ์ง ๋ง์ธ์. ๋ง์ฝ ๊ทธ๋ ๊ฒ ํด๋ฒ๋ฆฌ๋ฉด ์ปจํธ๋กค๋ฌ๋ฅผ ํ ์คํธํ๊ธฐ ์ด๋ ค์์ง๊ณ , ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ ์์น๋ ์๋ฐํ๊ฒ ๋ฉ๋๋ค. ์ปจํธ๋กค๋ฌ ๋์ ๋๋ ํฐ๋ธ๋ฅผ ์ฌ์ฉํ์๊ธฐ ๋ฐ๋๋๋ค.
์ปจํธ๋กค๋ฌ ์ด๋ฆ์ ์ปจํธ๋กค๋ฌ์ ๊ธฐ๋ฅ (์๋ฅผ ๋ค์ด shopping cart, homepage, admin panel)์ ๋ฐ๋ผ ๋ช ๋ช ํด์ผ ํ๋ฉฐ, ์ด๋ฆ์ ๋์๋
Ctrl์ ์ ๋ฏธ์ฌ๋ก ๋ถ์ฌ์ค๋๋ค.์ปจํธ๋กค๋ฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์ฑ์์ด๋ฉฐ, ๋ฐ๋ผ์ UpperCamelCase (
HomePageCtrl,ShoppingCartCtrl,AdminPanelCtrl๋ฑ)๋ก ๋ช ๋ช ๋์ด์ผ ํฉ๋๋ค.์ปจํธ๋กค๋ฌ๋ฅผ ์ ์ญ ๋ณ์๋ก ์ ์ํ์ง ๋ง์ธ์ (๋น๋ก AngularJS๊ฐ ์ง์ํ๊ธด ํ์ง๋ง, ์ ์ญ ๋ค์์คํ์ด์ค๋ฅผ ์ค์ผ์ํค๋ ๋์ ๋ฐฉ์์ ๋๋ค).
์ปจํธ๋กค๋ฌ๋ฅผ ์ ์ํ ๋์๋ ์๋ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ธ์.
function MyCtrl(dependency1, dependency2, ..., dependencyn) { // ... } module.controller('MyCtrl', MyCtrl);minification์์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ํผํ๋ ค๋ฉด, ng-annotate (Grunt์์๋ grunt-ng-annotate) ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์๋์ผ๋ก ๋ฐฐ์ด์ ๋ช ๋ช ๋ฌธ๋ฒ์ ์์ฑ์ํฌ ์ ์์ต๋๋ค.
๋๋, ์ด๋ ๊ฒ
$inject๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค.angular .module("app") .controller("Homepage", Homepage); Homepage.$inject = ["$scope", "ngRoute"]; function Homepage($scope, ngRoute) { // ... }controller as๋ฌธ๋ฒ์ ์ฌ์ฉํ์ธ์.<div ng-controller="MainCtrl as main"> {{ main.title }} </div>app.controller('MainCtrl', MainCtrl); function MainCtrl () { this.title = 'Some title'; }๋ ๋ค๋ฅธ ์ข์ ์์ ์ ๋๋ค.
app.controller('MainCtrl', MainCtrl); function MainCtrl () { var main = this; //๋ทฐ์์ ์ด๋ป๊ฒ ์ ์๋๋์ง ๋ ๋ช ์์ ์ผ๋ก ์ ์ ์์ main.title = 'Some title'; main.description = 'Some description'; }์ด ๋ฌธ๋ฒ์ ์ฌ์ฉํด์ ์๊ธฐ๋ ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- '๋
๋ฆฝ๋' ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ญ๋๋ค. ์ฆ, ํ๋กํผํฐ๋ค์ด
$scopeprototype chain์ ์ผ๋ถ๊ฐ ์๋๋๋ค. ์ด๊ฒ์ ์ข์ ๋ฐฉ์์ธ๋ฐ, ์๋ ํ๋ฉด$scopeprototype ์์์๋ ์ฃผ์ํ ๊ฒฐํจ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค (์๋ง Angular 2์์ ์ค์ฝํ ๊ฐ๋ ์ด ์ ๊ฑฐ๋ ์ด์ ์ด๊ธฐ๋ ํ ๊ฒ์ ๋๋ค).- ๋ฐ์ดํฐ๊ฐ ์ด๋์๋ถํฐ ์ค๋ ๊ฑด์ง ์ถ์ ํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
- ์ค์ฝํ์ ๊ฐ์ ๋ฐ๊พธ๋ ๊ฒ์ด ์๋์น ์๋ ๊ณณ์๋ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค.
- ๋ฆฌํฉํ ๋ง์ด ๋ ์ด๋ ต์ต๋๋ค.
- 'dot rule'.
- (
$scope.$broadcast๊ฐ์) ํน๋ณํ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด$scope๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์์ ํ์ธ์. AngularJS 2๋ฅผ ๋๋นํ๋ ๋ฐ์๋ ๋์์ด ๋ฉ๋๋ค. - ๋ฌธ๋ฒ์ด ์๋ฐ์คํฌ๋ฆฝํธ ์์ฑ์์ ๋ณธ์ง('vanilla')์ ์ถฉ์คํด์ง๋๋ค.
controller as์ ๋ํด ๋ ์์๋ณด๊ธฐ: digging-into-angulars-controller-as-syntax- '๋
๋ฆฝ๋' ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ญ๋๋ค. ์ฆ, ํ๋กํผํฐ๋ค์ด
๋ง์ฝ ๋ฐฐ์ด์ ๋ช ๋ช ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ค๋ฉด, ์์กด์ฑ์ ์๋ ์ด๋ฆ์ ์ฌ์ฉํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๊ฐ ์ฝ๊ธฐ ์ฌ์์ง๋๋ค.
function MyCtrl(s) { // ... } module.controller('MyCtrl', ['$scope', MyCtrl]);which is less readable than:
function MyCtrl($scope) { // ... } module.controller('MyCtrl', ['$scope', MyCtrl]);์ด ๋ฐฉ๋ฒ์ ์คํฌ๋กค์ด ํ์ํ ์ ๋๋ก ์ฝ๋๊ฐ ๊ธธ์ด์ก์ ๋ ํนํ ์ ์ฉํฉ๋๋ค. ๋ง์ฝ ์๋์ ์ด๋ฆ์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ๊ทธ ๋ณ์๊ฐ ์ด๋ค ์์กด์ฑ์ด์๋์ง ๊น๋จน๊ฒ ๋ ๊ฒ์ ๋๋ค.
์ปจํธ๋กค๋ฌ๋ ๊ฐ๋ฅํ ๊ฐ๋ฒผ์์ผ ํฉ๋๋ค. ๊ณตํต์ ์ผ๋ก ์ฌ์ฉ๋๋ ํจ์์ ์๋น์ค๋ก ์ถ์ํํ์ธ์.
์ปจํธ๋กค๋ฌ ๋ด์์ ๋น์ฆ๋์ค ๋ก์ง(business logic)์ ์์ฑํ์ง ๋ง์ธ์. ๋์ ์๋น์ค๋ก ๋ง๋
model์์ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ์ธ์. ์์://๋น์ฆ๋์ค ๋ก์ง์ ์ปจํธ๋กค๋ฌ ์์์ ์ฌ์ฉํ๋, ํํ ํ๋ ์ค์์ ๋๋ค. angular.module('Store', []) .controller('OrderCtrl', function ($scope) { $scope.items = []; $scope.addToOrder = function (item) { $scope.items.push(item);//--> ์ปจํธ๋กค๋ฌ ๋ด์ ๋น์ฆ๋์ค ๋ก์ง }; $scope.removeFromOrder = function (item) { $scope.items.splice($scope.items.indexOf(item), 1); //-->์ปจํธ๋กค๋ฌ ๋ด์ ๋น์ฆ๋์ค ๋ก์ง }; $scope.totalPrice = function () { return $scope.items.reduce(function (memo, item) { return memo + (item.qty * item.price); //-->์ปจํธ๋กค๋ฌ ๋ด์ ๋น์ฆ๋์ค ๋ก์ง }, 0); }; });๋ง์ฝ ๋น์ฆ๋์ค ๋ก์ง์ '๋ชจ๋ธ' ์๋น์ค์ ์์ํ๋ค๋ฉด, ์ปจํธ๋กค๋ฌ๋ ์ด๋ ๊ฒ ๋ฐ๋๊ฒ ๋ฉ๋๋ค (์๋น์ค-๋ชจ๋ธ์ ๊ตฌํ ๋ด์ฉ์ '์๋น์ค๋ก ๋ชจ๋ธ ๊ตฌํํ๊ธฐ'๋ฅผ ๋ณด์ธ์).
//Order๋ '๋ชจ๋ธ'๋ก ์ฌ์ฉ๋์์ angular.module('Store', []) .controller('OrderCtrl', function (Order) { $scope.items = Order.items; $scope.addToOrder = function (item) { Order.addToOrder(item); }; $scope.removeFromOrder = function (item) { Order.removeFromOrder(item); }; $scope.totalPrice = function () { return Order.total(); }; });Why business logic / app state inside controllers is bad?
- Controllers instantiated for each view and dies when the view unloads
- Controllers are not reusable - they are coupled with the view
- Controllers are not meant to be injected
๋ค๋ฅธ ์ปจํธ๋กค๋ฌ์ ํต์ ์ด ํ์ํ ๊ฒฝ์ฐ์๋ method invocation (์์ ์ปจํธ๋กค๋ฌ๋ ๋ถ๋ชจ์ ํต์ ์ด ๊ฐ๋ฅ)์ด๋
$emit,$broadcast,$on๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ธ์. emit์ด๋ broadcast๋ ๋ฉ์ธ์ง๋ ์ต์ํ์ ๋ด์ฉ๋ง ๋ด๊ณ ์์ด์ผ ํฉ๋๋ค.$emit๋$broadcast๋ฅผ ํตํด์ ๋๊ฒจ์ง๋ ๋ชจ๋ ๋ฉ์์ง๋ ์ด๋ฆ ์ถฉ๋์ด๋ ๋ฒ๊ทธ๋ฅผ ์ ๋ฐํ ์ ์๊ธฐ ๋๋ฌธ์, ๋ชฉ๋ก์ ๋ฐ๋ก ์์ฑํด์ ๊ด๋ฆฌํ์ธ์.์์:
// app.js /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Custom events: - 'authorization-message' - description of the message - { user, role, action } - data format - user - a string, which contains the username - role - an ID of the role the user has - action - specific action the user tries to perform * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */๋ฐ์ดํฐ ํํ๋ฅผ ๋ฐ๊ฟ(format) ๋์๋ formatting logic์ ํํฐ๋ก ์บก์ํํ๊ณ ์ด๋ฅผ ์์กด์ฑ์ผ๋ก ์ ์ธํ์ธ์.
function myFormat() { return function () { // ... }; } module.filter('myFormat', myFormat); function MyCtrl($scope, myFormatFilter) { // ... } module.controller('MyCtrl', MyCtrl);In case of nested controllers use "nested scoping" (the
controllerAssyntax):app.js
module.config(function ($routeProvider) { $routeProvider .when('/route', { templateUrl: 'partials/template.html', controller: 'HomeCtrl', controllerAs: 'home' }); });HomeCtrl
function HomeCtrl() { this.bindingValue = 42; }template.html
<div ng-bind="home.bindingValue"></div>
๋๋ ํฐ๋ธ
- ๋๋ ํฐ๋ธ์ ์ด๋ฆ์ lowerCamelCase๋ฅผ ์ฌ์ฉํ์ธ์.
- link ํจ์์์
$scope๊ฐ ์๋scope๋ฅผ ์ฌ์ฉํ์ธ์. complie ์ post/pre link ํจ์๋ค์ ํธ์ถํ ๋ ์ธ์(argument)๋ค์ด ์ด๋ฏธ ์ ์๋ ์ํ๋ก ๋์ด์ค๊ธฐ ๋๋ฌธ์ DI๋ฅผ ์ฌ์ฉํด ์ด๊ฒ๋ค์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ๋ํ $ ์ ๋์ด๋ก ์์ํ๋ ๋ณ์๋ช ์ AngularJS ์์ฒด ์ฝ๋์์๋ง ์ฌ์ฉํ๋ ์คํ์ผ์ ๋๋ค. - ์ฌ๋ฌ๋ถ๋ง์ ์ ์ผํ ์ ๋์ด๋ฅผ ๋ถ์ฌ์ ์ฌ์ฉํ์ธ์. ์ด๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ด๋ฆ์ด ์ถฉ๋ํ๋ ๊ฒ์ ๋ฐฉ์งํด์ค๋๋ค.
- ์ ๋์ด๋ก
ng์ui๋ฅผ ์ฌ์ฉํ์ง ๋ง์ธ์. ์ด ์ ๋์ด๋ AngularJS์ AngularJS UI์์๋ง ์ฌ์ฉํ๋ ์ ๋์ด์ ๋๋ค. - DOM ์กฐ์์ ์ค์ง ๋๋ ํฐ๋ธ๋ฅผ ํตํด์๋ง ํด์ฃผ์ธ์.
- ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ ๋ฆฝ๋ ์ค์ฝํ๋ฅผ ๋ง๋ค์ด์ฃผ์ธ์.
- ๋๋ ํฐ๋ธ๋ ์ฃผ์์ด๋ ํด๋์ค๋ณด๋ค๋ ์์(element)๋ ์์ฑ(attribute) ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ํฅ์๋ฉ๋๋ค.
$scope.$on('$destroy', fn)๋ฅผ ์ฌ์ฉํ์ฌ ๋ท์ ๋ฆฌ๋ฅผ ํด์ฃผ์ธ์. ์ด ๋ฐฉ์์ third-party ํ๋ฌ๊ทธ์ธ์ ๋๋ ํฐ๋ธ๋ก ๊ฐ์ธ์ ์ฌ์ฉํ ๋ ํนํ ์ ์ฉํฉ๋๋ค.- ์ ๋ขฐํ ์ ์๋ ์ปจํ
์ธ (untrusted content)๋ฅผ ๋ค๋ฃฐ ๋๋
$sce๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
ํํฐ
- ํํฐ ์ด๋ฆ์ lowerCamelCase๋ฅผ ์ฌ์ฉํ์ธ์.
- ํํฐ๋ ๊ฐ๋ฅํ ํ ๊ฐ๋ณ๊ฒ ๋ง๋ค์ด์ฃผ์ธ์. ํํฐ๋
$digest๋ฃจํ ์์ ์ข ์ข ํธ์ถ๋๊ธฐ ๋๋ฌธ์ ๋๋ฆฐ ํํฐ ํ๋๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด๋ฅผ ๋๋ฆฌ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. - ํํฐ๋ ํ ๊ฐ์ง ์์ ๋ง ํ๊ฒ ๋ง๋์ธ์. ๋ ๋ณต์กํ ์กฐ์์ ๊ธฐ์กด ํํฐ๋ค์ ์ฐ๊ฒฐ์์ผ์(piping) ํด๊ฒฐํ ์ ์์ต๋๋ค.
์๋น์ค
์ฌ๊ธฐ์๋ AngularJS์ ์๋น์ค ์ปดํฌ๋ํธ์ ๋ํด ๊ธฐ์ ํ๊ณ ์์ต๋๋ค. ๋ช
์์ ์ผ๋ก ์ธ๊ธ๋ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๋ฉด, ์ ์ ๋ฐฉ๋ฒ (provider, .factory, .service)๊ณผ๋ ๋ฌด๊ดํฉ๋๋ค.
์๋น์ค๋ช ์ camelCase๋ CamelCase๋ก ์์ฑํฉ๋๋ค.
- ์์ฑ์ ํจ์์ธ ์๋น์ค์ ์ด๋ฆ์ ๋ค์๊ณผ ๊ฐ์ด UpperCamelCase (PascalCase)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
function MainCtrl($scope, User) { $scope.user = new User('foo', 42); } module.controller('MainCtrl', MainCtrl); function User(name, age) { this.name = name; this.age = age; } module.factory('User', function () { return User; });- ๊ทธ ์ธ์ ์๋น์ค๋ค์ ๋ชจ๋ lowerCamelCase๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ชจ๋ ๋น์ฆ๋์ค ๋ก์ง์ ์๋น์ค๋ก ์บก์ํํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ์๋น์ค๋ฅผ
model๋ก ์ฌ์ฉํ์. ์์://Order๋ '๋ชจ๋ธ'์ angular.module('Store') .factory('Order', function () { var add = function (item) { this.items.push (item); }; var remove = function (item) { if (this.items.indexOf(item) > -1) { this.items.splice(this.items.indexOf(item), 1); } }; var total = function () { return this.items.reduce(function (memo, item) { return memo + (item.qty * item.price); }, 0); }; return { items: [], addToOrder: add, removeFromOrder: remove, totalPrice: total }; });์ด ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ์ปจํธ๋กค๋ฌ์ ์์๋ '์ปจํธ๋กค๋ฌ ๋ด์์ ๋น์ฆ๋์ค ๋ก์ง(business logic)์ ์์ฑํ์ง ๋ง์ธ์'๋ฅผ ๋ณด์ธ์.
Services representing the domain preferably a
serviceinstead of afactory. In this way we can take advantage of the "klassical" inheritance easier:function Human() { //body } Human.prototype.talk = function () { return "I'm talking"; }; function Developer() { //body } Developer.prototype = Object.create(Human.prototype); Developer.prototype.code = function () { return "I'm coding"; }; myModule.service('human', Human); myModule.service('developer', Developer);์ธ์ ๋ ๋ฒจ์ ์บ์๋
$cacheFactory๋ฅผ ์ฌ์ฉํ์ธ์. ์ด๋ ์์ฒญ(request) ๊ฒฐ๊ณผ๋ ๋ฌด๊ฑฐ์ด ์ฐ์ฐ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ ๋ ์ฌ์ฉํฉ๋๋ค.์ค์ (configuration)์ด ํ์ํ ์๋น์ค๋ผ๋ฉด, ์๋น์ค๋ฅผ provider๋ก ์ ์ํ๊ณ
config์ฝ๋ฐฑ์์ ์ค์ ์ ํฉ๋๋ค. ์์:angular.module('demo', []) .config(function ($provide) { $provide.provider('sample', function () { var foo = 42; return { setFoo: function (f) { foo = f; }, $get: function () { return { foo: foo }; } }; }); }); var demo = angular.module('demo'); demo.config(function (sampleProvider) { sampleProvider.setFoo(41); });
ํ ํ๋ฆฟ
- ๋ฌธ์๊ฐ ๊น๋นก์ด๋ ํ์์ ๋ฐฉ์งํ๊ธฐ ์ํด์
{{ }}๋ณด๋ค๋ng-bind๋ng-cloak์ ์ฌ์ฉํ์ธ์. - ํ ํ๋ฆฟ์์ ๋ณต์กํ ํํ์์ ํผํ์ธ์.
- ์ด๋ฏธ์ง์
src์์ฑ์ ๋์ ์ผ๋ก ์ค์ ํด์ผ ํ๋ค๋ฉดsrc์์ฑ์{{ }}ํ ํ๋ฆฟ์ ์ฌ์ฉํ์ง ๋ง๊ณ , ๊ทธ ๋์ng-src๋๋ ํฐ๋ธ๋ฅผ ์ฌ์ฉํ์ธ์. - ์ต์ปค ํ๊ทธ(a)์
href๋ฅผ ๋์ ์ผ๋ก ์ค์ ํ ๋์๋href์{{ }}ํ ํ๋ฆฟ์ ์ฌ์ฉํ๋ ๋์ ์ng-href๋๋ ํฐ๋ธ๋ฅผ ์ฌ์ฉํ์ธ์. - ์ค์ฝํ ๋ณ์๋ฅผ ๋ฌธ์์ด๋ก ๋ง๋ค๊ณ
style์{{ }}๋ก ์ค์ ํ๋ ๊ฒ ๋ณด๋ค๋, ์ค์ฝํ ๋ณ์๋ฅผ ์ค๋ธ์ ํธ๋ก ๋ง๋ค๊ณ 'ng-style` ๋๋ ํฐ๋ธ์์ ์ฌ์ฉํ๋ ๊ฒ ๋ซ์ต๋๋ค.
<script>
...
$scope.divStyle = {
width: 200,
position: 'relative'
};
...
</script>
<div ng-style="divStyle">my beautifully styled div which will work in IE</div>;
๋ผ์ฐํ
- ๋ทฐ๊ฐ ๋ํ๋๊ธฐ ์ ์ ์์กด๊ด๊ณ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค๋ฉด
resolve๋ฅผ ์ฌ์ฉํ์ธ์. - RESTful ์์ฒญ์
resolve์ฝ๋ฐฑ ๋ด์์ ์ง์ ์ฌ์ฉํ์ง ๋ง๊ณ , ์๋น์ค๋ก ๋ถ๋ฆฌํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ์บ์ฑ์ด ๊ฐ๋ฅํด์ง๊ณ , ๋ํ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ ์์น์ ๋ฐ๋ฅด๊ฒ ๋ฉ๋๋ค.
๊ตญ์ ํ
- ํ๋ ์์ํฌ ์ต์ ๋ฒ์ (>=1.4.0)์์๋ ๋ด์ฅ๋ ๊ตญ์ ํ(i18n) ํด์ ์ฌ์ฉํ์ธ์. ๊ตฌ๋ฒ์ (<1.4.0)์์๋
angular-translate๋ฅผ ์ฌ์ฉํ์ธ์.
์ฑ๋ฅ
Digest cycle ์ต์ ํ
- Watch only the most vital variables.
$digest๋ฃจํ๋ฅผ ๋ช ์์ ์ผ๋ก ์คํํ ํ์๊ฐ ์๋ค๋ฉด (๋งค์ฐ ์์ธ์ ์ธ ๊ฒฝ์ฐ์), ๊ผญ ํ์ํ ๊ฒฝ์ฐ์๋ง ํ์ธ์ (์์: ์ค์๊ฐ ํต์ ์ ํ๋ ๊ฒฝ์ฐ, ์์ ๋ ๊ฐ๊ฐ์ ๋ฉ์ธ์ง๊ฐ$digest๋ฃจํ๋ฅผ ์ ๋ฐํด์๋ ์๋ฉ๋๋ค). - ์ด๊ธฐ ์ค์ ๋ ์ดํ ๋ค์๋ ๋ณํ์ง ์๋ ๋ด์ฉ์ผ ๊ฒฝ์ฐ, one-time binding์ ์ฌ์ฉํ์ธ์ (AngularJS >= 1.3.0). AngularJS ๊ตฌ๋ฒ์ ์์๋
bindonce๊ฐ์ single-time watcher๋ฅผ ์ฌ์ฉํ์ธ์. $watch๋ด์ ์ฐ์ฐ์ ๊ฐ๋ฅํ ๊ฐ๋จํ๊ฒ ์์ฑํฉ๋๋ค. ํ๋์$watch์์์ ๋ฌด๊ฒ๊ณ ๋๋ฆฐ ์ฐ์ฐ์ ํ๋ ๊ฒ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด๋ฅผ ๋๋ฆฌ๊ฒ ๋ง๋ค ๊ฒ์ ๋๋ค (์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋๋ก ์๋ํ๋ฏ๋ก$digest๋ฃจํ ์ญ์ ์ฑ๊ธ ์ค๋ ๋๋ก ์๋ํฉ๋๋ค).- Collection์ watchํ ๋์๋, ๊ผญ ํ์ํ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๋ฉด deep watch๋ฅผ ํ์ง ๋ง์ธ์.๊ทธ ๋์ , ์์ ๊ฒ์ฌ(shallow check)๋ฅผ ์ํํ๋
$watchCollection์ ์ฌ์ฉํ์ธ์. (When watching collections, do not watch them deeply when not strongly required. Better use$watchCollection, which performs a shallow check for equality of the result of the watched expression and the previous value of the expression's evaluation.) - (
$timeout์ฌ์ฉ ์) ๋ง์ฝ ์ฝ๋ฐฑ ํจ์์ ์ํฅ์ ๋ฐ๋ ๋ณ์๊ฐ ํ๋๋ ์๋ ๊ฒฝ์ฐ์๋,$timeoutํจ์์ ์ธ ๋ฒ์งธ ํ๋ผ๋ฉํฐ๋ฅผ false๋ก ์ค์ ํด$digest๋ฃจํ๋ฅผ ๊ฑด๋๋ฐ๊ฒ ํฉ๋๋ค. - ๊ฑฐ์ ๋ฐ๋์ง ์๋ ๊ฑฐ๋ํ collection์ ๋ค๋ฃฐ ๋์๋, ๋ถ๋ณ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ์ธ์.
- Watch only the most vital variables.
๋คํธ์ํฌ ์์ฒญ์ ์ค์ด๊ธฐ ์ํด์, ์ฌ๋ฌ html ํ ํ๋ฆฟ ํ์ผ๋ค์ ํ๋๋ก ๋ฌถ๊ณ ๋ฉ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ์บ์ฑํ์ธ์. grunt-html2js๋ gulp-html2js๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค. ์์ธํ ๋ด์ฉ์ ์ฌ๊ธฐ์ ์ฌ๊ธฐ ๋ฅผ ์ฐธ๊ณ ํ์ธ์. ์ด๋ html ํ ํ๋ฆฟ ์กฐ๊ฐ์ด ์์ฃผ ๋ง์ ํ๋ก์ ํธ์์ ์ ์ฉํฉ๋๋ค. ์์ถ๋(minified and gzipped) ๋ฉ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ ํ๋๋ก ํด๊ฒฐํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ธฐ์ฌ
์ด ๋ฌธ์๋ communty-driven์ ์งํฅํ๋ฉฐ, ๋ฌธ์์ ๋ํ ๊ธฐ์ฌ๋ ์ธ์ ๋ ๋ํ์์ ๋๋ค. ๋ถ์กฑํ ๋ถ๋ถ์ ๋ณด์ถฉํด์ฃผ์๊ฑฐ๋ ์ฌ๋ฌ๋ถ์ด ์ฌ์ฉํ๋ ๋ชจ๊ตญ์ด๋ก ๋ฌธ์๋ฅผ ๋ฒ์ญํด์ฃผ์ ๋ ์ข์ต๋๋ค.
๊ธฐ์ฌ์ ๋ช ๋จ
| mgechev | morizotter | pascalockert | chatii2412 | yanivefraim | ericguirbal |
| agnislav | mainyaa | ray7551 | LeonardCModoran | elfinxx | Xuefeng-Zhu |
| SullyP | lukaszklis | giacomocusinato | susieyy | rubystream | jmblog |
| cironunes | guiltry | MertSKaan | mingchen | tornad | cavarzan |
| kuzzmi | cryptojuice | astalker | clbn | atodorov | apetro |
| whoan | valgreens | meetbryce | dwmkerr | dchest | gsamokovarov |
| grvcoelho | yassirh | bargaorobalo | hermankan | jabhishek | jesselpalmer |
| capaj | johnnyghost | jordanyee | nacyot | mariolamacchia | mischkl |
| kirstein | mo-gr | mortonfox | dreame4 | nikshulipa | olov |
| vorktanamobay | sahat | ganchiku | kaneshin | imaimiami | andela-abankole |
| thomastuts | UrielMiranda | VladimirKazan | dooart | grapswiz | coderhaoxin |
| giantray | ntaoo | kuzmeig1 |
๊ด๋ จ ํ๋ก์ ํธ ์ดํด๋ณด๊ธฐ
codecrafters-io/build-your-own-x
์ข์ํ๋ ๊ธฐ์ ์ ์ฒ์๋ถํฐ ๋ค์ ๊ตฌํํ๋ฉฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ง์คํฐํ์ธ์.
560,951 ์คํpublic-apis/public-apis
๋ฌด๋ฃ API๋ฅผ ๋ชจ์ ๋ ๋ชฉ๋ก
497,211 ์คํmorluto/rea
์์ด์ ํธ๋ฅผ ์ฌ์ฉํด ์ฑ ๋์๋ถํฐ ๋ค์ดํฐ๋ธ ๋ฐ์ด๋๋ฆฌ๊น์ง ๋ฌด์์ด๋ ๋ฆฌ๋ฒ์ค ์์ง๋์ด๋งํฉ๋๋ค.
442,709 ์คํopenclaw/openclaw
์ ๋ง๋ก ์ผ์ ํด๋ด๋ AI. ์ด๋ค ์ด์์ฒด์ ์ ํ๋ซํผ์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋์คํฐ ๋ฐฉ์. ๐ฆ
394,183 ์คํ