티스토리 뷰

728x90

▪️ String, StringBuilder, StringBuffer 란?

자바에서는 대표적으로 문자열을 다루는 자료형 클래스로 String, StringBuffer, StringBuilder 라는 3가지 자료형을 지원한다.

위 3가지 클래스 자료형은 모두 문자열을 다루는데 있어 공통적으로 사용되지만, 사용 목적에 따라 쓰임새가 많이 달라지게 된다.

 

1️⃣ String

기본적으로 자바에서는 String 객체의 값은 변경할 수 없다.

이는 한번 할당된 공간이 변하지 않는다고 해서 '불변(immutable)' 자료형 이라고 불리운다.

그래서 초기공간과 다른 값에 대한 연산에서 많은 시간과 자원을 사용하게 된다는 특징이 있다.

 

String str = "hello";
str = str + " world";

System.out.println(str); // hello world

 

"Hello" 문자열에 "World" 문자열을 더해서 "Hello World" 를 만든다는 것을 예로 들면, 코드로만 보면 변수 str 참조하는 메모리의 "Hello" 라는 값에 "World" 라는 문자열을 더해서 String 객체의 자체의 값을 업데이트 시킨 것으로 보일수 있다.

 

하지만 실제로는 메모리에 새로 "Hello World" 값을 저장한 영역을 따로 만들고 변수 str 를 다시 참조하는 식으로 작동한다.

 

 

💡 자바 언어에서 String을 불변으로 설정한 이유

 

String 객체를 불변하게 설계한 이유는 캐싱, 보안, 동기화, 성능측면 이점을 얻기 위해서이다.

1. 캐싱 : String을 불변하게 함으로써 String pool에 각 리터럴 문자열의 하나만 저장하며 다시 사용하거나 캐싱에 이용가능하며 이로 인해 힙 공간을 절약할 수 있다는 장점이 있다. 

2. 보안 : 예를 들어 데이터베이스 사용자 이름, 암호는 데이터베이스 연결을 수신하기 위해 문자열로 전달되는데, 만일 번지수의 문자열 값이 변경이 가능하다면 해커가 참조 값을 변경하여 애플리케이션에 보안 문제를 일으킬 수 있다.

3. 동기화 : 불변함으로써 동시에 실행되는 여러 스레드에서 안정적이게 공유가 가능하다.

 

2️⃣ StringBuffer, StringBuilder

StringBuffer, StringBuilder 클래스는 문자열을 연산(추가하거나 변경) 할 때 주로 사용하는 자료형이다.

물론 String 자료형만 으로도, + 연산이나 concat() 메소드로 문자열을 이어 붙일수 있지만, 덧셈(+) 연산자를 이용해 String 인스턴스의 문자열을 결합하면 내용이 합쳐진 새로운 String 인스턴스를 생성하게 되어, 문자열을 많이 결합하면 결합할수록 공간의 낭비뿐만 아니라 속도가 매우 느려지게 된다는 단점이 있다.

 

자바에서는 이러한 문자열 연산을 전용으로 하는 자료형을 따로 만들어 제공해주는데, StringBuffer 클래스는 내부적으로 버퍼(buffer)라고 하는 독립적인 공간을 가지게 되어, 문자열을 바로 추가할 수 있어 공간의 낭비도 없으며 문자열 연산 속도도 매우 빠르다는 특징이 있다.

 

StringBuffer sb = new StringBuffer();  // StringBuffer 객체 sb 생성
sb.append("hello");
sb.append(" ");
sb.append("world");
String result = sb.toString();
System.out.println(result); // hello world

 

StringBuffer나 StringBuilder의 경우 문자열 데이터를 다룬다는 점에서 String 객체와 같지만, 객체의 공간이 부족해지는 경우 버퍼의 크기를 유연하게 늘려주어 가변(mutable)적이라는 차이점이 있다.

두 클래스는 내부 Buffer(데이터를 임시로 저장하는 메모리)에 문자열을 저장해두고 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있다.

 

String 객체는 한번 생성되면 불변적인 특징 때문에 값을 업데이트하면, 매 연산 시마다 새로운 문자열을 가진 String 인스턴스가 생성되어 메모리공간을 차지하게 되지만, StringBuffer / StringBuilder 는 가변성 가지기 때문에 .append() .delete() 등을 이용하여 동일 객체내에서 문자열 크기를 변경하는 것이 가능하다.

 

따라서 값이 변경될 때마다 새롭게 객체를 만드는 String 보다 훨씬 빠르기 때문에, 문자열의 추가, 수정, 삭제가 빈번하게 발생할 경우라면 String 클래스가 아닌 StringBuffer / StringBuilder를 사용하는 것이 이상적이라 말할 수 있다.

 

💡 StringBuffer vs StringBuilder 차이점

StringBuffer와 StringBuilder 클래스는 둘 다 크기가 유연하게 변하는 가변적인 특성을 가지고 있으며, 제공하는 메서드도 똑같고 사용하는 방법도 동일하다.

이 둘의 차이점은 멀티 쓰레드(Thread)에서 안전(safe)하냐 아니냐 이 차이 뿐이다.

 

두 클래스는 문법이나 배열구성도 모두 같지만, 동기화(Synchronization)에서의 지원의 유무가 다르다. 

StringBuilder는 동기화를 지원하지 않는 반면, StringBuffer는 동기화를 지원하여 멀티 스레드 환경에서도 안전하게 동작할 수 있다.

그 이유는 StringBuffer는 메서드에서 synchronized 키워드를 사용하기 때문이다.

그래서 web이나 소켓환경과 같이 비동기로 동작하는 경우가 많을 때는 StringBuffer를 사용하는 것이 안전하다.

 

 

Reference Link

https://inpa.tistory.com/entry/JAVA-%E2%98%95-String-StringBuffer-StringBuilder-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%84%B1%EB%8A%A5-%EB%B9%84%EA%B5%90

728x90