Skip to content

Latest commit

ย 

History

History
1082 lines (753 loc) ยท 46.3 KB

File metadata and controls

1082 lines (753 loc) ยท 46.3 KB

์Šคํ„ฐ๋””์—์„œ ์•Œ์•„๊ฐ€๋Š” ๊ฒƒ

1. false์ธ ์ด์œ 

public class Test {
    private String name;

    public Test(String name) {
        this.name = name;
    }

    @Override
        public boolean equals(Object obj) {
            if (obj instanceof Test) {
                return this.name.equals(((Test) obj).name);
            }
            return false;
        }

    public static void main(String[] args) throws Exception {
        Set<Test> set = new HashSet<>();
        Test test = new Test("java");
        set.add(test);
        Test test2 = new Test("java");
        System.out.println(set.contains(test2)); //false
    }
}

์œ„ ์ฝ”๋“œ์—์„œ Set<Test>์— ๋™์ผํ•œ name ๊ฐ’์„ ๊ฐ€์ง„ ๊ฐ์ฒด(test์™€ test2)๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ๊ทธ ํ›„ set.contains(test2)๊ฐ€ false๋กœ ์ถœ๋ ฅ๋˜๋Š” ์ด์œ ๋Š” HashSet์ด ๋‚ด๋ถ€์ ์œผ๋กœ equals์™€ hashCode ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•ด ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ์„ ๋น„๊ตํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด์œ 

HashSet์€ ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ด์‹œ ๊ธฐ๋ฐ˜ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค. HashSet์ด ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์กฐํšŒํ•  ๋•Œ๋Š” equals๋ฟ๋งŒ ์•„๋‹ˆ๋ผ hashCode ๋ฉ”์„œ๋“œ๋„ ์‚ฌ์šฉํ•œ๋‹ค.

  • equals: ๋‘ ๊ฐ์ฒด๊ฐ€ ๋™์ผํ•œ์ง€ ๋น„๊ตํ•˜๋Š” ๋ฉ”์„œ์ด๋‹ค. ํ˜„์žฌ equals ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ name ๊ฐ’๋งŒ์„ ๊ธฐ์ค€์œผ๋กœ ๋น„๊ตํ•˜๋„๋ก ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ test์™€ test2๋Š” equals ๋ฉ”์„œ๋“œ ์ƒ์œผ๋กœ๋Š” ๋™์ผํ•œ ๊ฐ์ฒด๋กœ ํŒ๋‹จ
  • hashCode: ๊ฐ์ฒด๋ฅผ ํ•ด์‹œ ํ…Œ์ด๋ธ”์—์„œ ๋น ๋ฅด๊ฒŒ ์ฐพ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์ •์ˆ˜ ๊ฐ’์ด๋‹ค. HashSet์ด๋‚˜ HashMap๊ณผ ๊ฐ™์€ ํ•ด์‹œ ๊ธฐ๋ฐ˜ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•  ๋•Œ ๋จผ์ € hashCode๋ฅผ ๋น„๊ตํ•˜๊ณ , hashCode๊ฐ€ ๋™์ผํ•œ ๊ฒฝ์šฐ์—๋งŒ equals ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ตœ์ข…์ ์œผ๋กœ ๋™์ผ์„ฑ์„ ํŒ๋‹จํ•œ๋‹ค.

๋ฌธ์ œ๋Š” ํ˜„์žฌ Test ํด๋ž˜์Šค์—์„œ hashCode ๋ฉ”์„œ๋“œ๊ฐ€ ์˜ค๋ฒ„๋ผ์ด๋“œ๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ Object ํด๋ž˜์Šค์˜ hashCode๋Š” ๊ฐ์ฒด์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด์‹œ ๊ฐ’์„ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, test์™€ test2๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค.

๋”ฐ๋ผ์„œ, HashSet์€ test์™€ test2๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ ์ธ์‹ํ•˜๊ฒŒ ๋˜๋ฉฐ, set.contains(test2)๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

hashCode ๋ฉ”์„œ๋“œ๋ฅผ equals์™€ ์ผ๊ด€๋˜๊ฒŒ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์•ผ ํ•œ๋‹ค. name ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ hashCode๋ฅผ ์ƒ์„ฑํ•˜๋ฉด test์™€ test2๊ฐ€ ๊ฐ™์€ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜์–ด HashSet์ด ๋™์ผ ๊ฐ์ฒด๋กœ ์ธ์‹ํ•˜๊ฒŒ ๋œ๋‹ค.

์ˆ˜์ •๋œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

public class Test {
    private String name;

    public Test(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Test) {
            return this.name.equals(((Test) obj).name);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return name.hashCode(); // name ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ hashCode ์ƒ์„ฑ
    }

    public static void main(String[] args) throws Exception {
        Set<Test> set = new HashSet<>();
        Test test = new Test("java");
        set.add(test);
        Test test2 = new Test("java");
        System.out.println(set.contains(test2)); // true
    }
}

์„ค๋ช…:

  • hashCode ์˜ค๋ฒ„๋ผ์ด๋“œ: hashCode ๋ฉ”์„œ๋“œ๋ฅผ name ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ, name์ด ๋™์ผํ•œ ๊ฐ์ฒด๋Š” ๊ฐ™์€ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด์ œ test์™€ test2๋Š” ๊ฐ™์€ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, HashSet์ด ์ด ๋‘ ๊ฐ์ฒด๋ฅผ ๋™์ผํ•œ ๊ฐ์ฒด๋กœ ์ธ์‹ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด์ œ set.contains(test2)๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

2. ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ equals๋ฅผ ์–ธ์ œ์“ฐ๋ƒ

์ปฌ๋ ‰์…˜(Collection) ์ธํ„ฐํŽ˜์ด์Šค์—์„œ equals๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋‘ ์ปฌ๋ ‰์…˜์ด ๊ฐ™์€์ง€(๋™์ผํ•œ์ง€)๋ฅผ ๋น„๊ตํ•  ๋•Œ์ž…๋‹ˆ๋‹ค. Java ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋‹ค์–‘ํ•œ ๊ตฌํ˜„์ฒด๋“ค์€ equals ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ๋‘ ์ปฌ๋ ‰์…˜์˜ ์š”์†Œ๋“ค์ด ๋™์ผํ•œ์ง€๋ฅผ ํ™•์ธํ•˜๋Š” ๋กœ์ง์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

1. equals ์‚ฌ์šฉ ์‹œ์ 

a) ๋‘ ์ปฌ๋ ‰์…˜์ด ๋™์ผํ•œ์ง€ ๋น„๊ตํ•  ๋•Œ

equals ๋ฉ”์„œ๋“œ๋Š” ๋‘ ์ปฌ๋ ‰์…˜์˜ ํฌ๊ธฐ, ์š”์†Œ์˜ ์ˆœ์„œ, ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์š”์†Œ๊ฐ€ ๋™์ผํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‘ ์ปฌ๋ ‰์…˜์„ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ List, Set, Map๊ณผ ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ํƒ€์ž…์—์„œ ๊ฐ๊ฐ์˜ equals ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹น ํƒ€์ž…์˜ ํŠน์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

List<String> list1 = new ArrayList<>(Arrays.asList("a", "b", "c"));
List<String> list2 = new ArrayList<>(Arrays.asList("a", "b", "c"));

System.out.println(list1.equals(list2)); // true
  • **List**์—์„œ๋Š” ์š”์†Œ์˜ ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. list1๊ณผ list2์˜ ์š”์†Œ๋“ค์ด ์ˆœ์„œ๋Œ€๋กœ ๋ชจ๋‘ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— equals ๊ฒฐ๊ณผ๋Š” true์ž…๋‹ˆ๋‹ค.
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c"));
Set<String> set2 = new HashSet<>(Arrays.asList("c", "b", "a"));

