자바 String계열 클래스의 특징이 중요한이유는? StringBuilder와 StringBuffer가 존재하는 이유는?

자바  String계열 클래스의 특징이 중요한이유는? StringBuilder와 StringBuffer가 존재하는 이유는?


자바 String 뜯어보기 – 불변성과 StringBuilder, StringBuffer의 존재 이유

자바에서 String은 가장 많이 쓰이면서도 중요한 클래스다. 문자열을 다루는 거의 모든 상황에서 등장하고, 그 특징을 제대로 이해하지 못하면 성능 문제나 메모리 낭비를 일으키기 쉽다. 이번 글에서는 String의 불변성(Immutable) 개념과, 그로 인해 StringBuilder, StringBuffer 같은 클래스가 왜 필요한지 정리해본다.


String의 불변성(Immutable)

자바에서 String 객체는 불변 객체다.
즉, 한 번 만들어진 문자열은 절대 바뀌지 않는다. String의 메서드를 호출해도 원본 값은 변하지 않고, 항상 새로운 String 객체가 생성된다.

예를 들어,

String str1 = "hello";
String str2 = str1.toUpperCase();

위 코드에서 str1은 여전히 "hello"를 가리키고 있고, "HELLO"라는 새로운 문자열이 만들어져 str2가 참조한다. 원본 문자열은 전혀 변하지 않는다.


왜 불변성이 중요한가?

  1. 데이터 무결성 보장
    프로그램 중간에 다른 코드에서 문자열을 함부로 변경할 수 없다. 값이 변하지 않으니 예측 가능성이 높다.

  2. 멀티스레드 환경에서 안전
    여러 스레드가 동시에 같은 문자열을 참조해도 원본이 바뀌지 않으니 동기화 처리를 따로 하지 않아도 된다.

  3. 문자열 풀(String Pool) 활용
    자바는 문자열 리터럴을 효율적으로 관리하기 위해 String Pool을 사용한다. 동일한 문자열을 새로 만들지 않고 기존 객체를 재활용하여 메모리를 절약한다. 불변성이 보장되니 가능한 방식이다.


StringBuilder와 StringBuffer의 필요성

문제는 문자열 연산이 빈번할 때 발생한다.
String은 불변이라 concat(), replace() 등을 실행할 때마다 새로운 객체를 만든다. 반복적으로 문자열을 더하거나 바꾸는 작업이 많으면 메모리를 과도하게 쓰게 된다.

이럴 때 쓰는 것이 가변(Mutable) 클래스StringBuilderStringBuffer다.

  • StringBuilder : 가볍고 빠르다. 멀티스레드 환경에서 동기화를 보장하지 않는다.

  • StringBuffer : 동기화 처리가 되어 있어 멀티스레드 환경에서 안전하지만 무겁다.

일반적인 웹이나 단일 스레드 프로그램에서는 StringBuilder를 사용하는 게 효율적이다.

비유를 들자면,
만약 시체가 썩지 않고 계속 쌓인다고 생각해보자. 지구는 곧 시체로 가득 차 버릴 것이다. 그래서 시체는 썩어야 한다. String이 썩지 않는 시체라면, StringBuilderStringBuffer는 썩어 없어지며 재활용되는 시체와 같다.


String 주요 메서드 예제

예제 1

public class StringTest3 {
    public static void main(String[] args) {
        String str1 = new String("java Programing");
        String str2 = new String("재밌다");

        System.out.println(str1.startsWith("java")); // true
        System.out.println(str1.startsWith("test")); // false
        System.out.println(str1.endsWith("java"));   // false
        System.out.println(str1.endsWith("test"));   // false

        System.out.println(str1.contains("ja"));     // true
        System.out.println(str1.toUpperCase());      // JAVA PROGRAMING
        System.out.println(str1);                    // java Programing
        System.out.println(str1.toLowerCase());      // java programing

        System.out.println(str1.substring(5));       // Programing
        System.out.println(str1.substring(5, 10));   // Progr

        System.out.println(str1.replace('a','A'));   // jAvA ProgrAming
    }
}

예제 2

package api.lang;

