Java

[Java] ์˜ฌ๋ฐ”๋ฅธ Optional ์‚ฌ์šฉ์œผ๋กœ API ์„ค๊ณ„ํ•˜๊ธฐ

9taetae9 2025. 2. 26. 10:32
728x90

API๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ, ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋งŒ ๋ณด๊ณ ๋„ ๋ฐ˜ํ™˜๊ฐ’์ด ์„ ํƒํ˜•์ธ์ง€, ์ฆ‰ ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ์„ ์‰ฝ๊ฒŒ ์ธ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ›จ์”ฌ ์•ˆ์ „ํ•˜๊ณ  ๋ช…๋ฃŒํ•œ API๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด ๊ธ€์—์„œ๋Š” Java 8๋ถ€ํ„ฐ ๋„์ž…๋œ Optional ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•ด API ์„ค๊ณ„์˜ ๋ช…ํ™•์„ฑ์„ ๋†’์ด๊ณ , NullPointerException๊ณผ ๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ์˜ˆ๋ฐฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋ ค ํ•œ๋‹ค.

1. Optional์˜ ๊ธฐ๋ณธ ๊ฐœ๋…

public final class Optional<T>
extends Object

A container object which may or may not contain a non-null value. - ๊ณต์‹ ๋ฌธ์„œ ์ •์˜

Java 8 ๋ถ€ํ„ฐ ๋„์ž…๋œ Optional<T>๋Š” null์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๊ฐ์‹ธ๋Š” ๋ž˜ํผ(wrapper) ํด๋ž˜์Šค๋‹ค. ๊ฐ’์ด ์กด์žฌํ•  ์ˆ˜๋„, ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋Š” ์ปจํ…Œ์ด๋„ˆ ๊ฐ์ฒด๋กœ์„œ, null ์ฐธ์กฐ ๋Œ€์‹  ์‚ฌ์šฉํ•จ์œผ๋กœ์จ NPE(NullPointerException)๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.

  • ๊ฐ’์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ: ์‹ค์ œ ๊ฐ์ฒด๋ฅผ Optional๋กœ ๊ฐ์‹ธ ๋ฐ˜ํ™˜
  • ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ: Optional.empty()์™€ ๊ฐ™์ด ๋น„์–ด์žˆ๋Š” Optional ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜

์˜ˆ๋ฅผ ๋“ค์–ด, Optional<Car>์˜ ๊ฒฝ์šฐ ์ฐจ ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๊ฐ์‹ธ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋นˆ Optional์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ null ๋Œ€์‹  ์•ˆ์ „ํ•œ ๋ฐฉ์‹์œผ๋กœ “๊ฐ’ ์—†์Œ”์„ ํ‘œํ˜„ํ•œ๋‹ค.
์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์€ API ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ null ์ฒดํฌ์˜ ํ•„์š”์„ฑ์„ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ธ์ง€ํ•˜๋„๋ก ๋„์™€์ค„ ์ˆ˜ ์žˆ๋‹ค.

2. API ์„ค๊ณ„์— Optional ์ ์šฉํ•˜๊ธฐ

์ž˜ ์„ค๊ณ„๋œ API๋Š” ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋งŒ ๋ณด๊ณ ๋„ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•˜๋Š”์ง€, ์•„๋‹ˆ๋ฉด ์„ ํƒํ˜•์ธ์ง€ ๋ช…ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
์•„๋ž˜ ๋‘ ๊ฐ€์ง€ ์„ ์–ธ์„ ๋น„๊ตํ•ด๋ณด์ž.

  • ํ•„์ˆ˜ ๊ฐ’ ๋ฐ˜ํ™˜
    • public String getName();
    • ์ด ๊ฒฝ์šฐ, ๊ฐ’์ด ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•˜๋ฉฐ, ๋งŒ์•ฝ ๋‚ด๋ถ€์ ์œผ๋กœ null์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด NullPointerException์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ์„ ํƒํ˜• ๊ฐ’ ๋ฐ˜ํ™˜
    • public Optional<String> getName();
    • Optional์„ ๋ฐ˜ํ™˜ํ•จ์œผ๋กœ์จ, API ์‚ฌ์šฉ์ž๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์ด ์—†์„ ๊ฐ€๋Šฅ์„ฑ๋„ ํ•จ๊ป˜ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ null ์ฒดํฌ๋ฅผ ์ค„์ด๊ณ , ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ์˜ ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ(map, filter, ifPresent ๋“ฑ)๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

