๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Java] String์˜ intern() ์‚ฌ์šฉ ์‹œ์˜ ์„ฑ๋Šฅ ๋ฌธ์ œ์™€ ์ตœ์ ํ™”

์ถœ์ฒ˜

ChatGPT


String์˜ intern() ๋ฉ”์„œ๋“œ๋Š” ์ž๋ฐ” ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋ฌธ์ž์—ด์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•˜๊ณ  ๋ฌธ์ž์—ด ๋น„๊ต๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.

 

intern() ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘ ๋ฐฉ์‹

intern() ๋ฉ”์„œ๋“œ๋Š” ๋ฌธ์ž์—ด์„ String Constant Pool์— ์ €์žฅํ•˜๊ณ , ๋™์ผํ•œ ๋‚ด์šฉ์˜ ๋ฌธ์ž์—ด์ด intern() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜๋‹ค.

 

  • String Constant Pool์€ ํž™ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์˜ ํŠน์ • ์˜์—ญ์œผ๋กœ, ์ค‘๋ณต๋œ ๋ฌธ์ž์—ด ๊ฐ์ฒด๋ฅผ ์ค„์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • intern() ๋ฉ”์„œ๋“œ๋Š” ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด์ด ์ƒ์ˆ˜ ํ’€์— ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ๊ทธ ํ’€์— ์žˆ๋Š” ๋ฌธ์ž์—ด์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์—ฌ ํ’€์— ์ถ”๊ฐ€ํ•œ ํ›„ ๊ทธ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์‚ฌ์šฉ ์˜ˆ

String str1 = new String("hello");
String str2 = new String("hello");

String internedStr1 = str1.intern();
String internedStr2 = str2.intern();

System.out.println(internedStr1 == internedStr2); // true

 

 

์„ฑ๋Šฅ ๋ฌธ์ œ

 

๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ

  • ๋ฌธ์ œ: ์ž์ฃผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ž์—ด์„ intern() ๋ฉ”์„œ๋“œ๋กœ ์ƒ์ˆ˜ ํ’€์— ์ €์žฅํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•œ๋‹ค. ํŠนํžˆ, ๋Œ€๋Ÿ‰์˜ ๋ฌธ์ž์—ด์„ intern() ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์ด ๊ธ‰๊ฒฉํžˆ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์„ค๋ช…: ์ƒ์ˆ˜ ํ’€์˜ ํฌ๊ธฐ๊ฐ€ ์ œํ•œ๋˜์–ด ์žˆ์œผ๋ฉฐ, JVM ๊ตฌํ˜„์— ๋”ฐ๋ผ ํฌ๊ธฐ๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ณด๋‹ค ๋งŽ์€ ๋ฌธ์ž์—ด์„ ํ’€์— ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ํ•˜๋ฉด OutOfMemoryError๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๋น„์šฉ์ด ํฐ ์ƒ์ˆ˜ ํ’€ ๊ด€๋ฆฌ

  • ๋ฌธ์ œ: intern() ๋ฉ”์„œ๋“œ๋Š” ์ƒ์ˆ˜ ํ’€์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ๋น„์šฉ์ด ๋งŽ์ด ๋“ค๋ฉฐ, ํŠนํžˆ intern() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด ๋นˆ๋ฒˆํ•œ ๊ฒฝ์šฐ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์„ค๋ช…: ์ƒ์ˆ˜ ํ’€์— ์ƒˆ๋กœ์šด ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ณผ์ •์—์„œ ํ•ด์‹œ๋งต์˜ ์กฐํšŒ์™€ ์‚ฝ์ž… ๋น„์šฉ์ด ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋กœ ์ธํ•ด ์„ฑ๋Šฅ์ด ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค.

์“ฐ๋ ˆ๋“œ ๋™๊ธฐํ™” ๋ฌธ์ œ

  • ๋ฌธ์ œ: String.intern()์€ synchronized๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์–ด, ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์„ฑ๋Šฅ ์ €ํ•˜์™€ ๋ณ‘๋ชฉ ํ˜„์ƒ์„ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์„ค๋ช…: ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— intern()์„ ํ˜ธ์ถœํ•˜๋ฉด ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ตœ์ ํ™” ๋ฐฉ๋ฒ•

1. intern() ์‚ฌ์šฉ ์ œํ•œ

  • ์„ค๋ช…: ๋ฌด์กฐ๊ฑด์ ์ธ intern() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํ”ผํ•˜๊ณ , ์ •๋ง๋กœ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•œ๋‹ค. ํŠนํžˆ, ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” ์‚ฌ์šฉ์„ ํ”ผํ•ด์•ผ ํ•œ๋‹ค.
  • ์˜ˆ์‹œ ์ฝ”๋“œ:
String frequentlyUsed = "hello".intern();  // ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ์ž์—ด๋งŒ intern
String rarelyUsed = new String("world");   // ๋“œ๋ฌผ๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ์ž์—ด์€ internํ•˜์ง€ ์•Š์Œ

 

2. ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ž์—ด ์บ์‹ฑ

  • ์„ค๋ช…: ํŠน์ • ๋ฌธ์ž์—ด์ด ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค๋ฉด ์บ์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•˜๋„๋ก ์„ค๊ณ„ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ƒ์ˆ˜ ํ’€์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์˜ˆ์‹œ ์ฝ”๋“œ:
import java.util.Map;
import java.util.HashMap;

public class StringCaching {
    private static Map<String, String> cache = new HashMap<>();

    public static String getCachedString(String input) {
        return cache.computeIfAbsent(input, String::intern);
    }

    public static void main(String[] args) {
        String str1 = getCachedString("example");
        String str2 = getCachedString("example");
        System.out.println(str1 == str2); // true
    }
}

 

3. ํด๋ž˜์Šค ๋กœ๋”ฉ ์‹œ์˜ Intern ์‚ฌ์šฉ ์ฃผ์˜

  • ์„ค๋ช…: ํด๋ž˜์Šค ๋กœ๋”ฉ ์‹œ ๋Œ€๋Ÿ‰์˜ ๋ฌธ์ž์—ด์„ intern() ๋ฉ”์„œ๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด JVM์˜ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ํด๋ž˜์Šค ๋กœ๋”ฉ ์‹œ ๋ถˆํ•„์š”ํ•œ intern() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํ”ผํ•ด์•ผ ํ•œ๋‹ค.

4. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ์กฐ์ ˆ

  • ์„ค๋ช…: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ดˆ๊ธฐํ™” ์‹œ์ ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ž์—ด์„ intern() ๋ฉ”์„œ๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์กฐ์ ˆํ•œ๋‹ค.

5. ๋Œ€์ฒด ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์‚ฌ์šฉ

  • ์„ค๋ช…: ๋ฌธ์ž์—ด ์ค‘๋ณต์„ ์ค„์ด๊ธฐ ์œ„ํ•ด HashSet ๋˜๋Š” Map๊ณผ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ค‘๋ณต๋œ ๋ฌธ์ž์—ด์„ ๊ด€๋ฆฌํ•œ๋‹ค.
  • ์˜ˆ์‹œ ์ฝ”๋“œ:
import java.util.Set;
import java.util.HashSet;

public class StringSetExample {
    private static Set<String> stringSet = new HashSet<>();

    public static String getUniqueString(String input) {
        if (!stringSet.contains(input)) {
            stringSet.add(input);
        }
        return input;
    }

    public static void main(String[] args) {
        String str1 = getUniqueString("data");
        String str2 = getUniqueString("data");
        System.out.println(str1 == str2); // true
    }
}

 

6. GC ํŠœ๋‹ ๋ฐ ํ”„๋กœํŒŒ์ผ๋ง

  • ์„ค๋ช…: ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด JVM์˜ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜(GC) ์„ค์ •์„ ์กฐ์ •ํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํŒŒ์ผ๋ง์„ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ํŒจํ„ด์„ ๋ถ„์„ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.

์ถœ์ฒ˜

  1. ๊ณต์‹ Java ๋ฌธ์„œ
    • Java String Documentation
      • ๋‚ด์šฉ: String ํด๋ž˜์Šค์˜ intern() ๋ฉ”์„œ๋“œ์™€ ๊ด€๋ จ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๊ถŒ์œ„ ์žˆ๋Š” ์„œ์ 
    • "Effective Java" by Joshua Bloch
      • ๋‚ด์šฉ: String ๊ฐ์ฒด์˜ ์‚ฌ์šฉ๊ณผ ์ƒ์„ฑ ๋ฐฉ๋ฒ•์— ๊ด€ํ•œ ์ตœ์ ํ™”๋œ ์‚ฌ์šฉ ํŒจํ„ด๊ณผ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
      • ๋งํฌ: Effective Java
    • "Java Performance: The Definitive Guide" by Scott Oaks
      • ๋‚ด์šฉ: ์ž๋ฐ”์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์™€ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๋Š” ์„ค๋ช…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
      • ๋งํฌ: Java Performance: The Definitive Guide
  3. ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ ๋ฐ ์˜จ๋ผ์ธ ์ž๋ฃŒ
    • Baeldung: String Interning in Java
      • ๋‚ด์šฉ: intern() ๋ฉ”์„œ๋“œ์˜ ์‚ฌ์šฉ๋ฒ•๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • GeeksforGeeks: Java String intern() Method
      • ๋‚ด์šฉ: ์ž๋ฐ”์—์„œ intern() ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ์‚ฌ๋ก€์™€ ์„ค๋ช…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.