public class StringTest2 {
    public static void main(String[] args) {
        String str1 = new String("java Programing");
        String str2 = new String("재밌다");

        System.out.println(str2);

        System.out.println("charAt(1): " + str1.charAt(1)); 
        System.out.println("concat: " + str1.concat(str2));
        System.out.println("indexOf('a'): " + str1.indexOf('a')); // 왼쪽에서 찾기
        System.out.println("indexOf(\"합\"): " + str1.indexOf("합")); // 못 찾으면 -1 반환

        System.out.println("length: " + str1.length());
        System.out.println("lastIndexOf('a'): " + str1.lastIndexOf('a'));

        System.out.println("equals: " + str1.equals("java Programing"));        // true
        System.out.println("equals: " + str1.equals("Java Programing"));        // false
        System.out.println("equalsIgnoreCase: " + str1.equalsIgnoreCase("java Programing")); // true
        System.out.println("equalsIgnoreCase: " + str1.equalsIgnoreCase("JAVA Programing")); // true
    }
}

결론

  • String은 불변이라 안전하지만, 많은 문자열 연산에는 비효율적일 수 있다.

  • 이 문제를 해결하기 위해 StringBuilderStringBuffer 같은 가변 객체가 존재한다.

  • 멀티스레드 환경이 아니라면 보통 StringBuilder를 사용하는 것이 가장 효율적이다.


좋습니다 👍 요청하신 대로 시체가 썩는 비유 + 컴퓨터 자원 설명을 합쳐서 다시 정리해드릴게요. 블로그에 바로 올려도 되는 자연스러운 문체로 풀어 쓰겠습니다.


자바 String 뜯어보기 – 불변성과 StringBuilder, StringBuffer의 존재 이유

자바에서 String은 가장 많이 쓰이는 클래스다. 그런데 String은 **불변 객체(Immutable Object)**라서 한 번 만들어지면 절대 변하지 않는다. 이 특징이 왜 중요한지, 또 왜 StringBuilder, StringBuffer 같은 클래스가 필요한지 살펴보자.


String은 왜 불변일까?

String의 값은 한 번 정해지면 절대 바뀌지 않는다.

String str1 = "hello";
String str2 = str1.toUpperCase();

여기서 str1은 여전히 "hello"를 가리키고 있고, "HELLO"라는 새로운 문자열이 만들어져 str2가 참조한다.
즉, str1이 변하는 게 아니라 새로운 메모리 공간을 잡아 새로운 객체가 만들어지는 것이다.


불변성이 중요한 이유

  1. 데이터 안정성
    다른 코드에서 문자열을 함부로 바꿀 수 없으니 값이 안전하다.

  2. 멀티스레드 환경에서 안전
    여러 스레드가 동시에 같은 문자열을 참조해도 원본이 변하지 않는다.

  3. 문자열 풀(String Pool) 재사용
    동일한 문자열을 매번 새로 만들지 않고 기존 것을 재활용할 수 있다.


하지만 문제는 "자원 낭비"

불변 객체의 단점은 문자열 연산이 많을 때 드러난다.
concat(), replace() 같은 메서드를 호출할 때마다 새로운 String 객체가 만들어지니, 메모리를 계속 차지하게 된다.

비유를 들어보자.

  • 불변인 String = 썩지 않는 시체
    사람이 죽었는데 시체가 썩지 않는다고 상상해보자. 시간이 지날수록 시체가 계속 쌓이고, 지구는 곧 시체로 가득 찰 것이다.
    String도 마찬가지다. 한 번 만들어진 문자열이 변하지 않고, 변경할 때마다 새로운 객체가 생겨 메모리를 계속 차지한다.

  • 가변 객체(StringBuilder, StringBuffer) = 썩어서 사라지는 시체
    반대로 시체가 썩으면 땅이 비워져서 새 생명이 자라난다. StringBuilderStringBuffer는 이런 식이다.
    내부에서 같은 메모리 공간을 재활용하기 때문에 새로운 객체를 만들지 않고도 문자열을 바꿀 수 있다.

즉,

  • 불변 String → 매번 새로운 메모리 주소를 차지한다. (자원 낭비)

  • 가변 StringBuilder/StringBuffer → 같은 메모리 공간 안에서 값만 바꾼다. (자원 효율적)


