์น ์๋น์ค์์ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์กด๋๋ ๊ณ์ ์ฆ๊ฐํ๋ ์ถ์ธ๋ค. github์ ๋ฑ๋ก๋ ํ๋ก์ ํธ๋ค(2015๋ ๋ ์กฐ์ฌ ์๋ฃ)๋ง ๋ด๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋น์ค์ด ๊ฐ์ฅ ๋๊ณ , ์ค์ ๋ก ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ๋ค๋ ๋๋ถ๋ถ์ด ๊ทธ๋ด ๊ฒ์ด๋ค.
์ฌ๋ฌ๋ถ์ ํน์ ๋ค์์ ๊ฒฝ์ฐ๋ฅผ ๊ฒช์ง ์์๋๊ฐ?
1. ๋ค๋ฅธ ์ฌ๋์ด ์ด๋ฏธ ๋ง๋ค์ด ๋์ ์ฝ๋๊ฐ ์๋์ง ๋ชจ๋ฅด๊ณ ์ค๋ณต์ผ๋ก ์์
ํ๋ค.
(trim ๋ฑ์ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ค์ ํนํ ๊ทธ๋ฌ๊ธฐ ์ฝ๋ค)
2. ๊ฐ์ ์ฉ๋์ ํ๋ ์์์ ์ฌ๋ฌ๊ฐ ๋๋ ๋ฒ์ ๋ณ๋ก ์ถ๊ฐํ๊ณ , ์ฌ์ง์ด ํ ํ์ด์ง์์ ๊ฐ์ด ์ฌ์ฉํ๋ค.
(jQuery, prototype ...)
3. ์๋ก ๋ฃ์ผ๋ ค๋ ์ฝ๋๊ฐ ๊ธฐ์กด์ ์ฝ๋์ ๊ผฌ์ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
4. ์ ์ง๋ณด์ํ ๋ ์ด๋ฏธ ๊ฐ๋ฐ๋ HTMLํ์ด์ง์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ด๋์๋ถํฐ ์๋์ผ ํ ์ง ๋ชจ๋ฅด๊ฒ ๋ค.
(ํ์ด์ง ์ง์
๊ณผ ๋์์ ์คํ๋๋ ์ฝ๋ ํ์
์ด ์ด๋ ต๋ค)
๋ฌผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ตญํ๋ ๋ฌธ์ ๋ค์ ์๋์ง๋ง, ์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋๋๋ฌ์ง๊ฒ ๋ํ๋๋ ๋ฌธ์ ๋ค์ด๋ค.
์ด๋ฏธ ๊ทธ๋ฌ์ด์ผ ํ์ ์๋ ์๋ค.
์์ ์ ์ธ๋ถ์ ๋
ธ์ถ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๊น๋ํ๊ฒ ์ ๋ฆฌํ๋ ๊ฒ์ด๋ค. ๋ค์ ๋งํด window์ ์๋ฌด๋ ๊ฒ ๋ณ์๋ ํจ์๋ฅผ ์ถ๊ฐํ์ง ๋ง๊ณ ์ด๋ค ์ฝ๋๊ฐ ์ด๋์ ๋ค์ด๊ฐ์ผ ํ ์ง๋ฅผ ๋ช
ํํ๊ฒ ์ ๋ฆฌํด์ ์ธ๋ฐ์๋ ์ค๋ณต์ ํผํ๊ณ ๋ค๋ฅธ ์ฝ๋์ ๊ผฌ์ผ ์ผ์ด ์๋๋ก ์ถ์
๊ตฌ๋ฅผ ํ๋๋ง ๋ง๋๋ ๊ฒ์ด๋ค. (jQuery๋ window.$
์์ ์ฝ๋๋ค์ด ์ ๋ฆฌ๋์ด ์๋ค. ์ฐ๋ฆฌ๋ผ๊ณ ๋ชปํ ๊ฒ ๋ญ ์๊ฒ ๋๊ฐ! ์ ํ ์ด๋ ต์ง ์๋ค)
๋จผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด ์ฝ๋๋ฅผ ์ ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์์๋ณธ๋ค. ์ ๋ฆฌ๋ ์ฝ๋๊ฐ ๊ฐ์ ธ๋ค์ฃผ๋ ์ ์ง๋ณด์์ ํธ์๋ ์ฌ๋ฌ๋ถ์ด ๊ฒช์ด๋ด์ ์ด๋ฏธ ์ ๊ฒ์ด๋ค. (์ ์ด๋ ์์ ๊ฐ์ ๋ฌธ์ ๋ ์๋ฐฉํ ์ ์๋ค) ๊ทธ ํ CodeSnippet์ ์ ํธ๋ฆฌํฐ ๋ฉ์๋ defineNamespace
, defineModule
์ ํตํด ๋ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌํด ๋ณธ๋ค.
์ ์ญ์ ์ค์ผ์ํค๋ ๋ฌธ์ ์ ์ผ๋ก ์ฆ์์คํ ํจ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ์ ์ ๋ํด์๋ ๋ค๋ค ์๊ณ ์์ ๊ฒ์ด๋ค.
<body>
<script>
function login() {
/* ... */
}
</script>
</body>
์์ ์ฝ๋๋ login()
์ผ๋ก ์คํํ ์๋ ์์ง๋ง window.login()
์ผ๋ก๋ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ๋ค๋ฅธ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์ฌ ๋ฌธ์ ๋ฅผ ๋ฐ์์ํฌ ์ ์๋ ์ฌ์ง๊ฐ ์๋ค. (์ด๋ฐ ์ฝ๋๋ฅผ '์ ์ญ์ ์ค์ผ์ํค๋ ์ฝ๋' ๋ผ๊ณ ํ๋ค)
๊ทธ๋์ ์๋์ ๊ฐ์ด ์ฆ์์คํํจ์(IIFE)๋ฅผ ์ฌ์ฉํด ์ ์ญ์ ์ค์ผ์ํค๋ ๊ฒ์ ๋ฐฉ์งํ๋ค.
<body>
<script>
(function() {
function login() {
/* ... */
}
})();
login(); // ReferenceError
</script>
</body>
๋ฌธ์ ๋ login ํจ์๊ฐ ์ต๋ช ํจ์ (์ด๋ฆ ์๋ ํจ์) ๋ด์ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋๋ฌธ์ window
์ ์๋์ผ๋ก ์ธ๋ถ์์ ์ ๊ทผ ๊ฐ๋ฅํด์ผ ํ๋๊ฒ๋ค์ ์ถ๊ฐํด์ผ ํ๋ค. window์ ํ๋ก์ ํธ๋ช
์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ์ฌ๊ธฐ์ ์ ๋ฆฌํ๊ธฐ๋ก ํ๋ค.
<body>
<script>
(function(w) {
function login() {
/* ... */
}
w.myProject = {
login: login
};
})(window);
w.myProject.login(); // OK
</script>
</body>
login์ด๋ ๋ฉ์๋๊ฐ window.myProject
๋ผ๋ ๊ฐ์ฒด์ ํฌํจ๋์๋ค. ํ์ง๋ง ๋ถํธํ ์ ์ด ์๋ค. namespace ๊ฐ ์ฌ๋ฌ depth๋ฅผ ์ด๋ฃจ๊ณ ์์ ํ
๋ฐ ์ต๋ช
ํจ์ ๋ด์์ ์์ธ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ๋ค. ์๋ฅผ ๋ค๋ฉด myProject.common
์ ๋ง๋ค ๋ myProject
๊ฐ์ฒด๊ฐ ์๋์ง ๋ง์ด๋ค.
<body>
<script>
(function(w) {
function saveData() {
/* ... */
}
// myProject ๊ฐ ์๋์ง?
if (w.myProject) {
// myProject.user ๊ฐ ์๋์ง?
if (w.myProject.user) {
w.myProject.user.saveData = saveData;
} else {
w.myProject.user = {
saveData: saveData
};
}
}
})(window);
w.myProject.user.saveData();
</script>
</body>
CodeSnippet์ defindNamespace
๋ window์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ธฐ๋ฅ๋ค์ ์ฝ๊ฒ ์ฒด๊ณ์ ์ผ๋ก ๊ตฌ์กฐํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ์ด๋ฆ ๊ทธ๋๋ก Namespace๋ฅผ ์ ์ํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ค.
์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ์ด์ผ๊ธฐํ๋ ๋ถํธํ ๋ฌธ์ ์์ด ๊ณํ์ ์ผ๋ก ๊ธฐ๋ฅ๋ค์ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์๋ค.
<body>
<script>
var common = tui.util.defineNamespace("ne.myNote.common", {
trim: function() {
/* ... */
}
});
tui.util.defineNamespace("ne.myNote", {
login: function() {
/* ... */
}
});
ne.myNote.login();
ne.myNode.common.trim("test");
common.trim("test"); // ๋ณ์์ ํ ๋นํด ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค
</script>
</body>
ne.myNote
์ ne.myNote.common
๋ค์์คํ์ด์ค๋ฅผ ์ ์ํ๋ค. (์ฌ์ค ne.
๋ก ์์ํ๋ namespace๋ ์ฌ๋ด ํ์ค ๊ฐ์ด๋๋ค.) ์ฌ์ง์ด ne.myNote.common
์ ๋จผ์ ์ ์ธํ๋๋ผ๋ ๋ฌธ์ ์์ด ๋์ํ๋ค.
defineNamspace
๋ฅผ ์ฌ์ฉํด ์๋ฐ์คํฌ๋ฆฝํธ ๋ฉ์๋๋ค์ ๊ตฌ์กฐ์ ์ผ๋ก ๋
ธ์ถ์ํค๋ ๊ฒ๋ง์ผ๋ก๋ ๊ต์ฅํ ๊น๋ํ ์ฐ์ถ๋ฌผ์ ๋ง๋ค์ด ๋ผ ์ ์๋ค.
ํน์ ์ฌ๊ธฐ์ ๋ ๋์๊ฐ ์คํฌ๋ฆฝํธ๊ฐ ๋ก๋๋๋ ์์ ์ ์ด๊ธฐํ ๋ฉ์๋๋ฅผ ์คํํ๊ณ ์ถ๋ค๋ฉด defineModule
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
<body>
<script>
tui.util.defineModule("ne.myNote.settings", {
memberID: "<%= memberID %>",
initialize: function() {
// ํ์ด์ง ๋ก๋ฉ๊ณผ ๋์์ ๋น๋๊ธฐ ํต์ ์ ํด์ผ ํจ (์๋์คํ)
$.ajax(/* ... */);
}
});
ne.myNote.settings.memberID; // ์ฌ์ฉ์ ID
</script>
</body>
defineNamespace
์ defineModule
์ ์ฐจ์ด๋ ํ์ด์ง ๋ก๋ฉ ์์ ์ initialize
๋ผ๋ ์ด๋ฆ์ ๋ฉ์๋ ์คํ ์ฌ๋ถ ๋ฟ์ด๋ค.
defineModule
์ ํ ํ์ด์ง ๋จ์์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ง๋๋ ๋ฐ ์ธ ์ ์๋ค. initialize
์์ ํ์ด์ง ๋ก๋ฉ๊ณผ ํจ๊ป ์คํ๋์ด์ผ ํ๋ ๊ตฌํ์ ํ๋ ํํ๋ก ์ฌ์ฉํ ์ ์๋ค. (์ค๋ฌด ์์ ์์ ๋ค๋ฃฌ๋ค)
์ฌ๊ธฐ๊น์ง๋ง ํด๋ ์ถฉ๋ถํ์ง๋ง. ํน์, ๋ง์ฝ, ํด๋์ค ์๋ฎฌ๋ ์ด์
์ด ํ์ํ๋ค๋ฉด defineClass
๋ฅผ ์ฌ์ฉํ ์ ์๋ค. defineClass
๋ ๊ฒฐ๊ณผ๊ฐ ์์ฑ์ ํจ์์ด๋ฏ๋ก, ์ธ์คํด์คํ ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
<body>
<script>
var Comment = tui.util.defineClass({
init: function(content) {
this.content = content;
this.like = 0;
},
likeIt: function() {
this.like += 1;
}
});
var comment1 = new Comment("I like it!");
var comment2 = new Comment("I hate it!");
</script>
</body>
defineClass
๋ ๋ด๋ถ์ ์ผ๋ก prototype ํจํด์ ์ด์ฉํด ํด๋์ค๋ฅผ ์๋ฎฌ๋ ์ดํ
ํ๋ค. ๋ฐ๋ผ์ ํ๋กํผํฐ๋ ์ธ์คํด์ค์, ๋ฉ์๋๋ prototype๊ฐ์ฒด์ ์ถ๊ฐํ๋ฏ๋ก ๋ธ๋ผ์ฐ์ ๊ธฐ๋ฐ์ ํ์ ์ ์ธ ์์์์ ๋์ํ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ค๋ฃฐ ์ ์๋๋ก ํด ์ค๋ค. ๋ฌผ๋ก ์์๋ ๊ฐ๋ฅํ๋ค.
<body>
<script>
var PhotoComment = tui.util.defineClass(Comment, {
init: function(content) {
Comment.call(this, content);
this.photoUrl = ""; // Commentํด๋์ค์ photoUrl ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ค
}
});
var comment1 = new PhotoComment("I like it!");
</script>
</body>
๋ก๊ทธ์ธ ํ์ด์ง์์ ์ฌ์ฉํ ๋ชจ๋์ ๋ง๋ค์ด ๋ณด์. ์ถ๊ฐ์ ์ผ๋ก email ์ trim์ ์ ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ๋ฅผ ๊ฐ์ ํ๋ค.
// util.js
tui.util.defineNamespace("ne.myNote.util", {
trim: function(str) {
if (str.trim) {
return str.trim();
}
return str.replace(/^[\s]+|[\s]+$/g, "");
},
getElement: function(selector) {
return document.querySelector(selector);
}
});
util.js๋ ํ๋ก์ ํธ ์ ์ฒด์์ ์ฌ์ฉํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ฅผ ๋ชจ์ ๋ชจ๋์ด๋ค. getElement๋ jQuery์ $()์ ๊ฐ์ ๊ฒ์ด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
<body>
<form>
<input type="text" name="email" placeholder="Enter email address" />
<input type="password" name="password" placeholder="Enter password" />
<input type="submit" value="login" />
</form>
<script src="./util.js"></script>
<!-- ne.myNote.util -->
<script>
tui.util.defineModule("ne.myNote.page.login", {
$email: ne.myNote.util.getElement("input[name=email]"),
$form: ne.myNote.util.getElement("form"),
initialize: function() {
this.$form.addEventListener("submit", this.onSubmit.bind(this));
},
onSubmit: function(e) {
this.$email.value = ne.myNote.util.trim(this.$email.value);
}
});
</script>
</body>
๊ฐ ํ์ด์ง์์ ์ฌ์ฉํ๋ ์๋ฆฌ๋จผํธ์ ๋ํด ๋ชจ๋์ ํ๋กํผํฐ๋ก ์ ์ํ๋ค ($email, $form) ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์ฌ์ฉํ๋ ํ์ด์ง ๋ด ์๋ฆฌ๋จผํธ๋ฅผ ํ๋์ ๋ณผ ์ ์์ด ๊ด๋ฆฌํ๊ธฐ ์ฉ์ดํด์ก๋ค.
initialize
์์ ํ์ด์ง ์ด๊ธฐ์ ์คํ๋์ด์ผํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๊ตฌํํ๋ค. ์ด์ ํ์ด์ง ์ ์ฒดํ์ผ์ ํ์ง ์์๋ ๋ก๋ฉ ์์ ์ ์คํฌ๋ฆฝํธ๋ฅผ ๊ด๋ฆฌํ ์ ์๊ฒ ๋์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ฌธ์์ ๋ฐ์ธ๋ฉํ๋ ํผ ์๋ฆฌ๋จผํธ ์ด๋ฒคํธ๋ฅผ onSubmit
์ ์ค์ ํ๋ค. ์ด์ ๊ฐ์ด ์ด๋ฒคํธ ๋ฉ์๋์ ์ปจ๋ฒค์
์ ์ ์ํ ๊ฒฝ์ฐ ํ์ด์ง ๋ด์์ ์ด๋ค ์ด๋ฒคํธ๋ฅผ ๊ตฌํํ๋์ง ์ฝ๊ฒ ์์๋ณผ ์ ์๋ค.
CodeSnippet์ defineNamespace
, defineModule
, defineClass
๋ฅผ ์ฌ์ฉํ๋ฉด ์๋น์ค์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ฝ๊ฒ ๊ณํ์ ์ผ๋ก ๊ตฌ์กฐํํ ์ ์๋ค.
defineNamespace
: ์์ธ์ฒ๋ฆฌ ์์ด window์ ๊ฐ์ฒด ํํ์ ๋ค์์คํ์ด์ค๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ค.defineModule
: ํ์ด์ง ๋ก๋ ์์ ์ initialize
๋ฉ์๋๋ฅผ ์คํํ๋๊ฒ ๋นผ๊ณ defineNamespace
์ ๊ฐ๋คdefineClass
: ํด๋์ค ์๋ฎฌ๋ ์ดํ
์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ค.์๋น์ค ๊ฐ๋ฐ ์ด๊ธฐ์ namespace ๋ชฉ๋ก๊ณผ ๊ทธ ์ฉ๋๋ฅผ ์ ๋ฆฌํด ๊ณต์ ํ๋ค๋ฉด ์ด๋ฏธ ์๋ ๋ก์ง์ ์ค๋ณต์ผ๋ก ์ถ๊ฐํ๋ค๊ฑฐ๋, ๊ฐ์ ๊ธฐ๋ฅ์ ํ๋ ๋ค๋ฅธ ๋ฒค๋์ ํ๋ ์์์ ์ค๋ณต์ผ๋ก ์ถ๊ฐํ๋ค๊ฑฐ๋ ํ๋ ๋ถ์์ฌ๋ฅผ ์๋ฐฉํ ์ ์๋ค (jQuery์ prototype ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํํ์ด์ง์ ๊ฐ์ด ์ฐ๋ ํ๋ก์ ํธ๊ฐ ์์ง ๋ง๋ค...)
CodeSnippet์ ์ด ์ธ์๋ ์ฌ๋ฌ ์ ์ฉํ ๊ธฐ๋ฅ์ด ์๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ชจํธํ ํ์
์ฒดํน์ ํํผํ ์ ์๋ ์ ํธ๋ฆฌํฐ ๋ฉ์๋ ๋ถํฐ, ์ฌ์ฉํ๊ธฐ ๋ถํธํ๋ window.open
์ ํตํ ํ์
์ ์ฝ๊ฒ ์ฌ์ฉํ๊ณ ๊ด๋ฆฌํ ์ ์๋ ๋ฉ์๋๊น์ง ๋ง์ด๋ค. ๊ธฐ๋ฅ ๋ชฉ๋ก์ CodeSnippet Github Repository์์ ํ์ธํ ์ ์๋ค.
๋์ผ๋ก ์คํฌ๋ฆฝํธ์ ์ ์ฒด ์ฉ๋์ 23KB์ด๋ฉฐ GZIP ์์ถ ํ ์ฝ 6.94KB์ด๋ฏ๋ก ๋ถ๋ด์๋ ํฌ๊ธฐ์ด๋ค. ๋ ์ํ๋ ๊ธฐ๋ฅ์ ํ์ผ๋ง ๊ฐ๋ณ๋ก ์ฌ์ฉํ ์๋ ์๋ค. ์ฌ์ฉ ์ค ๋ฐ์ํ๋ ๋ฌธ์ ์ ๋ํด github์ด๋ dl_javascript@nhn.com์ผ๋ก ๋ฆฌํฌํ ํ๋ฉด ํฐ ์ด์๊ฐ ์๋ ํ ์ฆ๊ฐ ํผ๋๋ฐฑ์ ๋ฐ์ ์ ์๋ค.