System.out.println(set1.equals(set2)); // true
  • **Set**์€ ์ˆœ์„œ๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ณ , ์š”์†Œ์˜ ๋™์ผ์„ฑ๋งŒ์„ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. set1๊ณผ set2๋Š” ์ˆœ์„œ๋Š” ๋‹ค๋ฅด์ง€๋งŒ ๋™์ผํ•œ ์š”์†Œ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ equals ๊ฒฐ๊ณผ๋Š” true์ž…๋‹ˆ๋‹ค.

2. ์ปฌ๋ ‰์…˜ ๊ตฌํ˜„์ฒด์—์„œ equals ๋™์ž‘ ๋ฐฉ์‹

a) List:

  • List ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค (ArrayList, LinkedList ๋“ฑ)์—์„œ equals๋Š” ์š”์†Œ์˜ ์ˆœ์„œ์™€ ๋‚ด์šฉ์„ ๊ธฐ์ค€์œผ๋กœ ๋‘ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋™์ผํ•œ์ง€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.
  • ์š”์†Œ์˜ ์ˆœ์„œ๊ฐ€ ๋‹ค๋ฅด๋ฉด equals๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
List<String> list1 = Arrays.asList("a", "b", "c");
List<String> list2 = Arrays.asList("a", "c", "b");

System.out.println(list1.equals(list2)); // false (์ˆœ์„œ๊ฐ€ ๋‹ค๋ฆ„)

b) Set:

  • Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค (HashSet, TreeSet ๋“ฑ)์—์„œ equals๋Š” ์š”์†Œ์˜ ์ˆœ์„œ๋Š” ๋ฌด์‹œํ•˜๊ณ  ๋‚ด์šฉ๋งŒ์„ ๊ธฐ์ค€์œผ๋กœ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ™์€ ์š”์†Œ๋“ค์ด ์žˆ์œผ๋ฉด equals๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c"));
Set<String> set2 = new HashSet<>(Arrays.asList("c", "b", "a"));

System.out.println(set1.equals(set2)); // true (์ˆœ์„œ๊ฐ€ ๋ฌด์‹œ๋จ)

c) Map:

  • Map ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค (HashMap, TreeMap ๋“ฑ)์—์„œ equals๋Š” ํ‚ค(key)์™€ ๊ฐ’(value)์ด ๋ชจ๋‘ ๋™์ผํ•  ๋•Œ ๋‘ ๋งต์ด ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.
  • ํ‚ค์™€ ๊ฐ’์ด ๋ชจ๋‘ ๊ฐ™์•„์•ผ equals๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
Map<String, String> map1 = new HashMap<>();
map1.put("key1", "value1");
map1.put("key2", "value2");

Map<String, String> map2 = new HashMap<>();
map2.put("key1", "value1");
map2.put("key2", "value2");

System.out.println(map1.equals(map2)); // true

3. ์–ธ์ œ equals๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€?

  1. ์ปฌ๋ ‰์…˜์˜ ๋‚ด์šฉ ๋น„๊ต: ๋‘ ๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ, ์„ธํŠธ, ๋งต์ด ๊ฐ™์€์ง€ ๋น„๊ตํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๋‹จ์ˆœํžˆ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๊ฐ’(์ฃผ์†Œ)์„ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ปฌ๋ ‰์…˜ ๋‚ด๋ถ€์˜ ์š”์†Œ๊ฐ€ ๋™์ผํ•œ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  2. ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€์ฆ: ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์—์„œ ๋‘ ์ปฌ๋ ‰์…˜์ด ๋™์ผํ•œ์ง€(๋™์ผํ•œ ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€)๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
List<String> expected = Arrays.asList("a", "b", "c");
List<String> actual = Arrays.asList("a", "b", "c");
assertTrue(expected.equals(actual)); // ๊ฐ™์€์ง€ ํ…Œ์ŠคํŠธ
  1. ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ ํ™•์ธ: ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ๋‘ ์ปฌ๋ ‰์…˜์ด ๋™์ผํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๋กœ์ง์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

4. ๊ฒฐ๋ก 

Collection ์ธํ„ฐํŽ˜์ด์Šค์—์„œ equals๋Š” ์ปฌ๋ ‰์…˜์˜ ๋‚ด์šฉ์„ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ์ปฌ๋ ‰์…˜ ํƒ€์ž…(List, Set, Map)์€ ์ž์‹ ๋งŒ์˜ ๋ฐฉ์‹์œผ๋กœ equals๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๊ทธ ํŠน์„ฑ์— ๋งž๊ฒŒ ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. List๋Š” ์ˆœ์„œ์™€ ๋‚ด์šฉ์„ ๋น„๊ตํ•˜๊ณ , Set์€ ์ˆœ์„œ๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ๋‚ด์šฉ๋งŒ์„ ๋น„๊ตํ•˜๋ฉฐ, Map์€ ํ‚ค์™€ ๊ฐ’ ๋ชจ๋‘๋ฅผ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.

3. ๋ฃธ๋ถ์—์„œ๋„ equals๋ฅผ ์žฌ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์–ด? ๋ง‰.. final๋กœ ๋ง‰์•„๋ณด์ž๋Š”๊ฒŒ ๋ญ˜๊นŒ?

๋„ค, Lombok์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ equals ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Lombok์€ @EqualsAndHashCode ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์ž๋™์œผ๋กœ equals์™€ hashCode ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋•Œ๋กœ๋Š” ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณต๋˜๋Š” equals ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž ์ •์˜๋ฅผ ์œ„ํ•ด ์ง์ ‘ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. Lombok์—์„œ equals ๋ฉ”์„œ๋“œ ์ƒ์„ฑ

Lombok์˜ @EqualsAndHashCode ์–ด๋…ธํ…Œ์ด์…˜์„ ํด๋ž˜์Šค์— ์ถ”๊ฐ€ํ•˜๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ equals์™€ hashCode ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class MyClass {
    private String name;
    private int age;
}

์œ„ ์ฝ”๋“œ์—์„œ Lombok์€ ์ž๋™์œผ๋กœ equals ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ name๊ณผ age ํ•„๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‘ ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ์„ ๋น„๊ตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

2. Lombok์—์„œ equals๋ฅผ ์žฌ์ •์˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

๋•Œ๋•Œ๋กœ Lombok์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜, ํŠน์ • ํ•„๋“œ๋งŒ์„ ๋Œ€์ƒ์œผ๋กœ equals ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Lombok์˜ @EqualsAndHashCode ์–ด๋…ธํ…Œ์ด์…˜์€ ํ•„๋“œ ์„ ํƒ ์˜ต์…˜์„ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ํŠน์ • ํ•„๋“œ๋งŒ ํฌํ•จํ•˜๊ฑฐ๋‚˜ ์ œ์™ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import lombok.EqualsAndHashCode;

@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class MyClass {
    @EqualsAndHashCode.Include
    private String name;
    
    @EqualsAndHashCode.Exclude
    private int age;
}

์œ„ ์ฝ”๋“œ์—์„œ๋Š” name ํ•„๋“œ๋งŒ equals์™€ hashCode์— ํฌํ•จ๋˜๋ฉฐ, age๋Š” ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค.

3. final๋กœ ๋ง‰๋Š”๋‹ค๋Š” ์˜๋ฏธ

