0117 - 0123
# 0117 - 0123
# 0117 - GRASP ๊ฐ์ฒด์งํฅ ์ค๊ณ๊ธฐ๋ฒ
# GRASP Pattern(General Responsibility Assignment Software Patterns)์ด๋?
- Object-Oriented ๋์์ธ์ ํต์ฌ์ ๊ฐ ๊ฐ์ฒด์ ์ฑ ์์ ๋ถ์ฌํ๋ ๊ฒ
- ์ฑ ์์ ๋ถ์ฌํ๋ ์์น๋ค์ ๋งํ๊ณ ์๋ ํจํด
๊ตฌ์ฒด์ ์ธ ๊ตฌ์กฐ๋ ์์ง๋ง, ์ฒ ํ์ ๋ฐฐ์ธ ์ ์๋ค.
์ด 9๊ฐ์ง์ ์์น์ ๊ฐ์ง๊ณ ์๋ค.
- High Cohesion(์์กด์ฑ ๋๊ฒ, ์ฆ ๋์ ์์ง๋ ฅ)
- ๊ฐ ๊ฐ์ฒด๊ฐ ๋ฐ์ ํ๊ฒ ์ฐ๊ด๋ ์ฑ ์๋ค๋ง ๊ฐ์ง๋๋ก ๊ตฌ์ฑ.
- ํ ๊ฐ์ฒด, ํ ์์คํ ์ด ์๊ธฐ ์์ ์ด ๋ถ์ฌ๋ฐ์ ์ฑ ์๋ง์ ์ํํ๋๋ก ์ง์์ ์๊ฒ ๊ตฌ์ฑ
- ์์ ์ด ๋ถ์ฌ ๋ฐ์ ์ฑ ์์ ์ถฉ์กฑ์ํค๊ธฐ ์ํด ๋ค๋ฅธ ๊ฐ์ฒด๋ ์์คํ ์ ์ฐธ์กฐํ๋ ์ผ์ด ์ ์ผ๋ฉฐ ์์ฐ์ค๋ฝ๊ฒ Low Coupling์ด ๋๋ค.
- Low Coupling(์์กด์ฑ ๋ฎ๊ฒ)
- ๊ฐ์ฒด๋ค๊ฐ, ์๋ธ ์์คํ ๋ค๊ฐ์ ์ํธ์์กด๋๊ฐ ๋ฎ๊ฒ ์ฑ ์์ ๋ถ์ฌ
- ๊ฐ ๊ฐ์ฒด, ์๋ธ์์คํ ์ ์ฌ ์ฌ์ฉ์ฑ์ ๋์ด๊ณ , ์์คํ ๊ด๋ฆฌ์ ํธํ๊ฒ ํ๋ค.
- Object-Oriented ์์คํ ์ ๊ฐ ๊ฐ์ฒด๋ค๊ฐ์ Communication์ ํตํ์ฌ ๋น์ฆ๋์ค๋ฅผ ์์ฑ์ํด.
- ๊ฐ ๊ฐ์ฒด๋ค ์ฌ์ด์ Coupling์ด ์กด์ฌํ์ง ์์ ์๋ ์๋ค.
- Information Expert!***
- ์ฑ ์์ ์ํํ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ฒด์ ์ฑ ์์ ๋ถ์ฌํ๋ค.
- ๊ฐ์ฒด๋ ๋ฐ์ดํฐ์ ์ฒ๋ฆฌ๋ก์ง์ด ํจ๊ป ๋ฌถ์ฌ ์๋ ๊ฒ.
- ์ ๋ณด ์๋์ ํตํด ์์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ถ๊ณ ์ค์ง Method๋ก๋ง ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ์ธ๋ถ์๋ ๊ทธ ๊ธฐ๋ฅ(์ฑ ์)๋ง์ ์ ๊ณตํ๋ค.
- Polymorphism(๋คํ์ฑ)
- ๊ฐ์ฒด์ ์ข ๋ฅ์ ๋ฐ๋ผ ํ๋์์์ด ๋ฐ๋๋ค๋ฉด, Polymorphism ๊ธฐ๋ฅ์ ์ฌ์ฉ
- ๋ง์ฝ ๊ฐ์ฒด์ ์ข ๋ฅ์ ๋ฐ๋ผ ํ๋์ด ๋ฐ๋๋ค๋ฉด ๊ฐ์ฒด์ ์ข ๋ฅ๋ฅผ ์ฒดํฌํ๋ ์กฐ๊ฑด๋ฌผ์ ์ฌ์ฉํ์ง ๋ง๊ณ Object-Oriented ์์คํ ์ Polymorphism ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ผ.
- Pure Fabrication
- ๋๋ฉ์ธ์ ๊ด๋ จ๋ ๋ฌธ์ ๋ฅผ ๋ํํ๋ ๊ฒ์ด ์๋๋ผ๋ฉด ๊ธฐ๋ฅ์ ์ธ ์ฑ ์์ ๋ณ๋๋ก ํ ๊ณณ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ณด๋ฅผ ์ ์ฅํ๊ฑฐ๋, ๋ก๊ทธ ์ ๋ณด๋ฅผ ๊ธฐ๋กํ๋ ์ฑ ์์ ๋ํด ์๊ฐํด ๋ณด์. ๊ฐ ์ ๋ณด๋ ๊ฐ๊ฐ์ ๊ฐ์ฒด๋ค์ด ๊ฐ์ง๊ณ ์์ ๊ฒ์ด๋ค.
- ์์คํ ์ ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์๋ ๊ธฐ๋ฅ์ด ์๋ค๋ฉฐ, ๊ณตํต์ ์ธ ๊ธฐ๋ฅ์ ์ ๊ณ ํญํ๋ ์ฑ ์์ ํ ๊ณณ์ผ๋ก ๋ชจ์์ ๊ฐ์์ ๊ฐ์ฒด, ์๋ธ์์คํ ์ ๋ง๋ค์ด๋ผ.
- Indirection
- ๋ ๊ฐ์ฒด ์ฌ์ด์ ์ง์ ์ ์ธ Coupling์ ํผํ๊ณ ์ถ์ผ๋ฉด, ๊ทธ ์ฌ์ด์ ๋ค๋ฅธ ๋งค๊ฐ์ฒด๋ฅผ ํตํด ์ ๋ฌํ๋ ๊ฒ.
- ์ฃผ๋ก ๋ค๋ฅธ ๋งค๊ฐ์ฒด๋ ์ธํฐํ์ด์ค์ธ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
- ๊ทธ๋ฐ ํน๋ณํ ๊ฒฝ์ฐ๋ ์๋์ ์ค๋ช ๋ Protected Variations ํจํด์ด๋ผ๊ณ ๋ถ๋ฅผ ์ ์๋ค.
- Protected Variations
- ๋ณ๊ฒฝ๋ ์ฌ์ง๊ฐ ์๋ ๊ณณ์ ์์ ๋ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํด์ ์ฌ์ฉํ์.
- Creator
- ๊ฐ์ฒด์ ์์ฑ์ ์์ฑ๋๋ ๊ฐ์ฒด์ ์ปจํ ์คํธ๋ฅผ ์๊ณ ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด, ์ปจํ ์คํธ๋ฅผ ์๊ณ ์๋ ๊ฐ์ฒด์ ๋ถ์ฌ.
- Factory Pattern
- Controller
- ์์คํ ์ด๋ฒคํธ(์ฌ์ฉ์ ์์ฒญ)๋ฅผ ์ฒ๋ฆฌํ ๊ฐ์ฒด๋ฅด ๋ง๋ค์.
# 0118 - @Sql ์ ๋ํ ์ด์
# @Sql
ํ ์คํธ ํด๋์ค๋ ใ ํ ์คํธ ๋ฉ์๋์ ๋ถํํ๋ ์๋ํ ์ด์ ์ด๋ฉฐ, ์ง์ ๋ ํน์ SQL ์คํฌ๋ฆฝํธ ํน์ Statement๋ฅผ ์ํ์ํจ๋ค. ํตํฉํ ์คํธ์์ ํธ๋ฆฌํ๊ฒ DB ์คํค๋ง ์์ฑ๊ณผ ์ด๊ธฐ ๋ฐ์ดํฐ ์ฝ์ ๋ฐ ๋ฐ์ดํฐ ์ด๊ธฐํ ๋ฑ์ ์ํํ ์ ์๋ค.
- ์ฌ์ฉ ์์
@Sql("classpath:/truncate.sql")
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
public class SqlTest {
//...
}
- ๊ฐ๊ฐ์ ํ ์คํธ ๋ฉ์๋ ์คํ ์ @Sql ์๋ํ ์ด์ ์ด ์ง์ ํ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ค.
- excutionPhase๋ก ์คํฌ๋ฆฝํธ์ ์คํ ์์ ์ ์กฐ์ ํ ์ ์์ผ๋ฉฐ, ๊ธฐ๋ณธ๊ฐ์ BEFORE_TEST_METHOD๋ค.
- @Sql({"a.sql", "b.sql", "c.sql"}) ๊ณผ ๊ฐ์ด ๋ณต์์ ์คํฌ๋ฆฝํธ ํ์ผ์ ์ง์ ํ ์ ์๋ค.
# 0121 - Java Optional ๋ฐ๋ฅด๊ฒ ์ฐ๊ธฐ
# Optional์ ๋ง๋ ์๋
Brian Goetz๋ ์คํ ์ค๋ฒํ๋ก์ฐ์์ Optional์ ๋ง๋ ์๋์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ๋งํ๋ค.
โฆ it was not to be a general purpose Maybe type, as much as many people would have liked us to do so. Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent โno resultโ โฆ
Optional์ ๋ง์ ์ฌ๋๋ค์ด ์ฐ๋ฆฌ(์๋ฐ ์ธ์ด ์ค๊ณ์)์๊ฒ ๊ธฐ๋ํ๋ ๋ฒ์ฉ์ ์ธ Maybe ํ์ ๊ณผ๋ ๋ค๋ฅด๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฉ์๋๊ฐ ๋ฐํํ ๊ฒฐ๊ณผ๊ฐ์ด โ์์โ์ ๋ช ๋ฐฑํ๊ฒ ํํํ ํ์๊ฐ ์๋ ๊ณณ์์ ์ ํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ๋ ๊ฒ์ด Optional์ ๋ง๋ ์๋์๋ค.
- java9 API Note
API Note: Optional is primarily intended for use as a method return type where there is a clear need to represent โno result,โ and where using null is likely to cause errors. A variable whose type is Optional should never itself be null; it should always point to an Optional instance.
๋ฉ์๋๊ฐ ๋ฐํํ ๊ฒฐ๊ณผ๊ฐ์ด '์์'์ ๋ช ๋ฐฑํ๊ฒ ํํํ ํ์๊ฐ ์๊ณ , null์ ๋ฐํํ๋ฉด ์๋ฌ๋ฅผ ์ ๋ฐํ ๊ฐ๋ฅ์ฑ์ด ๋์ ์ํฉ์์ ๋ฉ์๋์ ๋ฐํ ํ์ ์ผ๋ก Optional์ ์ฌ์ฉํ์๋ ๊ฒ์ด Optional์ ๋ง๋ ์ฃผ๋ ๋ชฉ์ ์ด๋ค. Optional ํ์ ์ ๋ณ์์ ๊ฐ์ ์ ๋ null ์ด์ด์๋ ์ ๋๋ฉฐ, ํญ์ Optional ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฅด์ผ์ผ ํ๋ค.
# ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ๋ฒ (java8 ๊ธฐ์ค)
- isPresent()-get() ๋์ orElse()/orElseGet()/orElseThrow()
๋น์ผ Optional์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ฝ๋๋ผ๋ ์ค์ฌ์ผ ํ๋ค.
// ์ ์ข์
Optional<Member> member = ...;
if (member.isPresent()) {
return member.get();
} else {
return null;
}
// ์ข์
Optional<Member> member = ...;
return member.orElse(null);
// ์ ์ข์
Optional<Member> member = ...;
if (member.isPresent()) {
return member.get();
} else {
throw new NoSuchElementException();
}
// ์ข์
Optional<Member> member = ...;
return member.orElseThrow(() -> new NoSuchElementException());
- orElse(new ...) ๋์ orElseGet(() -> new ...)
orElse(...)์์ ...๋ Optional์ ๊ฐ์ด ์๋ ์๋ ๋ฌด์กฐ๊ฑด ์คํ๋๋ค. ๋ฐ๋ผ์ ...๊ฐ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฑฐ๋ ์๋ก์ด ์ฐ์ฐ์ ์ํํ๋ ๊ฒฝ์ฐ์๋ orElse() ๋์ orElseGet()์ ์ฌ์ฉํ๋ค. orElseGet(Supplier)์์ Supplier๋ Optional์ ๊ฐ์ด ์์ ๋๋ง ์คํ๋๋ค. ๋ฐ๋ผ์ Optional์ ๊ฐ์ด ์์ ๋๋ง ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฑฐ๋ ์ ์ฐ์ฐ์ ์ํด์๋ฏ๋ก ๋ถํ์ํ ์ค๋ฒํค๋๊ฐ ์๋ค.
// ์ ์ข์
Optional<Member> member = ...;
return member.orElse(new Member()); // member์ ๊ฐ์ด ์๋ ์๋ new Member()๋ ๋ฌด์กฐ๊ฑด ์คํ๋จ
// ์ข์
Optional<Member> member = ...;
return member.orElseGet(Member::new); // member์ ๊ฐ์ด ์์ ๋๋ง new Member()๊ฐ ์คํ๋จ
// ์ข์
Member EMPTY_MEMBER = new Member();
...
Optional<Member> member = ...;
return member.orElse(EMPTY_MEMBER); // ์ด๋ฏธ ์์ฑ๋๊ฑฐ๋ ๊ณ์ฐ๋ ๊ฐ์ orElse()๋ฅผ ์ฌ์ฉํด๋ ๋ฌด๋ฐฉ
- ๋จ์ง ๊ฐ์ ์ป์ ๋ชฉ์ ์ด๋ผ๋ฉด Optional ๋์ null ๋น๊ต
Optional์ ๋น์ธ๋ค. ๋ฐ๋ผ์ ๋จ์ํ ๊ฐ ๋๋ null์ ์ป์ ๋ชฉ์ ์ด๋ผ๋ฉด Optional ๋์ null ๋น๊ต๋ฅผ ์ฌ์ฉํ๋ค.
// ์ ์ข์
return Optional.ofNullable(status).orElse(READY);
// ์ข์
return status != null ? status : READY;
- Optional ๋์ ๋น์ด์๋ ์ปฌ๋ ์ ๋ฐํ
Optional์ ๋น์ธ๋ค. ๊ทธ๋ฆฌ๊ณ ์ปฌ๋ ์ ์ null์ด ์๋๋ผ ๋น์ด์๋ ์ปฌ๋ ์ ์ ๋ฐํํ๋ ๊ฒ์ด ์ข์ ๋๊ฐ ๋ง๋ค. ๋ฐ๋ผ์ ์ปฌ๋ ์ ์ Optional๋ก ๊ฐ์ธ์ ๋ฐํํ์ง ๋ง๊ณ ๋น์ด์๋ ์ปฌ๋ ์ ์ ๋ฐํํ๋ค.
// ์ ์ข์
List<Member> members = team.getMembers();
return Optional.ofNullable(members);
// ์ข์
List<Member> members = team.getMembers();
return members != null ? members : Collections.emptyList();
// ์ ์ข์
public interface MemberRepository<Member, Long> extends JpaRepository {
Optional<List<Member>> findAllByNameContaining(String part);
}
// ์ข์
public interface MemberRepository<Member, Long> extends JpaRepository {
List<Member> findAllByNameContaining(String part); // null์ด ๋ฐํ๋์ง ์์ผ๋ฏ๋ก Optional ๋ถํ์
}
- Optional์ ํ๋๋ก ์ฌ์ฉ ๊ธ์ง
Optional์ ํ๋์ ์ฌ์ฉํ ๋ชฉ์ ์ผ๋ก ๋ง๋ค์ด์ง์ง ์์์ผ๋ฉฐ, Serializable์ ๊ตฌํํ์ง ์์๋ค. ๋ฐ๋ผ์ Optional์ ํ๋๋ก ์ฌ์ฉํ์ง ๋ง์.
// ์ ์ข์
public class Member {
private Long id;
private String name;
private Optional<String> email = Optional.empty();
}
// ์ข์
public class Member {
private Long id;
private String name;
private String email;
}
- Optional์ ์์ฑ์๋ ๋ฉ์๋ ์ธ์๋ก ์ฌ์ฉ ๊ธ์ง
Optional์ ์์ฑ์๋ ๋ฉ์๋ ์ธ์๋ก ์ฌ์ฉํ๋ฉด, ํธ์ถํ ๋๋ง๋ค Optional์ ์์ฑํด์ ์ธ์๋ก ์ ๋ฌํด์ค์ผ ํ๋ค. ํ์ง๋ง ํธ์ถ๋๋ ์ชฝ, ์ฆ api๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฉ์๋์์๋ ์ธ์๊ฐ Optional ์ด๋ ์๋๋ null ์ฒดํฌ๋ฅผ ํ๋ ๊ฒ์ด ์ธ์ ๋ ์์ ํ๋ค. ๋ฐ๋ผ์ ๊ตณ์ด ๋น์ผ Optional์ ์ธ์๋ก ์ฌ์ฉํ์ง ๋ง๊ณ ํธ์ถ๋๋ ์ชฝ์ null ์ฒดํฌ ์ฑ ์์ ๋จ๊ฒจ๋๋ค.
// ์ ์ข์
public class HRManager {
public void increaseSalary(Optional<Member> member) {
member.ifPresent(member -> member.increaseSalary(10));
}
}
hrManager.increaseSalary(Optional.ofNullable(member));
// ์ข์
public class HRManager {
public void increaseSalary(Member member) {
if (member != null) {
member.increaseSalary(10);
}
}
}
hrManager.increaseSalary(member);
- Optional์ ์ปฌ๋ ์ ์ ์์๋ก ์ฌ์ฉ ๊ธ์ง
์ปฌ๋ ์ ์๋ ๋ง์ ์์๊ฐ ๋ค์ด๊ฐ ์ ์๋ค. ๋ฐ๋ผ์ ๋น์ผ Optional์ ์์๋ก ์ฌ์ฉํ์ง ๋ง๊ณ ์์๋ฅผ ๊บผ๋ผ๋๋ ์ฌ์ฉํ ๋ null ์ฒดํฌํ๋ ๊ฒ์ด ์ข๋ค. ํนํ Map์ getOrDefault(), putIfAbsent(), computeIfAbsent(), computeIfPresent() ์ฒ๋ผ null ์ฒดํฌ๊ฐ ํฌํจ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ฏ๋ก, Map์ ์์๋ก Optional์ ์ฌ์ฉํ์ง ๋ง๊ณ Map์ด ์ ๊ณตํ๋ ๋ฉ์๋๋ฅผ ํ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
// ์ ์ข์
Map<String, Optional<String>> sports = new HashMap<>();
sports.put("100", Optional.of("BasketBall"));
sports.put("101", Optional.ofNullable(someOtherSports));
String basketBall = sports.get("100").orElse("BasketBall");
String unknown = sports.get("101").orElse("");
// ์ข์
Map<String, String> sports = new HashMap<>();
sports.put("100", "BasketBall");
sports.put("101", null);
String basketBall = sports.getOrDefault("100", "BasketBall");
String unknown = sports.computeIfAbsent("101", k -> "");
- of(), ofNullable() ํผ๋ ์ฃผ์
of(X)๋ X๊ฐ null์ด ์๋์ด ํ์คํ ๋๋ง ์ฌ์ฉํด์ผ ํ๋ฉฐ, X๊ฐ null์ด๋ฉด NFE์ด ๋ฐ์ํ๋ค.
// ์ ์ข์
return Optional.of(member.getEmail()); // member์ email์ด null์ด๋ฉด NPE ๋ฐ์
// ์ข์
return Optional.ofNullable(member.getEmail());
// ์ ์ข์
return Optional.ofNullable("READY");
// ์ข์
return Optional.of("READY");
- Optional
๋์ OptionalInt, OptionalLong, OptionalDouble
Optional์ ๋ด๊ธธ ๊ฐ์ด int, long, double์ด๋ผ๋ฉด Optional
// ์ ์ข์
Optional<Integer> count = Optional.of(38); // boxing ๋ฐ์
for (int i = 0 ; i < count.get() ; i++) { ... } // unboxing ๋ฐ์
// ์ข์
OptionalInt count = OptionalInt.of(38); // boxing ๋ฐ์ ์ ํจ
for (int i = 0 ; i < count.getAsInt() ; i++) { ... } // unboxing ๋ฐ์ ์ ํจ
# 0122 - Java Serializable
# ์๋ฐ ์ง๋ ฌํ
๊ฐ๋จํ๊ฒ๋ Java ๋ด๋ถ ์์คํ ์์ ์ฌ์ฉ๋๋(๋๋ JVM ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ ค์ง) ๊ฐ์ฒด๋ ๋ฐ์ดํฐ๋ฅผ ์ธ๋ถ์์ ์ฌ์ฉํ ์ ์๋๋ก Byte ํํ๋ก ๋ณํํ๋ ๊ธฐ์ ๊ณผ ๋ฐ์ดํธ๋ก ๋ณํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ฒด๋ก ๋ณํํ๋ ๊ธฐ์ (์ญ์ง๋ ฌํ)์ ์์ธ๋ฌ์ ์ด์ผ๊ธฐํ๋ค.
๊ฐ์ฒด ์ง๋ ฌํ๋ ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ฐ์ดํธ ์คํธ๋ฆผ์ผ๋ก ๋ณํํ๋๋ฐ ์ฌ์ฉ๋๋ ํ๋ก์ธ์ค๋ก, ๋์คํฌ/ํ์ผ๋ก ์ ์ง๋๊ฑฐ๋ ๋คํธ์ํฌ ๋์ ์ ํตํด ์คํ์ค์ธ ๋ค๋ฅธ Java ๊ฐ์๋จธ์ ์ผ๋ก ์ ์ก๋ ์ ์๋ค. ์ญ์ง๋ ฌํ๋ ์ด๋ฌํ ๋ฐ์ดํธ ์คํธ๋ฆผ์ ๋ค์ ๊ฐ์ฒดํํ๋ก ๋ณํํ๋ ์์ ์ ๋งํ๋ค. ์์ฑ๋ ๋ฐ์ดํธ๋ ํ๋ซํผ์ ๋ ๋ฆฝ์ ์ด๋ค.
- ์์
import java.io.Serializable;
public class Member implements Serializable {
private String name;
private String email;
private int age;
public Member(String name, String email, int age) {
this.name = name;
this.email = email;
this.age = age;
}
@Override
public String toString() {
return String.format("Member{name='%s', email='%s', age='%s',", name, email, age);
}
}
- ์ง๋ ฌํ ๋ฐ ์ญ์ง๋ ฌํ ๋ฐฉ๋ฒ
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Base64;
// ObjectOutputStream ๊ฐ์ฒด์ ObjectInputStream ๊ฐ์ฒด๋ฅผ ์ฌ์ฉ
public class ObjectSerializableExam{
public static void main(String[] args) throws Exception {
Member member = new Member("์์ค์", "a790077714@gmail.com", 30);
byte[] serializedMember;
try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try(ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(member);
// ์ง๋ ฌํ๋ member ๊ฐ์ฒด
serializedMember = baos.toByteArray();
}
}
// base64๋ก ์ธ์ฝ๋ฉํ ๋ฌธ์์ด
String base64Member = Base64.getEncoder().encodeToString(serializedMember);
// base64๋ก ๋์ฝ๋ฉํ ๋ฌธ์์ด
byte[] deserializedMember = Base64.getDecoder().decode(base64Member);
try(ByteArrayInputStream bais = new ByteArrayInputStream(deserializedMember)) {
try(ObjectInputStream ois = new ObjectInputStream(bais)) {
Object objectMember = ois.readObject();
// member ๊ฐ์ฒด๋ก ์ญ์ง๋ ฌํ
Member readMember = (Member) objectMember;
System.out.println(member);
}
}
}
- ๋ฌธ์ ํํ์ ์ง๋ ฌํ ๋ฐฉ๋ฒ
์ง์ ๋ฐ์ดํฐ๋ฅผ ๋ฌธ์์ด ํํ๋ก ํ์ธ ๊ฐ๋ฅํ ์ง๋ ฌํ ๋ฐฉ๋ฒ. ๋ฒ์ฉ์ ์ธ API๋ ๋ฐ์ดํฐ๋ฅผ ๋ณํํ์ฌ ์ถ์ถํ ๋ ๋ง์ด ์ฌ์ฉ. ํํํ์ ๋ค๋์ ๋ฐ์ดํฐ๋ฅผ ์ง๋ ฌํ์ CSV๊ฐ ๋ง์ด ์ฐ์ด๊ณ ๊ตฌ์กฐ์ ์ธ ๋ฐ์ดํฐ๋ ์ด์ ์ XML ์ต๊ทผ์๋ JSON์ ๋ง์ด ์ฌ์ฉํ๋ค.
# serialVersionUID ์ฌ์ฉ ์ ์ฃผ์ํ ์
serialVersionUID๋ Java ์ง๋ ฌํ ๋ฐ ์ญ์ง๋ ฌํ ํ ๋ ํ์ํ ๋ฒ์ ์ ๋ณด์ด๋ค. ๋ง์ฝ ๊ฐ์ฒด๋ฅผ ์ง๋ ฌํํ๊ณ ํด๋์ค์ ๋ฉ๋ฒ๋ณ์๊ฐ ์ถ๊ฐ๋๋ค๋ฉด java.io.InvalidClassException ์์ธ๊ฐ ๋ฐ์ํ๋ค. Java ์ง๋ ฌํ ์คํ์ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- serialVersionUID์ ํ์ ๊ฐ์ ์๋๋ค.
- ํธํ ๊ฐ๋ฅํ ํด๋์ค๋ serialVersionUID ๊ฐ์ด ๊ณ ์ ๋์ด ์๋ค.
- serialVersionUID๊ฐ ์ ์ธ๋์ด ์์ง ์์ผ๋ฉด ํด๋์ค์ ๊ธฐ๋ณธ ํด์ฌ๊ฐ์ ์ฌ์ฉํ๋ค.
์์ ์คํ์ ์ดํด๋ณด๋ฉด ๋ณ๊ฒฝ์ ์ทจ์ฝํ ํด๋์ค๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ญ์ง๋ ฌํ ์์ ์์ธ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ ๊ฐ๋ฐ์๊ฐ serialVersionUID ๊ฐ์ ์ง์ ๊ด๋ฆฌํด์ฃผ์ด์ผ ํผ๋์ ์ค์ผ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ํ์ง๋ง ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค. ๋ง์ฝ ๊ธฐ์กด์ ์ง๋ ฌํ๋ ๊ฐ์ฒด์ ๋ฉค๋ฒ ๋ณ์์ ํ์ ์ด ๋ฐ๋๋ค๋ฉด ๋ง์ฐฌ๊ฐ์ง๋ก ์์ธ๊ฐ ๋ฐ์ํ๋ค. ์ด๊ฑธ ๋ณด๋ฉด Java์ง๋ ฌํ๋ ์๋นํ ํ์ ์ ์๊ฒฉํ๋ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ฆ, ํน๋ณํ ๋ฌธ์ ๊ฐ ์์ผ๋ฉด Java ์ง๋ ฌํ ๋ฒ์ SerialVersionUID ๊ฐ์ ๊ฐ๋ฐ ์ ์ง์ ๊ด๋ฆฌํด์ค์ผ ํ๋ค. ๊ฐ์ด ๋์ผํ๋ค๋ฉด ๋ฉค๋ฒ ๋ณ์ ๋ฐ ๋ฉ์๋ ์ถ๊ฐ๋ ํฌ๊ฒ ๋ฌธ์ ๊ฐ ๋์ง ์์ผ๋ฉฐ ๋ฉค๋ฒ ๋ณ์ ์ ๊ฑฐ ๋ฐ ์ด๋ฆ ๋ณ๊ฒฝ์ ์ค๋ฅ๋ ๋ฐ์ํ์ง ์๊ณ ๋ฐ์ดํฐ๊ฐ ๋๋ฝ๋๋ค.
# ๊ฒฐ๋ก
์ต๊ทผ์๋ Jsonํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ ์ง๋ ฌํ๋ฅผ ์ ์ฌ์ฉํ์ง ์๋๋ฐ Jsonํํ๋ก ์ ์ฅํ๋ ๊ฒ์ Class์์ ์ทจ๋ํ ์ ์๋ ๋ถ๋ถ๊น์ง ์ ์ฅํ๋ ๊ฒ์ด๊ณ private๊น์ง ์ ์ฅํ๋ ๊ฒ์ ์๋๋ค.