StringBuilder vs StringBuffer

  • StringBuilder : 가볍고 빠르다. 멀티스레드 환경에서는 안전하지 않지만, 일반적인 웹/앱 개발에서는 거의 이것만 쓰면 된다.

  • StringBuffer : 동기화 처리가 되어 있어 멀티스레드 환경에서 안전하다. 하지만 그만큼 무겁다.

👉 대부분의 경우 StringBuilder 사용이 정답이다.


예제 코드

public class StringTest3 {
    public static void main(String[] args) {
        String str1 = new String("java Programing");

        System.out.println(str1.toUpperCase());   // JAVA PROGRAMING (새 객체 생성)
        System.out.println(str1);                 // java Programing (원본은 그대로)

        // 불변 객체라 replace도 새로운 String 생성
        System.out.println(str1.replace('a','A')); // jAvA ProgrAming
    }
}

toUpperCase()replace()가 실행될 때마다 새로운 String 객체가 만들어진다.
즉, 불변이라 안전하지만, 연산이 많을 때는 메모리를 계속 먹는다.


결론

  • String은 불변이라 안전하고 예측 가능하다.

  • 하지만 문자열 연산이 많으면 메모리를 계속 차지한다.

  • 이 문제를 해결하기 위해 가변 객체StringBuilderStringBuffer가 존재한다.

  • 멀티스레드가 아니라면 StringBuilder를 쓰는 게 가장 효율적이다.


👉 한 줄 요약:
String은 "썩지 않는 시체"라 자원을 계속 차지한다. 그래서 "썩어서 사라지는 시체" 같은 StringBuilder를 써야 메모리를 아낄 수 있다.


스트링 버퍼와 스트링 빌더 둘다 스트링 클래스와 함수가 같나?
아닙니다. 
StringStringBufferStringBuilder는 서로 다른 목적과 특징을 가진 클래스이므로 제공하는 함수와 동작 방식이 다릅니다. 
핵심 차이점
구분 StringStringBufferStringBuilder
변동성불변(immutable)
생성된 문자열을 변경할 수 없으며, 변경 시 새로운 객체가 생성됩니다.
가변(mutable)
기존 객체 내에서 문자열 내용을 변경할 수 있습니다.
가변(mutable)
기존 객체 내에서 문자열 내용을 변경할 수 있습니다.
스레드 안정성안전
불변이므로 스레드로부터 안전합니다.
안전(Thread-safe)
동기화(synchronized)가 적용되어 멀티스레드 환경에서 안전합니다.
안전하지 않음(Not thread-safe)
동기화가 없어 단일 스레드 환경에서 사용됩니다.
성능문자열 변경 연산이 많을수록 성능이 떨어집니다 (새로운 객체 생성 때문).동기화 오버헤드 때문에 StringBuilder보다 느립니다.동기화가 없어 가장 빠릅니다. 단일 스레드 환경에서 최적의 성능을 제공합니다.



주요 함수 차이
  • String 클래스:
    • 주로 문자열 검색, 추출, 비교와 같은 불변 데이터를 다루는 함수를 제공합니다.
    • length()charAt()substring()equals() 등이 대표적입니다.
    • + 연산으로 문자열을 연결하면 내부적으로 StringBuilder를 사용해 새로운 String 객체를 만듭니다.
  • StringBuffer / StringBuilder 클래스:
    • 가변적인 문자열을 조작하기 위한 함수를 제공합니다. 두 클래스의 함수 목록은 거의 동일합니다.
    • append(): 문자열을 뒤에 덧붙입니다.
    • insert(): 특정 위치에 문자열을 삽입합니다.
    • delete(): 특정 범위의 문자를 삭제합니다.
    • reverse(): 문자열의 순서를 뒤집습니다.
    • replace(): 특정 범위의 문자를 다른 문자열로 교체합니다.
    • String 클래스의 substring()이나 length() 같은 함수도 포함하지만, 핵심 기능은 문자열 변경에 초점이 맞춰져 있습니다. 
