일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- PathVariable
- passwordencoder
- git revase
- localStorage
- springboot
- 부적합한열
- HTML
- assertequals
- Thymeleaf
- 이딴게개발자
- SQL
- content-box
- useContext
- JDBC
- WHEREIN
- BCryptPasswordEncoder
- git amend
- MVC
- ResultType
- 배열
- JavaScript
- Spring
- git
- Variabla
- oracle
- CRUD
- mybatis
- git reset
- Java
- react
- Today
- Total
개발새발
[Java] Getter & Setter란 무엇인가? 본문
안녕 님두락!!
(0명)
오늘의 글은 Getter와 Setter에 대해 다뤄보려고 합니다.
배울때부터 아리송했으며, 필요성을 느끼지 못하던 찰나.. 쏟아지는 private 변수 선언에 정신이 아득해져서
이대로면 답이 없겠다싶어 정리하는 차원에서 쓰게 됐습니다.
그나저나 상당히 대학교 교양수업같은 제목이군요. '~란 무엇인가'라니..
이렇게 말하니까 불현듯 떠오르는 추억이 하나 있네요.
안 궁금하신 분들은 그냥 넘어가도 지장 1도 없음
재학생 시절 '무엇인가' 한 과목은 꼭 들어야 졸업이 가능하다고해서
매학기 수강신청 시즌마다 강의목록을 보는데 진짜 다들 너무 재미가 없어보이지 뭡니까.
'우주란 무엇인가', '철학인가 무엇인가', '수학이란 무엇인가'....어쩌구부터해서 '컴퓨터란 무엇인가'까지..
그때 이걸 들었어야했는데
암튼 너무 듣기 싫어보이는 과목들만 한가득이라 4학년까지 안듣고 뻐팅기다가..
졸업을 하지 못할 위기에 처했는데 아니 이게 무슨 일이랍니까.
돌연 학교에서 무엇인가 과목 필수 이수 제도를 폐지한다는 공고가 내려왔지 뭡니까!!
심지어 신입생 한정도 아니고 기존 재학생에까지 소급 적용이라니 역시 존버는 성공합니다.
그래서 저는 무엇인가 과목을 단 한 개도 듣지 않고 스껄하게 졸업을 했고,
저학년 때 미리 들어놓은 동기들은 억울함을 토로하는 그런.. 기현상이 일어났더랬죠.
그러니까 여러분도 미룰 수 있을만큼 미루는 것도 나쁘지 않은 듯합니다.
서론이 넘 길었죠
그럼 드디어 본론으로 레지고~
1. Getter 와 Setter
객체지향 프로그래밍(Object Oriented Programming)의 중요한 개념 중 하나로,
클래스의 멤버 변수에 접근하고 값을 설정하는 메서드
객체의 상태를 보호하고, 객체간의 데이터를 안전하게 전달하는 역할을 한다
그냥 읽어만보았을 때는 이게 뭔데?싶겠지만 아무튼 메서드랍니다.
이것만 염두에 두어도 이해하는데 크게 어렵지 않을 듯합니다.
암튼 Getter 와 Setter, 각 역할에 대해 나눠서 좀 더 설명을 하자면
1) Getter
- 객체의 필드(멤버변수)값을 반환하는 역할
- 필드의 값을 가져와서 외부에서 읽게 해줌
- 메서드의 이름은 get으로 시작하고 필드의 이름과 유사하게 사용하는 것이 일반적
- 매개변수 필요 X
2) Setter
- 객체의 필드 값을 설정하거나 변경하는 역할
- 필드 값을 변경하려면 Setter 메서드를 호출하여 값을 설정
- 메서드의 이름은 set으로 시작하고 필드의 이름과 유사한 이름을 사용하는 것이 일반적
- Setter 일반적으로 매개변수를 받아 필드의 값을 설정
Getter와 Setter 메서드의 경우, 직접 타이핑해서 설정할 수도 있지만 Java에서는 클래스에 생성된 멤버변수 대상으로 한 번에 생성해주는 편리한 기능을 제공하고있습니다.
멤버변수가 존재하는 클래스 페이지에서 마우스 우클릭 > Source 선택 > Generate Getters and Setters
> 메서드 생성을 원하는 멤버변수 선택 > Generate
위 순서를 따라하면 자동 생성이 됩니다.
직접 타이핑을 하든, 자동 생성을 하든 예시를 들어볼까요
package com.kh.gettersetterPokemon;
public class Pokemon {
//멤버변수(필드)
private String pokemonName; //포켓몬 이름
private int pokedexNum; //포켓몬 도감번호
}
저는 Pokemon 클래스에 포켓몬의 이름과 도감번호를 저장하는 pokemonName과 pokedexNum이라는
멤버변수 두 개를 선언했습니다.
그리고 관례에 맞게 Getter와 Setter 메서드를 생성해보겠습니다.
package com.kh.gettersetterPokemon;
public class Pokemon {
//1. 멤버변수(필드) : 접근제한자를 private으로 설정
private String pokemonName;
private int pokedexNum;
//Getter: 멤버변수의 값을 반환해주는 메서드
public String getPokemonName() {
return pokemonName;
}
public int getPokedexNum() {
return pokedexNum;
}
//Setter: 멤버변수의 값을 설정할 수 있게 해주는 메서드
public void setPokemonName(String pokemonName) {
this.pokemonName = pokemonName;
}
public void setPokedexName(int pokedexNum) {
this.pokedexNum = pokedexNum;
}
}
저는 직접 타이핑해서 메서드를 생성하고, Getter와 Setter 메서드끼리 묶어서 코드를 정리해줬습니다.
자동생성 기능을 써도 Java가 알아서 관례에 맞는 이름으로 메서드를 생성해줍니다.
그렇다면 이제 여기서 드는 의문이 있습니다.
아니 Getter, Setter 기능은 이해가 되는데, 대체 뭐하러 이 고생을 하는거야? 그냥 멤버변수 접근제한을 public으로 풀고 쓰면 되지, 사서 고생을 하는 이유가 도대체 뭘까...
2. 캡슐화
이제 여기서 나오는 개념이 바로 캡슐화입니다.
그럼 또 그게 뭔데? 할텐데..
접근 제어자(private)을 사용해 필드를 선언하여 외부에서 직접 접근하기 못하도록 막아주고,
Getter와 Setter를 통해 필드에 접근할 수 있도록 해줌
위와 같은 기능을 구현하는 것 자체를 캡슐화라고 합니다.
말이 아리송해서 그렇지, 단어 그대로 감기약 처방 받으면 있는 캡슐에 담긴 약 생각하면 쉬울듯 해요. 약의 기능을 하는 요소인 가루는 캡슐 안에 들어있는데, 그걸 캡슐을 깨고 먹지 않았다고 약효가 들지 않는 것이 아닌 것처럼.. 멤버변수를 private으로 막아두는 모양새를 하고있는 겁니다.
사실 위에서 이미 구현한 기능이에요. 그럼 이걸 왜 하냐?
1) 외부로부터 데이터를 보호하기 위해 사용
성도지방 포켓몬의 도감번호를 저장하기 위한 멤버변수 pokedexNum이 있다고 칩니다.
그리고 성도지방의 포켓몬은 총 256 종으로, 이 외의 도감번호를 가진 포켓몬은 나올 수 없습니다.
public class HGSS {
public int pokedexNum;
}
이때 우리는 멤버변수를 public으로 선언을 했는데, 저런.. 어떤 고약한 장난꾸러기가 '골탕 좀 먹어봐라 히힛! 포켓몬 하나에 도감번호 257을 슬쩍 저장해봐야지!' 하고 마음을 먹었네요.
public class MyPokemon {
public static void main(String[] args) {
HGSS p = new HGSS(); //p라는 인스턴스 생성
p.pokedexNum= 257; //p의 도감번호에 257번 부여
}
}
세상에 성도지방에는 도저히 257번의 번호를 가진 포켓몬이 존재하지도 않는데, 이 말썽쟁이 한 명 때문에 엉뚱한 도감번호가 저장된 인스턴스 하나가 탄생해버렸습니다.
이때 우리는 멤버변수인 pokedexNum을 private으로 설정하여 외부에서 아무런 값이나 넣지 못하도록, 즉 데이터를 보호하도록 할 수 있습니다.
public class HGSS {
private int pokedexNum; //접근제어자를 private로 변경
}
코드는 위와 그대로지만 더 이상 HGSS클래스의 pokedexNum을 찾을 수 없다는 오류가 납니다.
캡슐화를 통해서 내부에서 원치않는 이상한 값을 외부에서 멋대로 필드에 설정할 수 없게 만든 것입니다.
그리고 경고창의 하단을 보면 Create getter and Setter for 'pokedexNum'이라고 가이드를 제시해주네요.
HGSS 클래스의 멤버변수인 pokedexNum이 private으로 접근제한이 걸려있어 직접 접근이 어려우니, Getter 혹은 Setter를 통해서 간접 접근을 하면 되겠습니다.
그럼 아제, 마냥 Setter를 만들어서 간접 접근을 허용하자니.. 또 거기다 이상한 값을 넣으면 어떻게 하나? 하게 됩니다.
이때 나오는 개념이 무결성 검증입니다~!
어려운 것 없고, 그냥 필드에 넣으려는 값이 유효한지 검증을 한 번 하고 넘어가는 절차라고 보면 됩니다.
**무결성 검증
우리는 private 변수를 선언함으로써 외부에서는 직접 접근을 하지 못하도록 넘어갔고, Getter와 Setter를 통해 간접접근을 허용하게 할 예정입니다. 특히 변수값을 설정하는 Setter 메서드의 경우, 외부에서 아무 값이나 넣지 못하도록하는 어떤 거름 장치가 필요하겠죠? 성도지방 포켓몬은 총 256 종으로, 이때의 도감번호는 1 ~ 256까지의 값만 받을 수 있습니다.
위 조건을 만족시키는 거름 장치를 만들어봅시다
public class HGSS{
private pokedexNum;
//Getter
public int getPokedexNum(){
return pokedexNum;
}
//Setter
public void setPokedexNum(int num){
//무결성 검증
if(num<1 || num>256) {
System.out.println("성도지방에 존재하지 않는 포켓몬 입니다.");
} else {
this.pokedexNum = num;
}
}
그리고 이번엔 Setter 메서드인 setPokedexNum에 접근하여 도감번호를 설정해봅시다.
Case 1) 도감번호에 부합하는 값을 주었을 경우
public class MyPokemon {
public static void main(String[] args) {
HGSS p = new HGSS();
p.setPokedexNum(252); //성도도감에 부합하는 번호 설정
System.out.println(p.getPokedexNum()); //getter통해 필드값 읽어오기
}
}
Case 2) 도감번호에 맞지 않는 값을 주었을 경우
public class MyPokemon {
public static void main(String[] args) {
HGSS p = new HGSS();
p.setPokedexNum(300); // 1 ~ 256번에 해당하지 않는 값 부여
System.out.println(p.getPokedexNum());
}
}
위의 Setter에서 거름망을 설치한 것 처럼 경고문구가 나오고, Getter를 통해 값을 뽑아봐도 지정한 값은 저장이 되지 않았습니다. 이것이 바로 무결성 검증입니다 참 쉽죠?
2) 내부적으로만 사용되는 부분을 감추기 위함
1번 이유를 설명하다가 너무 많은 이야기가 나왔네요. 아무튼 캡슐화를 사용하는 또 다른 이유 2번입니다.
위의 무결성 검증 기능을 갖춘 Setter 메서드를 보면..
메서드 하나에 필드값을 저장하고, 무결성을 검증하는 기능인 두 가지 역할을 수행하고 있습니다. 보기 좋고 간결한 코드를 위해 잠시 타당성을 검증하는 ValidNumber이라는 메서드를 추가로 만들어서 기능 분할을 해보겠습니다.
public void SetPokedexNum(int num) {
if(ValidNum(num)==false) {
return; //유효한 값이 아닌 경우이므로 반환값X
} else {
this.pokedexNum = num; //필드값 저장 기능
}
}
//매개변수로 넘겨진 num이 유효한지 확인해서 알려주는 메서드
public boolean ValidNum(int num) {
if(num<1 || num>256) {
System.out.println("성도지방에 존재하지 않는 포켓몬 입니다.");
return false; // false 반환해버리고 메서드 종료
}
return true;
}
이때 ValidNum 메서드의 경우에는, 검증 역할 외에는 기능이 없기 때문에 내부에서만 쓰이고 외부에서는 쓸 일도 없을 것입니다. 그래서 외부 클래스에서 필요가 없으므로 private으로 접근 제한을 걸 수도 있습니다.
또한 지금에야 간단하게 무결성을 체크하는 기능 뿐이지만, 나중에 어떤 조직에서 아이디어를 내 작성한 코드일 경우에는 외부로 함부로 유출이 되면 큰 문제가 생길 수도 있습니다.
이런 여러 이유 때문에 내부적으로만 사용될 것으로 예상되는 코드는 일단 private 제한을 걸고, 나중에 필요에 따라 접근 제한을 푸는 것이 좋습니다.
분명 이해했다고 생각해서 쓰기 시작한 글인데, 흐름에 따라 글을 작성하고아무것도 보지 않고 코드를 작성하려니 사실은 완전히 알고 있는게 아님을 절실히 깨닫게 되네요!그래도 오랜 시간에 걸쳐 쓴 글인만큼 더 이상 Getter와 Setter의 기능 및 필요성에 대해 혼란을 갖지는 않을 듯 합니다~
그리고 참고로 아까 사용한 유효값인 성도도감 252번의 정체는
끝!!
'Java > 개념을 Java' 카테고리의 다른 글
[Java] Overloading (1) | 2023.09.27 |
---|---|
[Java] 상속(inheritance)과 super (1) | 2023.09.27 |
[Java] JUnit (0) | 2023.09.22 |
[Java] 배열과 리스트 2 : ArrayList (0) | 2023.09.20 |
[Java] 배열과 리스트 1 : Array ~ 다차원 배열 (1) | 2023.09.18 |