3. Optional์˜ ์ƒ์„ฑ ๋ฐ ์‚ฌ์šฉ

Optional ํด๋ž˜์Šค๋Š” ์„ธ ๊ฐ€์ง€ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

  • Optional.empty(): ๋นˆ Optional ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜
    • Optional<Car> emptyCar = Optional.empty();
  • Optional.of: ๋ฐ˜๋“œ์‹œ null์ด ์•„๋‹Œ ๊ฐ’์„ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋ฉฐ, ๋งŒ์•ฝ null์ด ์ „๋‹ฌ๋˜๋ฉด ์ฆ‰์‹œ NullPointerException์ด ๋ฐœ์ƒํ•œ๋‹ค.
    • Optional<Car> optCar = Optional.of(car); //car๊ฐ€ null์ผ ๊ฒฝ์šฐ NullPointerException ๋ฐœ์ƒ!
    • ์ด๋Š” ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ ์˜ค๋ฅ˜๋ฅผ ๋…ธ์ถœ์‹œ์ผœ ๋ฌธ์ œ๋ฅผ ์กฐ๊ธฐ์— ํ•ด๊ฒฐํ•˜๋„๋ก ๋„์™€์ค€๋‹ค.
  • Optional.ofNullable: ๊ฐ’์ด null์ผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋ฉฐ, null์ด๋ฉด ๋นˆ Optional ๊ฐ์ฒด(Optional.empty())๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • Optional<Car> optCar = Optional.ofNullable(car);
    • ์ด ๋ฐฉ์‹์„ ํ†ตํ•ด null ์ฒดํฌ๋ฅผ ๋ณด๋‹ค ๋ช…์‹œ์ ์ด๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ถ”๊ฐ€์ ์œผ๋กœ, ๊ธฐ์กด์˜ null ์ฒดํฌ ํŒจํ„ด์„ ๋Œ€์ฒดํ•˜๊ธฐ ์œ„ํ•ด Optional์˜ map ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • Optional<Insurance> optInsurance = Optional.ofNullable(insurance); // null์ผ ์ˆ˜ ์žˆ์Œ(null ์ฒดํฌ ํ•„์š”)
      Optional<String> name = optInsurance.map(Insurance::getName); 
    • ์ด ๋ฐฉ์‹์€ insurance๊ฐ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ getName()์„ ํ˜ธ์ถœํ•˜๊ณ , null์ธ ๊ฒฝ์šฐ ๋นˆ Optional์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
 

4. Optional์„ ํ™œ์šฉํ•œ API ์„ค๊ณ„์˜ ์žฅ์ 

4.1. ๋ช…์‹œ์  ์˜๋„ ํ‘œํ˜„

๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— Optional์„ ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น ๊ฐ’์ด ์„ ํƒ์ ์ž„์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • API ์‚ฌ์šฉ์ž ์ธ์‹: ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋Š” ๊ฐ’์ด ์—†์„ ์ˆ˜ ์žˆ์Œ์„ ์ธ์ง€ํ•˜๊ณ , ์ ์ ˆํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋‚˜ ๋Œ€์ฒด ๋กœ์ง์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

4.2. ์ฝ”๋“œ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

Optional์€ null ์ฒดํฌ๋ฅผ ์œ„ํ•œ ๋ถˆํ•„์š”ํ•œ if ๋ฌธ์„ ์ค„์—ฌ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.

  • ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ: map, flatMap, filter ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋”์šฑ ์„ ์–ธ์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.
  • ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ์ : Optional.of๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด null ์ „๋‹ฌ ์‹œ์ ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ, ๋ฌธ์ œ์˜ ์›์ธ์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

5. Optional ์‚ฌ์šฉ ์‹œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์‚ฌํ•ญ

5.1. ๊ณผ๋„ํ•œ ๋‚จ์šฉ ๋ฐฉ์ง€

Optional์€ ๋ฐ˜ํ™˜ ํƒ€์ž…์—์„œ์˜ ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋˜๋ฉฐ, ํ•„๋“œ๋‚˜ ์ปฌ๋ ‰์…˜ ์š”์†Œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. (ํ•„๋“œ๋กœ ์‚ฌ์šฉํ–ˆ์„๋•Œ  ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ ๋ฌธ์ œ์ ์€ ์•„๋ž˜์— ์ถ”๊ฐ€๋กœ ์ •๋ฆฌํ•˜์˜€๋‹ค.)

  • ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ: Optional ๊ฐ์ฒด๋Š” ๋ž˜ํผ(wrapper) ํด๋ž˜์Šค์ด๋ฏ€๋กœ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋‚จ์šฉํ•  ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