요약
  • String: 변경이 거의 없는 상수 문자열에 적합합니다.
  • StringBuilder단일 스레드 환경에서 문자열을 자주 변경할 때 가장 좋은 성능을 제공합니다.
  • StringBuffer멀티스레드 환경에서 문자열을 자주 변경해야 할 때 안전하게 사용할 수 있습니다. 
AI 대답에는 오류가 있을 수 있습니다. 자세히 알아보기
  • [Java] String vs StringBuffer vs StringBuilder | da-nyee
    2025. 4. 26. — String vs StringBuffer, StringBuilder. String은 불...
    GitHub
  • String vs StringBuilder vs StringBuffer - Ethan's Coding Letter
    2021. 5. 13. — Java/Kotlin에서 문자열을 다루는 클래스로 String, StringBuilde...
    티스토리
  • [Java] String, StringBuffer, StringBuilder의 차이점과 사용이유
    2020. 5. 14. — StringBuffer와 StringBuilder클래스는 둘 다 크기가 유연하게 변하는...
    코딩팩토리
모두 표시
matches 함수랑 equals함수는 3개에 다 ㅣㅇㅆ지?
아닙니다. 
matches() 함수는 String 클래스에만 존재하며, StringBuffer와 StringBuilder에는 없습니다. equals() 함수는 세 클래스 모두에 있지만, 동작 방식이 다릅니다. 
matches() 함수
  • StringString.matches(String regex) 메서드를 통해 정규 표현식 패턴에 문자열 전체가 일치하는지 확인할 수 있습니다.
  • StringBufferStringBuilder: 이 두 클래스에는 matches() 메서드가 없습니다. 만약 StringBuffer나 StringBuilder의 내용을 정규 표현식과 비교하고 싶다면, toString() 메서드로 문자열로 변환한 후 String.matches()를 사용해야 합니다. 
equals() 함수 
  • StringString.equals(Object obj) 메서드는 두 문자열의 내용(콘텐츠)을 비교합니다. 내용이 완전히 동일하면 true를 반환합니다.
  • StringBufferStringBuilder: 이 두 클래스는 Object 클래스의 equals() 메서드를 상속받아 사용하며, 내용을 비교하도록 재정의하지 않습니다. 따라서 equals()를 호출하면 두 객체가 **동일한 메모리 주소(같은 객체)**를 가리키는지 비교합니다. 내용이 같더라도 다른 객체라면 false를 반환합니다.
    • 내용 비교 방법StringBuffer나 StringBuilder의 내용을 비교하려면, 마찬가지로 toString() 메서드를 사용해 String으로 변환한 후 String.equals()를 호출해야 합니다. 
AI 대답에는 오류가 있을 수 있습니다. 자세히 알아보기
  • Java .matches() - Strings - Codecademy
    2023. 2. 13. — matches() ... The . matches() method checks whet...
    Codecademy
  • Matcher appendReplacement(StringBuffer, String) method in ...
    2018. 11. 26. — The appendReplacement(StringBuffer, String) met...
    GeeksforGeeks
  • StringBuilder .equals Java - Stack Overflow
    2013. 9. 1. — Since StringBuilder does not have a equals method...
    Stack Overflow
