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

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

[Java] TreeMap ๊ตฌํ˜„

์ถœ์ฒ˜

ChatGPT

์ž๋ฐ” 8 ์†Œ์Šค ์ฝ”๋“œ


TreeMap์€ ์ž๋ฐ”์—์„œ ์ •๋ ฌ๋œ ํ‚ค-๊ฐ’ ์Œ์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” NavigableMap ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด์ด๋‹ค. TreeMap์€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ(Red-Black Tree) ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด ํ‚ค-๊ฐ’์„ ์ €์žฅํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์‚ฝ์ž…, ์‚ญ์ œ, ๊ฒ€์ƒ‰ ๋“ฑ์˜ ์—ฐ์‚ฐ์ด O(log n) ์‹œ๊ฐ„ ๋ณต์žก๋„๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

 

1. TreeMap์˜ ์ฃผ์š” ํŠน์ง•

์ •๋ ฌ๋œ ์ˆœ์„œ

TreeMap์€ ํ•ญ์ƒ ์ •๋ ฌ๋œ ์ƒํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ํ‚ค์˜ ์ž์—ฐ ์ˆœ์„œ(Natural Ordering)์— ๋”ฐ๋ผ ์ •๋ ฌ๋˜์ง€๋งŒ, Comparator๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •์˜ ์ •๋ ฌ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ ๊ธฐ๋ฐ˜

๋‚ด๋ถ€์ ์„๋กœ ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ๋ผ๋Š” ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ๋ณ€ํ˜•์„ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ๋Š” ์‚ฝ์ž…, ์‚ญ์ œ ์‹œ ์ž๋™์œผ๋กœ ๊ท ํ˜•์„ ๋งž์ถ”๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋„ O(log n) ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•œ๋‹ค.

์ค‘๋ณต๋œ ํ‚ค ํ—ˆ์šฉ ์•ˆ ํ•จ

TreeMap์€ ์ค‘๋ณต๋œ ํ‚ค๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋งŒ์•ฝ ๋™์ผํ•œ ํ‚ค๊ฐ€ ์‚ฝ์ž…๋˜๋ฉด, ๊ธฐ์กด ๊ฐ’์„ ๋ฎ์–ด์“ด๋‹ค.

Null ํ‚ค ๋ถˆํ—ˆ

TreeMap์€ null ํ‚ค๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋งŒ์•ฝ null ํ‚ค๋ฅผ ์‚ฝ์ž…ํ•˜๋ ค๊ณ  ํ•˜๋ฉด NullPointerException์ด ๋ฐœ์ƒํ•œ๋‹ค. ๋‹ค๋งŒ null ๊ฐ’์€ ํ—ˆ์šฉ๋œ๋‹ค.

 

2. TreeMap์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ

TreeMap์€ ๋‚ด๋ถ€์ ์œผ๋กœ TreeMap.Entry<K, V>๋ผ๋Š” ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ์—์„œ ํ•˜๋‚˜์˜ ํ‚ค-๊ฐ’ ์Œ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์™ผ์ชฝ ์ž์‹๊ณผ ์˜ค๋ฅธ์ชฝ ์ž์‹, ๋ถ€๋ชจ ๋…ธ๋“œ, ๊ทธ๋ฆฌ๊ณ  ์ƒ‰์ƒ ์ •๋ณด(๋ ˆ๋“œ ๋˜๋Š” ๋ธ”๋ž™)๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.

static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;  // ํ‚ค
    V value;  // ๊ฐ’
    Entry<K,V> left;  // ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ
    Entry<K,V> right;  // ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ
    Entry<K,V> parent;  // ๋ถ€๋ชจ ๋…ธ๋“œ
    boolean color = BLACK;  // ๋…ธ๋“œ์˜ ์ƒ‰์ƒ (RED ๋˜๋Š” BLACK)

    // Entry ์ƒ์„ฑ์ž
    Entry(K key, V value, Entry<K,V> parent) {
        this.key = key;
        this.value = value;
        this.parent = parent;
    }

    public K getKey() { return key; }
    public V getValue() { return value; }
    public V setValue(V value) {
        V oldValue = this.value;
        this.value = value;
        return oldValue;
    }
}

 