5.2. get() ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ์ฃผ์˜

Optional์˜ get() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ NoSuchElementException์ด ๋ฐœ์ƒํ•œ๋‹ค.

  • ๋Œ€์•ˆ: orElse, orElseThrow, ifPresent ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•ด ๋ณด๋‹ค ์•ˆ์ „ํ•˜๊ฒŒ ๊ฐ’์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.

5.2. Value-Based Class ํŠน์„ฑ ์œ ์˜

 Value-Based Class๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์„ฑ์„ ๊ฐ–๋Š”๋‹ค.

  • ์‹๋ณ„์„ฑ ์—†์Œ(No identity): ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ณ ์œ ํ•œ ์‹๋ณ„์„ฑ์„ ๊ฐ–์ง€ ์•Š์Œ
  • ๋ถˆ๋ณ€์„ฑ(Immutability): ์ƒ์„ฑ ํ›„ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ
  • ๊ฐ’ ์ค‘์‹ฌ(Value-oriented): ์ฐธ์กฐ๊ฐ€ ์•„๋‹Œ ๊ฐ’์œผ๋กœ ์ทจ๊ธ‰๋จ

Optional์€ value-based class์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์€ ํ”ผํ•ด์•ผ ํ•œ๋‹ค.

This is a value-based class; use of identity-sensitive operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided. -  ๊ณต์‹ ๋ฌธ์„œ ์ฐธ๊ณ 

  • ๋™์ผ์„ฑ ๊ฒ€์‚ฌ (==) ์‚ฌ์šฉ ๊ธˆ์ง€ (identity-sensitive ์—ฐ์‚ฐ ์‹œ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.)
  • ์ฆ‰, ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ ์•„๋‹Œ ๋‚ด๋ถ€ ์ƒํƒœ(๊ฐ’)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์—ฐ์‚ฐํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค.
  • Optional์˜ equals()๋Š” ๋‚ด๋ถ€ ๊ฐ’์˜ equals()๋ฅผ ๋น„๊ตํ•˜์—ฌ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. (equals()/hashCode() ์ •์˜ ํ•„์š”)
Optional<String> opt1 = Optional.of("value");
Optional<String> opt2 = Optional.of("value");

// ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ
boolean result = (opt1 == opt2); // ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฐ๊ณผ

// ๋Œ€์‹  .equals() ์‚ฌ์šฉ
boolean safeResult = opt1.equals(opt2); // ์˜ฌ๋ฐ”๋ฅธ ๋น„๊ต ๋ฐฉ๋ฒ•
  • JVM์€ value-based class์˜ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๊ฐ™์€ ๊ฐ’์„ ๊ฐ€์ง„ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ์บ์‹œํ•˜์—ฌ ๋™์ผํ•œ ์ฐธ์กฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” ๋ณด์žฅ๋œ ๋™์ž‘์ด ์•„๋‹ˆ๋ฏ€๋กœ == ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ์€ ์ง€์–‘ํ•ด์•ผ ํ•œ๋‹ค. (JVM์€ value-based class์— ๋Œ€ํ•ด ์ธ์Šคํ„ด์Šค ํ’€๋ง, ์ธ๋ผ์ด๋‹, ์Šค์นผ๋ผ ๋Œ€์ฒด ๋“ฑ ๋‹ค์–‘ํ•œ ์ตœ์ ํ™”๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ JVM ๊ตฌํ˜„/๋ฒ„์ „์— ๋”ฐ๋ผ ์‹๋ณ„์„ฑ ๊ธฐ๋ฐ˜ ์—ฐ์‚ฐ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.)
  • identityHashCode()๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ Optional ์ธ์Šคํ„ด์Šค๋ฅผ ๋™๊ธฐํ™”์˜ ๋Œ€์ƒ์œผ๋กœ ์‚ผ๋Š” ๊ฒƒ ์—ญ์‹œ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ๋”ฐ๋ผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ”ผํ•ด์•ผ ํ•œ๋‹ค.
  • ์ฆ‰, Optional ๋น„๊ต์‹œ equals()๋‚˜ hashCode() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฉฐ, ๋™๊ธฐํ™” ๋ธ”๋ก์˜ ๋ชจ๋‹ˆํ„ฐ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋œ๋‹ค.
  • Optional ์ธ์Šคํ„ด์Šค ์ž์ฒด๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ๋˜์ง€๋งŒ, ๋‚ด๋ถ€ ๊ฐ’์˜ ์ฐธ์กฐ๋Š” ์›๋ณธ ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•œ๋‹ค. (์•„๋ž˜ ์˜ˆ์‹œ ์ฐธ๊ณ )
