티스토리 뷰

개발을 하다 보면 String 문자열을 자주 사용하게 된다. 하지만 String을 잘못 사용하면 성능 저하메모리 낭비로 이어질 수 있다. 이 글에서는 String 사용 시 실제로 어떤 문제가 발생하고 어떻게 해결해야하는지 소개하겠다.

1. String이 왜 문제가 될까요?

다음과 같이 문자열을 덧붙이는 코드가 있다고 가장하자. 아래와 같은 연산을 수행할 경우 어떤 일이 발생할까?

String a = "abc";
a += "abc";
a += "abc";

위 코드를 그림으로 나타내면 다음과 같다.


이 코드에서 주목해야 할 점은 String의 불변(immutable) 특성이다. String은 한 번 생성되면 그 내용을 변경할 수 없는 특별한 객체다. 그래서 위 코드처럼 문자열을 덧붙이면 매번 새로운 String 객체가 힙에 생성되고 이전 문자열은 GC 대상이 된다. 이런 작업이 반복되면 불필요한 객체들이 메모리에 쌓여 메모리 낭비와 성능 저하로 이어지게 된다.

2. 해결 방법: StringBuilderStringBuffer

StringBuilder와 StringBuffer는 문자열을 가변적으로 다루기 위한 클래스이다.

StringBuilder b = new StringBuilder();
b.append("abc");
b.append("abc");
b.append("abc");

// StringBuffer도 동일하게 사용 가능


이 두 클래스는 문자열을 덧붙일 때 새로운 객체를 생성하지 않고, 내부 버퍼(char[])를 활용해 문자열을 이어 붙인다. 버퍼의 크기가 부족해질 경우에는 더 큰 버퍼를 생성해 기존 내용을 복사하고 확장한다. 두 클래스 모두 append(), insert(), delete() 등 동일한 메서드를 제공하지만, 주요 차이점은 스레드 안정성에 있다. StringBuffer는 스레드 세이프하기 때문에 멀티 스레드 환경이나 스레드 안전성이 확인되지 않은 경우에 사용하면 된다. 단일 스레드 환경에서는 StringBuilder의 성능이 더 좋다고 한다.

3. 기존 코드, 전부 고쳐야 하나요?

그렇다고 해서 모든 String 연산을 StringBuilder, StringBuffer로 변경해야하는 것은 아니다. 아래의 경우를 살펴보자.

public class StringConcatTest {
    public static void main(String[] args) {
        // 문자열 덧셈 연산 (컴파일러가 내부적으로 StringBuilder로 변환)
        String s = "Hello" + ", " + "world" + "!";

        // 반복문 안에서 문자열 += 연산
        String result = "";
        for (int i = 0; i < 3; i++) {
            result += i;
        }
    }
}

문자열 연산이 반복문 밖에 있는 코드와 반복문 안에 있는 코드를 비교해보자. 위 코드는 컴파일 단계에서 아래처럼 변하게 된다.

public class StringConcatTest {
    public static void main(String[] args) {
        // 문자열 덧셈 연산 (컴파일러가 내부적으로 StringBuilder로 변환)
        String var1 = "Hello, world!";  

        // 반복문 안에서 문자열 += 연산
        String var2 = "";  
        for(int var3 = 0; var3 < 3; ++var3) {  
            var2 = var2 + var3;  
        }
    }
}

일반 문자열 연산은 하나의 문자열로 변경되었고 반복문에 있는 문자열 연산은 그대로 String을 사용하게 됐다. JDK 버전에 따라 다르지만 일반적으로 문자열은 위와 같이 변하거나 StringBuilder로 변환된다. 하지만 반복문에서 사용되는 String 문자열 연산은 변환되지 않는다. 반복문에서 사용되는 String 연산은 반복문이 길어질 수록 메모리 낭비도 많아지기 때문에 반복문 연산에서만 String 연산을 피하는게 좋겠다.

요약

  • String은 불변 객체이기 때문에 +, += 연산 시마다 새 객체가 생성된다.
  • 반복문 안에서 += 연산을 사용하면 성능 저하와 메모리 낭비로 이어질 수 있다.
  • 문자열을 반복적으로 연결하는 경우에는 StringBuilder(또는 스레드 안전성이 필요한 경우 StringBuffer)를 사용하는 것이 좋다.
  • 단일 줄에서 사용하는 문자열 덧셈은 컴파일러가 자동으로 최적화하므로 성능 문제는 거의 없다.
  • 실무에서는 반복 문자열 연결이 있을 경우만 StringBuilder(StringBuffer)로 바꾸는 정도면 충분합니다.

'언어 > Java' 카테고리의 다른 글

JVM 메모리 구조 정리  (0) 2025.08.16
Java 버전 별 변화 변천사  (0) 2025.08.03
Jackson의 @JsonProperty로 JSON 키와 Java 필드 매핑하기  (0) 2025.04.09
JDBC란?  (0) 2025.03.22
DataSource란?  (0) 2025.03.22
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함