0117 - 0123


# 0117 - 0123

# 0117 - GRASP ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„๊ธฐ๋ฒ•

# GRASP Pattern(General Responsibility Assignment Software Patterns)์ด๋ž€?

  • Object-Oriented ๋””์ž์ธ์˜ ํ•ต์‹ฌ์€ ๊ฐ ๊ฐ์ฒด์— ์ฑ…์ž„์„ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ
  • ์ฑ…์ž„์„ ๋ถ€์—ฌํ•˜๋Š” ์›์น™๋“ค์„ ๋งํ•˜๊ณ  ์žˆ๋Š” ํŒจํ„ด

๊ตฌ์ฒด์ ์ธ ๊ตฌ์กฐ๋Š” ์—†์ง€๋งŒ, ์ฒ ํ•™์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋‹ค.
์ด 9๊ฐ€์ง€์˜ ์›์น™์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

  1. High Cohesion(์˜์กด์„ฑ ๋†’๊ฒŒ, ์ฆ‰ ๋†’์€ ์‘์ง‘๋ ฅ)
  • ๊ฐ ๊ฐ์ฒด๊ฐ€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ด€๋œ ์ฑ…์ž„๋“ค๋งŒ ๊ฐ€์ง€๋„๋ก ๊ตฌ์„ฑ.
  • ํ•œ ๊ฐ์ฒด, ํ•œ ์‹œ์Šคํ…œ์ด ์ž๊ธฐ ์ž์‹ ์ด ๋ถ€์—ฌ๋ฐ›์€ ์ฑ…์ž„๋งŒ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์งœ์ž„์ƒˆ ์žˆ๊ฒŒ ๊ตฌ์„ฑ
  • ์ž์‹ ์ด ๋ถ€์—ฌ ๋ฐ›์€ ์ฑ…์ž„์„ ์ถฉ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๊ฐ์ฒด๋‚˜ ์‹œ์Šคํ…œ์„ ์ฐธ์กฐํ•˜๋Š” ์ผ์ด ์ ์œผ๋ฉฐ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ Low Coupling์ด ๋œ๋‹ค.
  1. Low Coupling(์˜์กด์„ฑ ๋‚ฎ๊ฒŒ)
  • ๊ฐ์ฒด๋“ค๊ฐ„, ์„œ๋ธŒ ์‹œ์Šคํ…œ๋“ค๊ฐ„์˜ ์ƒํ˜ธ์˜์กด๋„๊ฐ€ ๋‚ฎ๊ฒŒ ์ฑ…์ž„์„ ๋ถ€์—ฌ
  • ๊ฐ ๊ฐ์ฒด, ์„œ๋ธŒ์‹œ์Šคํ…œ์˜ ์žฌ ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ณ , ์‹œ์Šคํ…œ ๊ด€๋ฆฌ์— ํŽธํ•˜๊ฒŒ ํ•œ๋‹ค.
  • Object-Oriented ์‹œ์Šคํ…œ์€ ๊ฐ ๊ฐ์ฒด๋“ค๊ฐ„์˜ Communication์„ ํ†ตํ•˜์—ฌ ๋น„์ฆˆ๋‹ˆ์Šค๋ฅผ ์™„์„ฑ์‹œํ‚ด.
  • ๊ฐ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์— Coupling์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜๋Š” ์—†๋‹ค.
  1. Information Expert!***
  • ์ฑ…์ž„์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์— ์ฑ…์ž„์„ ๋ถ€์—ฌํ•œ๋‹ค.
  • ๊ฐ์ฒด๋Š” ๋ฐ์ดํ„ฐ์™€ ์ฒ˜๋ฆฌ๋กœ์ง์ด ํ•จ๊ป˜ ๋ฌถ์—ฌ ์žˆ๋Š” ๊ฒƒ.
  • ์ •๋ณด ์€๋‹‰์„ ํ†ตํ•ด ์ž์‹ ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ถ”๊ณ  ์˜ค์ง Method๋กœ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ์™ธ๋ถ€์—๋Š” ๊ทธ ๊ธฐ๋Šฅ(์ฑ…์ž„)๋งŒ์„ ์ œ๊ณตํ•œ๋‹ค.
  1. Polymorphism(๋‹คํ˜•์„ฑ)
  • ๊ฐ์ฒด์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ํ–‰๋™์–‘์‹์ด ๋ฐ”๋€๋‹ค๋ฉด, Polymorphism ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ
  • ๋งŒ์•ฝ ๊ฐ์ฒด์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ํ–‰๋™์ด ๋ฐ”๋€๋‹ค๋ฉด ๊ฐ์ฒด์˜ ์ข…๋ฅ˜๋ฅผ ์ฒดํฌํ•˜๋Š” ์กฐ๊ฑด๋ฌผ์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  Object-Oriented ์‹œ์Šคํ…œ์˜ Polymorphism ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ผ.
  1. Pure Fabrication
  • ๋„๋ฉ”์ธ์— ๊ด€๋ จ๋œ ๋ฌธ์ œ๋ฅผ ๋Œ€ํ‘œํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ๋ฉด ๊ธฐ๋Šฅ์ ์ธ ์ฑ…์ž„์„ ๋ณ„๋„๋กœ ํ•œ ๊ณณ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜, ๋กœ๊ทธ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•˜๋Š” ์ฑ…์ž„์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด ๋ณด์ž. ๊ฐ ์ •๋ณด๋Š” ๊ฐ๊ฐ์˜ ๊ฐ์ฒด๋“ค์ด ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค.
  • ์‹œ์Šคํ…œ ์ „๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๋ฉฐ, ๊ณตํ†ต์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณ ํ•ญํ•˜๋Š” ์ฑ…์ž„์„ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์•„์„œ ๊ฐ€์ƒ์˜ ๊ฐ์ฒด, ์„œ๋ธŒ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ผ.
  1. Indirection
  • ๋‘ ๊ฐ์ฒด ์‚ฌ์ด์˜ ์ง์ ‘์ ์ธ Coupling์„ ํ”ผํ•˜๊ณ  ์‹ถ์œผ๋ฉด, ๊ทธ ์‚ฌ์ด์— ๋‹ค๋ฅธ ๋งค๊ฐœ์ฒด๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ.
  • ์ฃผ๋กœ ๋‹ค๋ฅธ ๋งค๊ฐœ์ฒด๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
    • ๊ทธ๋Ÿฐ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๋Š” ์•„๋ž˜์— ์„ค๋ช…๋œ Protected Variations ํŒจํ„ด์ด๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜ ์žˆ๋‹ค.
  1. Protected Variations
  • ๋ณ€๊ฒฝ๋  ์—ฌ์ง€๊ฐ€ ์žˆ๋Š” ๊ณณ์— ์•ˆ์ •๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜์ž.
  1. Creator
  • ๊ฐ์ฒด์˜ ์ƒ์„ฑ์€ ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ์•Œ๊ณ  ์žˆ๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ปจํ…์ŠคํŠธ๋ฅผ ์•Œ๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์— ๋ถ€์—ฌ.
  • Factory Pattern
  1. 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 ๊ธฐ์ค€)

  1. 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());
  1. 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()๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋ฌด๋ฐฉ
  1. ๋‹จ์ง€ ๊ฐ’์„ ์–ป์„ ๋ชฉ์ ์ด๋ผ๋ฉด Optional ๋Œ€์‹  null ๋น„๊ต

Optional์€ ๋น„์‹ธ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹จ์ˆœํžˆ ๊ฐ’ ๋˜๋Š” null์„ ์–ป์„ ๋ชฉ์ ์ด๋ผ๋ฉด Optional ๋Œ€์‹  null ๋น„๊ต๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

// ์•ˆ ์ข‹์Œ
return Optional.ofNullable(status).orElse(READY);

// ์ข‹์Œ
return status != null ? status : READY;
  1. 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 ๋ถˆํ•„์š”
}
  1. 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;
}
  1. 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);
  1. 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 -> "");
  1. 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");
  1. Optional ๋Œ€์‹  OptionalInt, OptionalLong, OptionalDouble

Optional์— ๋‹ด๊ธธ ๊ฐ’์ด int, long, double์ด๋ผ๋ฉด Optional๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Boxing/Unboxing์ด ๋ฐœ์ƒํ•œ๋‹ค.

// ์•ˆ ์ข‹์Œ
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๊นŒ์ง€ ์ €์žฅํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

Last update: September 13, 2022 21:44
Contributors: ahnjs