StringBuilder sb1 = new StringBuilder("A");
StringBuilder sb2 = sb1;  // ๋™์ผ ๊ฐ์ฒด ์ฐธ์กฐ

Optional<StringBuilder> opt1 = Optional.of(sb1);
Optional<StringBuilder> opt2 = Optional.of(sb2);

System.out.println(opt1.get() == opt2.get());  // true
sb1.append("B");  // ๊ฐ€๋ณ€ ๊ฐ์ฒด ์ˆ˜์ •
System.out.println(opt1.get());  // "AB" ์ถœ๋ ฅ (๋™์ผ ๊ฐ์ฒด ์ƒํƒœ ๋ณ€๊ฒฝ)
System.out.println(opt2.get());  // "AB"
System.out.println(opt1.get() == opt2.get()); //true

5.3. API ๋ฌธ์„œํ™”

Optional์„ ์‚ฌ์šฉํ•œ ๋ฉ”์„œ๋“œ์˜ ๊ฒฝ์šฐ, API ๋ฌธ์„œ์— ๊ฐ’์ด ์—†๋Š” ์ƒํ™ฉ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ธฐ์ˆ ํ•ด ๋‘๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋œ๋‹ค.

 

์ •๋ฆฌ

Optional ํด๋ž˜์Šค์˜ ์‚ฌ์šฉ์€ API ์„ค๊ณ„์— ์žˆ์–ด null ์•ˆ์ „์„ฑ๊ณผ ๋ช…์‹œ์  ์˜๋„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ•์ด๋‹ค.

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

6. Optional์„ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ด์•ผ ๋˜๋Š” ๊ฒฝ์šฐ

6.1. ํด๋ž˜์Šค ํ•„๋“œ๋กœ ์‚ฌ์šฉ ์ง€์–‘

Optional์€ Serializable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ง๋ ฌํ™”๊ฐ€ ํ•„์š”ํ•œ ํด๋ž˜์Šค์˜ ํ•„๋“œ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

(Serializable์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์œผ๋ฉฐ final ํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ธŒํด๋ž˜์‹ฑ์„ ํ†ตํ•œ ์ง๋ ฌํ™” ๊ตฌํ˜„๋„ ๋ถˆ๊ฐ€)

๋„๋ฉ”์ธ ๋ชจ๋ธ ์„ค๊ณ„์‹œ Optional์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ๋Š” ์˜๊ฒฌ์ด ๋งŽ์•˜์ง€๋งŒ,

"๋ชจ๋˜ ์ž๋ฐ” ์ธ ์•ก์…˜"์˜ ์ €์ž๋Š” ์ง๋ ฌํ™”๊ฐ€ ํ•„์š”ํ•œ ํ•„๋“œ์—์„œ๋Š” Optional ๋Œ€์‹  ์›์‹œ ํƒ€์ž… ๋˜๋Š” nullable ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ณ , Optional๋กœ ๊ฐ’์„ ๋ฐ˜ํ™˜๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ๋ผ๋„ Optional์„ ๋„๋ฉ”์ธ ๋ชจ๋ธ์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ธ์ •์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. (์•„๋ž˜ ์ฐธ๊ณ ) 

 

// ์•ˆํ‹ฐ ํŒจํ„ด: ํ•„๋“œ๋กœ Optional ์‚ฌ์šฉ
public class User {
    private String name;
    private Optional<Address> address; // ์ง๋ ฌํ™” ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ
}

// ์˜ฌ๋ฐ”๋ฅธ ์„ค๊ณ„
public class User {
    private String name;
    private Address address; // address๋Š” null์ผ ์ˆ˜ ์žˆ์Œ

    public Optional<Address> getAddress() {
        return Optional.ofNullable(address);
    }
}

 

