오랜만에 자바 포스팅으로 돌아왔다.
오늘은 문자열을 처리하는데 사용되는 String, StringBuffer, StringBuilder의 동작 방식, 성능, 사용 목적을 비교하며 각각의 클래스가 어떻게 동작하고 언제 사용하며 성능이 어떻게 다른지 설명하겠다.
String
불변 객체
- String 객체는 한 번 생성되면 더 이상 변경할 수 없다.
- 예를 들어 String 객체에서 문자열을 변경하는 작업이 발생하면 실제로는 새로운 String 객체가 생성되는 것이고 기존 객체는 가비지 컬렉터가 처리할 때까지 메모리 상에 남아 있다.
불변성의 장점
- String 객체는 불변성 덕분에 안전하게 여러 쓰레드에서 공유될 수 있다.
- String은 Java의 String Pool(메모리 사용 최적화하는 공간)에 의해 관리되며 동일한 리터럴 문자열은 재사용된다.
- 즉 "Hello"라는 문자열을 여러 번 사용하더라도 동일한 메모리 공간을 참조하게 되는 것이다. -> 메모리 효율성 높음
불변성의 단점
- 문자열을 자주 수정해야 하는 경우, 문자열이 변경될 때마다 새로운 객체가 생성되므로 성능과 메모리 측면에서 비효율적일 수 있다.
- 예를 들어, String 객체에 여러 번 + 연산을 하여 문자열을 연결하면 매번 새로운 String 객체가 생성되어 메모리 사용량이 증가하고 성능이 떨어진다.
코드 예시
String str = "Hello";
str += " World"; // 새로운 String 객체 생성
위의 코드는 "Hello" 라는 String 객체를 만들고, 그 다음에 "World"를 붙여서 새로운 String 객체를 생성한다.
원래 있던 str 객체는 가비지 컬렉션 대상이 된다.
StringBuffer
가변 객체
- StringBuffer는 내부적으로 버퍼를 사용하여 문자열을 관리한다.
- 문자열을 변경할 때마다 새로운 객체를 생성하는 대신, 같은 메모리 공간에서 내용을 변경한다.
- 따라서, 문자열을 빈번하게 변경해야 하는 경우 StringBuffer는 String보다 훨씬 더 효율적이다.
동기화
- StringBuffer는 동기화가 되어 있다. 즉 여러 쓰레드가 동시에 하나의 StringBuffer 객체에 접근하여 수정할 때도 안전하게 동작한다.
- 동기화는 성능을 약간 저하시킬 수 있다. 하지만 다중 쓰레드 환경에서는 데이터의 일관성을 유지하기 위해 필수적인 기능입니다.
사용 상황
- StringBuffer는 다중 쓰레드 환경에서 문자열을 빈번하게 변경해야 할 때 적합하다.
- 예를 들어, 서버에서 요청을 처리하는 과정에서 여러 쓰레드가 하나의 문자열을 수정할 필요가 있을 때 StringBuffer를 사용하면 안전하게 처리할 수 있다.
예시 코드
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World"); // 동일한 객체에서 문자열을 수정 (쓰레드 안전)
System.out.println(sb.toString());
쓰레드 안전 : StringBuffer는 동기화되어 있어 다중 스레드에서 안전하게 사용 가능
StringBuilder
가변 객체
- StringBuilder는 StringBuffer와 거의 동일한 방식으로 동작한다.
- 문자열을 수정할 때 같은 메모리 공간을 사용하므로 성능 면에서 효율적이다.
비동기화
- StringBuilder는 동기화되지 않는다는 점(Not Synchronized)에서 StringBuffer과 차이가 있다.
- 여러 쓰레드가 동시에 StringBuilder 객체를 수정할 경우 안전하지 않을 수 있다는 뜻
- 하지만 단일 쓰레드 환경에서 사용할 경우 동기화 괒어이 없기 때문에 StringBuffer보다 더 빠르게 동작한다.
사용 상황
- StringBuilder는 다중 쓰레드 환경이 아닌 단일 쓰레드 환경에서 문자열을 자주 변경할 필요가 있을 때 사용한다.
- GUI 프로그램이나 간단한 스크립트 등, 쓰레드 간 동기화가 필요 없는 상황에서 적합하다.
예시 코드
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 동일한 객체에서 문자열을 수정 (쓰레드 안전 X)
System.out.println(sb.toString());
비동기화: StringBuilder는 동기화되지 않으므로 다중 쓰레드 환경에선 안전하지 않지만 성능이 빠름.
세 클래스의 성능 비교
String:
- 불변성이기 때문에 문자열을 수정할 때마다 새로운 객체가 생성된다. 이는 힙 메모리를 더 많이 사용하게 하고, 빈번한 수정 작업이 성능을 크게 저하시킬 수 있다.
- 예시: 문자열 연결을 자주 해야 할 경우에 각 연결 작업에서 새로운 객체가 만들어지므로 성능이 매우 느려질 수 있다.
StringBuffer:
- 가변 객체이며 동기화 기능이 있어서 다중 쓰레드 환경에서도 안전하다.
- 그러나 동기화 과정이 성능을 약간 저하시킬 수 있다.
- 예시: 서버에서 여러 요청을 처리하면서 문자열을 수정하는 작업이 자주 발생하는 경우
StringBuilder:
- StringBuffer와 동일한 가변 객체이지만 동기화가 적용되지 않아 단일 쓰레드 환경에서 가장 빠르다.
- 동기화 오버헤드가 없기 때문에 StringBuffer보다 성능이 뛰어나다.
- 예시: 단일 쓰레드 환경에서 문자열을 빈번하게 수정할 때 가장 좋은 선택이다.
성능 비교 코드 예시
public class StringPerformanceTest {
public static void main(String[] args) {
long startTime, endTime;
// String 성능 테스트
startTime = System.nanoTime();
String str = "Hello";
for (int i = 0; i < 10000; i++) {
str += " World"; // 매번 새로운 객체 생성
}
endTime = System.nanoTime();
System.out.println("String Time: " + (endTime - startTime) + " ns");
// StringBuffer 성능 테스트
startTime = System.nanoTime();
StringBuffer sb = new StringBuffer("Hello");
for (int i = 0; i < 10000; i++) {
sb.append(" World"); // 동일 객체에서 수정
}
endTime = System.nanoTime();
System.out.println("StringBuffer Time: " + (endTime - startTime) + " ns");
// StringBuilder 성능 테스트
startTime = System.nanoTime();
StringBuilder sb2 = new StringBuilder("Hello");
for (int i = 0; i < 10000; i++) {
sb2.append(" World"); // 동일 객체에서 수정
}
endTime = System.nanoTime();
System.out.println("StringBuilder Time: " + (endTime - startTime) + " ns");
}
}
내가 예상한 순서로 결과가 나올까?
String Time: 105575300 ns
StringBuffer Time: 1372800 ns
StringBuilder Time: 825400 ns
String | StringBuffer | StringBuilder | |
가변 여부 | 불변 | 가변 | 가변 |
스레드 세이프 | O | O | X |
연산 속도 | 느림 | 빠름 | 아주 빠름 |
사용 시점 | 문자열 추가 연산이 적고, 스레드 세이프 환경에서 | 문자열 추가 연산이 많고, 스레드 세이프 환경에서 | 문자열 추가 연산이 많고, 빠른 연산이 필요한 경우 단일 스레드 환경일경우 |
'Language > Java' 카테고리의 다른 글
[Java] 예외처리 코드 연습 (0) | 2025.01.05 |
---|---|
[Java] 다형성의 본질과 활용 (0) | 2024.12.31 |
[Java] 인터페이스 (48) | 2024.06.22 |
[Java] 멤버 변수 초기화에 관하여 (52) | 2024.06.21 |
[Java] 형변환, 조건문, 반복문 (45) | 2024.06.14 |