[Java] Record
๐ Record๋?
์๋ฐ์ Record
๋ Java 16์์ ์ ์์ผ๋ก ๋์
๋ ํน๋ณํ ์ข
๋ฅ์ ํด๋์ค์ด๋ค. Record์ ํต์ฌ ๋ชฉ์ ์ ๋ถ๋ณ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ๋ ๊ฒ์ด๋ค.
Record๊ฐ ์๋ ์์
๋ณดํต Record๋ DTO์ ๊ฐ์ ๋ถ๋ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ฌ์ฉํ๋ค. ์ด๋ฅผ Record๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public final class Person {
private final String name;
private final int age;
public PersonClass(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PersonClass that = (PersonClass) o;
return age == that.age && java.util.Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return java.util.Objects.hash(name, age);
}
@Override
public String toString() {
return "PersonClass[" +
"name='" + name + '\'' +
", age=" + age +
']';
}
}
๋จผ์ ํด๋์ค์ final
ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ๋ง์์ผ ํ๊ณ , ํ๋๋ฅผ private final
๋ก ์ ์ธํ๊ณ , ๋ชจ๋ ํ๋๋ฅผ ์ด๊ธฐํํ๋ ์์ฑ์๋ฅผ ๋ง๋ค๊ณ , getter๋ฅผ ๋ง๋ค๊ณ , hashCode
์ equals
, toString
๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํ๋ค. ์ด์ ๋ค๋ฅธ ๋ถ๋ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์. ๋ฐฉ๊ธ ์์ฑํ ์ฝ๋๋ฅผ ๋ค์ ์์ฑํ๊ณ ์ถ์๊ฐ? ๊ทธ์ ๋ถ๋ณ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ์ถ์์ ๋ฟ์ธ๋ฐ, ์์ญ ์ค์ ์ฝ๋๋ฅผ ์ผ์ผํ ์์ฑํด์ผ ํ๋ค.
@Lombok
์ด๋
ธํ
์ด์
์ ๋ฑ์ฅ ๋ฐฐ๊ฒฝ์ ๋ณด๋ฉด ์๊ฒ ์ง๋ง, ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๋ฅผ ์ง์ ์์ฑํ๋ ๊ฒ์ ์ด๋ง๋ฌด์ํ ์์ฐ์ฑ ์ ํ๋ฅผ ๊ฐ์ ธ์จ๋ค.
์ด์ , Record๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ ์์ฑํด๋ณด์.
1
public record Person(String name, int age) {}
๋๋ผ์ธ ์ ๋๋ก ๊ฐ๋จํด์ง๋ค. Record๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ ์ ์์ฑํ private final
ํ๋์ ์์ฑ์, getter, equals
, hashCode
, toString
๋ฉ์๋๋ฅผ ์๋ฐ ์ปดํ์ผ๋ฌ๊ฐ ์ปดํ์ผ ์์ ์ ์๋์ผ๋ก ์์ฑํด์ค๋ค.
๐ ์ปดํฉํธ ์์ฑ์
Record๋ง์ ํน๋ณํ ๊ธฐ๋ฅ์ด ์๋๋ฐ, ์ปดํฉํธ ์์ฑ์์ด๋ค.
์ปดํฉํธ ์์ฑ์๋ Record๊ฐ ์๋์ผ๋ก ์์ฑํ๋ ์์ฑ์์ ๊ฒ์ฆ, ๊ธฐ๋ณธ ๊ฐ ํ ๋น ๋ฑ๊ณผ ๊ฐ์ ๋ก์ง์ ๊ฐ๋จํ๊ฒ ์ถ๊ฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฐ๋ ์ด๋ค. Record๊ฐ ๋ชจ๋ ํ๋๋ฅผ ์ธ์๋ก ๋ฐ์ ์ด๊ธฐํํ๋ ์์ฑ์๋ฅผ ๋ง๋ค๊ธฐ ์ ์ ๋์ํ๋ค.
1
2
3
4
5
public Person {
if (age < 0) {
throw new IllegalArgumentException("๋์ด๋ ์์์ผ ์ ์์ต๋๋ค.");
}
}
์ฌํ ์์ฑ์์ ๊ฐ์ฅ ํฐ ํน์ง์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋ ์๊ดํธ๊ฐ ์๋ค๋ ๊ฒ์ด๋ค. ์๋ฌต์ ์ผ๋ก Record์ ์ ์๋ ๋ชจ๋ ํ๋๋ฅผ ๋ฐ๋๋ค. ์ปดํฉํธ ์์ฑ์ ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋ณ์๋ final
ํ๋๊ฐ ์๋๋ผ ๊ฐ๋ณ์ ์ธ ํ๋ผ๋ฏธํฐ๋ก, ๊ฐ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ค. ์ปดํฉํธ ์์ฑ์์ ๋ชจ๋ ๋ก์ง์ด ์คํ๋ ํ ์ต์ข
์ ์ผ๋ก ๊ฒฐ์ก๋ ํ๋ฆฌ๋ฏธํฐ ๊ฐ๋ค์ด final
ํ๋์ ํ ๋น๋๋ค.
๐ ์ฌ์ฉ ์์
์ธ๊ธํ๋ค์๋ฏธ DTO๋ฅผ Record๋ฅผ ํตํด ๋ง์ด ๊ตฌํํ๋ค.
1
2
3
4
5
6
7
8
public record Coordinate(int x, int y) {}
public class GameMap {
Map<Coordinate, String> worldMap = new HashMap<>();
// ...
}
๊ทธ ์ธ์๋ JSON๊ณผ ๋งคํ๋๋ API์ ๋ฐ์ดํฐ ๋ชจ๋ธ, Map
์ ํค๋ก ์ฌ์ฉ๋ ๋ณตํฉ์ ์ธ ๊ฐ์ ํํํ ๋ ์ฌ์ฉํ๋ค.
๐ ํ๊ณ์
๋จผ์ JPA Entity๋ก ์ฌ์ฉํ ์ ์๋ค. JPA์ Lazy Loading ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ธ๋ฐ, Lazy Loading์ ํตํด ์ํฐํฐ๋ฅผ ์์๋ฐ๋ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ๊ทธ๋ฌ๋ Record๋ final
ํด๋์ค์ด๋ฏ๋ก ์์์ด ๋ถ๊ฐ๋ฅํ๋ค.
๋ํ ๋ชจ๋ ํ๋๋ final
์ด๋ฏ๋ก setter๋ฅผ ๊ฐ์ง ์ ์๋ค. ์ฆ, ์ํ ๋ณ๊ฒฝ์ด ํ์ํ ๊ฐ์ฒด์๋ Record๊ฐ ์ ํฉํ์ง ์๋ค.