빠른 비교
String name = "Kim";
int score = 95;
// String.format — 새 문자열 반환
String msg = String.format("이름: %s, 점수: %d", name, score);
// formatted() — Java 15+, 동일한 결과
String msg2 = "이름: %s, 점수: %d".formatted(name, score);
// 문자열 보간처럼 읽히는 방식 (Java 21+ 미리보기는 아직 없음)
System.out.printf("이름: %s, 점수: %d%n", name, score);갈리는 기준
어떤 문자열 출력 방식을 먼저 떠올리면 되나
| 상황 | 먼저 떠올릴 선택 |
|---|---|
| 문자열 값을 만들어 반환 | String.format(...) |
| 콘솔에 바로 출력 | System.out.printf(...) |
| 이미 문자열 인스턴스에서 포매팅 | "template".formatted(...) |
| 여러 줄 텍스트 선언 | 텍스트 블록 \"\"\" |
| 숫자/날짜 형식 지정 | 포맷 지정자 + Formatter 계열 |
포맷 지정자 — 타입에 맞는 형식 선택
포맷 문자열의 % 지정자는 뒤에 오는 인수의 타입과 표시 방식을 결정합니다. 타입이 맞지 않으면 IllegalFormatConversionException이 발생합니다.
// 자주 쓰는 포맷 지정자
String.format("%s", "hello"); // 문자열
String.format("%d", 42); // 정수 (int, long)
String.format("%f", 3.14); // 실수 (소수점 6자리 기본)
String.format("%.2f", 3.14159); // 소수점 2자리
String.format("%05d", 42); // 0으로 채워 5자리
String.format("%-10s|", "left"); // 왼쪽 정렬, 10자리
String.format("%,d", 1000000); // 천 단위 구분자: 1,000,000
String.format("%b", true); // boolean
String.format("%n"); // 줄 바꿈 (OS 독립적, \n보다 권장)String.format vs printf vs formatted()
세 방식 모두 같은 포맷 문자열을 씁니다. 차이는 결과를 어디에 쓰느냐입니다.
String.format()은 새 String 객체를 반환합니다. 변수에 저장하거나 메서드에 전달할 때 씁니다. System.out.printf()는 결과를 표준 출력에 직접 씁니다. "...".formatted()는 Java 15+에서 추가된 인스턴스 메서드로, 메서드 체인에서 읽기 좋습니다.
// String.format — 변수에 저장
String line = String.format("[%s] %d점", name, score);
// printf — 출력에 직접 (반환값 없음)
System.out.printf("[%s] %d점%n", name, score);
// formatted() — 체인 친화적
String line = "[%s] %d점".formatted(name, score);
// 로깅에서는 포맷 문자열보다 {} 플레이스홀더 권장 (SLF4J)
log.info("이름: {}, 점수: {}", name, score); // 출력할 때만 문자열 생성텍스트 블록 — 여러 줄 문자열의 들여쓰기 처리
Java 15+의 텍스트 블록(""")은 여러 줄 문자열을 이스케이프 없이 작성합니다. 들여쓰기는 닫는 """의 위치를 기준으로 자동으로 제거됩니다.
// ❌ 전통 방식 — 이스케이프와 연결이 난잡
String json = "{\n" +
" \"name\": \"Kim\",\n" +
" \"age\": 30\n" +
"}";
// ✅ 텍스트 블록 — 들여쓰기 자동 처리
String json = """
{
"name": "Kim",
"age": 30
}
"""; // 닫는 """ 위치가 들여쓰기 기준선
// 텍스트 블록 안에서도 포맷 사용 가능
String query = """
SELECT *
FROM users
WHERE name = '%s'
""".formatted(name);format vs printf vs formatted
반환값이 필요하면 String.format이나 formatted, 콘솔 출력만 하면 printf가 자연스럽습니다. 문자열 인스턴스에 바로 이어 쓰고 싶으면 formatted()가 가장 읽기 쉽습니다.
String line1 = String.format("[%s] %d점", name, score);
String line2 = "[%s] %d점".formatted(name, score);
System.out.printf("[%s] %d점%n", name, score);선택 기준
| 상황 | 선택 |
|---|---|
| 포맷 결과를 변수에 저장 | String.format() 또는 formatted() |
| 콘솔에 바로 출력 | System.out.printf() |
| 여러 줄 문자열 | 텍스트 블록 (""") |
| 정수 | %d |
| 실수 (소수점 n자리) | %.nf |
| OS 독립적 줄 바꿈 | %n |
| 로깅 | SLF4J {} 플레이스홀더 |
주의할 점
포맷 지정자와 인수의 타입이 맞지 않으면 IllegalFormatConversionException이 발생합니다. 특히 %d에 double을 넣거나 %f에 정수를 넣는 실수가 잦습니다.
double price = 9.99;
// ❌ 타입 불일치 — IllegalFormatConversionException
String.format("가격: %d", price); // double에 %d 사용 불가
// ✅ 올바른 지정자
String.format("가격: %.2f", price); // "가격: 9.99"
String.format("가격: %d", (int) price); // "가격: 9" (소수점 버림)사용자 입력이나 SQL 조각을 String.format으로 직접 이어 붙이면 포매팅 문제를 넘어서 보안 문제로 이어질 수 있습니다.
// ❌ 쿼리 문자열 직접 조합
String query = "SELECT * FROM users WHERE name = '%s'".formatted(name);
// ✅ 실제 DB 접근은 PreparedStatement 사용참고 링크
2 sources