Javascript에서 객체(Object)안의 요소를 프로퍼티(property)라고 부릅니다. 그리고 프로퍼티는 두 가지 종류로 나뉩니다. 우리가 흔히 사용하는 데이터 프로퍼티(data property)와 접근자 프로퍼티(access property)입니다. 두 가지의 프로퍼티를 코드로 작성하면 이런 모양이 됩니다.
let obj = {
name: '정약용', // 데이터 프로퍼티
nickname: '다산',
get fullName() {}, // 접근자 프로퍼티, getter, 획득자
set fullName(value) {} // 접근자 프로퍼티, setter, 설정자
}
데이터 프로퍼티는 우리가 흔히 객체의 프로퍼티라고 말하는 그것입니다. Key-Value로 한 쌍을 이루는 모양의 프로퍼티입니다. 접근자 프로퍼티는 뭘까요? 접근자 프로퍼티는 getter(획득자)와 setter(설정자)메서드로 표현됩니다. 각각 객체 안에서 get ~
, set ~
으로 나타낼 수 있습니다. getter 메소드는 객체안의 데이터프로퍼티를 읽으려고 할 때 사용되고, setter 메서드는 데이터 프로퍼티의 값을 변경할 때 사용됩니다.
그럼 어떻게 사용될까요?? 위의 코드를 활용해서 접근자 프로퍼티를 한 번 활용해보겠습니다.
let obj = {
name: '정약용',
nickname: '다산',
get fullName() {
return `${nickname} ${name}`
},
set fullName(value) {
if (typeof value !== 'string') {
console.log('입력한 값이 문자열이 아닙니다.')
return
}
[nickname, name] = value.split(" ")
}
}
// getter 활용
console.log(obj.fullName) // 다산 정약용
// setter 활용
obj.fullName = '율곡 이이'
console.log(obj.name) // 이이
console.log(obj.nickname) // 율곡
console.log(obj.fullName) // 율곡 이이
getter 메서드와 setter 메서드에 알맞은 내용을 넣어보았습니다.
어떤 프로퍼티에 접근할 때마다 그 값을 계산하도록 해야 하거나, 내부 변수의 상태를 명시적인 함수 호출 없이 보여주고 싶을 때, JavaScript의 getter를 이용할 수 있습니다. getter가 바인딩된 프로퍼티는 동시에 실제 값을 가질 수는 없지만, getter와 setter를 동시에 바인딩해 일종의 유사 프로퍼티(pseudo-property)를 만들 수는 있습니다. - MDN
obj 객체 안의 name
과 nickname
을 한 번에 출력하는 코드를 getter 메서드에 넣었고 해당 getter 메서드의 이름인 fullName
을 일반 데이터 프로퍼티처럼 사용하면 그대로 불러올 수 있습니다. 마치 fullName
이라는 키에 '다산 정약용'이라는 값이 있는 것 처럼 말이죠!
자바스크립트에서, setter는 특정한 속성에 값이 변경되어 질 때마다 함수를 실행하는데 사용될 수 있다. Setter는 유사(pseudo)-property 타입을 생성하는 getter와 함께 가장 자주 사용된다. 실제 값을 가지는 property와 이 property의 setter 를 동시에 갖는 것은 불가능하다. - MDN
setter 메서드에는 입력받은 값을 이용해 띄워쓰기로 가공해서 name
과 nickname
을 설정해주는 코드를 집어넣었습니다. 그래서 데이터 프로퍼티의 값을 설정할 때와 같이 값을 설정해 주면 setter 메서드 내부의 파라미터인 value
를 이용해 객체의 데이터 프로퍼티 값을 설정하게 됩니다. 그리고 조건문을 활용해 데이터의 형식을 지정하거나 제한할 수 있습니다! 많이 유용하죠?
그렇다면 왜 사용할까요? 객체지향 프로그래밍(Object-Oriented Programming, OOP)의 4가지 특징을 알고 계신가요? 이중에서 캡슐화를 위해 사용하는 경우가 많습니다. 캡슐화는 다음과 같은 특징을 가지고 있습니다.
캡슐화(영어: encapsulation)는 객체 지향 프로그래밍에서 다음 2가지 측면이 있다: 객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다. - 위키백과
접근자 프로퍼티를 사용하면 사용자에게 데이터 프로퍼티에 대한 접근을 제한하고, 저장하는 값에 대해서 강제할 수 있습니다.
let square = {
get size() {
return this._width * this._height
}
set size(value) {
if (value.width < 0 || value.height < 0) {
console.log('높이와 너비는 음수가 될 수 없습니다.')
return
}
this._width = value.width
this._height = value.height
}
}
square.size = { width: 10, height: 20 }
console.log(square.size) // 200
width
와 height
를 사용할 때 직접 건들이지 않고, size
메서드를 이용해서 간접적으로 접근할 수 있게 합니다. 이렇게 되면 필드를 private으로 설정해 위부의 접근을 제한하고, getter와 setter를 이용해 본 필드의 값을 은닉한 채 내부에서 가공한 값을 사용할 수 있습니다. 물론 square._width
처럼 직접 접근이 가능합니다. 하지만 _
가 붙은 프로퍼티는 외부에서 접근하지 않는 것이 좋습니다!
이렇게 프로그래밍 하는 이유는 객체의 무결성을 보장하기 위해서입니다. size
메서드를 사용하면 _width
와 _height
가 음수가 되는 것을 막을 수 있습니다. square
라는 객체의 무결성을 보장할 수 있습니다. 하지만 square._width
에 -100
을 넣어버리면 객체의 무결성이 깨져버리겠죠?