본문 바로가기

Java 오류 & 개발/Java 기본 문법 & 오류

[Java] String, StringBuilder, StringBuffer 차이점과 성능 비교

1. String, StringBuilder, StringBuffer란?

Java에서 문자열을 다룰 때, 가장 많이 사용하는 클래스는 String, StringBuilder, StringBuffer입니다.

이 세 가지 클래스는 문자열을 처리하는 기능을 제공하지만, 동작 방식과 성능 면에서 차이가 있습니다.

✅ 각 클래스의 특징

클래스 특징 멀티쓰레드 지원 성능
String 불변(Immutable) 객체, 값이 변하면 새로운 객체 생성 지원 안함 속도가 느림 (새로운 객체 생성 비용 발생)
StringBuilder 가변(Mutable) 객체, 문자열 변경 가능 지원 안함 빠름 (객체 재사용 가능)
StringBuffer 가변(Mutable) 객체, Thread-Safe (동기화 지원) 지원함 StringBuilder보다 느림 (동기화 비용 발생)

2. String vs StringBuilder vs StringBuffer 예제

✅ String (불변 객체 예제)


public class StringExample {
    public static void main(String[] args) {
        String str = "Hello";
        str += " World";  // 새로운 객체가 생성됨
        System.out.println(str);  // "Hello World"
    }
}

🚨 주의: 위 코드에서 문자열을 변경하면 기존 객체가 수정되는 것이 아니라 새로운 객체가 생성됨 → 메모리 낭비 발생

✅ StringBuilder (가변 객체 예제)


public class StringBuilderExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("Hello");
        sb.append(" World");  // 기존 객체에 추가됨
        System.out.println(sb.toString());  // "Hello World"
    }
}

🚀 특징: 기존 객체를 유지하면서 문자열을 수정할 수 있어 성능이 뛰어남

✅ StringBuffer (멀티쓰레드 환경 예제)


public class StringBufferExample {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        sb.append(" World");  // 동기화된 메서드 사용
        System.out.println(sb.toString());  // "Hello World"
    }
}

🔒 특징: StringBuffer는 멀티쓰레드 환경에서 안전하지만, 동기화 오버헤드가 발생하여 성능이 다소 떨어짐


3. 성능 비교 (반복문에서 문자열 연결 테스트)

1,000,000번 문자열을 추가하는 성능 비교 실험


public class StringPerformanceTest {
    public static void main(String[] args) {
        long startTime, endTime;

        // String 테스트
        startTime = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < 1000000; i++) {
            str += "a";  // 새로운 객체가 계속 생성됨
        }
        endTime = System.currentTimeMillis();
        System.out.println("String 소요 시간: " + (endTime - startTime) + "ms");

        // StringBuilder 테스트
        startTime = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1000000; i++) {
            sb.append("a");
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder 소요 시간: " + (endTime - startTime) + "ms");

        // StringBuffer 테스트
        startTime = System.currentTimeMillis();
        StringBuffer sf = new StringBuffer();
        for (int i = 0; i < 1000000; i++) {
            sf.append("a");
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer 소요 시간: " + (endTime - startTime) + "ms");
    }
}

✅ 실행 결과 (예상)

String 소요 시간: 5000ms 이상
StringBuilder 소요 시간: 50ms 미만
StringBuffer 소요 시간: 80ms 미만

 

🔎 결론: 문자열을 자주 변경하는 경우, StringBuilder가 가장 빠름!


4. 언제 무엇을 사용할까?

  • ✔ 문자열 변경이 거의 없다면 → String 사용 (메모리 절약)
  • ✔ 문자열 변경이 많고, 멀티쓰레드 환경이 아니라면 → StringBuilder 사용 (최고 성능)
  • ✔ 멀티쓰레드 환경에서 문자열 변경이 필요하다면 → StringBuffer 사용

📌 정리

클래스 불변 / 가변 멀티쓰레드 지원 주요 사용처
String 불변 (Immutable) 아님 변경이 적은 문자열
StringBuilder 가변 (Mutable) 아님 변경이 많은 문자열 (단일 쓰레드 환경)
StringBuffer 가변 (Mutable) 지원 변경이 많은 문자열 (멀티쓰레드 환경)

🔎 더 많은 Java 성능 최적화 기법이 궁금하다면?

다른 Java 성능 최적화 글도 함께 확인해보세요!