Programming languages/Java

StringBuilder Vs StringBuffer

yoooCo 2025. 4. 29. 20:43

๐ŸŽฏ StringBuilder & StringBuffer๋ž€?

๋ฌธ์ž์—ด์„ ์ˆ˜์ • ๊ฐ€๋Šฅ(mutable) ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์ž๋ฐ” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

String์€ ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด์ง€๋ฉด ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์ง€๋งŒ,
StringBuilder์™€ StringBuffer๋Š” ๊ธฐ์กด ๋ฌธ์ž์—ด์„ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ”ฅ String๊ณผ ์ฐจ์ด์ ์€?

๐Ÿ“Œ ๊ธฐ๋ณธ ๊ฐœ๋… ๋น„๊ต

๊ตฌ๋ถ„ String StringBuilder / StringBuffer
๋ณ€๊ฒฝ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ โŒ ๋ถˆ๋ณ€ (immutable) โœ… ๊ฐ€๋ณ€ (mutable)
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ์ƒˆ ๊ฐ์ฒด ๊ณ„์† ์ƒ์„ฑ ๊ธฐ์กด ๊ฐ์ฒด ์ˆ˜์ •
์„ฑ๋Šฅ ์ˆ˜์ • ๋งŽ์œผ๋ฉด ๋А๋ฆผ ๋น ๋ฆ„ (์ˆ˜์ •์— ์ตœ์ ํ™”)
โœจ ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด

String์€ ๋งค๋ฒˆ ์ƒˆ ์ข…์ด์— ์ƒˆ๋กœ ์“ฐ๋Š” ๋А๋‚Œ.
StringBuilder/StringBuffer๋Š” ๊ธฐ์กด ์ข…์ด์— ๊ณ ์ณ ์“ฐ๋Š” ๋А๋‚Œ!


๐ŸŽ๏ธ StringBuilder vs StringBuffer

๐Ÿ“Œ ๋‘˜์˜ ์ฐจ์ด

๊ตฌ๋ถ„ StringBuilder StringBuffer
์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ โŒ ๋น„๋™๊ธฐ (์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ์šฉ) โœ… ๋™๊ธฐํ™” (๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ์šฉ)
์„ฑ๋Šฅ ๋” ๋น ๋ฆ„ ๐Ÿš€ ์•ฝ๊ฐ„ ๋А๋ฆผ ๐Ÿข
์‚ฌ์šฉ ํ™˜๊ฒฝ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ

๐Ÿ’ก ํ˜ผ์ž ์“ฐ๋ฉด StringBuilder,
์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์™€ ๊ณต์œ ํ•˜๋ฉด StringBuffer๋ฅผ ์“ฐ์ž!

๐Ÿงฐ ๋‚ด๋ถ€ ๊ตฌ์กฐ

// StringBuilder (StringBuffer์™€ ๊ฑฐ์˜ ๋™์ผ)
public final class StringBuilder implements java.io.Serializable, CharSequence {
    private char[] value;
    private int count;
}
  • value : ์‹ค์ œ ๋ฌธ์ž๊ฐ€ ์ €์žฅ๋˜๋Š” ๋ฐฐ์—ด
  • count : ์ €์žฅ๋œ ๋ฌธ์ž ์ˆ˜

๐Ÿ—๏ธ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

โœ… ์ฃผ์š” ๊ธฐ๋Šฅ ์˜ˆ์‹œ

StringBuilder sb = new StringBuilder("Hello");

sb.append(" World");     // ๋ฌธ์ž์—ด ์ถ”๊ฐ€  --> Hello World
sb.insert(5, " Java");   // ํŠน์ • ์œ„์น˜์— ์‚ฝ์ž… --> Hello Java World
sb.delete(0, 6);          // ์ผ๋ถ€ ์‚ญ์ œ --> Java World
sb.reverse();             // ๋ฌธ์ž์—ด ๋’ค์ง‘๊ธฐ
๐Ÿ“ฅ ์ถœ๋ ฅ ๊ฒฐ๊ณผ
dlroW avaJ

๐Ÿ”‘ ์ฃผ์š” ๋ฉ”์„œ๋“œ ์ •๋ฆฌ

๋ฉ”์„œ๋“œ ์„ค๋ช…
append(str) ๋ฌธ์ž์—ด ๋์— ์ถ”๊ฐ€
insert(offset, str) ํŠน์ • ์œ„์น˜์— ์‚ฝ์ž…
delete(start, end) ๋ฒ”์œ„ ์‚ญ์ œ
replace(start, end, str) ๋ฒ”์œ„ ๊ต์ฒด
reverse() ๋ฌธ์ž์—ด ๋’ค์ง‘๊ธฐ
toString() ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ String์œผ๋กœ ๋ณ€ํ™˜