final๋กœ ๋ง‰๋Š”๋‹ค๋Š” ๊ฒƒ์€ ์ฃผ๋กœ ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์ƒ์†๋˜์ง€ ์•Š๋„๋ก ๋ฐฉ์ง€ํ•˜๊ฑฐ๋‚˜, ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†๋„๋ก ์ œํ•œํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ์—์„œ final: ๋ฉ”์„œ๋“œ๋ฅผ final๋กœ ์„ ์–ธํ•˜๋ฉด ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜(overriding)ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, equals ๋ฉ”์„œ๋“œ๋ฅผ final๋กœ ์„ ์–ธํ•˜๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ๋‹ค๋ฅธ ํด๋ž˜์Šค๊ฐ€ ์ด๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

    @EqualsAndHashCode
    public class MyClass {
        private String name;
        
        @Override
        public final boolean equals(Object obj) {
            // ์ปค์Šคํ…€ equals ๊ตฌํ˜„
        }
    }
  • ํด๋ž˜์Šค์—์„œ final: ํด๋ž˜์Šค๋ฅผ final๋กœ ์„ ์–ธํ•˜๋ฉด, ๊ทธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ƒ์†์„ ํ†ตํ•œ equals ์žฌ์ •์˜๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    public final class MyClass {
        private String name;
        
        // Lombok์˜ @EqualsAndHashCode๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑ๋œ equals ๋ฉ”์„œ๋“œ
    }

4. final๋กœ ๋ง‰์•„๋ณด์ž๋Š” ์˜๋ฏธ

์ฃผ๋กœ equals๋‚˜ hashCode์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ์˜ ์žฌ์ •์˜๋ฅผ ๋ง‰๋Š” ๊ฒƒ์€ ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ ๋น„๊ต ๋กœ์ง์ด ๋ณ€ํ•˜์ง€ ์•Š๋„๋ก ๊ฐ•์ œํ•˜๋ ค๋Š” ๋ชฉ์ ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ equals ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•œ๋‹ค๋ฉด, ๋™์ผ ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•  ๋•Œ ์˜๋„ํ•˜์ง€ ์•Š์€ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์ด๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ ๋น„๊ต๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ, equals ๋ฉ”์„œ๋“œ๋ฅผ final๋กœ ์ง€์ •ํ•จ์œผ๋กœ์จ ์ด๋Ÿฌํ•œ ์žฌ์ •์˜๋ฅผ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

  • Lombok์„ ์‚ฌ์šฉํ•˜๋ฉด @EqualsAndHashCode๋กœ ์ž๋™์œผ๋กœ equals ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํŠน์ • ์š”๊ตฌ ์‚ฌํ•ญ์ด ์žˆ์„ ๊ฒฝ์šฐ ์ด๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด equals๋‚˜ hashCode๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†๊ฒŒ ๋ง‰์Œ์œผ๋กœ์จ ๊ฐ์ฒด์˜ ๋™์ผ์„ฑ ๋น„๊ต ๋กœ์ง์ด ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๊ฐ์ฒด์˜ ์ผ๊ด€์„ฑ๊ณผ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

4. @AutoValue๋Š” lomback์ด ๋‚˜์˜จ์ดํ›„๋กœ ๋ชปํ•œ๋‹ค..?

@AutoValue์™€ Lombok์€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋ฉฐ, ๋‘˜ ๋‹ค Java์—์„œ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ(getter, setter, equals, hashCode ๋“ฑ)๋ฅผ ์ค„์—ฌ์ฃผ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Lombok์ด ๋“ฑ์žฅํ•œ ์ดํ›„์— @AutoValue๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฑฐ๋‚˜ ๋ชปํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋‘ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์ด ์žˆ์œผ๋ฉฐ, ์–ด๋А ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ง€๋Š” ํ”„๋กœ์ ํŠธ ์š”๊ตฌ ์‚ฌํ•ญ๊ณผ ๊ฐœ๋ฐœ์ž์˜ ์„ ํ˜ธ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

1. @AutoValue์™€ Lombok ๋น„๊ต

@AutoValue

  • ๊ตฌ๊ธ€์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ์ฃผ๋กœ ๋ถˆ๋ณ€ ๊ฐ์ฒด(Immutable Object) ์ƒ์„ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  • ์ฃผ๋กœ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค(๊ฐ’ ๊ฐ์ฒด)์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ปดํŒŒ์ผ ํƒ€์ž„์— ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • ๋ถˆ๋ณ€์„ฑ์„ ๋ณด์žฅํ•˜๊ณ , equals, hashCode, toString ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    ์˜ˆ:

    @AutoValue
    public abstract class Person {
        public abstract String name();
        public abstract int age();
    
        public static Person create(String name, int age) {
            return new AutoValue_Person(name, age);
        }
    }
    • @AutoValue๋Š” ์ƒ์„ฑ์ž๊ฐ€ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๋ฉฐ, ํด๋ž˜์Šค์˜ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋ฐ ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
    • ๋ถˆ๋ณ€์„ฑ(Immutable)์„ ๋ณด์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ฐ์ฒด์— ์ฃผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Lombok

  • Lombok์€ ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, @Getter, @Setter, @EqualsAndHashCode, @ToString ๋“ฑ ๋‹ค์–‘ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์ž๋™ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Lombok์€ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ @Value ์–ด๋…ธํ…Œ์ด์…˜๋„ ์ œ๊ณตํ•˜๋ฉฐ, @Builder, @AllArgsConstructor, @NoArgsConstructor ๋“ฑ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋” ๋งŽ์€ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ์˜ˆ:

    @Data
    public class Person {
        private final String name;
        private final int age;
    }
    • @Data๋Š” @Getter, @Setter, @EqualsAndHashCode, @ToString ๋“ฑ์„ ํ•œ ๋ฒˆ์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • Lombok์€ ๋งค์šฐ ์œ ์—ฐํ•˜๋ฉฐ, ๋ถˆ๋ณ€์„ฑ๊ณผ ๊ฐ€๋ณ€์„ฑ ๋‘˜ ๋‹ค ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์™œ @AutoValue๊ฐ€ Lombok๋ณด๋‹ค ๋œ ์‚ฌ์šฉ๋˜๋Š”๊ฐ€?

Lombok์ด ๋” ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์ด์œ ๋Š” ๊ทธ ์œ ์—ฐ์„ฑ๊ณผ ๊ด‘๋ฒ”์œ„ํ•œ ๊ธฐ๋Šฅ ๋•๋ถ„์ž…๋‹ˆ๋‹ค. @AutoValue๋Š” ์ฃผ๋กœ ๋ถˆ๋ณ€ ๊ฐ์ฒด ์ƒ์„ฑ์— ํŠนํ™”๋˜์–ด ์žˆ๊ณ , Lombok์€ ๋‹ค์–‘ํ•œ ๋ชฉ์ ์— ๋” ์ ํ•ฉํ•˜๋ฉฐ ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  @AutoValue๋Š” ์—ฌ์ „ํžˆ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์ฃผ์š” ์ฐจ์ด์ :

  1. Lombok์˜ ์œ ์—ฐ์„ฑ: Lombok์€ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ฐ€๋ณ€ ๊ฐ์ฒด, ๋นŒ๋” ํŒจํ„ด, ๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ๋ฐ˜ ๊ธฐ๋Šฅ๊นŒ์ง€ ์ง€์›ํ•˜์—ฌ ๋” ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ํ”„๋กœ์ ํŠธ ์š”๊ตฌ ์‚ฌํ•ญ: ๋ถˆ๋ณ€์„ฑ์„ ์—„๊ฒฉํ•˜๊ฒŒ ์š”๊ตฌํ•˜๋Š” ๊ฒฝ์šฐ @AutoValue๊ฐ€ ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ€๋ณ€ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๊ฑฐ๋‚˜ ๋” ๋งŽ์€ ์œ ์—ฐ์„ฑ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด Lombok์ด ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

3. "Lombok ์ดํ›„์— AutoValue๋ฅผ ๋ชปํ•œ๋‹ค"๋Š” ์˜๋ฏธ?

