Java에서 String은 불변(immutable) 객체이다.

따라서 문자열을 + 로 더할 때마다 새로운 문자열 객체가 계속 만들어진다

String s = "a";
s += "b"; // 새로운 "ab" 문자열 생성

만약 반복해서 문자열을 더해 계속 새로운 문자열 객체를 만들게 되면 메모리 낭비와 성능 저하 문제가 발생할 수 있다. 이런 String의 단점을 보완하기 위해 나온 클래스가 StringBuilder와 StringBuffer이다.

두 클래스에서 제공하는 메서드는 동일한데, StringBuffer는 Thread safe(동기화) 하다고 하며, String Builder는 Thread safe 하지 않다고 한다.

두 클래스는 내부적으로 가변적인 문자열을 처리할 수 있도록 설계되었으며, append(), insert(), delete(), reverse() 등 거의 동일한 메서드를 제공한다.

그러나 이 두 클래스 사이에는 중요한 차이점이 있다. 바로 동기화 처리 여부이다. StringBuffer는 멀티스레드 환경에서 안전하게 사용할 수 있도록 모든 주요 메서드에 synchronized 키워드가 적용되어 있다. 따라서 여러 스레드가 동시에 접근하더라도 데이터 일관성이 보장되며, Thread-safe하다.

반면, StringBuildersynchronized 처리가 되어 있지 않기 때문에 Thread-safe하지 않다. 그러나 그만큼 동기화 비용이 없기 때문에 싱글 스레드 환경에서는 StringBuffer보다 훨씬 빠른 성능을 보인다.

결론적으로, 단일 스레드 환경에서는 StringBuilder를 사용하는 것이 성능상 유리하고, 여러 스레드가 동시에 접근하는 멀티스레드 환경에서는 StringBuffer를 사용하는 것이 안전하다. 최근에는 StringBuffer 대신 StringBuilder를 사용하면서, 필요한 경우 외부에서 synchronized 블록을 적용하여 동기화를 직접 관리하는 방식이 선호되기도 한다.

<aside>

Java 5 (JDK 5) 이후

java 5 이상에서는 String의 더하기 연산을 할 경우, 컴파일 시 자동으로 해당 연산을 StringBuilder로 변환해준다. 따라서 일일이 더하는 작업을 변환해 줄 필요는 없지만 for 루프와 같이 반복 연산을 할 때에는 자동으로 변환을 해 주지 않기 때문에 반드시 사용해줘야한다.

</aside>

정리하면,

단일 스레드 환경 (ex. 일반적인 루프, 문자열 처리)에서는 StringBuilder를 써서 속도를 높이는 게 좋고,

여러 스레드에서 동시에 접근할 수 있는 공유 객체라면 StringBuffer로 안전하게 처리하는 게 좋다

StringBuilder 기본 사용법

StringBuilder sb = new StringBuilder();

sb.append("Hello");
sb.append(" ");
sb.append("World!");

String result = sb.toString(); // 최종 문자열로 변환

System.out.println(result); // 출력: Hello World!