๊ธฐ๋ณธ Jackson ์„ค์ •์œผ๋กœ Optional ํ•„๋“œ๋ฅผ ์ง๋ ฌํ™”ํ•˜๋ฉด java 8์—์„œ๋Š” {"present":true}, java 15์—์„œ๋Š” {"empty":false,"present":true}๊ณผ ๊ฐ™์ด ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ณ , ์—ญ์ง๋ ฌํ™” ์‹œ์—๋Š” MismatchedInputException, InvalidDefinitionException ๋“ฑ์˜ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ ํ•œ๋‹ค.

 

Optional์„ ํ•„๋“œ๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ ์ด๋Ÿฌํ•œ ์ง๋ ฌํ™” ๋ฌธ์ œ๋Š” Jackson-datatype-jdk8 ์˜์กด์„ฑ ์ถ”๊ฐ€๋ฅผ ํ†ตํ•ด Optional ๊ฐ’์„ ์ผ๋ฐ˜ ๊ฐ์ฒด๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

Jackson์ด ๋น„์–ด ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ null๋กœ, ๊ฐ’์ด ์žˆ๋Š” ๊ฐ์ฒด๋Š” ํ•ด๋‹น ๊ฐ’์„ ํฌํ•จํ•˜๋Š” ํ•„๋“œ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. (jackson-modules-java8 ํ”„๋กœ์ ํŠธ ๋งํฌ ์ฐธ๊ณ ) https://github.com/FasterXML/jackson-modules-java8

 

 

๊ทธ๋Ÿฌ๋‚˜ JSON์—์„œ null์„ Optional.empty()๋กœ ๋ณ€ํ™˜ํ•˜์ง€ ์•Š๊ณ  Optional ์ž์ฒด๋ฅผ null๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ null ์ฒ˜๋ฆฌ ๋…ผ๋ฆฌ ์ถฉ๋Œํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ ์‹œ๋‚˜๋ฆฌ์˜ค

{"something": null} → something ํ•„๋“œ๊ฐ€ null (Optional.empty() ์•„๋‹˜)

// ์˜ˆ์ƒ: Optional.empty()

// ์‹ค์ œ: Test.something = null → NPE ๋ฐœ์ƒ ๊ฐ€๋Šฅ


์กฐ์‚ฌ ๊ฒฐ๊ณผ Jdk8Module + NON_ABSENT + ๊ธฐ๋ณธ๊ฐ’ ์ดˆ๊ธฐํ™”์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ์ผ๋ฐ˜์ ์ธ null ๋ฐฉ์ง€๊ฐ€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ JSON์—์„œ ๋ช…์‹œ์ ์œผ๋กœ null ์ „์†ก ์‹œ ์ปค์Šคํ…€ ์—ญ์ง๋ ฌํ™”๊ฐ€ ํ•„์š”ํ•ด ๋ณด์ธ๋‹ค.

https://stackoverflow.com/questions/75844408/how-to-make-jackson-deserialize-explicit-null-to-optional-empty-but-not-to-seri

 

 ์ด๋Ÿฌํ•œ ์—ฌ๋Ÿฌ ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์„ ์ˆ™์ง€ํ–ˆ๋‹ค๋ฉด ๋„๋ฉ”์ธ ์„ค๊ณ„์‹œ์—๋Š” ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ œํ•œ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์•„์ง ์•Œ์ง€ ๋ชปํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฌธ์ œ๊ฐ€ ๋‚ด์ œ๋˜์–ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„ ์•„์˜ˆ Optional์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

 

6.2. ์ƒ์„ฑ์ž๋‚˜ ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉ ์ง€์–‘

Optional์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

// ์•ˆํ‹ฐ ํŒจํ„ด: ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ Optional ์‚ฌ์šฉ
User user = new User("john@gmail.com", "1234", Optional.empty());

// ๊ถŒ์žฅ
User user = new User("john@gmail.com", "1234", null);
// ๋‹ค๋ฅธ ๋Œ€์•ˆ: ๋นŒ๋” ํŒจํ„ด์ด๋‚˜ ์˜ค๋ฒ„๋กœ๋“œ๋œ ์ƒ์„ฑ์ž ์‚ฌ์šฉ
User user = new User.Builder()
    .email("john@gmail.com")
    .password("1234")
    .build();

 

6.3. ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•œ Optional ์‚ฌ์šฉ ์ง€์–‘

๋นˆ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๊ถŒ์žฅ๋œ๋‹ค.

// ์•ˆํ‹ฐ ํŒจํ„ด
public Optional<List<User>> getUsers() { ... }

