이펙티브 자바 완벽 공략 1부
아이템 12. toString을 항상 재정의하라
카테고리 : 이펙티브 자바 완벽 공략 1부
아이템 12. toString을 항상 재정의하라
- 아이템 12. toString을 항상 재정의하라
toString은 항상 재정의하라
toString()은 생각보다 훨씬 중요한 메서드다. 단순히 “문자열 출력용”이라고 보기 쉽지만, 실제로는 디버깅, 로깅, 데이터 표현까지 깊게 연결된다.
기본 toString의 문제점
Object의 기본 구현은 다음과 같은 형태다.
클래스이름@16진수해시코드
예:
PhoneNumber@6d06d69c
👉 문제
- 의미 있는 정보 없음
- 디버깅 시 도움 안 됨
- 로그 분석 불가능
왜 toString을 재정의해야 하는가
객체의 상태를 사람이 이해할 수 있는 형태로 표현하기 위해서
실제 사용 상황
System.out.println(obj)- 로그 출력
- 문자열 결합
👉 이 모든 상황에서 toString() 자동 호출
좋은 toString의 기준
1. 사람이 읽을 수 있어야 한다
@Override
public String toString() {
return "010-1234-5678";
}
👉 직관적 표현
2. 객체의 핵심 상태를 포함해야 한다
@Override
public String toString() {
return "PhoneNumber{areaCode=010, prefix=1234, lineNum=5678}";
}
3. 일관된 포맷을 유지해야 한다
- 로그 분석
- 디버깅 자동화
- 파싱 가능성
값 객체(Value Object)에서의 toString
값 객체는 특히 중요하다.
예: PhoneNumber
010-1234-5678
👉 단순 출력이 아니라
- 표현 포맷 정의
- 도메인 의미 전달
정적 팩토리 메서드와의 조합
toString 포맷과 입력 포맷을 맞추면 더 강력해진다.
예
public static PhoneNumber of(String number) {
// "010-1234-5678" 파싱
}
👉 장점
- 입력 → 객체 변환 가능
- 출력 → 동일 포맷 유지
⚠️ 보안 관점에서의 toString
여기서 중요한 포인트가 하나 있다.
toString은 “외부 공개 정보”다
toString() → public 데이터
절대 포함하면 안 되는 것
- 개인정보
- 인증 정보
- 결제 정보
- 민감 데이터
실제 사례
Order{userId=..., creditCard=..., address=...}
👉 이런 출력은 매우 위험
안전한 예
Order{id=12345}
👉 핵심 식별 정보만 노출
“모든 필드 출력”이 항상 좋은 것은 아니다
책에서는 “모든 정보 출력”을 권장하지만 실무에서는 상황에 따라 다르다.
실무 기준
| 경우 | 출력 여부 |
|---|---|
| 디버깅용 내부 객체 | 대부분 포함 |
| 외부 노출 객체 | 최소화 |
| 민감 데이터 포함 | 제외 |
getter 제공의 필요성
책에서 강조하는 중요한 포인트
문제 상황
String s = obj.toString();
// 문자열 파싱해서 값 추출
👉 매우 안 좋은 코드
해결 방법
obj.getAreaCode();
obj.getPrefix();
👉 명시적인 API 제공
자동 생성 vs 직접 구현
1. 자동 생성 (IDE, Lombok)
@ToString
👉 빠르고 편리
2. 직접 구현
👉 필요한 경우
- 특정 포맷 필요
- 사용자 친화적 출력
- 도메인 의미 강조
언제 직접 구현해야 하는가
✔ 전화번호
010-1234-5678
✔ 주소
Seoul, Gangnam, ...
✔ 좌표
(37.123, 127.456)
👉 사람이 읽기 쉬운 포맷이 중요한 경우
핵심 정리
- 기본 toString은 쓸모 없다
- 반드시 재정의하는 것이 좋다
- 사람이 이해할 수 있는 형태로 출력해야 한다
- 보안 데이터는 절대 포함하지 않는다
- 필요한 경우 직접 포맷 정의
- getter 제공으로 문자열 파싱 방지
한 줄 결론
toString은 “객체의 얼굴”이다 — 사람이 이해할 수 있게, 그리고 안전하게 보여줘야 한다