모두 표시
정규식을 안쓰고 메시지를 인식하는 방법은 뭐지?
자바에서 정규식을 사용하지 않고 메시지 내용을 인식하는 방법은 여러 가지가 있으며, 대부분 
String 클래스가 제공하는 기본 메서드를 활용합니다. 어떤 방법을 사용할지는 요구사항의 복잡도에 따라 달라집니다. 
1. startsWith()와 endsWith()
메시지가 특정 문자열로 시작하거나 끝나는지를 확인할 때 사용합니다. 정규식 ^... 또는 ...$를 대체할 수 있습니다. 
예시:
java
// `rmsg`가 "led"로 시작하고 "on"을 포함하는지 확인 (정규식 대체)
// "led...on" 형태의 메시지 처리
if (rmsg.startsWith("led") && rmsg.contains("on")) {
    System.out.println("led켜기");
}
// `rmsg`가 "led"로 시작하고 "off"를 포함하는지 확인 (정규식 대체)
// "led...off" 형태의 메시지 처리
else if (rmsg.startsWith("led") && rmsg.contains("off")) {
    System.out.println("led끄기");
}
코드를 사용할 때는 주의가 필요합니다.
2. contains()
메시지에 특정 문자열이 포함되어 있는지 확인할 때 사용합니다. 
예시:
java
// 메시지에 "오류"라는 단어가 포함되어 있는지 확인
if (rmsg.contains("오류")) {
    System.out.println("오류 메시지 처리");
}
코드를 사용할 때는 주의가 필요합니다.
3. indexOf()
특정 문자열이 메시지 내에 처음 나타나는 인덱스를 반환합니다. 찾지 못하면 -1을 반환합니다. contains()보다 더 세밀한 위치 정보가 필요할 때 유용합니다. 
예시:
java
// "경고"라는 단어가 메시지에 있는지 확인
if (rmsg.indexOf("경고") != -1) {
    System.out.println("경고 메시지 처리");
}
코드를 사용할 때는 주의가 필요합니다.
4. split()
메시지를 특정 구분자로 나누어 배열로 만든 후 처리합니다. 구조화된 메시지를 다룰 때 유용합니다. split() 메서드는 인자로 정규식을 받지만, 일반적인 문자열 리터럴(","" ")을 사용해 간단히 나눌 수 있습니다. 
예시:
java
// "temp:25"와 같은 메시지를 처리
if (rmsg.startsWith("temp:")) {
    String[] parts = rmsg.split(":");
    int temperature = Integer.parseInt(parts[1]);
    System.out.println("현재 온도: " + temperature);
}
코드를 사용할 때는 주의가 필요합니다.
5. switch 문
메시지가 정확히 일치하는 여러 문자열 중 하나일 때 사용합니다. equals()를 여러 번 사용하는 것보다 가독성이 좋고 효율적일 수 있습니다. 
예시:
java
switch (rmsg) {
    case "ledon":
        System.out.println("led켜기");
        break;
    case "ledoff":
        System.out.println("led끄기");
        break;
    default:
        // 처리할 내용 없음
}
코드를 사용할 때는 주의가 필요합니다.
언제 어떤 방법을 사용할까?
  • 간단한 패턴 (시작, 끝, 포함): startsWith()endsWith()contains() 메서드를 사용하면 코드가 더 간결하고 읽기 쉽습니다.
  • 고정된 메시지 목록: switch 문을 사용하면 여러 equals() 조건문을 대체하여 깔끔한 코드를 만들 수 있습니다.
  • 복잡한 패턴: startsWith()contains()와 같은 메서드 조합으로 복잡한 로직을 구성할 수도 있지만, 이 경우 정규식을 사용하는 것이 오히려 코드를 더 간결하게 만들 수 있습니다.
요약: 정규식은 강력하지만 가독성이 낮고 오버헤드가 발생할 수 있습니다. 패턴이 간단할 때는 위에서 제시한 기본 String 메서드만으로도 충분히 메시지를 처리할 수 있습니다


자바 - 자바의 문자열 처리 스트링 버퍼와 스트링 빌더 둘다 스트링 클래스와 함수가 같을까?


스트링 버퍼와 스트링 빌더 둘다 스트링 클래스와 함수가 같나?
아닙니다. 
StringStringBufferStringBuilder는 서로 다른 목적과 특징을 가진 클래스이므로 제공하는 함수와 동작 방식이 다릅니다. 
핵심 차이점
구분 StringStringBufferStringBuilder
변동성불변(immutable)
생성된 문자열을 변경할 수 없으며, 변경 시 새로운 객체가 생성됩니다.
가변(mutable)
기존 객체 내에서 문자열 내용을 변경할 수 있습니다.
가변(mutable)
기존 객체 내에서 문자열 내용을 변경할 수 있습니다.
스레드 안정성안전
불변이므로 스레드로부터 안전합니다.
안전(Thread-safe)
동기화(synchronized)가 적용되어 멀티스레드 환경에서 안전합니다.
안전하지 않음(Not thread-safe)
동기화가 없어 단일 스레드 환경에서 사용됩니다.
성능문자열 변경 연산이 많을수록 성능이 떨어집니다 (새로운 객체 생성 때문).동기화 오버헤드 때문에 StringBuilder보다 느립니다.동기화가 없어 가장 빠릅니다. 단일 스레드 환경에서 최적의 성능을 제공합니다.