// ๋นˆ ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
public List<User> getUsers() {
    return users != null ? users : Collections.emptyList();
}

 

7. orElse vs orElseGet ์˜ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ

orElse๋Š” ํ•ญ์ƒ ํ‰๊ฐ€๋˜์ง€๋งŒ, orElseGet์€ Optional์ด ๋น„์–ด์žˆ์„ ๋•Œ๋งŒ ํ‰๊ฐ€๋œ๋‹ค.

// ํ•ญ์ƒ createDefaultUser()๊ฐ€ ํ˜ธ์ถœ๋จ
User user = userOpt.orElse(createDefaultUser());

// Optional์ด ๋น„์–ด์žˆ์„ ๋•Œ๋งŒ createDefaultUser()๊ฐ€ ํ˜ธ์ถœ๋จ
User user = userOpt.orElseGet(() -> createDefaultUser());

 

7.1. orElse ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค- ์ฆ‰์‹œ ํ‰๊ฐ€

User user = userOpt.orElse(createDefaultUser());

 

  • step 1: createDefaultUser()๊ฐ€ ๋จผ์ € ํ˜ธ์ถœ๋˜์–ด ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
  • step 2: ์ƒ์„ฑ๋œ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ๊ฐ์ฒด๊ฐ€ ์ธ์ž๋กœ ์ „๋‹ฌ
  • step 3: userOpt๊ฐ€ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๊ทธ ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜์ง€๋งŒ ์ด๋ฏธ createDefaultUser()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ๋น„์šฉ์ด ๋ฐœ์ƒ
  • step 4: ๋งŒ์•ฝ userOpt๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, ์ธ์ž๋กœ ์ „๋‹ฌ๋œ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜

์ฆ‰, ํ•ญ์ƒ createDefaultUser()๊ฐ€ ์‹คํ–‰๋˜๋ฏ€๋กœ, ์‹ค์ œ๋กœ ๊ธฐ๋ณธ๊ฐ’์ด ํ•„์š” ์—†๋”๋ผ๋„ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ๊ณผ ๋ถ€์ˆ˜ ํšจ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ์„ ์ธ์ง€ํ•˜์ž.

 

 

orElse ์‚ฌ์šฉ์ด ์ ์ ˆํ•œ ์ผ€์ด์Šค

๊ฐ„๋‹จํ•˜๊ณ  ๋น„์šฉ์ด ๋‚ฎ์€ ๊ฒฝ์šฐ
๋งŒ์•ฝ ๊ธฐ๋ณธ๊ฐ’์ด ์ด๋ฏธ ์ค€๋น„๋˜์–ด ์žˆ๊ฑฐ๋‚˜, ์ƒ์„ฑ ๋น„์šฉ์ด ๊ทนํžˆ ๋‚ฎ๊ณ  ๋ถ€์ˆ˜ ํšจ๊ณผ๊ฐ€ ์ „ํ˜€ ์—†๋‹ค๋ฉด orElse๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง€๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒ์ˆ˜ ๊ฐ’์ด๋‚˜ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐ๋œ ๊ฐ’์ด๋ผ๋ฉด ๊ตณ์ด ์ง€์—ฐ ํ‰๊ฐ€๋ฅผ ์œ„ํ•ด orElseGet์„ ์“ธ ํ•„์š”๊ฐ€ ์—†๋‹ค.

 