์ด ๋ง์€ Lombok์ด ๋” ์œ ์—ฐํ•˜๊ณ  ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์€ ํ”„๋กœ์ ํŠธ์—์„œ Lombok์ด ๋” ์„ ํ˜ธ๋œ๋‹ค๋Š” ์˜๋ฏธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Lombok์„ ๋„์ž…ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” @AutoValue๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŒ€ ๋‚ด์—์„œ ํ•˜๋‚˜์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ํ†ต์ผ์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด @AutoValue๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. Lombok์ด ๋‚˜์˜จ ์ดํ›„์—๋„ @AutoValue๋Š” ์—ฌ์ „ํžˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํŠน์ •ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ด๋‚˜ ์ƒํ™ฉ์—์„œ๋Š” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

  • @AutoValue๋Š” ์—ฌ์ „ํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠนํžˆ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.
  • Lombok์€ ๋” ๋งŽ์€ ๊ธฐ๋Šฅ๊ณผ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์—ฌ ๋” ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ๋ž˜์„œ ๋งŽ์€ ํ”„๋กœ์ ํŠธ์—์„œ Lombok์ด ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค.
  • ์–ด๋А ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ง€ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ ์‚ฌํ•ญ๊ณผ ๊ฐœ๋ฐœ์ž์˜ ์„ ํ˜ธ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

5. equals๋Š” jvm๋‚ด์— ์žˆ๋Š” ๊ฐ์ฒด๋งŒ ๊ฐ€์ง€๊ณ  ํŒ๋‹จํ•ด์•ผ ํ•˜๋Š”๋ฐ ๋„คํŠธ์›Œํฌ๋ฅผ ํƒ€๊ฒŒ ๋˜๋ฉด.. ๋งค๋ฒˆ ๋‹ฌ๋ผ์ง€๊ฒŒ ๋œ๋‹ค? ip์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๊ฒŒ ๋œ๋‹ค๊ณ  ํ•œ๋‹ค..

{% embed url="https://stackoverflow.com/questions/3771081/proper-way-to-check-for-url-equality" %}

6. ๋กœ๊ทธ ์ถ”์ ์„ ์œ„ํ•œ ๊ฒƒ

  • ELK

{% embed url="https://spring.io/projects/spring-cloud-sleuth" %}

7. private๋กœ ํ–ˆ์„ ๋•Œ.. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ๋ฐ›๋Š” ๋ฐฉ๋ฒ•

์Œ ๋‚˜๋Š” ๊ถ๊ธˆํ•œ๊ฒŒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณ€๊ฒฝํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ํ•„๋“œ๋‚˜ ๊ทธ๋Ÿฐ๊ฑฐ์— private๋ฅผ ์“ฐ๋ž˜ ๊ทผ๋ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ’์„ ์ž…๋ ฅํ•˜๋ฉด ๋ฐ›์•„์„œ ๋˜ ์ €์žฅํ•˜๊ณ  ๋ณด์—ฌ์ค˜์•ผ ํ•˜์ž–์•„? ๊ทผ๋ฐ ๊ทธ๋Ÿฌ๋ฉด private๋ฅผ ์“ฐ๋ฉด ๊ทธ๊ฒŒ ๋ถˆ๊ฐ€ํ•˜์ง€ ์•Š์•„?

์ข‹์€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค! private ์ ‘๊ทผ ์ œ์–ด์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ํ•„๋“œ๋ฅผ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ’์„ ์ž…๋ ฅํ•˜๊ณ  ์ €์žฅํ•˜๊ณ  ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ๊ฐ€์š”?

  1. ์ƒ์„ฑ์ž๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ž…๋ ฅ๋ฐ›์Šต๋‹ˆ๋‹ค:
    • ์ƒ์„ฑ์ž: ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•„์š”ํ•œ ๊ฐ’์„ ๋ฐ›์•„์„œ private ํ•„๋“œ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฉ”์„œ๋“œ: public ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€์—์„œ ๊ฐ’์„ ์ž…๋ ฅ๋ฐ›์•„ private ํ•„๋“œ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ ‘๊ทผ์ž(getter) ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:
    • public ์ ‘๊ทผ์ž๋ฅผ ๊ฐ€์ง„ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ private ํ•„๋“œ์˜ ๊ฐ’์„ ์™ธ๋ถ€์— ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•„๋“œ์˜ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ ์ฝ”๋“œ

์•„๋ž˜๋Š” User ํด๋ž˜์Šค๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

public final class User {

    // ํ•„๋“œ๋ฅผ private์œผ๋กœ ์„ ์–ธํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘๊ทผ์„ ๋ง‰์Œ
    private final String name;
    private int age;

    // ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐ ๊ฐ’ ์„ค์ •
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // public ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์„ค์ • (ํ•„์š”ํ•œ ๊ฒฝ์šฐ)
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        } else {
            System.out.println("์œ ํšจํ•œ ๋‚˜์ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.");
        }
    }

    // ์ ‘๊ทผ์ž ๋ฉ”์„œ๋“œ๋กœ ํ•„๋“œ ๊ฐ’ ๋ฐ˜ํ™˜
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    // ์ถ”๊ฐ€์ ์ธ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ
    public void displayUserInfo() {
        System.out.println("์ด๋ฆ„: " + name + ", ๋‚˜์ด: " + age);
    }
}

์„ค๋ช…

  • private ํ•„๋“œ:
    • name๊ณผ age ํ•„๋“œ๋ฅผ private์œผ๋กœ ์„ ์–ธํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•œ ์ดˆ๊ธฐํ™”:
    • User ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด name๊ณผ age ๊ฐ’์„ ์ž…๋ ฅ๋ฐ›์•„ ํ•„๋“œ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • public ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ๊ฐ’ ์„ค์ •:
    • setAge(int age) ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ **ํŠน์ • ์กฐ๊ฑด(์˜ˆ: ๋‚˜์ด๊ฐ€ 0๋ณด๋‹ค ํฐ์ง€ ํ™•์ธ)**์„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ age ํ•„๋“œ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ์ ‘๊ทผ์ž ๋ฉ”์„œ๋“œ:
    • getName()๊ณผ getAge() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด private ํ•„๋“œ์˜ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ •๋ณด ํ‘œ์‹œ ๋ฉ”์„œ๋“œ:
    • displayUserInfo() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ ์˜ˆ์‹œ

public class Main {

    public static void main(String[] args) {
        // ๊ฐ์ฒด ์ƒ์„ฑ
        User user = new User("ํ™๊ธธ๋™", 25);

        // ์ •๋ณด ์ถœ๋ ฅ
        user.displayUserInfo(); // ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ๋‚˜์ด: 25

        // ๋‚˜์ด ๋ณ€๊ฒฝ
        user.setAge(30);

        // ๋ณ€๊ฒฝ๋œ ์ •๋ณด ์ถœ๋ ฅ
        user.displayUserInfo(); // ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ๋‚˜์ด: 30

        // ํ•„๋“œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ค๋ฅ˜ ๋ฐœ์ƒ
        // user.age = 35; // ์ปดํŒŒ์ผ ์˜ค๋ฅ˜: age has private access in User
    }
}