๐Ÿ›‘ ์ฃผ์˜ํ•  ์ : ์šฉ๋Ÿ‰(capacity) ๊ด€๋ฆฌ

๐Ÿ“Œ ์šฉ๋Ÿ‰ ์ฆ๊ฐ€ ๋กœ์ง

  • ๊ธฐ๋ณธ ์šฉ๋Ÿ‰: 16์นธ
  • ๋„˜์น˜๋ฉด (ํ˜„์žฌ ์šฉ๋Ÿ‰ ร— 2) + 2 ํฌ๊ธฐ๋กœ ์ž๋™ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค.
StringBuilder sb = new StringBuilder();
System.out.println(sb.capacity());  // 16

sb.append("12345678901234567");
System.out.println(sb.capacity());  // 34
์‰ฝ๊ฒŒ๋งํ•ด

์ž‘์€ ๊ณต์ฑ…์ด ๊ฝ‰ ์ฐจ๋ฉด,
๋‘ ๋ฐฐ ๋„˜๊ฒŒ ๋” ํฐ ์ƒˆ ๊ณต์ฑ…์œผ๋กœ ๊ฐˆ์•„ํƒ€๋Š” ๋А๋‚Œ์ด์—์š”!


๐ŸŒŸ ์‹ฌํ™”: StringBuilder ์ตœ์ ํ™” (Tuning)

๐Ÿ› ๏ธ 1. ์ดˆ๊ธฐ ์šฉ๋Ÿ‰(capacity) ์„ค์ •ํ•˜๊ธฐ

๋ฌธ์ž์—ด ํฌ๊ธฐ๊ฐ€ ๋Œ€๋žต ์˜ˆ์ƒ๋œ๋‹ค๋ฉด, ์ฒ˜์Œ๋ถ€ํ„ฐ ๋„‰๋„‰ํ•˜๊ฒŒ ์šฉ๋Ÿ‰์„ ์žก์•„์ฃผ์„ธ์š”.

StringBuilder sb = new StringBuilder(100);
๐Ÿ’ก ์žฅ์ : ์ค‘๊ฐ„์— ๋ฉ”๋ชจ๋ฆฌ ์žฌํ• ๋‹น์ด ์ผ์–ด๋‚˜์ง€ ์•Š์•„ ์„ฑ๋Šฅ์ด ์ข‹์•„์ง‘๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ 2. trimToSize()๋กœ ๋‚จ๋Š” ๊ณต๊ฐ„ ์ค„์ด๊ธฐ

์ž‘์—…์ด ๋๋‚œ ํ›„ ๋‚จ์€ ์—ฌ์œ  ๊ณต๊ฐ„์„ ๊น”๋”ํžˆ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

sb.trimToSize();
๐Ÿ’ก ์žฅ์ : ๋ถˆํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ค„์—ฌ ํšจ์œจ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ 3. append() ์ฒด์ด๋‹ ์ ๊ทน ํ™œ์šฉํ•˜๊ธฐ

  • append()๋ฅผ ์—ฐ์† ํ˜ธ์ถœํ•  ๋•Œ ์ฒด์ด๋‹ํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•˜๊ณ  ๋น ๋ฆ…๋‹ˆ๋‹ค.
  • ์ค‘๊ฐ„์— toString() ํ˜ธ์ถœ์€ ์ตœ๋Œ€ํ•œ ํ”ผํ•˜์„ธ์š”.
String result = new StringBuilder()
                    .append("Hello")
                    .append(" ")
                    .append("World")
                    .toString(); //toString()์€ ๊ฐ€๋Šฅํ•˜๋ฉด ๋งˆ์ง€๋ง‰์—!

๐ŸŒ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ StringBuffer ์ฃผ์˜์‚ฌํ•ญ

๐Ÿงฎ StringBuffer๋Š” ์ •๋ง ์™„๋ฒฝํ•˜๊ฒŒ ์•ˆ์ „ํ• ๊นŒ?

โŒ ๋ฉ”์„œ๋“œ ํ•˜๋‚˜ํ•˜๋‚˜๋Š” ์•ˆ์ „ํ•˜์ง€๋งŒ,
์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์กฐํ•ฉํ•  ๋•Œ๋Š” ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!

  • StringBuffer๋Š” ๊ฐ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ๋™๊ธฐํ™”๋˜์–ด ์žˆ์–ด์š”.
  • ํ•˜์ง€๋งŒ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์–ด์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š”, ๊ทธ ์งง์€ ์ˆœ๊ฐ„์— ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ผ์–ด๋“ค ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ‘‡ ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณผ๊ฒŒ์š”๐Ÿ‘‡