์ฃผ์š” ํ•„๋“œ

  • key : ํŠธ๋ฆฌ์—์„œ ํ‚ค
  • value : ํ‚ค์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’
  • left, right : ์™ผ์ชฝ ๋ฐ ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ
  • parent : ๋ถ€๋ชจ ๋…ธ๋“œ
  • color : ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์—์„œ ๋…ธ๋“œ์˜ ์ƒ‰์ƒ(๋นจ๊ฐ• ๋˜๋Š” ๊ฒ€์ •)

 

3. ๋ ˆ๋“œ ๋ธ”๋ž™ ํŠธ๋ฆฌ๋ž€?

๋ ˆ๋“œ ๋ธ”๋ž™ ํŠธ๋ฆฌ(Red-Balck Tree)๋Š” ์ž๊ฐ€ ๊ท ํ˜• ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์ผ์ •์œผ๋กœ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์„ ๋”ฐ๋ฅธ๋‹ค.

  • ๊ฐ ๋…ธ๋“œ๋Š” ๋นจ๊ฐ„์ƒ‰(RED) ๋˜๋Š” ๊ฒ€์ •์ƒ‰(BLACK) ์ค‘ ํ•˜๋‚˜์˜ ์ƒ‰์„ ๊ฐ€์ง„๋‹ค.
  • ๋ฃจํŠธ ๋…ธ๋“œ๋Š” ํ•ญ์ƒ ๊ฒ€์€์ƒ‰์ด๋‹ค
  • ๋ชจ๋“  ๋ฆฌํ”„ ๋…ธ๋“œ(NIL)๋Š” ๊ฒ€์€์ƒ‰์ด๋‹ค. 
  • ๋นจ๊ฐ„์ƒ‰ ๋…ธ๋“œ์˜ ์ž์‹์€ ๋ฐ˜๋“œ์‹œ ๊ฒ€์€์ƒ‰์ด๋‹ค.(์ฆ‰, ๋‘ ๊ฐœ์˜ ๋นจ๊ฐ„์ƒ‰ ๋…ธ๋“œ๊ฐ€ ์—ฐ์†ํ•ด ๋‚˜ํƒ€๋‚  ์ˆ˜ ์—†๋‹ค.)
  • ๋ฃจํŠธ์—์„œ ๊ฐ ๋ฆฌํ”„ ๋…ธ๋“œ๊นŒ์ง€์˜ ๋ชจ๋“  ๊ฒฝ๋กœ๋Š” ๋™์ผํ•œ ์ˆ˜์˜ ๊ฒ€์€์ƒ‰ ๋…ธ๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค.(๊ท ํ˜• ์กฐ๊ฑด)

์ด ๊ทœ์น™์„ ํ†ตํ•ด ํŠธ๋ฆฌ๊ฐ€ ๋ถˆ๊ท ํ˜•ํ•˜๊ฒŒ ์ž๋ผ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋„ O(log n)์˜ ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•œ๋‹ค.

 

4. TreeMap์˜ ์ฃผ์š” ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„

1. ์‚ฝ์ž… ์—ฐ์‚ฐ put() ๋ฉ”์†Œ๋“œ

TreeMap์—์„œ ์š”์†Œ๋ฅผ ์‚ฝ์ž…ํ•  ๋•Œ๋Š” ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ์‚ฝ์ž… ๊ทœ์น™์„ ๋”ฐ๋ฅธ๋‹ค. ์š”์†Œ๋ฅผ ํŠธ๋ฆฌ์— ์‚ฝ์ž…ํ•œ ํ›„, ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๋„๋ก ํŠธ๋ฆฌ๋ฅผ ์žฌ์กฐ์ •(ํšŒ์ „ ๋ฐ ์ƒ‰์ƒ ๋ณ€๊ฒฝ)ํ•œ๋‹ค.

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    int cmp;
    Entry<K,V> parent;
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
        Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    Entry<K,V> e = new Entry<>(key, value, parent);
    if (cmp < 0)
        parent.left = e;
    else
        parent.right = e;
    fixAfterInsertion(e);
    size++;
    modCount++;
    return null;
}

 