ํ•ต์‹ฌ ํฌ์ธํŠธ

  • ์บก์Аํ™”(Encapsulation):
    • private ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณดํ˜ธํ•˜๊ณ , ํด๋ž˜์Šค ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์ˆจ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์™ธ๋ถ€์—์„œ๋Š” ์ œ๊ณต๋œ public ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ํ•„๋“œ์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ์œ ์ง€:
    • setAge() ๋ฉ”์„œ๋“œ์—์„œ ๋‚˜์ด๊ฐ€ 0๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ํ•„๋“œ ๊ฐ’์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ด๋ฅผ ํ†ตํ•ด ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„๋“œ์— ์ €์žฅ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ:
    • ๋‚ด๋ถ€ ๊ตฌํ˜„์ด ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค(public ๋ฉ”์„œ๋“œ)๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ์ด ์™ธ๋ถ€์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

  • private ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ƒ์„ฑ์ž๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ๊ฐ’์„ ์ž…๋ ฅ๋ฐ›๊ณ  ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • public ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ•„๋“œ์˜ ๊ฐ’์„ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ๋Š” ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ํ•„์š”ํ•œ ๋™์ž‘์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทผ๋ฐ setter๋„ ์•ˆ์“ฐ๋Š”๊ฒŒ ์ข‹๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ user.setAge๋Š” ์ƒ์„ฑ์ž๋ผ ๊ดœ์ฐฎ์€๊ฑฐ์•ผ? ์ƒ์„ฑ์ž๋Š” ๋ถˆ๋ณ€์œผ๋กœ ์•ˆ ๋งŒ๋“ค์–ด๋„ ๋ผ?

์ข‹์€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค! **๋ถˆ๋ณ€ ํด๋ž˜์Šค(Immutable Class)**๋ฅผ ๋งŒ๋“ค ๋•Œ setter ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ๋ง์”€๋“œ๋ ธ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ƒ์„ฑ์ž๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•„์ˆ˜์ ์ธ ์š”์†Œ์ด๋ฉฐ, ๊ฐ์ฒด์˜ ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

Setter์™€ ์ƒ์„ฑ์ž์˜ ์ฐจ์ด์ 

  • Setter ๋ฉ”์„œ๋“œ:
    • ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ ์ดํ›„์— ํ•„๋“œ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋Š” ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ถˆ๋ณ€์„ฑ์ด ๊นจ์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ์ž:
    • ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋ฉฐ, ํ•„๋“œ์˜ ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋„ ํ•„์ˆ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•œ ํ›„์—๋Š” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์˜ˆ์‹œ๋กœ ์„ค๋ช…

๋‹น์‹ ์ด ์ œ๊ณตํ•œ ์ฝ”๋“œ์—์„œ user.setAge(30);์€ setter ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ age ํ•„๋“œ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฏ€๋กœ ๋ถˆ๋ณ€ ํด๋ž˜์Šค์˜ ์›์น™์— ์œ„๋ฐฐ๋ฉ๋‹ˆ๋‹ค.

public class User {

    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // ์ด ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฏ€๋กœ ๋ถˆ๋ณ€์„ฑ์„ ๊นจ๋œจ๋ฆฝ๋‹ˆ๋‹ค.
    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void displayUserInfo() {
        System.out.println("์ด๋ฆ„: " + name + ", ๋‚˜์ด: " + age);
    }
}

์œ„ ์ฝ”๋“œ์—์„œ setAge ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฏ€๋กœ ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋Š” ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ถˆ๋ณ€ ํด๋ž˜์Šค๋กœ ์ˆ˜์ •ํ•˜๊ธฐ

๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  1. ํ•„๋“œ๋ฅผ private final๋กœ ์„ ์–ธํ•˜์—ฌ ๊ฐ์ฒด ์ƒ์„ฑ ํ›„์—๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  2. Setter ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ํ•„๋“œ ์ดˆ๊ธฐํ™”๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
public final class User {

    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter ๋ฉ”์„œ๋“œ๋งŒ ์ œ๊ณต
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void displayUserInfo() {
        System.out.println("์ด๋ฆ„: " + name + ", ๋‚˜์ด: " + age);
    }
}

์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ•˜๋ฉด User ํด๋ž˜์Šค๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ํ›„์—๋Š” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„๋“œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ ์˜ˆ์‹œ

public class Main {

    public static void main(String[] args) {
        User user = new User("ํ™๊ธธ๋™", 25);

        user.displayUserInfo(); // ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ๋‚˜์ด: 25

        // ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด
        // user.setAge(30); // ์˜ค๋ฅ˜: setAge(int)์€ User ํด๋ž˜์Šค์—์„œ ์ •์˜๋˜์ง€ ์•Š์Œ

        // ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ’ ๋ณ€๊ฒฝ
        User updatedUser = new User("ํ™๊ธธ๋™", 30);
        updatedUser.displayUserInfo(); // ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ๋‚˜์ด: 30
    }
}

์ƒ์„ฑ์ž๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊นŒ?

  • ์ƒ์„ฑ์ž ์ž์ฒด๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋ฉฐ, ํ•„๋“œ์˜ ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ์ž ๋‚ด๋ถ€์—์„œ ํ•„๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ๊ฐ์ฒด์˜ ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๋ถˆ๋ณ€์„ฑ์— ์œ„๋ฐฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ƒ์„ฑ์ž๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋„ ํ•„์ˆ˜์ ์ด๋ฉฐ, ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ์˜ ๊ฐ’ ๋ณ€๊ฒฝ์€ ์–ด๋–ป๊ฒŒ ํ•˜๋‚˜์š”?

๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋Š” ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๊ฐ’์„ ๊ฐ–๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ๋‚˜์ด๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

User user = new User("ํ™๊ธธ๋™", 25);

// ๋‚˜์ด๋ฅผ 30์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ
User updatedUser = new User(user.getName(), 30);

user.displayUserInfo();         // ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ๋‚˜์ด: 25
updatedUser.displayUserInfo();  // ์ถœ๋ ฅ: ์ด๋ฆ„: ํ™๊ธธ๋™, ๋‚˜์ด: 30

๋ถˆ๋ณ€ ํด๋ž˜์Šค์˜ ์žฅ์  ๋‹ค์‹œ ์ •๋ฆฌ

  • ์•ˆ์ „์„ฑ: ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•œ ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ: ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹จ์ˆœ์„ฑ: ๊ฐ์ฒด์˜ ์ƒํƒœ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ๋ณต์žกํ•œ ๋กœ์ง์„ ๊ด€๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

  • Setter ๋ฉ”์„œ๋“œ๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ์ž๋Š” ๊ฐ์ฒด์˜ ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, ๋ถˆ๋ณ€ ํด๋ž˜์Šค์—์„œ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ํ•„๋“œ๋ฅผ private final๋กœ ์„ ์–ธํ•˜๊ณ , ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐํ™”ํ•˜๋ฉฐ, Setter ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•  ๋•Œ๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

8. ๊ทธ๋ ‡๋‹ค๋ฉด ์Šคํ”„๋ง์—์„œ์˜ ๋ถˆ๋ณ€ ํด๋ž˜์Šค

์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ์˜ ๋ถˆ๋ณ€ ํด๋ž˜์Šค ์‚ฌ์šฉ

์Šคํ”„๋ง(Spring) ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ž๋ฐ” ๊ฐœ๋ฐœ์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ์ฃผ๋กœ **์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)**๊ณผ **์ œ์–ด์˜ ์—ญ์ „(Inversion of Control)**์„ ํ†ตํ•ด ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์Šคํ”„๋ง์—์„œ ๊ฐ์ฒด์˜ ์ƒํƒœ ๊ด€๋ฆฌ์™€ ๋ถˆ๋ณ€ ํด๋ž˜์Šค์˜ ์‚ฌ์šฉ์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•˜์‹  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ๋Š” ์Šคํ”„๋ง์—์„œ ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๊ณ , ์–ด๋–ค ์ƒํ™ฉ์—์„œ ์ฃผ์˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ์„ค๋ช…ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.


1. ์Šคํ”„๋ง๊ณผ ์ž๋ฐ”๋นˆ ๊ทœ์•ฝ

