[Java] 생성자, Getter, Setter, toString — 왜 사용하는가?
Java로 웹개발을 하다 보면, 생성자(Constructor), toString(), Getter, Setter를 아무 생각 없이 습관적으로 사용하곤 한다.
나 같은 초보 개발자만 그럴 수도 있지만, 문득 이런 생각이 들었다.
이걸 왜 사용하는 걸까?
언제 필요한 걸까?
필요하지 않은 경우도 있을까?
이 글에서는 그 본질을 한 번 되짚어보려 한다.
1. 생성자 (Constructor)
역할
- 객체가 생성될 때 초기 상태를 설정하는 메서드
- 클래스 이름과 동일하며, 반환 타입이 없음
사용하는 이유
- 필수 데이터로 객체의 초기 상태를 강제
- 불완전한 객체 생성을 방지
웹개발에서의 활용
- DTO, Entity 객체 생성 시 자주 사용
- @RequestBody로 JSON 바인딩 시, 생성자를 통해 객체 생성
- Lombok의 @AllArgsConstructor, @NoArgsConstructor로 자동 생성 가능
@NoArgsConstructor vs @AllArgsConstructor
어노테이션 생성자 형태 설명
| @NoArgsConstructor | public User() {} | 파라미터 없는 기본 생성자 |
| @AllArgsConstructor | public User(String name, int age) | 모든 필드를 받는 생성자 |
언제 어떤 생성자가 필요한가?
상황 필요한 생성자 이유
| JSON 바인딩 (@RequestBody) | @NoArgsConstructor | Jackson이 기본 생성자로 객체 생성 후 setter로 값 주입 |
| 객체 초기값 강제 (DTO, Entity) | @AllArgsConstructor | 생성 시 필수 데이터 설정 가능 |
| 불변 객체 설계 | @AllArgsConstructor + final 필드 | 한 번 설정 후 변경 불가, 안전 |
2. toString() — 문자열 표현
역할
- 객체를 문자열로 표현하는 메서드
- Object 클래스의 메서드를 오버라이딩
사용하는 이유
- 객체 내부 값을 사람이 읽을 수 있도록 출력
- 디버깅, 로깅 시 객체 상태를 확인하기 위해
웹개발에서의 활용
- System.out.println(user)
- log.info("User info: {}", user)
- 템플릿 출력 (Thymeleaf, JSP 등)
주의할 점
- toString()에 민감 정보(비밀번호 등)를 포함하면 안 됨
- → 롬복에서는 @ToString(exclude = "password") 사용 가능
3. Getter / Setter
역할
- Getter: 필드 값을 읽기
- Setter: 필드 값을 쓰기 (변경)
사용하는 이유
- 캡슐화(Encapsulation) 원칙을 지키기 위해
- 필드에 직접 접근을 막고, 통제된 방식으로 접근하게 함
웹개발에서의 활용
- JSON → 객체 매핑 시 (@RequestBody)
- JPA Entity의 필드 접근
- DTO 필드 접근
- Lombok의 @Getter, @Setter로 자동화 가능
주의할 점
모든 필드에 Setter가 필요할까?
아니다.
- 값이 수정될 일이 없다면 Setter는 제거해도 됨
- 예: 조회 전용 DTO, 읽기 전용 Entity 등
Getter/Setter 없이도 가능한가?
가능하다.
- Java의 record 문법 또는
- Lombok + 불변 객체 설계로 getter/setter 없이도 설계 가능
record란?
Java 14+부터 도입된 불변 데이터 객체 전용 문법
문법 예시
public record User(String name, int age) { }
내부적으로 생성되는 코드
public final class User {
private final String name;
private final int age;
public User(String name, int age) { ... }
public String name() { return name; }
public int age() { return age; }
public String toString() { return ... }
}
특징
- 모든 필드는 final → 불변 객체
- Getter, 생성자, equals(), hashCode(), toString() 자동 생성
- 호출 시 user.name() 형태로 필드에 접근
Lombok + 불변 객체 설계
예시
@Getter
@RequiredArgsConstructor
public class UserDto {
private final String name;
private final int age;
}
설명
- @Getter: 모든 필드에 대해 getter 자동 생성
- @RequiredArgsConstructor: final 필드만 받는 생성자 생성
- setter 없음 → 불변 객체
- 유지보수와 안정성에 매우 유리
마무리 요약
항목 본질 사용 이유 불필요한 경우
| 생성자 | 객체 초기화 | 객체 생성 시 상태 설정 | 불변/단순 조회 시 NoArgs만으로 충분 |
| toString | 문자열 표현 | 로그, 디버깅, 템플릿 렌더링 | 민감 정보 포함되면 ❌ |
| Getter | 읽기 접근 | JSON 매핑, 템플릿 사용 등 | record나 불변 객체에서 대체 가능 |
| Setter | 쓰기 접근 | 수정 가능 객체 설계 시 | 수정이 필요 없을 때 ❌ |
마치며
처음엔 관성적으로 사용했던 생성자, toString(), Getter, Setter…
하지만 이들을 왜 쓰는지, 언제 쓰는지, 안 써도 되는 상황은 어떤 건지를 스스로 정리하는 일은 개발자로서의 깊이를 더해준다.
앞으로 코드 한 줄을 짜더라도 의도와 목적을 알고 쓰는 개발자가 되자.
이 글이 그 첫걸음이 되었기를 바란다.
'BackEnd > Java' 카테고리의 다른 글
| 코딩 테스트에서의 입출력 (0) | 2026.05.21 |
|---|---|
| java 대소문자 바꾸는 법 (0) | 2026.02.03 |