본문 바로가기
TIL(Today I Learned)

[Java] String, StringBuilder, StringBuffer 파고 들어보기

by kkkdh 2023. 8. 4.
728x90

들어가면서..

이번 글은 String과 String을 보완해 준다고들 흔히 언급되는 StringBuilder, StringBuffer에 대해서 제가 할 수 있는 선의 깊이까지 들어가 이해하는 과정을 정리해보려 합니다.

 

 

String은 문자열을 다루기 위해 여러 가지 편한 기능들을 제공하고, 특히 참조형 타입 중 유일하게 + 연산을 지원합니다. (concatenation 작업을 수행)

 

그러나, + 연산을 수행하는 과정에서 사실은 컴파일러에 의해 StringBuilder를 이용한 concatenation 작업이 수행되기 때문에 String을 변하는 문자열 값을 다루기 위해 사용하는 것이 효율적이지 못합니다.

 

 

여기까지는 저도 잘 알고 있었는데, 다만 StringBuffer과 StringBuilder의 차이점을 "동기화 지원"이라는 말로 많은 곳에서 설명하고 있는데, 뭔가 와닿지 않아서 이 부분을 파고들어 보려고 합니다.


이런 상황을 한 번 확인해 봅시다

String testString = "Hello";
testString = testString + " world!!";

 이렇게 String의 + 연산을 통해 문자열을 이어 붙인 결과를 다시 testString 변수에 담게 되면, 기존의 "Hello" 값을 저장하는 heap 메모리 영역의 constant pool 일부는 GC(Garbage Collection)의 대상이 됩니다. (물론 다른 변수가 가리키고 있다면 그렇지는 않겠죠?)

 

이러한 연산을 반복적으로 사용하는 경우 메모리 공간의 낭비도 더해지고, 연산 수행 시마다 새로운 String 객체를 만들어야 하는 문제가 발생합니다. (String은 불변 객체이므로)

 

이런 이유들로 StringBuffer나 StringBuilder를 이용해 변경되는 문자열에 대해서 다루고는 합니다.


먼저 StringBuffer와 StringBuilder에 대해 정리해 보자

그렇다면, StringBuffer와 StringBuilder의 코드를 통해 둘의 차이점을 이해해보겠습니다. 

StringBuffer
StringBuilder

전체 코드가 너무 길기에 우선 클래스 선언 부분만 가져왔습니다.

 

 

코드를 통해 확인 가능한 공통점은 다음과 같습니다.

  • 두 클래스 모두 상속이 불가능하도록 final class로 선언되어있다.
  • Serializable, Comparable, CharSequence interface를 구현한다.

 

이 CharSequence는 String class도 구현하고 있다는 점과 String class 또한 이후 상속이 불가능하도록 final로 선언되어 있다는 점이 동일합니다.

 

다음으로 동기화를 보장한다는 키워드의 출처를 알아보기 위해 append method의 선언 부분을 가져와봤습니다.

StringBuffer.append
StringBuilder.append

일단 가장 큰 차이점은 synchronized가 method의 선언부에 있다는 점이 눈에 띕니다.

 

 

synchronized 예약어를 method 선언부에 작성하는 경우 해당 method는 한순간에 하나의 thread에서의 접근만을 허용한다는 특징으로 미루어 보았을 때,

 

둘의 차이점을 "synchronized 유무에 따른 thread-safe 보장 여부"라고 이해할 수 있었습니다.

 

 

이에 따라 저는 동기화의 보장이라는 뜻은 multi-thread 실행 환경에서 method의 실행 순서 보장을 통한 의도된 대로 결과가 나오는 것을 보장한다는 개념을 표현하고자 한 것 같다고 느꼈습니다.

 

 

append를 제외하더라도, StringBuffer의 거의 모든 method에는 synchronized 예약어가 같이 작성되어 thread-safe를 보장하고 있어, 이를 통해 StringBuffer와 StringBuilder의 차이점을 이해할 수 있었습니다.

 

 

이에 따라서 StringBuilder가 당연히 StringBuffer보다 성능이 좋은 이유도 알 수 있었습니다. (thread-safe 처리가 안되어있으니)

728x90

댓글