Front_End [JS기반]/자바스크립트

[ 3D Web : Front_JavaScript ] 자스 핵심 개념 - Getter & Setter 정리.

안다미로 : Web3 & D.S 2024. 11. 3. 21:46

 

 

 

 

 

 

[ 3D Web : Front_JavaScript ] 자스 핵심 개념 - Getter & Setter 정리.

 

 


 

∇ 자바스크립트에서의 Getter & Setter

목   차

1. 코딩에서 Getter & Setter 개념
2. JS에서 Getter & Setter
    2-1 접근자 프로퍼티
    2-2 Getter & Setter 주의점
    2-3 Object.defineProperty

 

 

1. 코딩에서 Getter & Setter 개념


        ☆ " Getter 와  Setter " 는 '객체지향프로그램(OOP)'에서 사용되는 개념이며, 일종의 메서드라고 할 수 있습니다.

 

                 ◎ 단어 그대로,

                          " Getter"는 속성(Property) 값을 반환하는 메서드이며,

                          " Setter"는 객체의 속성 값을 설정 & 변경하는 메서드. !

 

                  ex) 'user'라는 객체가 있을 경우,

 

                            - 보통이라면 user.name 으로 속성(프로퍼티)으로 바로 접근해서 값을 가져오거나 재설정할텐데

const user = {
	name: '안다미로',
    age: 30
}

console.log(user.name); // 안다미로

user.name = 'Andamiro';

 

 

               위의 코드처럼 바로 속성에 접근하지 말고, 

 

           ★    " getName()",  "setName()" 메서드를 통해

                    한번 경유해서 설정하도록 하는 기법이 Getter와 Setter 개념이라고 보면 됩니다.

const user = {
	name: '안다미로',
    age: 30,
    
    // 객체의 메서드(함수)
    getName() {
    	return user.name;
    },
    setName(value) {
    	user.name = value;
    }
}

console.log(user.getName()); // 안다미로

user.setName('Andamiro');

 

 


         § Getter & Setter 활용하기.


             ☆  굳이 번거롭게 Getter와 Setter를 만들어서 경유해서 접근하는 이유는 무엇일까요??

 

                   A. Getter & Setter를 사용하면  객체 내부 프로퍼티(속성)에 직접 접근하지 않기 때문에

                       객체의 '정보 은닉'을 가능하게 해주어 보안을 강화 할 수 있고, 코드의 안전성과 유지보수성을 높일 수 있음!

 

                   B. 속성에 옳지 못한 값을 넣으려고 할 때 미연에 방지 가능. ( if문을 함께 활용 )

 

 

                         ex) 위에 코드에 나이값을 1000이라는 말도 안되는 숫자를 넣으려고 하는 것을 막으려고 한다면

                                   Setter 메서드를 통해서 값 입력을 한번 경유하도록 설정해서  

                                   메서드 내에서 if문을 통해서 필터링합니다.

 

const user = {
	name: '안다미로',
    age: 30,
    
    getAge() {
    	return user.age;
    },
    setAge(value) {
    	// 만일 나이 값이 100 초과일 경우 바로 함수를 리턴해서 user.name이 재설정되지 않도록 필터링
    	if(value > 100) {
        	console.error('나이는 100을 초과할 수 없습니다.')
            return;
        }
        	
    	user.name = value;
    }
}

user.setAge(1000); // 나이는 100을 초과할 수 없습니다.

 

 


2. JS에서 Getter & Setter


       - Getter와 Setter는 이론적인 개념으로만 보면

         보통 위의 코드들처럼  " get프로퍼티명() " ,  " set프로퍼티명() " 형식으로 메스드 이름을 짓는 식으로 사용하지만

 

         ○ ES6로 들어서면서,  JS에 Getter와 Setter를 간단하게 정의할 수 있는 문법이 별도로 추가되었습니다.

            - > 객체 리터럴 안에서 속성 이름 앞에   " get " 또는 " set " 키워드만 붙여서

                   Getter와 Setter를 정의 가능해졌습니다.

                   [ 코드 간결성 & 가독성 증가 ]

const user = {
	name: '안다미로',
    age: 30,
    
    // userName() 메서드 왼쪽에 get, set 키워드만 붙이면 알아서 Getter, Setter 로서 동작된다
    get userName() {
    	return user.name;
    },
    set userName(value) {
    	user.name = value;
    }
}

 

   ★   이때의 Getter와 Setter는  함수 호출 형식이 아닌, ' 일반 프로퍼티(속성) ' 처럼 사용 됩니다. 

 

                getter와 setter 메서드를 구현하면, 객체엔 userName이라는 가상의 프로퍼티(속성)이 생기는데

                  이 가상의 프로퍼티는 읽고 쓸수는 있지만 실제로는 존재하지 않는 프로퍼티입니다.

 

 

 

           


               ∇ 접근자 프로퍼티

                        - JS 상 '객체의 프로퍼티'는 크게 2가지 종류로 나룰 수 있습니다. 

 

                                  ① 데이터 프로퍼티 ( data property )

                                         = > 객체 내부에 저장된 실제 데이터 값.

                                            == 우리가 일반적으로 '프로퍼티'라고 부르는 대상.

 

                                  ② 접근자 프로퍼티 ( accessor property )

                                        = > 일반적인 프로퍼티와 달리, 키(key)와 값(value)을 가지지 않고

                                                  getter와 setter라는 함수를 가지는 특수한 프로퍼티.

 

                           ==>  ◎ 자바스크립트 객체 속성에 접근하듯이 접근자 프로퍼티를 호출하면,

                                           함수 호출 문법이 아니더라도  getter & setter 함수가 호출되는 것과 동일.

 

                           ☆정리하자면,  Getter & Setter 함수 자체가 접근자 프로퍼티