์ฃผ์š” ๋™์ž‘

  • ํ‚ค ๋น„๊ต : ์ฃผ์–ด์ง„ ํ‚ค๋ฅผ ํŠธ๋ฆฌ์˜ ๊ธฐ์กด ํ‚ค๋“ค๊ณผ ๋น„๊ตํ•œ๋‹ค. ๋น„๊ต๋Š” ์ž์—ฐ ์ˆœ์„œ๋‚˜ Comparator๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์‚ฝ์ž… ์œ„์น˜ ๊ฒฐ์ • : ์ƒˆ ํ‚ค์˜ ์œ„์น˜๊ฐ€ ๊ฒฐ์ •๋˜๋ฉด ํŠธ๋ฆฌ์— ์‚ฝ์ž…๋œ๋‹ค.
  • ํŠธ๋ฆฌ ์žฌ์กฐ์ • : ์‚ฝ์ž… ํ›„ ํŠธ๋ฆฌ์˜ ๊ท ํ˜•์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ํšŒ์ „๊ณผ ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์ž‘์—…์ด ์ด๋ฃจ์–ด์ง„๋‹ค. ์ด๋Š” fixAfterInsertion() ๋ฉ”์†Œ๋“œ์—์„œ ์ˆ˜ํ–‰๋œ๋‹ค.

2. ๊ฒ€์ƒ‰ ์—ฐ์‚ฐ get() ๋ฉ”์†Œ๋“œ

TreeMap์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•  ๋•Œ๋Š” ์ด์ง„ ํƒ์ƒ‰์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ฃผ์–ด์ง„ ํ‚ค์™€ ํŠธ๋ฆฌ์˜ ๊ฐ ๋…ธ๋“œ์˜ ํ‚ค๋ฅผ ๋น„๊ตํ•ด ๊ฒ€์ƒ‰ํ•œ๋‹ค.

public V get(Object key) {
    Entry<K,V> p = getEntry(key);
    return (p == null ? null : p.value);
}

final Entry<K,V> getEntry(Object key) {
    if (comparator != null)
        return getEntryUsingComparator(key);
    if (key == null)
        throw new NullPointerException();
    @SuppressWarnings("unchecked")
    Comparable<? super K> k = (Comparable<? super K>) key;
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = k.compareTo(p.key);
        if (cmp < 0)
            p = p.left;
        else if (cmp > 0)
            p = p.right;
        else
            return p;
    }
    return null;
}

 

์ฃผ์š” ๋™์ž‘

  • ํ‚ค ๋น„๊ต : ๊ฒ€์ƒ‰ํ•  ํ‚ค๋ฅผ ํŠธ๋ฆฌ์˜ ๊ฐ ๋…ธ๋“œ์˜ ํ‚ค์™€ ๋น„๊ตํ•˜๋ฉฐ ์™ผ์ชฝ ๋˜๋Š” ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™ํ•œ๋‹ค.
  • ํ‚ค ๋ฐœ๊ฒฌ : ์ฃผ์–ด์ง„ ํ‚ค๋ฅผ ์ฐพ์œผ๋ฉด ํ•ด๋‹น ํ‚ค์— ๋งคํ•‘๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ฐพ์ง€ ๋ชปํ•  ๊ฒฝ์šฐ null์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

3. ์‚ญ์ œ ์—ฐ์‚ฐ remove() ๋ฉ”์†Œ๋“œ

TreeMap์—์„œ ๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•  ๋•Œ๋Š” ํŠธ๋ฆฌ์˜ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

  1. ์ž์‹์ด ์—†๋Š” ๋…ธ๋“œ : ๋‹จ์ˆœํžˆ ๋…ธ๋“œ๋ฅผ ์ œ๊ฑฐ
  2. ํ•˜๋‚˜์˜ ์ž์‹์ด ์žˆ๋Š” ๋…ธ๋“œ : ์ž์‹์„ ๋ถ€๋ชจ ๋…ธ๋“œ์— ์—ฐ๊ฒฐ
  3. ๋‘ ๊ฐœ์˜ ์ž์‹์ด ์žˆ๋Š” ๋…ธ๋“œ : ์ค‘์œ„ ํ›„์†์ž(successor) ๋…ธ๋“œ๋กœ ๊ต์ฒดํ•œ ํ›„, ํ›„์†์ž๋ฅผ ์‚ญ์ œ

์‚ญ์ œ ํ›„์—๋„ ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ๊ทœ์น™์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํŠธ๋ฆฌ๋ฅผ ์žฌ์กฐ์ •ํ•œ๋‹ค.

public V remove(Object key) {
    Entry<K,V> p = getEntry(key);
    if (p == null)
        return null;

    V oldValue = p.value;
    deleteEntry(p);
    return oldValue;
}

