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๋ฅผ ๋ฐํํ๊ฒ ๋ฉ๋๋ค.
์ปฌ๋ ์
(Collection) ์ธํฐํ์ด์ค์์ equals๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๋ ์ปฌ๋ ์
์ด ๊ฐ์์ง(๋์ผํ์ง)๋ฅผ ๋น๊ตํ ๋์
๋๋ค. Java ์ปฌ๋ ์
ํ๋ ์์ํฌ์ ๋ค์ํ ๊ตฌํ์ฒด๋ค์ 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์ ๋๋ค.
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- ์ปฌ๋ ์ ์ ๋ด์ฉ ๋น๊ต: ๋ ๊ฐ์ ๋ฆฌ์คํธ, ์ธํธ, ๋งต์ด ๊ฐ์์ง ๋น๊ตํ ๋ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๋จ์ํ ๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ(์ฃผ์)์ ๋น๊ตํ๋ ๊ฒ์ด ์๋๋ผ ์ปฌ๋ ์ ๋ด๋ถ์ ์์๊ฐ ๋์ผํ์ง ํ์ธํฉ๋๋ค.
- ํ ์คํธ ๋ฐ ๊ฒ์ฆ: ๋จ์ ํ ์คํธ์์ ๋ ์ปฌ๋ ์ ์ด ๋์ผํ์ง(๋์ผํ ์์๋ฅผ ๊ฐ์ง๊ณ ์๋์ง)๋ฅผ ๊ฒ์ฆํ ๋ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
List<String> expected = Arrays.asList("a", "b", "c");
List<String> actual = Arrays.asList("a", "b", "c");
assertTrue(expected.equals(actual)); // ๊ฐ์์ง ํ
์คํธ- ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ ํ์ธ: ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ค ๋ ์ปฌ๋ ์ ์ด ๋์ผํ์ง ํ์ธํ๋ ๋ก์ง์ ํตํด ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌ๋์๋์ง ๊ฒ์ฆํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
Collection ์ธํฐํ์ด์ค์์ equals๋ ์ปฌ๋ ์
์ ๋ด์ฉ์ ๋น๊ตํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ๊ฐ ์ปฌ๋ ์
ํ์
(List, Set, Map)์ ์์ ๋ง์ ๋ฐฉ์์ผ๋ก equals๋ฅผ ๊ตฌํํ์ฌ ๊ทธ ํน์ฑ์ ๋ง๊ฒ ๋น๊ต๋ฅผ ์ํํฉ๋๋ค. List๋ ์์์ ๋ด์ฉ์ ๋น๊ตํ๊ณ , Set์ ์์๋ฅผ ๋ฌด์ํ๊ณ ๋ด์ฉ๋ง์ ๋น๊ตํ๋ฉฐ, Map์ ํค์ ๊ฐ ๋ชจ๋๋ฅผ ๋น๊ตํฉ๋๋ค.
3. ๋ฃธ๋ถ์์๋ equals๋ฅผ ์ฌ์ ์ํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์์ด? ๋ง.. final๋ก ๋ง์๋ณด์๋๊ฒ ๋ญ๊น?
๋ค, Lombok์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ equals ๋ฉ์๋๋ฅผ ์ฌ์ ์ํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค. Lombok์ @EqualsAndHashCode ์ด๋
ธํ
์ด์
์ ํตํด ์๋์ผ๋ก equals์ hashCode ๋ฉ์๋๋ฅผ ์์ฑํด์ค๋๋ค. ํ์ง๋ง, ๋๋ก๋ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ equals ๊ตฌํ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ฌ์ฉ์ ์ ์๋ฅผ ์ํด ์ง์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
Lombok์ @EqualsAndHashCode ์ด๋
ธํ
์ด์
์ ํด๋์ค์ ์ถ๊ฐํ๋ฉด, ํด๋น ํด๋์ค์ ๋ชจ๋ ํ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก equals์ hashCode ๋ฉ์๋๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class MyClass {
private String name;
private int age;
}์ ์ฝ๋์์ Lombok์ ์๋์ผ๋ก equals ๋ฉ์๋๋ฅผ ์์ฑํ์ฌ name๊ณผ age ํ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ ๊ฐ์ฒด์ ๋์ผ์ฑ์ ๋น๊ตํ๊ฒ ๋ฉ๋๋ค.
๋๋๋ก 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๋ ์ ์ธ๋ฉ๋๋ค.
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 ๋ฉ์๋ }
์ฃผ๋ก equals๋ hashCode์ ๊ฐ์ ๋ฉ์๋์ ์ฌ์ ์๋ฅผ ๋ง๋ ๊ฒ์ ๊ฐ์ฒด์ ๋์ผ์ฑ ๋น๊ต ๋ก์ง์ด ๋ณํ์ง ์๋๋ก ๊ฐ์ ํ๋ ค๋ ๋ชฉ์ ์
๋๋ค. ๋ง์ฝ equals ๋ฉ์๋๋ฅผ ํ์ ํด๋์ค์์ ์ฌ์ ์ํ๋ค๋ฉด, ๋์ผ ๊ฐ์ฒด๋ฅผ ๋น๊ตํ ๋ ์๋ํ์ง ์์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด final ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ์ง ๋ชปํ๋๋ก ๋ง์ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ด๋ ๋น์ฆ๋์ค ๋ก์ง์์ ๊ฐ์ฒด์ ๋์ผ์ฑ ๋น๊ต๊ฐ ์ค์ํ ๊ฒฝ์ฐ, equals ๋ฉ์๋๋ฅผ final๋ก ์ง์ ํจ์ผ๋ก์จ ์ด๋ฌํ ์ฌ์ ์๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
- Lombok์ ์ฌ์ฉํ๋ฉด
@EqualsAndHashCode๋ก ์๋์ผ๋กequals๋ฉ์๋๋ฅผ ์์ฑํ ์ ์์ง๋ง, ํน์ ์๊ตฌ ์ฌํญ์ด ์์ ๊ฒฝ์ฐ ์ด๋ฅผ ์ฌ์ ์ํ ์ ์์ต๋๋ค. finalํค์๋๋ฅผ ์ฌ์ฉํดequals๋hashCode๋ฅผ ์ฌ์ ์ํ ์ ์๊ฒ ๋ง์์ผ๋ก์จ ๊ฐ์ฒด์ ๋์ผ์ฑ ๋น๊ต ๋ก์ง์ด ์ผ๊ด๋๊ฒ ์ ์ง๋๋๋ก ํ ์ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ๊ฐ์ฒด์ ์ผ๊ด์ฑ๊ณผ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๋ ค๋ ๊ฒฝ์ฐ์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ฉ๋๋ค.
@AutoValue์ Lombok์ ์๋ก ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ฉฐ, ๋ ๋ค Java์์ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋(getter, setter, equals, hashCode ๋ฑ)๋ฅผ ์ค์ฌ์ฃผ๋ ์ญํ ์ ํฉ๋๋ค. ํ์ง๋ง Lombok์ด ๋ฑ์ฅํ ์ดํ์ @AutoValue๋ฅผ ์ฌ์ฉํ ์ ์๊ฑฐ๋ ๋ชปํ๋ ๊ฒ์ ์๋๋๋ค. ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋ ๊ฐ๊ฐ์ ์ฅ๋จ์ ์ด ์์ผ๋ฉฐ, ์ด๋ ๊ฒ์ ์ฌ์ฉํ ์ง๋ ํ๋ก์ ํธ ์๊ตฌ ์ฌํญ๊ณผ ๊ฐ๋ฐ์์ ์ ํธ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
@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์ ๋งค์ฐ ์ ์ฐํ๋ฉฐ, ๋ถ๋ณ์ฑ๊ณผ ๊ฐ๋ณ์ฑ ๋ ๋ค ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
Lombok์ด ๋ ๋ง์ด ์ฌ์ฉ๋๋ ์ด์ ๋ ๊ทธ ์ ์ฐ์ฑ๊ณผ ๊ด๋ฒ์ํ ๊ธฐ๋ฅ ๋๋ถ์
๋๋ค. @AutoValue๋ ์ฃผ๋ก ๋ถ๋ณ ๊ฐ์ฒด ์์ฑ์ ํนํ๋์ด ์๊ณ , Lombok์ ๋ค์ํ ๋ชฉ์ ์ ๋ ์ ํฉํ๋ฉฐ ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ @AutoValue๋ ์ฌ์ ํ ๋ถ๋ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋ ๊ฐ๋ ฅํ ๋๊ตฌ์
๋๋ค.
์ฃผ์ ์ฐจ์ด์ :
- Lombok์ ์ ์ฐ์ฑ: Lombok์ ๋ถ๋ณ ๊ฐ์ฒด๋ฟ๋ง ์๋๋ผ ๊ฐ๋ณ ๊ฐ์ฒด, ๋น๋ ํจํด, ๋ฆฌํ๋ ์ ๊ธฐ๋ฐ ๊ธฐ๋ฅ๊น์ง ์ง์ํ์ฌ ๋ ๋ค์ํ ์ํฉ์ ์ ์ฉํ ์ ์์ต๋๋ค.
- ํ๋ก์ ํธ ์๊ตฌ ์ฌํญ: ๋ถ๋ณ์ฑ์ ์๊ฒฉํ๊ฒ ์๊ตฌํ๋ ๊ฒฝ์ฐ
@AutoValue๊ฐ ๋ ์ ํฉํ ์ ์์ผ๋ฉฐ, ๊ฐ๋ณ ๊ฐ์ฒด๊ฐ ํ์ํ๊ฑฐ๋ ๋ ๋ง์ ์ ์ฐ์ฑ์ด ํ์ํ๋ค๋ฉด Lombok์ด ์ ํฉํฉ๋๋ค.
์ด ๋ง์ 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" %}
- ELK
{% embed url="https://spring.io/projects/spring-cloud-sleuth" %}
์ ๋๋ ๊ถ๊ธํ๊ฒ ํด๋ผ์ด์ธํธ๊ฐ ๋ณ๊ฒฝํ์ง ๋ชปํ๊ฒ ํ๋๋ ๊ทธ๋ฐ๊ฑฐ์ private๋ฅผ ์ฐ๋ ๊ทผ๋ฐ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ์ ๋ ฅํ๋ฉด ๋ฐ์์ ๋ ์ ์ฅํ๊ณ ๋ณด์ฌ์ค์ผ ํ์์? ๊ทผ๋ฐ ๊ทธ๋ฌ๋ฉด private๋ฅผ ์ฐ๋ฉด ๊ทธ๊ฒ ๋ถ๊ฐํ์ง ์์?
์ข์ ์ง๋ฌธ์
๋๋ค! private ์ ๊ทผ ์ ์ด์๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋์ค ๋ด๋ถ์ ํ๋๋ฅผ ์ธ๋ถ์์ ์ง์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ๋ง์ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๊ฒ์ด ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ์
๋ ฅํ๊ณ ์ ์ฅํ๊ณ ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ์ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฒ์ ์๋๋๋ค.
- ์์ฑ์๋ ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ ์
๋ ฅ๋ฐ์ต๋๋ค:
- ์์ฑ์: ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ํ์ํ ๊ฐ์ ๋ฐ์์
privateํ๋์ ์ ์ฅํฉ๋๋ค. - ๋ฉ์๋:
public๋ฉ์๋๋ฅผ ํตํด ์ธ๋ถ์์ ๊ฐ์ ์ ๋ ฅ๋ฐ์privateํ๋์ ์ ์ฅํ ์ ์์ต๋๋ค.
- ์์ฑ์: ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ํ์ํ ๊ฐ์ ๋ฐ์์
- ์ ๊ทผ์(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 ๋ฉ์๋:
- ๊ฐ์ฒด๊ฐ ์์ฑ๋ ์ดํ์ ํ๋์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๊ฒ ํฉ๋๋ค.
- ๋ถ๋ณ ํด๋์ค์์๋ ์ ๊ณตํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ์๋ํ๋ฉด ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ถ๋ณ์ฑ์ด ๊นจ์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
- ์์ฑ์:
- ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ํ ๋ฒ๋ง ํธ์ถ๋๋ฉฐ, ํ๋์ ์ด๊ธฐ๊ฐ์ ์ค์ ํฉ๋๋ค.
- ๋ถ๋ณ ํด๋์ค์์๋ ํ์์ ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ์์ฑ์๋ฅผ ํตํด ์ด๊ธฐ ์ํ๋ฅผ ์ค์ ํ ํ์๋ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋๋ก ํฉ๋๋ค.
๋น์ ์ด ์ ๊ณตํ ์ฝ๋์์ 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 ๋ฉ์๋๋ ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ฏ๋ก ๋ถ๋ณ ํด๋์ค์์๋ ์ ๊ฑฐํด์ผ ํฉ๋๋ค.
๋ถ๋ณ ํด๋์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ผ ํฉ๋๋ค:
- ํ๋๋ฅผ
private final๋ก ์ ์ธํ์ฌ ๊ฐ์ฒด ์์ฑ ํ์๋ ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์๋๋ก ํฉ๋๋ค. - Setter ๋ฉ์๋๋ฅผ ์ ๊ฑฐํ์ฌ ์ธ๋ถ์์ ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ํฉ๋๋ค.
- ์์ฑ์๋ฅผ ํตํด ํ๋ ์ด๊ธฐํ๋ฅผ ์งํํฉ๋๋ค.
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 ๋ฉ์๋๋ฅผ ์ ๊ฑฐํ๋ฉด ๋ถ๋ณ ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. - ๊ฐ์ ๋ณ๊ฒฝ์ด ํ์ํ ๋๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์คํ๋ง(Spring) ํ๋ ์์ํฌ๋ ์๋ฐ ๊ฐ๋ฐ์์ ๋๋ฆฌ ์ฌ์ฉ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ๋ก, ์ฃผ๋ก **์์กด์ฑ ์ฃผ์ (Dependency Injection)**๊ณผ **์ ์ด์ ์ญ์ (Inversion of Control)**์ ํตํด ๊ฐ์ฒด์ ์์ฑ๊ณผ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํฉ๋๋ค. ์คํ๋ง์์ ๊ฐ์ฒด์ ์ํ ๊ด๋ฆฌ์ ๋ถ๋ณ ํด๋์ค์ ์ฌ์ฉ์ ๋ํด ๊ถ๊ธํ์ ๊ฒ ๊ฐ์ต๋๋ค. ์๋์์๋ ์คํ๋ง์์ ๋ถ๋ณ ํด๋์ค๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ๊ณ , ์ด๋ค ์ํฉ์์ ์ฃผ์ํด์ผ ํ๋์ง ์ค๋ช ํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์คํ๋ง์ ์ ํต์ ์ผ๋ก ์๋ฐ๋น(JavaBean) ๊ท์ฝ์ ๋ฐ๋ฅด๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค. ์๋ฐ๋น์ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ ๊ฐ์ต๋๋ค:
- ๊ธฐ๋ณธ ์์ฑ์ ์ ๊ณต: ํ๋ผ๋ฏธํฐ๊ฐ ์๋ public ๊ธฐ๋ณธ ์์ฑ์.
- ํ๋ผ์ด๋น ํ๋์ ๊ณต๊ฐ๋ Getter/Setter: ํ๋๋
private์ผ๋ก ์ ์ธํ๊ณ ,public์ ๊ทผ์์ ๋ณ๊ฒฝ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ด๋ฌํ ๊ท์ฝ์ ์คํ๋ง์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ๋ฐ ์ฉ์ดํ๊ฒ ๋ง๋ค์ด์ค๋๋ค. ํนํ, ์คํ๋ง์ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด๋ ํ๋กํผํฐ ์ค์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๋ ์ ์ฉํฉ๋๋ค.
๋ถ๋ณ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ์ฌ๋ฌ ๊ฐ์ง ์ฅ์ ์ ์ป์ ์ ์์ง๋ง, ์คํ๋ง์์๋ ๋ค์๊ณผ ๊ฐ์ ๊ณ ๋ ค์ฌํญ์ด ์์ต๋๋ค:
- ์์กด์ฑ ์ฃผ์ ๊ณผ ์์ฑ์ ์ฌ์ฉ: ์คํ๋ง์ ์์กด์ฑ ์ฃผ์ ์ **์์ฑ์ ์ฃผ์ (Constructor Injection)**์ ์ง์ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ถ๋ณ ํด๋์ค์ ํ๋๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
- Setter๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋ฐฉ์: ์์ฑ์ ์ฃผ์ ์ ์ฌ์ฉํ๋ฉด Setter ๋ฉ์๋๊ฐ ์์ด๋ ๋ฉ๋๋ค.
์์: ๋ถ๋ณ ํด๋์ค๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ๊ธฐ
@Component
public class UserService {
private final UserRepository userRepository;
// ์์ฑ์ ์ฃผ์
์ ํตํด ์์กด์ฑ ์ฃผ์
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// ๋น์ฆ๋์ค ๋ก์ง ๋ฉ์๋
}UserService๋userRepository๋ฅผ ์์ฑ์๋ฅผ ํตํด ์ฃผ์ ๋ฐ์ผ๋ฉฐ, ํ๋๋private final๋ก ์ ์ธ๋์ด ์์ต๋๋ค.- ์คํ๋ง์ ์์ฑ์๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์ ํ ์ ์์ผ๋ฏ๋ก Setter๊ฐ ํ์ ์์ต๋๋ค.
์คํ๋ง ๋ฐ์ดํฐ 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๋ก ์ ์ธํ ์๋ ์์ผ๋ฏ๋ก ์์ ํ ๋ถ๋ณ์ฑ์ ๋ฌ์ฑํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค.
์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์ ์์ 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๋ฅผ ์์ฑํ๋ฉฐ, ์์ฑ์๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
์คํ๋ง์์๋ ์ ํ๋ฆฌ์ผ์ด์
์ค์ ๊ฐ์ ๋ฐ์ธ๋ฉํ๊ธฐ ์ํด @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๋ง ์ ๊ณต
}- ์ด๋ ๊ฒ ํ๋ฉด ํ๋กํผํฐ ๊ฐ์ด ์์ฑ์๋ฅผ ํตํด ์ฃผ์ ๋๋ฉฐ, ๋ถ๋ณ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
- ์คํ๋ง์์ ๋ถ๋ณ ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์์ฑ์ ์ฃผ์ ๊ณผ Getter๋ฅผ ํ์ฉํ์ฌ ๋ถ๋ณ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
- JPA ์ํฐํฐ๋ ์ผ๋ถ ์คํ๋ง ๊ธฐ๋ฅ์์๋ ๋ถ๋ณ์ฑ์ ์๋ฒฝํ ์ ์งํ๊ธฐ ์ด๋ ค์ธ ์ ์์ง๋ง, ๊ฐ๋ฅํ ๋ฒ์ ๋ด์์ ๋ถ๋ณ์ฑ์ ์งํค๋ ๊ฒ์ด ์ข์ต๋๋ค.
- Setter ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ง ์๊ณ , ํ์ํ๋ค๋ฉด ์์ฑ์๋ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
- Lombok์ด๋ Immutable๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ๋ฉด ๋ถ๋ณ ํด๋์ค๋ฅผ ๋ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
- ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์์ ์์ ์ฑ, ์์ธก ๊ฐ๋ฅํ ์ฝ๋ ์์ฑ, ์ ์ง๋ณด์์ฑ ํฅ์ ๋ฑ์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค.
๋ ์ด์ค ์ปจ๋์ (Race Condition)์ด๋ ๋ฌด์์ธ๊ฐ์?
๋ ์ด์ค ์ปจ๋์ ์ ๋ฉํฐ์ค๋ ๋ ๋๋ ๋ฉํฐํ๋ก์ธ์ค ํ๊ฒฝ์์ ๋ ๊ฐ ์ด์์ ์ค๋ ๋๋ ํ๋ก์ธ์ค๊ฐ ๋์์ ๊ณต์ ์์์ ์ ๊ทผํ๊ฑฐ๋ ์กฐ์ํ๋ ค๊ณ ํ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋งํฉ๋๋ค. ์ด๋ก ์ธํด ํ๋ก๊ทธ๋จ์ ์คํ ๊ฒฐ๊ณผ๊ฐ ์๋์น ์๊ฒ ๋ฌ๋ผ์ง๊ฑฐ๋ ์๊ธฐ์น ์์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ๋๊ธฐํ ๋ถ์กฑ: ๊ณต์ ์์์ ๋ํ ์ ๊ทผ์ด ์ ์ ํ ๋๊ธฐํ๋์ง ์์ผ๋ฉด, ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์์์ ์ ๊ทผํ์ฌ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ๋น๊ฒฐ์ ์ ์คํ ์์: ์ค๋ ๋์ ์คํ ์์๋ ์ด์์ฒด์ ์ ์ค์ผ์ค๋ง์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ฉฐ, ์์ธกํ ์ ์์ต๋๋ค. ์ด๋ก ์ธํด ์คํ ๊ฒฐ๊ณผ๊ฐ ๋งค๋ฒ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค.
๊ฐ๋จํ ์๋ก, ๋ ๊ฐ์ ์ค๋ ๋๊ฐ ํ๋์ ๋ณ์ counter๋ฅผ ์ฆ๊ฐ์ํค๋ ์์
์ ์ํํ๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค.
public class Counter {
private int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
}๋ ์ค๋ ๋๊ฐ ๋์์ increment() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค:
- ์ค๋ ๋ A๊ฐ
counter์ ๊ฐ์ ์ฝ์ (counter = 0) - ์ค๋ ๋ B๊ฐ
counter์ ๊ฐ์ ์ฝ์ (counter = 0) - ์ค๋ ๋ A๊ฐ
counter๋ฅผ 1 ์ฆ๊ฐ์ํด (counter = 1) - ์ค๋ ๋ 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(); } }
-
๋ถ๋ณ ๊ฐ์ฒด ์ฌ์ฉ: ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํ๋ ๋ถ๋ณ ๊ฐ์ฒด ํจํด์ ์ฌ์ฉํ๋ฉด ๋ ์ด์ค ์ปจ๋์ ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
๋ ์ด์ค ์ปจ๋์ ์ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ๋งค์ฐ ํํ๊ฒ ๋ฐ์ํ๋ ๋ฌธ์ ๋ก, ํ๋ก๊ทธ๋จ์ ์ ๋ขฐ์ฑ๊ณผ ์์ ์ฑ์ ํด์น ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ๊ณต์ ์์์ ๋ํ ์ ๊ทผ์ ๋ฐ๋์ ์ ์ ํ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ ์ ์ดํด์ผ ํฉ๋๋ค.
**์๊ธฐ์ฌ์ฉ(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()๋ฅผ ์๊ธฐ์ฌ์ฉํ๊ณ ์๋ ๊ฒ์
๋๋ค.
์๊ธฐ์ฌ์ฉ์ ํด๋์ค์ ๋ด๋ถ ๊ตฌํ ๋ฐฉ์์ ํด๋นํ๋ฉฐ, ์ธ๋ถ์ ๊ณต๊ฐ๋์ง ์์ ๊ตฌํ ์ธ๋ถ์ฌํญ์ ๋๋ค. ๋ฐ๋ผ์ ์์ ํด๋์ค๊ฐ ๋ถ๋ชจ ํด๋์ค์ ์๊ธฐ์ฌ์ฉ ์ฌ๋ถ์ ์์กดํ์ฌ ๋์์ ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ๋ด๋ถ ๊ตฌํ ๋ณ๊ฒฝ ์ ๋ฌธ์ ๋ฐ์:
- ๋ถ๋ชจ ํด๋์ค์ ๋ด๋ถ ๊ตฌํ์ด ๋ณ๊ฒฝ๋๋ฉด ์์ ํด๋์ค์ ๋์์ด ์๋์น ์๊ฒ ๋ณํ ์ ์์ต๋๋ค.
- ์๋ฅผ ๋ค์ด, ๋ค์ ๋ฒ์ ์์
HashSet์addAll()์ด ๋ ์ด์add()๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ง์ ์์๋ฅผ ์ถ๊ฐํ๋๋ก ๊ตฌํ์ด ๋ณ๊ฒฝ๋๋ค๋ฉด, ์์ ํด๋์ค์์add()๋ฅผ ์ฌ์ ์ํ์ฌ ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ถ๋ถ์ด ๋ ์ด์ ๋์ํ์ง ์์ ์ ์์ต๋๋ค.
- ์์ ํด๋์ค์ ์ฌ์์ ์๋ ๋์์ ์์กด:
HashSet์ ๊ณต์ ๋ฌธ์๋ API ์ฌ์์๋addAll()์ดadd()๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ๋๋ค๋ ๋ด์ฉ์ด ์์ต๋๋ค.- ์ฆ, ์ด๋ ๊ตฌํ ์ธ๋ถ์ฌํญ์ด๋ฉฐ, ์ธ๋ถ์์ ์ ์ ์๊ณ ์์กดํด์๋ ์ ๋๋ ๋ถ๋ถ์ ๋๋ค.
- ์ฝ๋์ ์ ์ง๋ณด์์ฑ ๋ฐ ์์ ์ฑ ์ ํ:
- ์์ ํด๋์ค์ ๋ด๋ถ ๊ตฌํ์ ์์กดํ๋ฉด, ์์ ํด๋์ค์ ์ ๋ฐ์ดํธ๋ ์์ ์ ์ทจ์ฝํด์ง๋๋ค.
- ์ด๋ ์ฝ๋์ ์์ ์ฑ์ ์ ํดํ๊ณ , ์๊ธฐ์น ์์ ๋ฒ๊ทธ๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค.
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)์ ํด๋์ค์ ๋ด๋ถ ๊ตฌํ ๋ฐฉ์์ด๋ฉฐ, ์ธ๋ถ์์๋ ์ ์ ์๋ ๋ถ๋ถ์ ๋๋ค. ์์์ ํตํด ์์ ํด๋์ค์์ ๋ถ๋ชจ ํด๋์ค์ ์๊ธฐ์ฌ์ฉ์ ์์กดํ์ฌ ๋์์ ๊ตฌํํ๋ฉด, ๋ถ๋ชจ ํด๋์ค์ ๋ด๋ถ ๊ตฌํ ๋ณ๊ฒฝ ์ ์์ ํด๋์ค์ ๋์์ด ๊นจ์ง ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์์๋ณด๋ค๋ ์ปดํฌ์ง์ ๊ณผ ์์์ ์ฌ์ฉํ์ฌ ์์ ํ๊ณ ์ ์ฐํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
.png)
.png)