์Šคํ”„๋ง์€ ์ „ํ†ต์ ์œผ๋กœ ์ž๋ฐ”๋นˆ(JavaBean) ๊ทœ์•ฝ์„ ๋”ฐ๋ฅด๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฐ”๋นˆ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ–์Šต๋‹ˆ๋‹ค:

  • ๊ธฐ๋ณธ ์ƒ์„ฑ์ž ์ œ๊ณต: ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋Š” public ๊ธฐ๋ณธ ์ƒ์„ฑ์ž.
  • ํ”„๋ผ์ด๋น— ํ•„๋“œ์™€ ๊ณต๊ฐœ๋œ Getter/Setter: ํ•„๋“œ๋Š” private์œผ๋กœ ์„ ์–ธํ•˜๊ณ , public ์ ‘๊ทผ์ž์™€ ๋ณ€๊ฒฝ์ž๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ทœ์•ฝ์€ ์Šคํ”„๋ง์ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์šฉ์ดํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ํŠนํžˆ, ์Šคํ”„๋ง์˜ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์ด๋‚˜ ํ”„๋กœํผํ‹ฐ ์„ค์ • ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


2. ๋ถˆ๋ณ€ ํด๋ž˜์Šค์™€ ์Šคํ”„๋ง

๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žฅ์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์Šคํ”„๋ง์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณ ๋ ค์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • ์˜์กด์„ฑ ์ฃผ์ž…๊ณผ ์ƒ์„ฑ์ž ์‚ฌ์šฉ: ์Šคํ”„๋ง์€ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ **์ƒ์„ฑ์ž ์ฃผ์ž…(Constructor Injection)**์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ถˆ๋ณ€ ํด๋ž˜์Šค์˜ ํ•„๋“œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Setter๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹: ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด Setter ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ

@Component
public class UserService {

    private final UserRepository userRepository;

    // ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ํ†ตํ•ด ์˜์กด์„ฑ ์ฃผ์ž…
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ฉ”์„œ๋“œ
}
  • UserService๋Š” userRepository๋ฅผ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ฃผ์ž…๋ฐ›์œผ๋ฉฐ, ํ•„๋“œ๋Š” private final๋กœ ์„ ์–ธ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์Šคํ”„๋ง์€ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Setter๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

3. ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ์™€ ์—”ํ‹ฐํ‹ฐ ๋ถˆ๋ณ€์„ฑ

์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜ํ•  ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • JPA ์—”ํ‹ฐํ‹ฐ๋Š” ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์กฐํšŒ ์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ํ•„๋“œ๋Š” ํ”„๋ผ์ด๋น—์œผ๋กœ ์„ ์–ธํ•˜๊ณ  Getter/Setter๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.
  • ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋ ค๋ฉด:
    • ํ•„๋“œ๋ฅผ final๋กœ ์„ ์–ธํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.
    • Setter๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ , ํ•„์š”ํ•  ๊ฒฝ์šฐ ์ ‘๊ทผ ์ˆ˜์ค€์„ protected๋กœ ๋‚ฎ์ถ”์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ๋ถˆ๋ณ€ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค

@Entity
public class User {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž: JPA ๊ตฌํ˜„์ฒด๊ฐ€ ์‚ฌ์šฉ (์ ‘๊ทผ ์ œํ•œ์ž๋ฅผ protected๋กœ ์„ค์ •)
    protected User() {
    }

    // ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ํ•„๋“œ ์ดˆ๊ธฐํ™”
    public User(String name) {
        this.name = name;
    }

    // Getter๋งŒ ์ œ๊ณต
    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    // Setter๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์Œ์œผ๋กœ์จ ๋ถˆ๋ณ€์„ฑ ์œ ์ง€
}
  • ์ฃผ์˜์ : JPA ์—”ํ‹ฐํ‹ฐ์˜ ๊ฒฝ์šฐ ํ”„๋ก์‹œ ์ƒ์„ฑ์„ ์œ„ํ•ด ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ, ์ด๋Š” protected๋กœ ์„ ์–ธํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • Setter๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์Œ์œผ๋กœ์จ ์—”ํ‹ฐํ‹ฐ์˜ ๋ถˆ๋ณ€์„ฑ์„ ์–ด๋А ์ •๋„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ํ•„๋“œ๋ฅผ final๋กœ ์„ ์–ธํ•  ์ˆ˜๋Š” ์—†์œผ๋ฏ€๋กœ ์™„์ „ํ•œ ๋ถˆ๋ณ€์„ฑ์„ ๋‹ฌ์„ฑํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

4. DTO(Data Transfer Object)์™€ ๋ถˆ๋ณ€์„ฑ

์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ DTO๋Š” ๊ณ„์ธต ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. DTO๋ฅผ ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • ์•ˆ์ „ํ•œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ: ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•„ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์ˆ˜์ •์œผ๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธ๋ฉ๋‹ˆ๋‹ค.
  • ์ง๋ ฌํ™”์™€ ์—ญ์ง๋ ฌํ™”: JSON ๋“ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ๋ถˆ๋ณ€ DTO ํด๋ž˜์Šค

public final class UserDto {

    private final String name;
    private final int age;

    @JsonCreator
    public UserDto(@JsonProperty("name") String name, @JsonProperty("age") int age) {
        this.name = name;
        this.age = age;
    }

    // Getter๋งŒ ์ œ๊ณต
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}
  • Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆ๋ณ€ DTO๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Lombok์„ ์‚ฌ์šฉํ•œ ๋ถˆ๋ณ€ DTO

import lombok.Value;

@Value
public class UserDto {
    String name;
    int age;
}
  • @Value ์–ด๋…ธํ…Œ์ด์…˜์€ ๋ชจ๋“  ํ•„๋“œ๋ฅผ private final๋กœ ์„ ์–ธํ•˜๊ณ , Getter๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ, ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

5. ConfigurationProperties์™€ ๋ถˆ๋ณ€์„ฑ

์Šคํ”„๋ง์—์„œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ • ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ ์œ„ํ•ด @ConfigurationProperties๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ๋„ ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ: ๋ถˆ๋ณ€ ์„ค์ • ํด๋ž˜์Šค

@Configuration
@EnableConfigurationProperties(AppProperties.class)
public class AppConfig {
}

@ConfigurationProperties(prefix = "app")
public class AppProperties {

    private final String name;
    private final String version;

    public AppProperties(String name, String version) {
        this.name = name;
        this.version = version;
    }

    // Getter๋งŒ ์ œ๊ณต
    public String getName() {
        return name;
    }

    public String getVersion() {
        return version;
    }
}
  • ๊ทธ๋Ÿฌ๋‚˜ @ConfigurationProperties๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Setter๋ฅผ ํ†ตํ•ด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฃผ์ž…ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Constructor Binding์„ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์Šคํ”„๋ง ๋ถ€ํŠธ 2.2 ์ด์ƒ์—์„œ๋Š” @ConstructorBinding์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ์ž ๋ฐ”์ธ๋”ฉ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒ์„ฑ์ž ๋ฐ”์ธ๋”ฉ ์˜ˆ์‹œ

@ConfigurationProperties(prefix = "app")
@ConstructorBinding
public class AppProperties {

    private final String name;
    private final String version;

    public AppProperties(String name, String version) {
        this.name = name;
        this.version = version;
    }

    // Getter๋งŒ ์ œ๊ณต
}
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ”„๋กœํผํ‹ฐ ๊ฐ’์ด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ฃผ์ž…๋˜๋ฉฐ, ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