private void deleteEntry(Entry<K,V> p) {
    modCount++;
    size--;

    if (p.left != null && p.right != null) {
        Entry<K,V> s = successor(p);
        p.key = s.key;
        p.value = s.value;
        p = s;
    }

    Entry<K,V> replacement = (p.left != null ? p.left : p.right);

    if (replacement != null) {
        replacement.parent = p.parent;
        if (p.parent == null)
            root = replacement;
        else if (p == p.parent.left)
            p.parent.left = replacement;
        else
            p.parent.right = replacement;

        p.left = p.right = p.parent = null;

        if (p.color == BLACK)
            fixAfterDeletion(replacement);
    } else if (p.parent == null) {
        root = null;
    } else {
        if (p.color == BLACK)
            fixAfterDeletion(p);

        if (p.parent != null) {
            if (p == p.parent.left)
                p.parent.left = null;
            else if (p == p.parent.right)
                p.parent.right = null;
            p.parent = null;
        }
    }
}

 

์ฃผ์š” ๋™์ž‘

  • ๋…ธ๋“œ ์‚ญ์ œ : ์‚ญ์ œํ•  ๋…ธ๋“œ๋ฅผ ์ฐพ๊ณ , ์ž์‹ ๋…ธ๋“œ์˜ ์ˆ˜์— ๋”ฐ๋ผ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์‚ญ์ œ
  • ํŠธ๋ฆฌ ์žฌ์กฐ์ • : ์‚ญ์ œ ํ›„ ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ๊ท ํ˜•์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด fixAfterDeletion() ๋ฉ”์†Œ๋“œ์—์„œ ํŠธ๋ฆฌ๋ฅผ ์žฌ์กฐ์ •ํ•œ๋‹ค.

 

5. ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ๊ท ํ˜• ์œ ์ง€ (ํšŒ์ „ ๋ฐ ์ƒ‰์ƒ ๋ณ€๊ฒฝ)

์‚ฝ์ž…๊ณผ ์‚ญ์ œ ํ›„ ํŠธ๋ฆฌ์˜ ๊ท ํ˜•์„ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ํšŒ์ „๊ณผ ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์ž‘์—…์ด ์ด๋ฃจ์–ด์ง„๋‹ค. TreeMap์˜ ๋‚ด๋ถ€์—์„œ๋Š” fixAfterInsertion()๊ณผ fixAfterDeletion() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ๊ทœ์น™์„ ์œ ์ง€ํ•œ๋‹ค.

  • ํšŒ์ „ : ์‚ฝ์ž… ๋˜๋Š” ์‚ญ์ œ๋กœ ์ธํ•œ ํŠธ๋ฆฌ๊ฐ€ ๋ถˆ๊ท ํ˜•ํ•ด์ง€๋ฉด, ์™ผ์ชฝ ๋˜๋Š” ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํšŒ์ „ํ•ด ํŠธ๋ฆฌ์˜ ๊ท ํ˜•์„ ๋งž์ถ˜๋‹ค.
  • ์ƒ‰์ƒ ๋ณ€๊ฒฝ : ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ๊ทœ์น™์— ๋”ฐ๋ผ ๋…ธ๋“œ์˜ ์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•ด ํŠธ๋ฆฌ์˜ ๊ท ํ˜•์„ ์œ ์ง€ํ•œ๋‹ค.

 

6. TreeMap์˜ ์„ฑ๋Šฅ

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : TreeMap์˜ ๋ชจ๋“  ์—ฐ์‚ฐ(์‚ฝ์ž…, ์‚ญ์ œ, ๊ฒ€์ƒ‰)์€ O(log n) ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค. ์ด๋Š” ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ์˜ ์ž๊ฐ€ ๊ท ํ˜• ํŠน์„ฑ ๋•๋ถ„์ด๋‹ค.
  • ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ: TreeMap์€ ๊ฐ ๋…ธ๋“œ๊ฐ€ ์ถ”๊ฐ€์ ์ธ ์ƒ‰์ƒ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ HashMap๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๋‹ค์†Œ ๋†’์„ ์ˆ˜ ์žˆ๋‹ค.

 

๊ฒฐ๋ก 

TreeMap์€ ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋œ ์ •๋ ฌ๋œ ๋งต์œผ๋กœ, ์‚ฝ์ž…, ์‚ญ์ œ, ๊ฒ€์ƒ‰ ๋“ฑ์—์„œ O(log n) ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ํ•ญ์ƒ ์ •๋ ฌ๋œ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜, ๋ฒ”์œ„ ๊ฒ€์ƒ‰์ด ์ž์ฃผ ํ•„์š”ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•œ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.