โ›”๏ธ ์ž˜๋ชป๋œ ์ฝ”๋“œ
if (buffer.length() == 0) {
    buffer.append("Hello");
}
  • length()๋กœ ๊ธธ์ด๋ฅผ ํ™•์ธํ•˜๊ณ 
  • ๊ทธ ๋‹ค์Œ append()๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‚ฌ์ด์— ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ผ์–ด๋“ค ์ˆ˜ ์žˆ์–ด์š”.
โœ… ์˜ฌ๋ฐ”๋ฅธ ์ฝ”๋“œ
synchronized(buffer) {
    if (buffer.length() == 0) {
        buffer.append("Hello");
    }
}
  • synchronized ๋ธ”๋ก์œผ๋กœ ์ „์ฒด ๊ณผ์ •์„ ๋ฌถ์œผ๋ฉด, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ผ์–ด๋“ค ํ‹ˆ์ด ์—†์Šต๋‹ˆ๋‹ค.
๐Ÿ“ ๋งŒ์•ฝ

์นœ๊ตฌ๋ž‘ ๊ฐ™์€ ๋ฌธ์„œ๋ฅผ ํŽธ์ง‘ํ•˜๋Š” ์ค‘์ธ๋ฐ,
๋‚ด๊ฐ€ โ€œ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ ํ›„์— ๊ทธ๋ฆผ์„ ์“ฐ๋ ค๊ณ โ€ ํ•˜๋Š” ์ˆœ๊ฐ„,
๋‹ค๋ฅธ ์นœ๊ตฌ๊ฐ€ ๋จผ์ € ๊ทธ ์ž๋ฆฌ์— ๊ธ€์„ ์จ๋ฒ„๋ฆฌ๋ฉด ๋‚ด๊ฐ€ ์“ฐ๋ ค๊ณ  ํ–ˆ๋˜ ๋‚ด์šฉ์€ ์ถฉ๋Œ์ด ๋‚˜๊ฑฐ๋‚˜ ๋‹ค์‹œ ์จ์•ผ ํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.

์ด๋Ÿฐ ์ƒํ™ฉ์„ ๋ง‰์œผ๋ ค๋ฉด, length()์™€ append()์ฒ˜๋Ÿผ ์—ฐ์†๋œ ์ž‘์—…์€ ํ•˜๋‚˜๋กœ ๋ฌถ๊ณ ,
๋‚ด๊ฐ€ ์ˆ˜์ •ํ•˜๋Š” ๋™์•ˆ์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋ผ์–ด๋“ค ์ˆ˜ ์—†๋„๋ก ์ž ๊ฐ€๋‘๋Š” ๊ฒŒ ์•ˆ์ „ํ•ด์š”.**

๐Ÿงฎ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋„ StringBuilder๋ฅผ ์“ธ ์ˆ˜ ์žˆ์„๊นŒ?

๋„ค! ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž๊ธฐ๋งŒ์˜ StringBuilder ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ 
  • ์„œ๋กœ ๊ณต์œ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ œ ์—†์Šต๋‹ˆ๋‹ค.
์˜ˆ์‹œ
public String buildMessage() {
    StringBuilder sb = new StringBuilder();
    sb.append("Hello");
    sb.append("World");
    return sb.toString();
}
  • ์—ฌ๊ธฐ์„œ๋Š” sb๊ฐ€ ์ด ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์•ˆ์ „ํ•ด์š”.

๐Ÿ’ก ๊ณต์œ ๋งŒ ์•ˆ ํ•˜๋ฉด, ๋ฌด์กฐ๊ฑด ๋น ๋ฅธ StringBuilder๋ฅผ ์“ฐ์ž! ๐Ÿš€


๐Ÿงฉ ์ตœ์ข… ์š”์•ฝ

๊ตฌ๋ถ„ ํŠน์ง• ์‚ฌ์šฉ ๊ฒฝ์šฐ
String ๋ถˆ๋ณ€ ๊ฐ์ฒด, ์ฝ๊ธฐ ์ค‘์‹ฌ ๋ฌธ์ž์—ด์ด ๋ณ€ํ•˜์ง€ ์•Š์„ ๋•Œ
StringBuilder ๊ฐ€๋ณ€ ๊ฐ์ฒด, ๋น ๋ฆ„ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ์ˆ˜์ • ์ž‘์—…
StringBuffer ๊ฐ€๋ณ€ ๊ฐ์ฒด, ๋А๋ฆผ (๋™๊ธฐํ™”) ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ์ˆ˜์ • ์ž‘์—…

๋ณ€๊ฒฝ์ด ์—†๋‹ค๋ฉด String, ๋น ๋ฅธ ์ˆ˜์ •์€ StringBuilder, ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ๋Š” StringBuffer!