주요 함수 차이
  • String 클래스:
    • 주로 문자열 검색, 추출, 비교와 같은 불변 데이터를 다루는 함수를 제공합니다.
    • length()charAt()substring()equals() 등이 대표적입니다.
    • + 연산으로 문자열을 연결하면 내부적으로 StringBuilder를 사용해 새로운 String 객체를 만듭니다.
  • StringBuffer / StringBuilder 클래스:
    • 가변적인 문자열을 조작하기 위한 함수를 제공합니다. 두 클래스의 함수 목록은 거의 동일합니다.
    • append(): 문자열을 뒤에 덧붙입니다.
    • insert(): 특정 위치에 문자열을 삽입합니다.
    • delete(): 특정 범위의 문자를 삭제합니다.
    • reverse(): 문자열의 순서를 뒤집습니다.
    • replace(): 특정 범위의 문자를 다른 문자열로 교체합니다.
    • String 클래스의 substring()이나 length() 같은 함수도 포함하지만, 핵심 기능은 문자열 변경에 초점이 맞춰져 있습니다. 
요약
  • String: 변경이 거의 없는 상수 문자열에 적합합니다.
  • StringBuilder단일 스레드 환경에서 문자열을 자주 변경할 때 가장 좋은 성능을 제공합니다.
  • StringBuffer멀티스레드 환경에서 문자열을 자주 변경해야 할 때 안전하게 사용할 수 있습니다. 
AI 대답에는 오류가 있을 수 있습니다. 자세히 알아보기
  • [Java] String vs StringBuffer vs StringBuilder | da-nyee
    2025. 4. 26. — String vs StringBuffer, StringBuilder. String은 불...
    GitHub
  • String vs StringBuilder vs StringBuffer - Ethan's Coding Letter
    2021. 5. 13. — Java/Kotlin에서 문자열을 다루는 클래스로 String, StringBuilde...
    티스토리
  • [Java] String, StringBuffer, StringBuilder의 차이점과 사용이유
    2020. 5. 14. — StringBuffer와 StringBuilder클래스는 둘 다 크기가 유연하게 변하는...
    코딩팩토리
모두 표시
matches 함수랑 equals함수는 3개에 다 ㅣㅇㅆ지?
아닙니다. 
matches() 함수는 String 클래스에만 존재하며, StringBuffer와 StringBuilder에는 없습니다. equals() 함수는 세 클래스 모두에 있지만, 동작 방식이 다릅니다. 
matches() 함수
  • StringString.matches(String regex) 메서드를 통해 정규 표현식 패턴에 문자열 전체가 일치하는지 확인할 수 있습니다.
  • StringBufferStringBuilder: 이 두 클래스에는 matches() 메서드가 없습니다. 만약 StringBuffer나 StringBuilder의 내용을 정규 표현식과 비교하고 싶다면, toString() 메서드로 문자열로 변환한 후 String.matches()를 사용해야 합니다. 
equals() 함수 
  • StringString.equals(Object obj) 메서드는 두 문자열의 내용(콘텐츠)을 비교합니다. 내용이 완전히 동일하면 true를 반환합니다.
  • StringBufferStringBuilder: 이 두 클래스는 Object 클래스의 equals() 메서드를 상속받아 사용하며, 내용을 비교하도록 재정의하지 않습니다. 따라서 equals()를 호출하면 두 객체가 **동일한 메모리 주소(같은 객체)**를 가리키는지 비교합니다. 내용이 같더라도 다른 객체라면 false를 반환합니다.
    • 내용 비교 방법StringBuffer나 StringBuilder의 내용을 비교하려면, 마찬가지로 toString() 메서드를 사용해 String으로 변환한 후 String.equals()를 호출해야 합니다. 
AI 대답에는 오류가 있을 수 있습니다. 자세히 알아보기
  • Java .matches() - Strings - Codecademy
    2023. 2. 13. — matches() ... The . matches() method checks whet...
    Codecademy
  • Matcher appendReplacement(StringBuffer, String) method in ...
    2018. 11. 26. — The appendReplacement(StringBuffer, String) met...
    GeeksforGeeks
  • StringBuilder .equals Java - Stack Overflow
    2013. 9. 1. — Since StringBuilder does not have a equals method...
    Stack Overflow
