@Setter를 남발하지 말자

DEV NAHYUN·2025년 2월 25일
0

Spring

목록 보기
7/8

📌 @Setter를 남발하면 안 되는 이유 (안 쓰는 게 좋다는 의견)

  1. 불변성(Immutable) 깨짐
    모든 필드에 @Setter를 달면 어디서든 값이 변경될 수 있어 객체 안정성↓
    해결책: 필요한 필드에만 setter 제공

  2. 객체 캡슐화(Encapsulation) 원칙 위배
    필드를 무조건 수정할 수 있으면 객체 내부 규칙을 지키기 어려움.
    예) password를 암호화 없이 바로 바꿀 수 있는 setter가 있으면 보안 취약

  3. 객체의 일관성이 깨질 가능성
    setter 없이 생성자/빌더 패턴(@Builder)으로 객체 생성하면 객체 일관성 유지 가능
    User user = new User(); user.setEmail(null); → 이런 코드 방지

📌 Setter를 쓰지 않는 대안 (객체의 안전한 값 변경 방법)
✅ 1. 생성자(생성 시 값 설정) + 불변 객체 사용

생성할 때만 값을 설정하고, 이후에는 변경 불가능하게 만듦.
이점: 객체 일관성이 유지됨.

@Getter
public class User {
    private final String email;
    private final String nickname;

    public User(String email, String nickname) {
        this.email = email;
        this.nickname = nickname;
    }
}

⚠️ 문제점:

객체 생성 후에는 값을 변경할 수 없음 → 일부 필드는 변경 가능해야 하는 경우가 있음.

✅ 2. @Builder 패턴 사용 (가독성 + 불변성 유지)

값을 직접 변경하는 것이 아니라, 새로운 객체를 생성하는 방식.

@Getter
@Builder
@AllArgsConstructor
public class User {
    private final String email;
    private final String nickname;
}

⚠️ 문제점:

객체를 새로 만들어야 하므로 성능 면에서 부담이 있을 수 있음.

✅ 3. 비즈니스 메서드 사용 (값 변경을 위한 명확한 메서드 제공)

필요한 값만 변경하는 메서드를 제공하여, 객체의 일관성을 유지함.
Setter를 직접 열어두지 않고, 비즈니스 로직을 포함한 메서드에서 값 변경.

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String nickname;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private Role role;

    // 📌 Setter 대신 비즈니스 메서드 사용
    public void changeNickname(String newNickname) {
        if (newNickname == null || newNickname.trim().isEmpty()) {
            throw new IllegalArgumentException("닉네임은 비어있을 수 없습니다.");
        }
        this.nickname = newNickname;
    }

    public void changePassword(String newPassword) {
        if (newPassword.length() < 8) {
            throw new IllegalArgumentException("비밀번호는 최소 8자 이상이어야 합니다.");
        }
        this.password = newPassword; // 보통 암호화 후 저장
    }
}

✅ 이점

User.setNickname("newName") 같은 무분별한 변경을 막을 수 있음.
로직을 추가하여 값 변경에 대한 유효성 검사를 수행 가능.
도메인 규칙을 강제할 수 있음 (e.g. 닉네임 길이 제한).

profile
나만 알아보면 된다는 마음으로 작더라도 조금씩

0개의 댓글

관련 채용 정보