Logo
Hyunsu Blog
encapsulation

๐Ÿ“†Published :May 20, 2021 โ€ข

๐Ÿ“†Updated :May 20, 2021 โ€ข

โ˜•๏ธ2min

OOP Encapsulation in JavaScript

  • ์ด ํฌ์ŠคํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ฐ์ฒด์ง€ํ–ฅ์„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ์ ์€ ๋…ธํŠธ ์ž…๋‹ˆ๋‹ค. ๋ฐœ์ „ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋  ์ˆ˜ ์žˆ๋„๋ก ์„ค๋ช…์ด ์ž˜๋ชป๋˜์—ˆ๋‹ค๊ฑฐ๋‚˜ ์กฐ๊ธˆ ๋” ๋ณด์ถฉ์„ค๋ช…์ด ํ•„์š”ํ•˜์‹œ๋‹ค๊ณ  ์ƒ๊ฐ๋˜์‹œ๋ฉด ๋Œ“๊ธ€ ๋‚จ๊ฒจ ์ฃผ์„ธ์š”. ์–ธ์ œ๋“ ์ง€ ํ™˜์˜์ž…๋‹ˆ๋‹ค ๐Ÿ˜„

์บก์Šํ™”๋Š” ์œ„ ์ด๋ฏธ์ง€์˜ ์บก์Š๊ณผ ๊ฐ™์ด ํด๋ž˜์Šค ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ์™€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ์ž‘๋™ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋ฒˆ๋“ค๋กœ ๋ฌถ์–ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.์ฆ‰, ํด๋ž˜์Šค ์™ธ๋ถ€์—์„œ ํด๋ž˜์Šค ๋‚ด์— ์žˆ๋Š” ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋งˆ์น˜ ๋‚ด ๊ฐ€๋ฐฉ์€ ์˜ค์ง ๋‚˜๋งŒ ์†๋Œˆ ์ˆ˜ ์žˆ๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์† ๋Œˆ ์ˆ˜ ์—†๋Š” ๊ฑฐ๋‚˜ ๋งˆ์ฐฌ๊ฐ€์ง€ ๋ผ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์•ˆ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์บก์Šํ™” ๊ตฌํ˜„

ํด๋ž˜์Šค ํƒ€์ž… ๊ธฐ๋ฐ˜์˜ ๊ฐ์ฒด ์ง€ํ–ฅ ์–ธ์–ด(์ž๋ฐ”)๋Š”

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.

๋ฐœ์ทŒ : MDN Closures

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๋ฅผ ์ฐธ๊ณ  ํ•˜์„ธ์š”.


์ฐธ๊ณ ์ž๋ฃŒ

Hi, I'm Hyunsu ๐Ÿ‘‹

Profile Image

์•ˆ๋…•ํ•˜์„ธ์š”. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ฃผํ˜„์ˆ˜์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ํ’๋ถ€ํ•˜๊ณ  ๊ฐ€์น˜ ์žˆ๋Š” ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋Š” ์ผ์— ๋ฟŒ๋“ฏํ•จ์„ ๋Š๋‚๋‹ˆ๋‹ค.

์˜ต์‹œ๋””์–ธ(Obsidian)์—์„œ ํ˜„์žฌ ๋ธ”๋กœ๊ทธ๋กœ ํ•˜๋‚˜์”ฉ ๊ธ€์„ ์˜ฎ๊ธฐ๋Š” ๊ณผ์ •์— ์žˆ์–ด์š”. โ˜•๏ธ ๐Ÿ‘ฉโ€๐Ÿ’ป โ›ท

Github on ViewReach Me Out