모두 표시
정규식을 안쓰고 메시지를 인식하는 방법은 뭐지?
자바에서 정규식을 사용하지 않고 메시지 내용을 인식하는 방법은 여러 가지가 있으며, 대부분 
String 클래스가 제공하는 기본 메서드를 활용합니다. 어떤 방법을 사용할지는 요구사항의 복잡도에 따라 달라집니다. 
1. startsWith()와 endsWith()
메시지가 특정 문자열로 시작하거나 끝나는지를 확인할 때 사용합니다. 정규식 ^... 또는 ...$를 대체할 수 있습니다. 
예시:
java
// `rmsg`가 "led"로 시작하고 "on"을 포함하는지 확인 (정규식 대체)
// "led...on" 형태의 메시지 처리
if (rmsg.startsWith("led") && rmsg.contains("on")) {
    System.out.println("led켜기");
}
// `rmsg`가 "led"로 시작하고 "off"를 포함하는지 확인 (정규식 대체)
// "led...off" 형태의 메시지 처리
else if (rmsg.startsWith("led") && rmsg.contains("off")) {
    System.out.println("led끄기");
}
코드를 사용할 때는 주의가 필요합니다.
2. contains()
메시지에 특정 문자열이 포함되어 있는지 확인할 때 사용합니다. 
예시:
java
// 메시지에 "오류"라는 단어가 포함되어 있는지 확인
if (rmsg.contains("오류")) {
    System.out.println("오류 메시지 처리");
}
코드를 사용할 때는 주의가 필요합니다.
3. indexOf()
특정 문자열이 메시지 내에 처음 나타나는 인덱스를 반환합니다. 찾지 못하면 -1을 반환합니다. contains()보다 더 세밀한 위치 정보가 필요할 때 유용합니다. 
예시:
java
// "경고"라는 단어가 메시지에 있는지 확인
if (rmsg.indexOf("경고") != -1) {
    System.out.println("경고 메시지 처리");
}
코드를 사용할 때는 주의가 필요합니다.
4. split()
메시지를 특정 구분자로 나누어 배열로 만든 후 처리합니다. 구조화된 메시지를 다룰 때 유용합니다. split() 메서드는 인자로 정규식을 받지만, 일반적인 문자열 리터럴(","" ")을 사용해 간단히 나눌 수 있습니다. 
예시:
java
// "temp:25"와 같은 메시지를 처리
if (rmsg.startsWith("temp:")) {
    String[] parts = rmsg.split(":");
    int temperature = Integer.parseInt(parts[1]);
    System.out.println("현재 온도: " + temperature);
}
코드를 사용할 때는 주의가 필요합니다.
5. switch 문
메시지가 정확히 일치하는 여러 문자열 중 하나일 때 사용합니다. equals()를 여러 번 사용하는 것보다 가독성이 좋고 효율적일 수 있습니다. 
예시:
java
switch (rmsg) {
    case "ledon":
        System.out.println("led켜기");
        break;
    case "ledoff":
        System.out.println("led끄기");
        break;
    default:
        // 처리할 내용 없음
}
코드를 사용할 때는 주의가 필요합니다.
언제 어떤 방법을 사용할까?
  • 간단한 패턴 (시작, 끝, 포함): startsWith()endsWith()contains() 메서드를 사용하면 코드가 더 간결하고 읽기 쉽습니다.
  • 고정된 메시지 목록: switch 문을 사용하면 여러 equals() 조건문을 대체하여 깔끔한 코드를 만들 수 있습니다.
  • 복잡한 패턴: startsWith()contains()와 같은 메서드 조합으로 복잡한 로직을 구성할 수도 있지만, 이 경우 정규식을 사용하는 것이 오히려 코드를 더 간결하게 만들 수 있습니다.
요약: 정규식은 강력하지만 가독성이 낮고 오버헤드가 발생할 수 있습니다. 패턴이 간단할 때는 위에서 제시한 기본 String 메서드만으로도 충분히 메시지를 처리할 수 있습니다