let person = {
  /* 데이터 프로퍼티 */
  firstName: "John",
  lastName: "Doe",
  
  /* 접근자 프로퍼티 */
  get fullName() {
    return this.firstName + " " + this.lastName;
  },
  set fullName(name) {
    let names = name.split(" ");
    this.firstName = names[0];
    this.lastName = names[1];
  }
};

console.log(person.firstName); // "Jane" 출력
console.log(person.lastName); // "Doe" 출력

console.log(person.fullName); // "John Doe" 출력
person.fullName = "Jane Doe"; // Setter 호출

 

 


               ∇ Getter & Setter 주의점.

 

                       ◇ Getter만 선언할 시.

 

                                    - Getter만 선언하고 Setter를 선언하지 않는다면,

                                           아래 코드처럼, 값을 할당하려고 하면 에러가 발생하게 됩니다.

 

let user = {
  get fullName() {
    return `...`;
  }
};

user.fullName = "Test"; // Error (프로퍼티에 getter 메서드만 있어서 에러가 발생합니다.)

 

 

                       ◇ Setter 무한 루프.

 

                                - 데이터 프로퍼티명과 접근자 프로퍼티명이 동일할 경우,

                                   Setter의 무한 루프에 빠져버리게 됩니다.

 

                               - 절대로, 접근자 프로퍼티의 이름을 중복되게 하면 안됩니다.

let user = {
	name : 'inpa',
    
    get name() {
    	return user.name;	
    },
    
    set name(value) {
    	user.name = value;
    }
}

// user 객체의 name 프로퍼티 값을 변경
user.name = 'inpa2';

 

           -> 무한 루프의 발생 원인은   setter가 자기 자신을 계속해서 호출하기 때문입니다.

 

코드에서 person.name 에 값을 할당할때 setter 함수가 호출되게 됩니다.

 

그런데 setter 함수 내에서 this.name = value 를 통해 자기 자신에 값을 할당하고 있습니다.

 

 

이 행위는 곧,  자기 자신인 setter 접근자 프로퍼티 호출과 같은 행위이고

결국은 이 재귀 행위가 무한적으로 반복되어 무한 루프가 일어나는 것

 

 

  이를 방지하고 싶다면,

                                   -  접근자 프로퍼티명과 데이터 프로퍼티명을 다르게 하거나,

                                   -  내부적으로 다른 변수에 값을 저장하도록 하면 됩니다.

 

const person = {
  _name: "Inpa", // 데이터 프로퍼티명을 _name으로 변경
  set name (value) {
    this._name = value; // _name에 값을 할당
  }
};

person.name = "Inpa2";

 

 


               ∇ Object.defineProperty

ES6가 나오기전 ES5에서는 Getter와 Setter를 구현하기 위해 Object.defineProperty() 메서드를 사용했었습니다.

 

Object.defineProperty()는 객체의 속성을 정의하고 수정하는 메서드로,

프로토타입 체인을 이용한 상속과 같이 고급 기능을 구현할 때 유용하게 사용될 수 있습니다.

 

하지만 코드의 가독성이 떨어지고 디버깅이 어려워질 수 있으므로,

실무 프로젝트에서 사용 빈도가 감소하고 있는 편입니다.

 

let person = {
  firstName: "John",
  lastName: "Doe"
};

// person 객체에 fullName 속성 추가
Object.defineProperty(person, "fullName", {
  // getter 함수 정의
  get: function() {
    return this.firstName + " " + this.lastName;
  },
  // setter 함수 정의
  set: function(name) {
    let names = name.split(" ");
    this.firstName = names[0];
    this.lastName = names[1];
  }
});

// fullName 속성에 접근하여 getter 함수 호출
console.log(person.fullName); // "John Doe" 출력

// fullName 속성에 접근하여 setter 함수 호출
person.fullName = "Jane Doe";

// firstName 속성과 lastName 속성이 setter 함수에 의해 업데이트되었는지 확인
console.log(person.firstName); // "Jane" 출력
console.log(person.lastName); // "Doe" 출력

// fullName 속성에 접근하여 getter 함수 호출
console.log(person.fullName); // "Jane Doe" 출력