- ์ด ํฌ์คํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฐ์ฒด์งํฅ์ ๊ณต๋ถํ๋ฉด์ ์ ์ ๋ ธํธ ์ ๋๋ค. ๋ฐ์ ํ๋ ๊ฐ๋ฐ์๊ฐ ๋ ์ ์๋๋ก ์ค๋ช ์ด ์๋ชป๋์๋ค๊ฑฐ๋ ์กฐ๊ธ ๋ ๋ณด์ถฉ์ค๋ช ์ด ํ์ํ์๋ค๊ณ ์๊ฐ๋์๋ฉด ๋๊ธ ๋จ๊ฒจ ์ฃผ์ธ์. ์ธ์ ๋ ์ง ํ์์ ๋๋ค ๐
์บก์ํ๋ ์ ์ด๋ฏธ์ง์ ์บก์๊ณผ ๊ฐ์ด ํด๋์ค ๋ด์์ ๋ฐ์ดํฐ์ ํด๋น ๋ฐ์ดํฐ์ ๋ํด ์๋ํ๋ ๋ฉ์๋๋ฅผ ๋ฒ๋ค๋ก ๋ฌถ์ด ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.์ฆ, ํด๋์ค ์ธ๋ถ์์ ํด๋์ค ๋ด์ ์๋ ๋ฉค๋ฒ ๋ณ์์ ์ ๊ทผ ํ ์ ์์ต๋๋ค. ๋ง์น ๋ด ๊ฐ๋ฐฉ์ ์ค์ง ๋๋ง ์๋ ์ ์๊ณ ๋ค๋ฅธ ์ฌ๋์ด ์ ๋ ์ ์๋ ๊ฑฐ๋ ๋ง์ฐฌ๊ฐ์ง ๋ผ๋ ๋ฉ์ปค๋์ฆ์ ์๊ณ ์์ต๋๋ค.
์บก์ํ ๊ตฌํ
ํด๋์ค ํ์ ๊ธฐ๋ฐ์ ๊ฐ์ฒด ์งํฅ ์ธ์ด(์๋ฐ)๋
1 . private
์ด๋ผ๋ ํค์๋๋ฅผ ํด๋์ค ๋ด๋ถ ์์๋ง ์ธ ์ ์๋ ์์ฃผ privateํ ํด๋์ค ๋ฉค๋ฒ๋ผ๊ณ ๋ช
์์ ์ผ๋ก ๋ํ๋ผ ์ ์์ต๋๋ค.
2 . getter์ setter๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ
ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ES2019(ES10)์ด ๋์ค๊ธฐ ์ ๊น์ง private๋ผ๋ ํค์๋๊ฐ ์ ๊ณต๋์ง ์์ต๋๋ค. ํ์ง๋ง getter/setter,Closures๋ฅผ ์ฌ์ฉํ์ฌ ์๋์ฑ์ ๊ฐ์ง๋ ๋ก์ง์ ๊ตฌํํ ์ ์์์ต๋๋ค.ES2019 (ES10) ์ด ๋์ด์์ผ Private ํ๋๊ฐ ์ ๊ณต๋์ด์ก๊ณ browser compatibility๋ Node.js 12, Chrome 74, and Babel ์ ๋๋ค.
1. getter/setter
getter์ setter๋ฅผ ์ด์ฉํ์ฌ ํน์ ํ๋กํผํฐ์ ์ ๊ทผ์ ๋ฐ๋ก ์ ๊ทผ ํ์ง ์๊ณ ์ฐํ์ ์ผ๋ก getter๊ณผ setter๋ฅผ ์ด์ฉํ์ฌ ์ ๊ทผ ํฉ๋๋ค. ์๋ฒฝํ ์บก์ํ๋ ์๋์ง๋ง ํ๋ก๊ทธ๋จ์ ์์ ์ฑ ๋์์ง๋ ๋ฐฉ๋ฒ์ ๋๋ค.
class User {
constructor(lastName, email) {
this.email = email //์ฌ๊ธฐ์์ this๋ constructor function์ผ๋ก ์์ฑํ ์ ์๋ ํด๋น ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค.
this.lastName = lastName
}
get email() {
return `Email Address is ${this._email}`
}
set email(address) {
if (!address.includes('@')) {
throw new Error(`invalid email: ${address}email should have a @`)
}
this._email = address
}
}
const user2 = new User('user1@gmail.com', 'sue')
console.log((user2.email = 'user2gmail.com')) //๋ฐ๋ก ์ ๊ทผ๊ฐ๋ฅ && ์์ ๊ฐ๋ฅ
console.log(user2)
setter,getter๋ ์ธ๋ถ๋ก๋ถํฐ ์ํ์ง ์๋ ์กฐ๊ฑด์ ๊ฐ์ง ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ฌ ๋ ์ธ๋ถ์๊ฒ ์ํ์ง ์๋ ์ด์ ์ ํจ๊ป ๋ค์ ์ธ๋ถ๋ก ๋๋ ค ๋ณด๋ผ ์ ์๋ ์ญํ ์ ํ๊ฒ ๋ฉ๋๋ค.
User ํด๋์ค๋ฅผ new๋ผ๋ ํค์๋๋ฅผ ์ด์ฉํด ๊ฐ์ฒด๋ฅผ ์์ฑํ์๊ณ user2
๋ผ๋ ์ฐธ์กฐ ๋ณ์์ ํ ๋น๋์์ต๋๋ค. ๋ง์ฝ getter ์ setter๋ฅผ ์ฐ์ง ์์ผ๋ฉด, user.email์ ๋ฐ๋ก ์ง์ ์ ๊ทผ์ด ๊ฐ๋ฅํ์ฌ ์ค์ ์ด๋ฉ์ผ ํ์์ด ์๋ 999-999-9999 ์ ๊ฐ์ ๋ค๋ฅธ ํ์์ ๊ฐ๋ค์ ๋ฃ์ ์ ๋ ์์ต๋๋ค.
์ด๋ฐ ์ํฉ์ ๋ฐฉ์งํ๊ณ ์ set email(address) ์์ ์ธ๋ถ์ ๋ฐ์ดํฐ address๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๊ณ ๋ง์ฝ address์ @๊ฐ ํฌํจ๋์ด์์ง ์๋ค๋ฉด error๋ฅผ @๊ฐ ํฌํจ๋์ด ์์ง ์๋ค๋ผ๋ ์ด์ ์ ํจ๊ป ์ธ๋ถ์ ๋ค์ ๋์ ธ ์ฌ์ฉ์ or ๋ค๋ฅธ ๋๋ฒจ๋กํผ๋ค์ด ์ ์ ์๊ฒ ํด์ค๋๋ค.
์ฌ๊ธฐ์ setter์ getter๋ ์ฌ์ฉ์ ๋๋ ๋ค๋ฅธ ๋๋ฒจ๋กํผ์ ๊ด์ ์์ ์ฌ์ ํ ๊ฐ์ฒด์ ์์ฑ์ ๋ํ ์ ๊ทผ(access)๋ ๊ฐ๋ฅํฉ๋๋ค. user2.email = "aaagmail.com"
ํ์ง๋ง setter ๋ด์ ๋ก์ง์ ์ํด ์กฐ๊ฑด์ด ๋ง์ง ์๋ค๋ฉด ์์ ์ ๋ถ๊ฐ๋ฅ ํฉ๋๋ค. ์ด๋ฐ ๋ฐฉ๋ฒ์ผ๋ก ํ๋ก๊ทธ๋จ์ ์๋๋ ๋ก์ง๊ณผ ๋ง๋ ๋ฐ์ดํฐ ๋ค๋ก๋ง ์บก์ํํ ์ ์์ต๋๋ค.
2. Closures
ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ์๋ฒฝํ๊ฒ ๋ฉค๋ฒ๋ณ์๋ฅผ privateํ๊ฒ ์ธ๋ถ์์ ์ ๊ทผํ์ง ๋ชปํ๊ฒ ํ ์ ์์ต๋๋ค.
ํด๋ก์ ๋ MDN์ ์ํ๋ฉด,
In other words, a closure gives you access to an outer functionโs scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
inner function์์ outer function ์ค์ฝํ์ ์ ๊ทผ๊ฐ๋ฅํ ๊ฒ์ closure๋ผ๊ณ ์ ์ ํ๊ณ ์์ต๋๋ค. ์ด๋ฐ ๊ตฌ์กฐ๋ function ์์ function์ด ์ ์ ๋ ๊ตฌ์กฐ์ ๋๋ค. ๋ฐ๊นฅ์ค์ฝํ์ ์ ๊ทผ ๊ฐ๋ฅ ํ ํด๋ก์ ๋ ์บก์ํ๋ ์ด๋ค ๊ด๊ณ๊ฐ ์์๊น์? ์บก์ํ์ ๊ฐ์ฅ ์๋ฏธ์๋ ๋ชฉ์ ์ธ ์ธ๋ถ์์ ํด๋์ค ๋ด์ ์๋ ๋ฉค๋ฒ ๋ณ์์ ์ ๊ทผ ํ ์ ์๋ ๊ฒ์ ๋ฌ์ฑํ๋๋ฐ ํด๋ก์ ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํด๋ก์ ์ ๊ตฌ์กฐ์ธ ํจ์์์ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
constructor function
function User(email, lastName) {
this.lastName = lastName //public memeber
let _email = email //private member
this.getEmail = function () {
return _email
}
this.setEmail = function () {
_email = email
}
}
const user1 = new User('a@gmail.com', 'sue')
console.log(user1.lastName) //sue public member variable
console.log(user1.getEmail()) //a@gmail.com public member function
console.log(user1._email) // undefined
user1.setEmail('b@gmail.com')
console.log(user1.getEmail()) // b@gmail.com
์ฌ๊ธฐ์ public ๋ฉ์๋์ธ getName(),setName()๊ฐ ํด๋ก์ ์ญํ ์ ํ๊ฒ๋ฉ๋๋ค. getEmail(),setEmail() ์์ _email ์ parameter๋ก ๋ณด๋ด์ง ์์์์๋, ๋ฐ๊นฅ ํจ์์ ์ค์ฝํ์ ์๋ _email์ด๋ ๋ณ์์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์๋ณ์ ํด๊ฒฐ์ ์ํด ๋จ๊ณ์ ์ผ๋ก ์ธ๋ถ์ค์ฝํ๋ฅผ ์ฐธ์กฐํ๋๋ฐ _email๋ณ์๋ฅผ ์ธ๋ถ์ค์ฝํ์์ ์ฐธ์กฐํ ๊ฒ์ ๋๋ค. ๊ทธ๋์ public ๋ฉค๋ฒ ํจ์, ์์ ์ฝ๋ ๋ฒ ์ด์ค์์ getEmail()๊ณผ setEmail()์ด ํด๋ก์ ๊ฐ ๋๋ฉด์ private์ ๋ณ์์ธ _email์ ์ฐธ์กฐํ๊ฒ๋ฉ๋๋ค.
getEmail()๊ณผ setEmail() ํจ์๋ this๊ฐ์ฒด์ ํ๋กํผํฐ๋ก ์ ์ธํ์์ผ๋ฏ๋ก, ์ธ๋ถ์์ new ํค์๋๋ก ์์ฑํ ๊ฐ์ฒด๋ก ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋์ public์ ๊ทผ์ด ๊ฐ๋ฅํ ๊ฒ์ด๊ณ , ๋ฐ๋ฉด _email ๋ณ์๋ฅผ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ก ์ง์ ์ ๊ทผํ๋ ค ํ ๋๋, console.log(user.email)
undefined
๋ฅผ ๋ฆฌํดํ๋ฉฐ ์ธ๋ถ์์ ์ง์ ์ ๊ทผ ํ ์๊ฐ ์์ต๋๋ค. ์ด๋ ๊ฒ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ธ๋ถ์ ์ ๊ทผ์ ์ฐจ๋จํ์ฌ ๋ฉค๋ฒ ๋ณ์์ ์๋์ฑ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
ES06 ์์ Class๋ฅผ ์ฌ์ฉํ ๋ฒ์ ์ ๋๋ค.
class User {
constructor(email, lastName) {
let _email = email
this.lastName = lastName
}
set email(email) {
if (!email.includes('@')) {
throw new Error(`invalid email: ${email}email should have a @`)
}
this._email = email
}
}
const user1 = new User('a@gmail.com', 'sue')
console.log(user1.lastName) //sue public member variable
console.log(user1.email) //a@gmail.com public member function
console.log(user1._email) // undefined
console.log((user1.email = 'b@gmail.com'))
console.log(user1.email) // b@gmail.com
3. private fields
ํด์ฌ(#)๋ฅผ ์ถ๊ฐํด private class ํ๋๋ฅผ ์ ์ธํฉ๋๋ค.
class User {
#lastName = ''
#firstChar = ''
constructor(lastName, email) {
this.#lastName = lastName
this.email = email
}
returnFirstChar() {
return (this.#firstChar = this.#lastName.charAt(0))
}
get nickName() {
return this.returnFirstChar()
}
}
const user = new User('sue', 'user@gmail.com') //์ธ์๋ฅผ ๋ฃ์ง ์์ผ๋ฉด undefined ๋ก ๋ฆฌํดํ๋ค.
console.log(user.email) //user@gmail.com <--public
console.log(user.#lastName) //โ SyntaxError: Private field '#lastName' must be declared in an enclosing class
console.log(user.nickName) //s
console.log((user.#lastName = 'kelly')) //โ SyntaxError
์์ฑ์ (constructor)์์ ๋งค๊ฐ๋ณ์๋ก lastName ์ ๋ฐ์ private ์์ฑ์ผ๋ก ์ง์ ํจ์ผ๋ก์จ ์ธ๋ถ์์ user.#lastName
์ผ๋ก ์ง์ ์ ๊ทผํ๋ฉด ์๋ฌ๋ฅผ ๋ด๋ณด์
๋๋ค. #private
๋ ์์์ ์๊ฐํ ๋ฐฉ๋ฒ๋ค ๋ณด๋ค ์ข ๋ ๋ช
์์ ์ด๋ฉฐ ๋ฉค๋ฒ ๋ณ์์ ๋ํ ์๋ฒฝํ ์๋์ ์คํํ ์ ์๋ ๋ฐฉ๋ฒ์
๋๋ค. private ์ฌ์ฉ๋ฒ์ ๋ํด ์ข ๋ ์๊ณ ์ถ๋ค๋ฉด MDN Private class fields๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ฐธ๊ณ ์๋ฃ
- [๋์ - ์กํ์ฃผ/๊ณ ํ์ค, ์ธ์ฌ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ, ํ๋น ๋ฏธ๋์ด ]
- MDN Closures
- How to create private members in a JavaScript Class
- data-flair.training Java
- mycho๋์ Javascript์ OOP ๋ธ๋ก๊ทธ