코딩테스트에서 스트링 빌더를 사용하며 실무에서는 스트링을 사용하나?


좋은 질문입니다. 이 부분은 코딩테스트 vs 실무에서 사용하는 기준이 조금 다릅니다.

결론부터 말하면 👇

코딩테스트 → StringBuilder 자주 사용
실무 → 대부분 String 그대로 사용 (필요할 때만 StringBuilder)

이유를 차근차근 설명해보겠습니다.


1️⃣ 코딩테스트에서 StringBuilder를 많이 쓰는 이유

코딩테스트에서는 성능이 중요한 경우가 많습니다.

예를 들어

String s = "";

for(int i=0;i<100000;i++){
    s += i;
}

이 코드는 내부적으로

새 String 생성
기존 문자열 복사

100000번 발생합니다.

그래서 시간복잡도가 사실상

O(N²)

에 가까워질 수 있습니다.

그래서 코테에서는 이렇게 씁니다.

StringBuilder sb = new StringBuilder();

for(int i=0;i<100000;i++){
    sb.append(i);
}

String result = sb.toString();

이 경우

같은 메모리를 계속 사용

하므로

O(N)

이 됩니다.

그래서 코테에서는 거의 습관적으로 StringBuilder를 사용합니다.

특히 이런 문제에서 많이 씁니다.

  • 문자열 누적

  • 출력 문자열 만들기

  • 큰 문자열 생성

예)

백준
프로그래머스

2️⃣ 실무에서는 왜 대부분 String을 사용할까?

실무에서는 대부분 이렇게 씁니다.

String message = "user : " + name;

이유는 JVM 최적화 때문입니다.

자바 컴파일러는 이런 코드를 보면

String result = a + b + c;

실제로는 내부적으로

new StringBuilder()
.append(a)
.append(b)
.append(c)
.toString();

로 바꿔서 실행합니다.

단순한 문자열 연결은 JVM이 자동으로 StringBuilder로 변환합니다.

그래서 실무에서는 굳이 이렇게 안 씁니다.

StringBuilder sb = new StringBuilder();
sb.append("user:");
sb.append(name);

가독성이 떨어지기 때문입니다.


3️⃣ 실무에서 StringBuilder를 쓰는 경우

실무에서도 문자열을 반복해서 붙일 때는 StringBuilder를 씁니다.

예)

로그 문자열 생성

StringBuilder log = new StringBuilder();

for(User user : users){
    log.append(user.getName())
       .append(", ");
}

CSV / JSON 생성

StringBuilder csv = new StringBuilder();

for(Data d : list){
    csv.append(d.getName())
       .append(",")
       .append(d.getAge())
       .append("\n");
}

대용량 문자열 처리

  • HTML 생성

  • 파일 문자열 생성

  • 데이터 export


4️⃣ StringBuffer는 언제 쓰나?

솔직히 요즘 거의 안 씁니다.

이유

StringBuffer = synchronized

멀티스레드 안전

하지만 실무에서는 보통

StringBuilder + 다른 동기화

를 사용합니다.

그래서 대부분

StringBuilder > StringBuffer

입니다.


5️⃣ 실무 기준 정리

상황사용
문자열 상수String
단순 문자열 연결String
반복 문자열 생성StringBuilder
멀티스레드 문자열 수정StringBuffer (거의 안씀)

6️⃣ 면접에서 좋아하는 대답

면접에서 이 질문이 나오면 이렇게 답하면 좋습니다.

코딩테스트에서는 문자열을 반복적으로 생성하는 경우가 많아서 성능 때문에 StringBuilder를 사용합니다.
하지만 실무에서는 단순 문자열 연결은 JVM이 내부적으로 StringBuilder로 최적화하기 때문에 대부분 String을 사용하고, 반복적으로 문자열을 생성하는 경우에만 StringBuilder를 사용합니다.

이렇게 말하면 자바 내부 동작을 이해하는 개발자로 보입니다.


원하시면 제가 개발자들이 많이 틀리는 String 면접 질문 TOP 7도 정리해 드릴게요.
(실제로 네이버 / 카카오 면접에서도 자주 나오는 것들입니다.)





댓글