+ ๊ธฐ๋ณธ๊ฐ’ ์ƒ์„ฑ ๋น„์šฉ์ด ๋‚ฎ๋‹ค๊ณ  ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ

  • ๋‹จ์ˆœ ๊ฐ์ฒด ์ƒ์„ฑ
    ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹จ์ˆœ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ(์˜ˆ: new User("default", "default@example.com"))์ฒ˜๋Ÿผ ์—ฐ์‚ฐ์ด ๋งค์šฐ ๊ฐ€๋ณ๊ณ  ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ๋น„์šฉ์ด ๋ฏธ๋ฏธํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ณ„์‚ฐ์ด๋‚˜ ์™ธ๋ถ€ ์—ฐ์‚ฐ์ด ์—†๋Š” ๊ฒฝ์šฐ
    ๊ธฐ๋ณธ๊ฐ’์„ ์ƒ์„ฑํ•  ๋•Œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ, ํŒŒ์ผ ์ž…์ถœ๋ ฅ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ, ๋ณต์žกํ•œ ๊ณ„์‚ฐ ๋“ฑ์˜ ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ์ด ์ „ํ˜€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด, ์ด ๊ฒฝ์šฐ๋Š” ๊ธฐ๋ณธ๊ฐ’ ์ƒ์„ฑ ๋น„์šฉ์ด ๋‚ฎ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ถ€์ˆ˜ ํšจ๊ณผ๊ฐ€ ์—†๋Š” ์ˆœ์ˆ˜ ๋ฉ”์„œ๋“œ
    ๊ธฐ๋ณธ๊ฐ’์„ ๋งŒ๋“œ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ˆœ์ˆ˜ ๋ฉ”์„œ๋“œ๋ผ๋ฉด, ์ฆ‰ ์ž…๋ ฅ์ด ๊ฐ™์œผ๋ฉด ํ•ญ์ƒ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์™ธ๋ถ€ ์ƒํƒœ๋‚˜ ๋ถ€์ˆ˜ ํšจ๊ณผ(๋กœ๊ทธ, ์ƒํƒœ ๋ณ€๊ฒฝ ๋“ฑ)๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋น„์šฉ ๋ถ€๋‹ด์ด ๋‚ฎ๋‹ค๊ณ  ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.

7.2. orElseGet ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค - ์ง€์—ฐ ํ‰๊ฐ€

User user = userOpt.orElseGet(() -> createDefaultUser());

 

  • step 1: ๋จผ์ € userOpt ๋‚ด๋ถ€์˜ ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • step 2: ๋งŒ์•ฝ userOpt๊ฐ€ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๊ทธ ๊ฐ’์ด ๋ฐ”๋กœ ๋ฐ˜ํ™˜๋˜๊ณ  ๋žŒ๋‹ค ํ•จ์ˆ˜๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ
  • step 3: ๋งŒ์•ฝ userOpt๊ฐ€ ๋น„์–ด์žˆ๋‹ค๋ฉด, ๋žŒ๋‹ค ํ•จ์ˆ˜ ๋‚ด์˜ createDefaultUser()๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ํ›„ ๋ฐ˜ํ™˜

 

๋”ฐ๋ผ์„œ orElseGet ์‚ฌ์šฉ ์‹œ, Optional์ด ๋น„์–ด์žˆ์„ ๋•Œ๋งŒ createDefaultUser()๊ฐ€ ์‹คํ–‰๋˜์–ด ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ๊ณผ ๋ถ€์ˆ˜ ํšจ๊ณผ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

 

orElse Get ์‚ฌ์šฉ์ด ์ ์ ˆํ•œ ์ผ€์ด์Šค

๋น„์šฉ๊ณผ ๋ถ€์ˆ˜ ํšจ๊ณผ๊ฐ€ ๋†’์€ ๊ฒฝ์šฐ

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

์œ„์˜ ์˜ˆ์‹œ์˜ createDefaultUser()๊ฐ€ ๋งŒ์•ฝ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ์ด๋‚˜ ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ํฌํ•จํ•œ๋‹ค๋ฉด, userOpt์— ๊ฐ’์ด ์กด์žฌํ•  ๋•Œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ ๋ฉด์—์„œ ์œ ๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.

 

 

์ฐธ๊ณ  ์ž๋ฃŒ :

๋ชจ๋˜ ์ž๋ฐ” ์ธ ์•ก์…˜

https://docs.oracle.com/javase/8/docs/api///?java/util/Optional.html

 

Java Platform SE 8

 

docs.oracle.com

 

https://dzone.com/articles/java-8-optional-usage-and-best-practices

 

Java 8 Optional Usage and Best Practices

Check out this post where we look at Optional, first introduced in Java 8, how to use it, and best practices for implementing it in your existing projects.

dzone.com

https://nipafx.dev/java-value-based-classes/

 

Value-Based Classes // nipafx

An explanation of value-based classes in Java 8. Why do they exist? What are their limitations? How (not) to use them?

nipafx.dev

https://www.baeldung.com/java-optional-or-else-vs-or-else-get

https://github.com/FasterXML/jackson-modules-java8

 

GitHub - FasterXML/jackson-modules-java8: Set of support modules for Java 8 datatypes (Optionals, date/time) and features (param

Set of support modules for Java 8 datatypes (Optionals, date/time) and features (parameter names) - FasterXML/jackson-modules-java8

github.com

https://www.codekru.com/java/java-optional-with-jackson

 

728x90