6. ๊ฒฐ๋ก  ๋ฐ ๊ถŒ์žฅ ์‚ฌํ•ญ

  • ์Šคํ”„๋ง์—์„œ ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒ์„ฑ์ž ์ฃผ์ž…๊ณผ Getter๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • JPA ์—”ํ‹ฐํ‹ฐ๋‚˜ ์ผ๋ถ€ ์Šคํ”„๋ง ๊ธฐ๋Šฅ์—์„œ๋Š” ๋ถˆ๋ณ€์„ฑ์„ ์™„๋ฒฝํžˆ ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ฐ€๋Šฅํ•œ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • Setter ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๊ณ , ํ•„์š”ํ•˜๋‹ค๋ฉด ์ƒ์„ฑ์ž๋‚˜ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • Lombok์ด๋‚˜ Immutable๊ณผ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ถˆ๋ณ€ ํด๋ž˜์Šค๋ฅผ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ์˜ ์•ˆ์ „์„ฑ, ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ์ž‘์„ฑ, ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ ๋“ฑ์˜ ์ด์ ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

9. ๋ ˆ์ด์Šค ์ปจ๋””์…˜

๋ ˆ์ด์Šค ์ปจ๋””์…˜(Race Condition)์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

๋ ˆ์ด์Šค ์ปจ๋””์…˜์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋˜๋Š” ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค ํ™˜๊ฒฝ์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋™์‹œ์— ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์กฐ์ž‘ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ์˜๋„์น˜ ์•Š๊ฒŒ ๋‹ฌ๋ผ์ง€๊ฑฐ๋‚˜ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ ๋ฐœ์ƒํ•˜๋‚˜์š”?

  • ๋™๊ธฐํ™” ๋ถ€์กฑ: ๊ณต์œ  ์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์ด ์ ์ ˆํžˆ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์œผ๋ฉด, ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ž์›์— ์ ‘๊ทผํ•˜์—ฌ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋น„๊ฒฐ์ •์  ์‹คํ–‰ ์ˆœ์„œ: ์Šค๋ ˆ๋“œ์˜ ์‹คํ–‰ ์ˆœ์„œ๋Š” ์šด์˜์ฒด์ œ์˜ ์Šค์ผ€์ค„๋ง์— ๋”ฐ๋ผ ๊ฒฐ์ •๋˜๋ฉฐ, ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ๋งค๋ฒˆ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ

๊ฐ„๋‹จํ•œ ์˜ˆ๋กœ, ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜ counter๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class Counter {
    private int counter = 0;

    public void increment() {
        counter++;
    }

    public int getCounter() {
        return counter;
    }
}

๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— increment() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  1. ์Šค๋ ˆ๋“œ A๊ฐ€ counter์˜ ๊ฐ’์„ ์ฝ์Œ (counter = 0)
  2. ์Šค๋ ˆ๋“œ B๊ฐ€ counter์˜ ๊ฐ’์„ ์ฝ์Œ (counter = 0)
  3. ์Šค๋ ˆ๋“œ A๊ฐ€ counter๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ด (counter = 1)
  4. ์Šค๋ ˆ๋“œ B๊ฐ€ counter๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ด (counter = 1)

์ด ๊ฒฝ์šฐ, ๋‘ ๋ฒˆ ์ฆ๊ฐ€์‹œ์ผฐ์ง€๋งŒ counter์˜ ๊ฐ’์€ 1์ด ๋ฉ๋‹ˆ๋‹ค. ์˜๋„ํ•œ ๊ฒฐ๊ณผ๋Š” 2์—ฌ์•ผ ํ•˜์ง€๋งŒ, ๋ ˆ์ด์Šค ์ปจ๋””์…˜์œผ๋กœ ์ธํ•ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  • ๋™๊ธฐํ™” ์‚ฌ์šฉ: synchronized ํ‚ค์›Œ๋“œ๋‚˜ Lock ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณต์œ  ์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ง๋ ฌํ™”ํ•ฉ๋‹ˆ๋‹ค.

    public class Counter {
        private int counter = 0;
    
        public synchronized void increment() {
            counter++;
        }
    
        public synchronized int getCounter() {
            return counter;
        }
    }
  • ์›์ž์  ์—ฐ์‚ฐ ์‚ฌ์šฉ: AtomicInteger์™€ ๊ฐ™์€ ์›์ž์  ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™๊ธฐํ™” ์—†์ด๋„ ์•ˆ์ „ํ•˜๊ฒŒ ์—ฐ์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    import java.util.concurrent.atomic.AtomicInteger;
    
    public class Counter {
        private AtomicInteger counter = new AtomicInteger(0);
    
        public void increment() {
            counter.incrementAndGet();
        }
    
        public int getCounter() {
            return counter.get();
        }
    }
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด ์‚ฌ์šฉ: ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ ˆ์ด์Šค ์ปจ๋””์…˜์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

๋ ˆ์ด์Šค ์ปจ๋””์…˜์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋งค์šฐ ํ”ํ•˜๊ฒŒ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋กœ, ํ”„๋กœ๊ทธ๋žจ์˜ ์‹ ๋ขฐ์„ฑ๊ณผ ์•ˆ์ •์„ฑ์„ ํ•ด์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ณต์œ  ์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์€ ๋ฐ˜๋“œ์‹œ ์ ์ ˆํ•œ ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ œ์–ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

10. ์ž๊ธฐ์‚ฌ์šฉ์ด๋ž€ ๋ญ๊ณ  ์™œ ๋ฌธ์ œ๊ฐ€ ๋ ๊นŒ? - item 18

์ž๊ธฐ์‚ฌ์šฉ(self-use)์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

**์ž๊ธฐ์‚ฌ์šฉ(self-use)**์€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ํด๋ž˜์Šค ๋‚ด์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๊ฐ™์€ ํด๋ž˜์Šค์˜ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋“ค์ด ์„œ๋กœ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ๋กœ ์ดํ•ดํ•˜๊ธฐ

์˜ˆ๋ฅผ ๋“ค์–ด, HashSet ํด๋ž˜์Šค์—์„œ addAll() ๋ฉ”์„œ๋“œ๊ฐ€ add() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ด๋Š” addAll() ๋ฉ”์„œ๋“œ๊ฐ€ add() ๋ฉ”์„œ๋“œ๋ฅผ ์ž๊ธฐ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

public class HashSet<E> implements Set<E> {
    // ...

    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c) {
            if (add(e)) { // ์—ฌ๊ธฐ์„œ add() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
                modified = true;
            }
        }
        return modified;
    }

    public boolean add(E e) {
        // ์›์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋กœ์ง
    }

    // ...
}

์œ„ ์ฝ”๋“œ์—์„œ ๋ณด๋“ฏ์ด, addAll() ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ add() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ปฌ๋ ‰์…˜์˜ ๊ฐ ์›์†Œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” addAll()์ด add()๋ฅผ ์ž๊ธฐ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์™œ ์ž๊ธฐ์‚ฌ์šฉ์ด ๋ฌธ์ œ๊ฐ€ ๋ ๊นŒ์š”?

์ž๊ธฐ์‚ฌ์šฉ์€ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ฐฉ์‹์— ํ•ด๋‹นํ•˜๋ฉฐ, ์™ธ๋ถ€์— ๊ณต๊ฐœ๋˜์ง€ ์•Š์€ ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ž๊ธฐ์‚ฌ์šฉ ์—ฌ๋ถ€์— ์˜์กดํ•˜์—ฌ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ณ€๊ฒฝ ์‹œ ๋ฌธ์ œ ๋ฐœ์ƒ:
    • ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ž์‹ ํด๋ž˜์Šค์˜ ๋™์ž‘์ด ์˜๋„์น˜ ์•Š๊ฒŒ ๋ณ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ๋ฒ„์ „์—์„œ HashSet์˜ addAll()์ด ๋” ์ด์ƒ add()๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ง์ ‘ ์›์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ๊ตฌํ˜„์ด ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด, ์ž์‹ ํด๋ž˜์Šค์—์„œ add()๋ฅผ ์žฌ์ •์˜ํ•˜์—ฌ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ๋ถ€๋ถ„์ด ๋” ์ด์ƒ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์‚ฌ์–‘์— ์—†๋Š” ๋™์ž‘์— ์˜์กด:
    • HashSet์˜ ๊ณต์‹ ๋ฌธ์„œ๋‚˜ API ์‚ฌ์–‘์—๋Š” addAll()์ด add()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋œ๋‹ค๋Š” ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.
    • ์ฆ‰, ์ด๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์ด๋ฉฐ, ์™ธ๋ถ€์—์„œ ์•Œ ์ˆ˜ ์—†๊ณ  ์˜์กดํ•ด์„œ๋„ ์•ˆ ๋˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
  3. ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ ๋ฐ ์•ˆ์ •์„ฑ ์ €ํ•˜:
    • ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜๋ฉด, ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์—…๋ฐ์ดํŠธ๋‚˜ ์ˆ˜์ •์— ์ทจ์•ฝํ•ด์ง‘๋‹ˆ๋‹ค.
    • ์ด๋Š” ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ์„ ์ €ํ•ดํ•˜๊ณ , ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ฒ„๊ทธ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

