'StringBuffer'에 해당되는 글 1건

  1. 2008.04.26 StringBuffer와 StringBuilder 클래스를 아시나요?

Creative Commons License



일반적으로 String 객체를 가지고 조작하는 일들이 빈번하게 일어나는데 가장 흔하게 볼 수 있는 사례가 다음과 같다.

String name = "아무개";
System.out.println("안녕하세요, 저는 " + name + "입니다");


이 예에서는 3 개의 String 객체들이 사용되고 있다.

  • "아무개"
  • "안녕하세요, 저는 "
  • "입니다"

이 세 개의 String 객체들이 + 연산자에 의해 더해지고 그 결과를 System.out.println()으로 전달한다.

문제는 String 클래스가 불변 클래스라는 데에 있다. 불변 클래스란 내부 속성이 변하지 않는 클래스를 말한다. 따라서 String 객체에 대한 + 연산자는 첫 번째 String 객체에 다음 String 객체를 더하는 것이 아니라 둘을 포함하는 새로운 String 객체를 생성한다. 위의 예가 처리되는 과정을 자세히 살펴보면 다음과 같다.

  1. String 객체0 "아무개"를 String 변수 name에 설정한다.
  2. String 객체1 "안녕하세요, 저는 "을 생성한다.
  3. String 객체2 "입니다"를 생성한다.
  4. 객체1과 객체0를 이용하여 String 객체3 "안녕하세요, 저는 아무개"를 생성한다.
  5. 객체3과 객체2를 이용하여 String 객체4 "안녕하세요, 저는 아무개입니다"를 생성한다.
  6. 객체4를 System.out.println()으로 전달한다.

알게 모르게 객체3과 객체4라는 낭비가 발생한다. 사실 이 예에서는 그리 심각한 문제가 아니지만 String에 대한 + 연산이 매우 빈번하게 일어나면 티끌 모아 태산이라고 퍼포먼스 저하를 발생시킬 수 있다. 이는 전적으로 String 클래스가 불변 클래스이기 때문에 발생한다.

이러한 문제 때문에 JDK는 StringBuffer 클래스를 제공한다. StringBuffer 클래스는 불변 클래스가 아니며, append() 를 통해 내부 속성을 변형시킬 수 있다. StringBuffer 클래스를 이용해 수정한 코드는 다음과 같다.

String name = "아무개";
StringBuffer buffer = new StringBuffer();
buffer.append("안녕하세요, 저는 ").append(name).append("입니다");
System.out.println(buffer.toString());


StringBuffer 클래스를 이용하면 위의 예에서 생긴 객체3과 객체4와 같은 낭비를 발생시키지 않는다. toString()을 호출할 때 비로소 최종 결과물을 String 객체로 반환하는 것이 전부일 뿐이다.

StringBuffer 클래스의 모든 메소드는 동기화되어있다. 멀티스레딩 환경에 적응하기 위함인데 두 번째 예에서처럼 멀티스레딩을 고려할 필요가 없는 상황에서라면 동기화는 역시 퍼포먼스 저하를 일으킨다. JDK는 이에 대해 StringBuilder 클래스를 제공한다. StringBuilder 클래스는 StringBuffer 클래스와 API가 동일하며 동기화를 하지 않는다.

String 객체에 대한 + 연산은 사실 개발 과정에서 매우 빈번하게 일어난다. 대부분 로그를 남기는 목적으로 사용하는데 로그를 남기는 행위가 필요 이상으로 퍼포먼스를 갉아먹는 것은 꽤나 바람직하지 못하다. 로그 등의 목적이라면 StringBuilder 클래스를, 동기화가 필요한 곳이라면 StringBuffer 클래스를 사용하라!

Posted by 서오석
,