[Spring] Getter, Setter (+Mapping)

Hood·2025년 1월 10일
0

Spring Boot

목록 보기
5/14
post-thumbnail

✍ Back-End 지식을 늘리자!

백엔드 개발자를 준비하며 생기는 의문들을 정리한 포스트입니다.


들어가기 전

데이터베이스의 객체를 만들다 보면 외부로부터 데이터를 보호하고 접근 로직을 분리하기 위해
자바의 private 접근 제어자를 사용하게 됩니다.

자바의 접근 제어자에는 4가지 종류가 있으며

  • private : 같은 클래스 내에서만 접근
  • default : 같은 패키지 내에서만 접근
  • protected : 같은 패키지 내 또는 자손 클래스일 경우 접근
  • public : 제한 없음

이번 포스트에서는 데이터를 보호하기 위해 은닉된 접근 제어자 private에
멤버변수에 접근하는 방법인 Getter, Setter의 정의를 알아보려고 합니다.


Getter, Setter

Getter, Setter 는 객체의 속성(데이터)를 가져오거나 수정하는 메서드(함수)를 의미합니다.
즉 객체의 데이터 보호와 조작을 위한 중요한 개념입니다.

Getter란?

Getter 는 값을 읽을 수 있게 해줍니다.
즉 읽기 전용 메서드이며 보통 get이라는 접두사와 함께 사용됩니다.

private class Person {
    var name: String = "John" // 기본 값
        get() = field // Getter: 값을 반환함
}

fun main() {
    val person = Person()
    println("이름: ${person.name}")  // Getter 호출
}

//출력: 이름: John

위에는 Person 클래스 안에 이름의 기본 값을 John을 두고 getter를 사용하여
Person 클래스의 Getter를 호출하여 값을 반환해 출력하는 예제입니다.
private로 지정하면 클래스 외부에서 멤버 변수를 접근할 수 없지만
이러한 객체의 데이터를 읽기 위한 메서드로 사용할 수 있습니다.

Setter란?

Setter란 값을 수정할 수 있게 해줍니다.
쓰기 전용 메소드라고 불리는데 보통 set이라는 접두사와 함께 사용됩니다.

private class Person {
    var name: String = "John"
        set(value) {  // Setter: 값을 수정함
            field = value
        }
}

fun main() {
    val person = Person()
    person.name = "Alice"  // Setter 호출 (값을 변경)
    println("이름: ${person.name}")  // 변경된 값 출력
}

//출력: 이름: Alice

똑같이 Person 클래스 안에 이름의 기본 값을 John으로 두었지만
이번에는 setter를 호출해 값을 수정하게 만들어 주었고
메인 함수에서 이름을 변경해 줌으로써 새로운 값이 할당 된 것을 확인할 수 있습니다.


Getter & Setter를 함께 사용해보면?

private class Person {
    var age: Int = 0
        get() = field
        set(value) {
            if (value >= 0) field = value
            else println("나이는 0 이상이어야 합니다.")
        }
}

fun main() {
    val person = Person()
    person.age = 25  // Setter 호출
    println("나이: ${person.age}")  // Getter 호출
    person.age = -5  // 잘못된 값 (오류 메시지 출력)
}

//출력 : 
//나이: 25
//나이는 0 이상이어야 합니다.

이번에는 나이가 0살이 넘지 않는다면 setter 내에서 오류 메세지를 내보내고
변환된 값을 getter로 출력하는 예제입니다.

코드만 보면 예상할 수 있듯 25살로 값을 할당해주면 정상적으로 Getter는 변환된
Setter의 값을 반환하여 나이 : 25를 출력하지만
-5의 나이를 준다면 setter 내에서 조건문에 충족하지 못하기에
나이는 0 이상이어야 합니다. 라는 데이터 검증된 결과를 보여줍니다.


+Mapping

매핑이란? 데이터를 서로 연결화는 과정을 말하며
일상적인 예로는 지도에 실제 도로와 지형을 지도에 표현한 것에 해당하고
번역에 영어 문장을 한국어로 변환하는 과정을 매핑이라고 합니다.

그럼 코딩에서의 매핑은 무엇을 의미할까요?
바로 객체의 데이터(속성)을 데이터베이스의 테이블과 연결하는 과정을 의미합니다.

  • 객체 필드 <-> 데이터베이스 컬럼
  • 객체 간 관계 <-> 데이터베이스의 관계(FK)

JPA에서 매핑

테이블과 객체를 단순 매핑한다면?

@Entity
data class User(
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0,

    @Column(name = "user_name", nullable = false)
    var name: String
)

해당 예제처럼 @Entity를 User 클래스에 데이터베이스 테이블로 매핑하고
@Columm을 사용하여 name 필드에 user_name 컬럼에 매핑하였습니다.
이처럼 단순 JPA에서의 1:1관계 매핑은 어노테이션을 통해 사용할 수 있습니다.

다음 1:N의 관계의 매핑은?

@Entity
data class User(
    @Id @GeneratedValue
    val id: Long = 0,
    var name: String,

    @OneToMany(mappedBy = "user", cascade = [CascadeType.ALL])
    val posts: MutableList<Post> = mutableListOf()
)

@Entity
data class Post(
    @Id @GeneratedValue
    val id: Long = 0,
    var content: String,

    @ManyToOne
    @JoinColumn(name = "user_id")
    val user: User
)

지금 User와 Post는 1:N의 관계를 가지며
User(1명) 가 여러 개의 Post(N개) 를 가질 수 있는 예제입니다.

그래서 User 클래스 에는 @OneToMany(mappedBy = "user") 를 통해
여러 개의 Post를 참조하게 만들고

반대로 Post 클래스에는 @ManyToOne을 사용하여
하나의 User를 참조하도록 만들어주었습니다.
또한 @JoinColumm(name = "user_id")를 사용하여
Post 테이블의 user_id 컬럼을 외래 키로 설정해주었습니다.


📌결론

GetterSetter는 객체의 데이터 보호 및 제어를 위해 사용되며
1. 데이터의 일관성을 위해 외부에서 직접 수정하지 못하게 보호하기 위해서
데이터 캡슐화 하려는 목적
2. 데이터를 가져오는 방식과 내부 저장 방식을 분리하려는 데이터 접근 로직의 분리 목적
두 개의 필요성을 가진 코드 유지보수와 가독성을 위해 사용됩니다.

Mapping은 단순 객체와 데이터베이스를 쉽게 연결하기 위해 사용됩니다.

profile
달을 향해 쏴라, 빗나가도 별이 될 테니 👊

0개의 댓글