InstrumentedHashSet์—์„œ์˜ ๋ฌธ์ œ์ 

InstrumentedHashSet ํด๋ž˜์Šค๋Š” HashSet์„ ์ƒ์†๋ฐ›์•„ ์›์†Œ๊ฐ€ ์ถ”๊ฐ€๋œ ํšŸ์ˆ˜๋ฅผ ์„ธ๊ธฐ ์œ„ํ•ด add()์™€ addAll() ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

public class InstrumentedHashSet<E> extends HashSet<E> {
    private int addCount = 0;

    @Override
    public boolean add(E e) {
        addCount++; // ์›์†Œ ์ถ”๊ฐ€ ์นด์šดํŠธ ์ฆ๊ฐ€
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size(); // ์ถ”๊ฐ€๋˜๋Š” ์›์†Œ ์ˆ˜๋งŒํผ ์นด์šดํŠธ ์ฆ๊ฐ€
        return super.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }
}

๋ฌธ์ œ ๋ฐœ์ƒ ์ƒํ™ฉ:

  • addAll() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์›์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด addCount๊ฐ€ ๋‘ ๋ฐฐ๋กœ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    • addAll()์—์„œ addCount += c.size();๋กœ ์ฆ๊ฐ€.
    • super.addAll(c);๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด HashSet์˜ addAll()์ด ๋‚ด๋ถ€์ ์œผ๋กœ add()๋ฅผ ํ˜ธ์ถœ.
    • add()๋Š” ์žฌ์ •์˜๋œ add() ๋ฉ”์„œ๋“œ์ด๋ฏ€๋กœ addCount++๋กœ ๋‹ค์‹œ ์ฆ๊ฐ€.

์›์ธ:

  • InstrumentedHashSet์ด HashSet์˜ **์ž๊ธฐ์‚ฌ์šฉ(self-use)**์— ์˜์กดํ•˜์—ฌ ๋™์ž‘ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • HashSet์˜ addAll()์ด add()๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ๋‚ด๋ถ€ ๊ตฌํ˜„์€ ์–ธ์ œ๋“ ์ง€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณ€๊ฒฝ ์‹œ InstrumentedHashSet์˜ ๋™์ž‘์ด ๊นจ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ž๊ธฐ์‚ฌ์šฉ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์„ค๊ณ„ ๋ฐฉ๋ฒ•

**์ปดํฌ์ง€์…˜๊ณผ ์œ„์ž„(Delegation)**์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

InstrumentedSet ๊ตฌํ˜„ ์˜ˆ์‹œ

public class InstrumentedSet<E> implements Set<E> {
    private final Set<E> set; // ์‹ค์ œ ์ž‘์—…์„ ์œ„์ž„ํ•  Set ๊ฐ์ฒด
    private int addCount = 0;

    public InstrumentedSet(Set<E> set) {
        this.set = set;
    }

    @Override
    public boolean add(E e) {
        addCount++;
        return set.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return set.addAll(c);
    }

    public int getAddCount() {
        return addCount;
    }

    // ๋‚˜๋จธ์ง€ ๋ฉ”์„œ๋“œ๋“ค์€ set ๊ฐ์ฒด์— ์œ„์ž„
    // ...
}
  • ์ปดํฌ์ง€์…˜ ์‚ฌ์šฉ: InstrumentedSet ํด๋ž˜์Šค๋Š” Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๋‚ด๋ถ€์— ๋‹ค๋ฅธ Set ์ธ์Šคํ„ด์Šค๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
  • ์œ„์ž„ ์‚ฌ์šฉ: ๋ฉ”์„œ๋“œ๋“ค์€ ๋‚ด๋ถ€์˜ set ๊ฐ์ฒด์— ๋™์ž‘์„ ์œ„์ž„ํ•ฉ๋‹ˆ๋‹ค.
  • ์žฅ์ :
    • ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ณ€๊ฒฝ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

์š”์•ฝ

  • **์ž๊ธฐ์‚ฌ์šฉ(self-use)**์€ ํด๋ž˜์Šค ๋‚ด์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒ์†์„ ์‚ฌ์šฉํ•  ๋•Œ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์ž๊ธฐ์‚ฌ์šฉ ์—ฌ๋ถ€์— ์˜์กดํ•˜๋ฉด ์œ„ํ—˜ํ•ฉ๋‹ˆ๋‹ค.
    • ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์€ ์–ธ์ œ๋“ ์ง€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ์€ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์„ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด๊ฒฐ์ฑ…:
    • ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜๊ณผ ์œ„์ž„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.
    • ์ด๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ๊ณผ ์œ ์—ฐ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์˜ˆ์‹œ: ์ž๊ธฐ์‚ฌ์šฉ์˜ ๋ฌธ์ œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ

public class Parent {
    public void methodA() {
        System.out.println("Parent.methodA()");
        methodB();
    }

    public void methodB() {
        System.out.println("Parent.methodB()");
    }
}

public class Child extends Parent {
    @Override
    public void methodB() {
        System.out.println("Child.methodB()");
    }
}

์„ค๋ช…:

  • Parent ํด๋ž˜์Šค์˜ methodA()๋Š” methodB()๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • Child ํด๋ž˜์Šค๋Š” Parent๋ฅผ ์ƒ์†ํ•˜๊ณ  methodB()๋ฅผ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • Child์˜ ์ธ์Šคํ„ด์Šค๋กœ methodA()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ๊นŒ์š”?

์‹คํ–‰ ์ฝ”๋“œ:

Child child = new Child();
child.methodA();

์ถœ๋ ฅ ๊ฒฐ๊ณผ:

Parent.methodA()
Child.methodB()

๋ถ„์„:

  • Parent์˜ methodA()์—์„œ methodB()๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, ์žฌ์ •์˜๋œ Child์˜ methodB()๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋Š” Parent ํด๋ž˜์Šค์˜ ์ž๊ธฐ์‚ฌ์šฉ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์ด ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์žฌ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜์–ด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ:

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

๊ฒฐ๋ก 

์ž๊ธฐ์‚ฌ์šฉ(self-use)์€ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ฐฉ์‹์ด๋ฉฐ, ์™ธ๋ถ€์—์„œ๋Š” ์•Œ ์ˆ˜ ์—†๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์ƒ์†์„ ํ†ตํ•ด ์ž์‹ ํด๋ž˜์Šค์—์„œ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ž๊ธฐ์‚ฌ์šฉ์— ์˜์กดํ•˜์—ฌ ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋ฉด, ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ณ€๊ฒฝ ์‹œ ์ž์‹ ํด๋ž˜์Šค์˜ ๋™์ž‘์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜๊ณผ ์œ„์ž„์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ณ  ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.