week 9 jisoo - GANGNAM-JAVA/JAVA-STUDY GitHub Wiki

java optional์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ ์„ค๋ช…๊ณผ ์˜ˆ์‹œ๋ฅผ ์„ค๋ช…ํ•ด๋ณด์‹œ์˜ค

Optional ํด๋ž˜์Šค

java.util.Optional ํด๋ž˜์Šค

Optional ํด๋ž˜์Šค๋Š” Integer๋‚˜ Double ํด๋ž˜์Šค์ฒ˜๋Ÿผ 'T'ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ํฌ์žฅํ•ด ์ฃผ๋Š” ๋ž˜ํผ ํด๋ž˜์Šค(Wrapper class)์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Optional ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋“  ํƒ€์ž…์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ Optional ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ NullPointerException ์˜ˆ์™ธ๋ฅผ ์ œ๊ณต๋˜๋Š” ๋ฉ”์†Œ๋“œ๋กœ ๊ฐ„๋‹จํžˆ ํšŒํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ๋ณต์žกํ•œ ์กฐ๊ฑด๋ฌธ ์—†์ด๋„ ๋„(null) ๊ฐ’์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Optional ๊ฐ์ฒด์˜ ์ƒ์„ฑ of() ๋ฉ”์†Œ๋“œ๋‚˜ ofNullable() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Optional ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

of() ๋ฉ”์†Œ๋“œ๋Š” null์ด ์•„๋‹Œ ๋ช…์‹œ๋œ ๊ฐ’์„ ๊ฐ€์ง€๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ of() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ Optional ๊ฐ์ฒด์— null์ด ์ €์žฅ๋˜๋ฉด NullPointerException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋งŒ์•ฝ ์ฐธ์กฐ ๋ณ€์ˆ˜์˜ ๊ฐ’์ด ๋งŒ์— ํ•˜๋‚˜ null์ด ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค๋ฉด, ofNullable() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Optional ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

ofNullable() ๋ฉ”์†Œ๋“œ๋Š” ๋ช…์‹œ๋œ ๊ฐ’์ด null์ด ์•„๋‹ˆ๋ฉด ๋ช…์‹œ๋œ ๊ฐ’์„ ๊ฐ€์ง€๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ๋ช…์‹œ๋œ ๊ฐ’์ด null์ด๋ฉด ๋น„์–ด์žˆ๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ

Optional opt = Optional.ofNullable("์ž๋ฐ” Optional ๊ฐ์ฒด");

System.out.println(opt.get());

์ฝ”๋”ฉ์—ฐ์Šต โ–ถ

์‹คํ–‰ ๊ฒฐ๊ณผ ์ž๋ฐ” Optional ๊ฐ์ฒด

Optional ๊ฐ์ฒด์— ์ ‘๊ทผ get() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’์ด null์ด๋ฉด, NoSuchElementException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ get() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— isPresent() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’์ด null์ธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ๋จผ์ € ํ™•์ธํ•œ ํ›„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ๋Š” isPresent() ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ข€ ๋” ์•ˆ์ „ํ•˜๊ฒŒ Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’์— ์ ‘๊ทผํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

์˜ˆ์ œ

Optional<String> opt = Optional.ofNullable("์ž๋ฐ” Optional ๊ฐ์ฒด");

 

if(opt.isPresent()) {

    System.out.println(opt.get());

}

์ฝ”๋”ฉ์—ฐ์Šต โ–ถ

์‹คํ–‰ ๊ฒฐ๊ณผ ์ž๋ฐ” Optional ๊ฐ์ฒด

๋˜ํ•œ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ null ๋Œ€์‹ ์— ๋Œ€์ฒดํ•  ๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. orElse() ๋ฉ”์†Œ๋“œ : ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ.

  2. orElseGet() ๋ฉ”์†Œ๋“œ : ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ด๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ.

  3. orElseThrow() ๋ฉ”์†Œ๋“œ : ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด.

์˜ˆ์ œ

Optional<String> opt = Optional.empty(); // Optional๋ฅผ null๋กœ ์ดˆ๊ธฐํ™”ํ•จ.

System.out.println(opt.orElse("๋นˆ Optional ๊ฐ์ฒด"));
System.out.println(opt.orElseGet(String::new));

์ฝ”๋”ฉ์—ฐ์Šต โ–ถ

์‹คํ–‰ ๊ฒฐ๊ณผ ๋นˆ Optional ๊ฐ์ฒด

์œ„์˜ ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ๋œ empty() ๋ฉ”์†Œ๋“œ๋Š” Optional ๊ฐ์ฒด๋ฅผ null๋กœ ์ดˆ๊ธฐํ™”ํ•ด์ค๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ํƒ€์ž…์˜ Optional ํด๋ž˜์Šค ์ž๋ฐ”์—์„œ๋Š” IntStream ํด๋ž˜์Šค์™€ ๊ฐ™์ด ๊ธฐ๋ณธ ํƒ€์ž… ์ŠคํŠธ๋ฆผ์„ ์œ„ํ•œ ๋ณ„๋„์˜ Optional ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  1. OptionalInt ํด๋ž˜์Šค

  2. OptionalLong ํด๋ž˜์Šค

  3. OptionalDouble ํด๋ž˜์Šค

์ด๋Ÿฌํ•œ ํด๋ž˜์Šค๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…์ด Optional ํƒ€์ž…์ด ์•„๋‹ˆ๋ผ ํ•ด๋‹น ๊ธฐ๋ณธ ํƒ€์ž…์ด๋ผ๋Š” ์‚ฌ์‹ค๋งŒ ์ œ์™ธํ•˜๋ฉด ๊ฑฐ์˜ ๋ชจ๋“  ๋ฉด์—์„œ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, Optional ๊ฐ์ฒด์—์„œ get() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ๋œ ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํด๋ž˜์Šค๋ณ„๋กœ ์ €์žฅ๋œ ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šค ์ €์žฅ๋œ ๊ฐ’์— ์ ‘๊ทผํ•˜๋Š” ๋ฉ”์†Œ๋“œ Optional T get() OptionalInt int getAsInt() OptionalLong long getAsLong() OptionalDouble double getAsDouble()

์˜ˆ์ œ IntStream stream = IntStream.of(4, 2, 1, 3);

OptionalInt result = stream.findFirst();

System.out.println(result.getAsInt());

์ฝ”๋”ฉ์—ฐ์Šต โ–ถ

์‹คํ–‰ ๊ฒฐ๊ณผ

4

Optional ๋ฉ”์†Œ๋“œ

Optional ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ฉ”์†Œ๋“œ ์„ค๋ช… static <T> Optional<T> empty() ์•„๋ฌด๋Ÿฐ ๊ฐ’๋„ ๊ฐ€์ง€์ง€ ์•Š๋Š” ๋น„์–ด์žˆ๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•จ. T get() Optional ๊ฐ์ฒด์— ์ €์žฅ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ.

boolean isPresent() ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•จ.

static <T> Optional<T> of(T value) null์ด ์•„๋‹Œ ๋ช…์‹œ๋œ ๊ฐ’์„ ๊ฐ€์ง€๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•จ.

static <T> Optional<T> ofNullable(T value) ๋ช…์‹œ๋œ ๊ฐ’์ด null์ด ์•„๋‹ˆ๋ฉด ๋ช…์‹œ๋œ ๊ฐ’์„ ๊ฐ€์ง€๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ๋ช…์‹œ๋œ ๊ฐ’์ด null์ด๋ฉด ๋น„์–ด์žˆ๋Š” Optional ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•จ.

T orElse(T other) ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ.

T orElseGet(Supplier<? extends T> other) ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ด๊ฐ’์„ ๋ฐ˜ํ™˜ํ•จ.

<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) ์ €์žฅ๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด.

์ž๋ฐ” ๋žŒ๋‹ค & ํด๋กœ์ €๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

๋žŒ๋‹ค์™€ ํด๋กœ์ €

  • ์ž๋ฐ” ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ๋Š” ํด๋กœ์ €์™€ ๋žŒ๋‹ค๋ฅผ ํ˜ผ์šฉํ•˜๋ฉด์„œ ๊ฐœ๋… ์ƒ ํ˜ผ๋ž€์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ž๋ฐ” 8๋ถ€ํ„ฐ ํด๋กœ์ €๋ฅผ ์ง€์›ํ•œ๋‹ค๋Š” ๊ธ€์„ ๋ณด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ž๋ฐ”์—์„œ์˜ ๋žŒ๋‹ค์™€ ํด๋กœ์ €๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

ํด๋กœ์ € Closure

  • ๋ณดํ†ต์˜ ํ•จ์ˆ˜๋Š” ์™ธ๋ถ€์—์„œ ์ธ์ž๋ฅผ ๋ฐ›์•„์„œ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • ๊ทธ๋Ÿฐ๋ฐ ํด๋กœ์ €๋Š” ์ž์‹ ์„ ๋‘˜๋Ÿฌ์‹ผ context ๋‚ด์˜ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ฆ‰, ์™ธ๋ถ€ ๋ฒ”์œ„์˜ ๋ณ€์ˆ˜๋ฅผ ํ•จ์ˆ˜ ๋‚ด๋ถ€๋กœ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.

  • ํŠน์ดํ•œ ์ ์€ ์ž์‹ ์„ ๋‘˜๋Ÿฌ์‹ผ ์™ธ๋ถ€ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋”๋ผ๋„ ์ด ๊ฐ’์ด ์œ ์ง€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

  • ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ’๋“ค์€ ํด๋กœ์ €๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์—์„œ ์ •์˜๋˜๊ณ  ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ๋ณต์‚ฌ๋˜์–ด ๋”ฐ๋กœ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

function add(x)
  function addX(y)
    return y + x
  return addX
  • ํ•จ์ˆ˜ addX ๋‚ด๋ถ€์—์„œ x ๋Š” ํ˜„์žฌ ํ•จ์ˆ˜๋ฅผ ๋‘˜๋Ÿฌ์‹ธ๊ณ  ์žˆ๋Š” ์™ธ๋ถ€ ์ปจํ…์ŠคํŠธ์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
  • add ์—์„œ ์ด ํ•จ์ˆ˜๊ฐ€ ๋ฆฌํ„ด๋˜๋Š”๋ฐ x ์˜ ๊ฐ’(value)์ด๋‚˜ ์ฐธ์กฐ(reference)๋ฅผ ๋ณต์‚ฌํ•œ ํด๋กœ์ €๊ฐ€ ๋ฆฌํ„ด๋ฉ๋‹ˆ๋‹ค.
  • ํ•จ์ˆ˜๋ฅผ ์ผ๊ธ‰ ๊ฐ์ฒด (first-class citizens) ๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ์–ธ์–ด์—์„œ๋Š” ์ด๋ฅผ ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ๋„ฃ์–ด์ฃผ๋Š” x ๊ฐ’์— ๋”ฐ๋ผ ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
variable add1 = add(1) // return y + 1
variable add5 = add(5) // return y + 5

assert add1(3) = 4
assert add5(3) = 8

์ž๋ฐ” ์† ํด๋กœ์ €

  • ๊ทธ๋ ‡๋‹ค๋ฉด ์ž๋ฐ”์—์„œ์˜ ํด๋กœ์ €๋Š” ์–ด๋–จ๊นŒ์š”? ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ํ•„๋“œ์— ์ ‘๊ทผํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค.
  • ์ด๋ฏธ ์ž๋ฐ”์—์„œ๋Š” ํด๋กœ์ €๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”์†Œ๋“œ ๋‚ด์—์„œ ์™ธ๋ถ€ ์ปจํ…์ŠคํŠธ์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์ฃ . ํ•˜์ง€๋งŒ ๋ฉ”์†Œ๋“œ๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๊ณ , ์ผ๊ธ‰ ๊ฐ์ฒด๋„ ์•„๋‹™๋‹ˆ๋‹ค.

์ž๋ฐ”์—์„œ์˜ ํด๋กœ์ € ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class ClosureTest {
  private Integer b = 2;
  
  private Stream<Integer> calculate(Stream<Integer> stream, Integer a) {
    return stream.map(t -> t * a + b);
  }

  public static void main(String... args) {
    
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    List<Integer> result = new ClosureTest()
      .calculate(list.stream(), 3)
      .collect(Collectors.toList());
    System.out.println(result); // [5, 8, 11, 14, 17]
  }
}
  • calculate ๋ฉ”์†Œ๋“œ์—์„œ map ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ธ์ž๋กœ ๋„˜์–ด๊ฐ€๋Š” ๋žŒ๋‹ค๊ฐ€ ์žˆ๋Š”๋ฐ ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ๋ณ€์ˆ˜์ธ a์™€ b๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ a ์™€ b ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ final ๋กœ ๊ฐ„์ฃผํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€์—์„œ ํ•„์š”๋กœ ํ•˜๋Š” ์ •๋ณด๋ฅผ ๋„˜๊ธธ ๋•Œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ๊ฐ’์€ ๋ณ€ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ํ•ด๋‹น ๊ฐ’์„ ์ƒ์ˆ˜๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ๊ฑฐ์ฃ . ์ด์ „ ํฌ์ŠคํŠธ์—์„œ ์œ ์‚ฌ ํŒŒ์ด๋„(effectively final)์„ ์‚ดํŽด๋ดค์—ˆ์ฃ . ๋”ฐ๋ผ์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ปดํŒŒ์ผ ์—๋Ÿฌ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
private Stream<Integer> calculate(Stream<Integer> stream, Integer a) {
  a = 10; // ๊ฐ’ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€
  // Variable used in lambda expression should be final or effectively final
  return stream.map(t -> t * a + b);
}

์ด๋ฅผ ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด์ „ ํฌ์ŠคํŠธ์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ˆ์ œ๋ฅผ ๋ณ€๊ฒฝํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class ClosureTest {
  private Integer b = 2;

  private Integer getB() {
    return b;
  }

  private Stream<Integer> calculate(Stream<Integer> stream, Int a) {
    a.setValue(10); // ๊ฐ’ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
    return stream.map(t -> t * a.value + getB());
  }
}

class Int {
  public int value;
  public Int(int value) {
    this.value = value;
  }
  public void setValue(int value) {
    this.value = value;
  }
}
  • ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์ฐธ์กฐ๊ฐ’์ด final ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด ์•ˆ์˜ ๊ฐ’์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
public static void main(String... args) {

  List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
  List<Integer> result = new ClosureTest()
    .calculate(list.stream(), new Int(3))
    .collect(Collectors.toList());
  System.out.println(result); // [12, 22, 32, 42, 52]
}
  • ํ•˜์ง€๋งŒ ์ด๋Š” side effect ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด ์œ„ํ—˜ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ฐจ์ด์ 

  • ๋žŒ๋‹ค์™€ ํด๋กœ์ €๋Š” ๋ชจ๋‘ ์ต๋ช…์˜ ํŠน์ • ๊ธฐ๋Šฅ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค. ์ฐจ์ด์ ์€ ํด๋กœ์ €๋Š” ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ณ , ๋žŒ๋‹ค๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ์ฐธ์กฐํ•œ๋‹ค๋Š” ๊ฒ๋‹ˆ๋‹ค.
// Lambda.
(server) -> server.isRunning();

// Closure. ์™ธ๋ถ€์˜ server ๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐ
() -> server.isRunning();
  • ํด๋กœ์ €๋Š” ์™ธ๋ถ€์— ์˜์กด์„ฑ์ด ์žˆ๊ณ , ๋žŒ๋‹ค๋Š” ์™ธ๋ถ€์— ์˜์กด์„ฑ์ด ์—†๋Š” ์Šคํƒœํ‹ฑ ๋ฉ”์†Œ๋“œ์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ๋Š” ํด๋ง ํ›„ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋Œ€๊ธฐํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค. Predicate ๋ฅผ ์ด์šฉํ•ด ๊ฒ€์ฆํ•˜๊ณ  ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค.

static <T> void waitFor(T input, Predicate<T> predicate) throws InterruptedException {
  while (!predicate.test(input)) {
    Thread.sleep(250);
  }
}

์–ด๋–ค HTTP ์„œ๋ฒ„๊ฐ€ ๊ตฌ๋™ ์ค‘์ธ์ง€ ํ™•์ธํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋žŒ๋‹ค๋ฅผ ๋„˜๊ฒจ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์™ธ์˜ ์™ธ๋ถ€ ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์—†์ฃ . ๋Ÿฐํƒ€์ž„์— ์ œ๊ณตํ•˜๋Š” ์„œ๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ฐธ๊ณ ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๋žŒ๋‹ค์ž…๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๋ณ€์ˆ˜์— ์˜ํ–ฅ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋” ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

waitFor(new HttpServer(), (server) -> !server.isRunning());
waitFor(new HttpServer(), HttpServer::isRunning); // ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ

์ด๋ฒˆ์—” ๋™์ผํ•œ ๋กœ์ง์„ ํด๋กœ์ €๋ฅผ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ธ์ž ์—†์ด boolean ๊ฐ’์„ ๋ฆฌํ„ดํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

static <T> void waitFor(Condition condition) throws InterruptedException {
  while (!condition.isSatisfied()) {
    Thread.sleep(250);
  }
}

@FunctionalInterface
interface Condition {
  boolean isSatisfied();
}

๋ฐ›์•„์˜ค๋Š” ์ •๋ณด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ๋Š” ํŒ๋‹จ์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์™ธ๋ถ€์—์„œ ์ฐธ์กฐํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ณ€์ˆ˜๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์— ์˜ํ•ด ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํด๋กœ์ €์ž…๋‹ˆ๋‹ค.

void closure() throws InterruptedException {
  HttpServer server = new HttpServer();
  waitFor(() -> !server.isRunning());
}

์ž๋ฐ”์—์„œ ํด๋กœ์ €๋Š” ํ•จ์ˆ˜์˜ ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค. ๋žŒ๋‹ค๊ฐ€ ์Šคํƒœํ‹ฑ ๋ฉ”์†Œ๋“œ์™€ ๋น„์Šทํ•˜๋‹ค๋ฉด ์™ธ๋ถ€ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ต๋ช… ํด๋ž˜์Šค๊ฐ€ ํด๋กœ์ €์™€ ๋น„์Šทํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

void anonymousClassClosure() throws InterruptedException {
  HttpServer server = new HttpServer();
  waitFor(new Condition() {
    @Override
    public boolean isSatisfied() {
      return !server.isRunning();
    }
  });
}

๊ฒฐ๋ก 

์„ค๋ช…์ด ๊ธธ์—ˆ๋Š”๋ฐ, ๊ฒฐ๋ก ์€ ๋žŒ๋‹ค๋Š” ํด๋กœ์ €๋ฅผ ํฌํ•จํ•˜๋Š” ๋” ํฐ ๊ฐœ๋…์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋žŒ๋‹ค๊ฐ€ ์ž์‹ ์˜ ๋ฒ”์œ„ ๋ฐ–์— ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๊ฒƒ์€ ๋žŒ๋‹ค์ธ ๋™์‹œ์— ํด๋กœ์ €์ž…๋‹ˆ๋‹ค.

์Šคํ”„๋ง5์˜ ํŠน์ง•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์‹œ์˜ค

  • Spring Framework 5.0์€ 2013 ๋…„ 12 ์›” ๋ฒ„์ „ 4๊ฐ€ ์ถœ์‹œ ๋œ ์ดํ›„ Spring Framework์˜ ์ฒซ ๋ฒˆ์งธ ์ฃผ์š” ๋ฆด๋ฆฌ์Šค์ž…๋‹ˆ๋‹ค. Spring Framework ํ”„๋กœ์ ํŠธ ์ฑ…์ž„์ž ์ธ Juergen Hoeller ๋Š” 2016 ๋…„ 7 ์›” 28 ์ผ์— ์ฒซ ๋ฒˆ์งธ Spring Framework 5.0 ๋งˆ์ผ์Šคํ†ค (5.0 M1)์„ ๋ฐœํ‘œํ–ˆ์Šต๋‹ˆ๋‹ค .

  • ์ด์ œ ๊ฑฐ์˜ 1 ๋…„ ํ›„, ๋ฆด๋ฆฌ์Šค ํ›„๋ณด 3 (RC3)์ด 2017 ๋…„ 7 ์›” 18 ์ผ์— ๋ฆด๋ฆฌ์Šค ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Spring Framework์˜ ์ฒซ ๋ฒˆ์งธ GA (์ผ๋ฐ˜ ๊ฐ€์šฉ์„ฑ) ๋ฆด๋ฆฌ์Šค ์— ๋Œ€ํ•œ ๋กœ๋“œ๋งต ์˜ ์ตœ์ข… ๋ฆด๋ฆฌ์Šค๊ฐ€ ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.

  • ๋†’์€ ์ˆ˜์ค€์—์„œ Spring Framework 5.0์˜ ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถ„๋ฅ˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


  • JDK ๊ธฐ์ค€ ์—…๋ฐ์ดํŠธ.
  • ํ•ต์‹ฌ ํ”„๋ ˆ์ž„ ์›Œํฌ ๊ฐœ์ •.
  • ํ•ต์‹ฌ ์ปจํ…Œ์ด๋„ˆ ์—…๋ฐ์ดํŠธ.
  • Kotlin์„ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ.
  • ๋ฐ˜์‘ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ.
  • ํ…Œ์ŠคํŠธ ๊ฐœ์„ .
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ง€์›.
  • ์ง€์› ์ค‘๋‹จ.

Spring Framework 5.0 ์šฉ JDK ๊ธฐ์ค€ ์—…๋ฐ์ดํŠธ

  • ์ „์ฒด Spring Framework 5.0 ์ฝ”๋“œ๋ฒ ์ด์Šค๋Š” Java 8์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Java 8์€ Spring Framework 5.0์—์„œ ์ž‘๋™ํ•˜๊ธฐ์œ„ํ•œ ์ตœ์†Œ ์š”๊ตฌ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

  • ์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ํ”„๋ ˆ์ž„ ์›Œํฌ์—์„œ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋กœ์„œ ์šฐ๋ฆฌ๋Š” ์ตœ์‹  Java ๋ฆด๋ฆฌ์Šค์—์žˆ๋Š” ๋ชจ๋“  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ฆ๊ธธ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„ ์›Œํฌ ์ž์ฒด๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” Java ๋ฆด๋ฆฌ์Šค๋ฅผ ์ง€์›ํ•˜๋Š” ๋ฐ ๋งŽ์€ ์ง์„ ์‹ฃ๊ณ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์›๋ž˜ Spring Framework 5.0์€ Java 9์—์„œ ๋ฆด๋ฆฌ์Šค ๋  ์˜ˆ์ •์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Java 9 ๋ฆด๋ฆฌ์Šค๊ฐ€ 18 ๊ฐœ์›” ๋Šฆ๊ฒŒ ์‹คํ–‰๋˜๋ฉด์„œ Spring ํŒ€ ์€ Spring Framework 5.0 ๋ฆด๋ฆฌ์Šค๋ฅผ Java 9์—์„œ ๋ถ„๋ฆฌํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Java 9๊ฐ€ ์ถœ์‹œ๋˜๋ฉด ( 2017 ๋…„ 9 ์›” ์˜ˆ์ • ) Spring Framework 5.0์ด ์ค€๋น„๋ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ํ”„๋ ˆ์ž„ ์›Œํฌ ๊ฐœ์ •

  • ํ•ต์‹ฌ Spring Framework 5.0์€ Java 8์— ๋„์ž… ๋œ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋„๋ก ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Java 8 ๋ฆฌํ”Œ๋ ‰์…˜ ํ–ฅ์ƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ Spring Framework 5.0์˜ ๋ฉ”์„œ๋“œ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ํšจ์œจ์ ์œผ๋กœ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Core Spring ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ด์ œ Java 8 ๊ธฐ๋ณธ ๋ฉ”์†Œ๋“œ์— ๋นŒ๋“œ ๋œ ์„ ํƒ์  ์„ ์–ธ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • @Nullable ๋ฐ @NotNull ์ฃผ์„ ๋ช…์‹œ ์ ์œผ๋กœ ๋„ (NULL) ์ธ์ˆ˜์™€ ๋ฐ˜ํ™˜ ๊ฐ’์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์— NullPointerException์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋Œ€์‹  ์ปดํŒŒ์ผ ํƒ€์ž„์— null ๊ฐ’์„ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋กœ๊น… ์ธก๋ฉด์—์„œ Spring Framework 5.0์€ ํ‘œ์ค€ Commons Logging ๋Œ€์‹  spring-jcl์ด๋ผ๋Š” Commons Logging ๋ธŒ๋ฆฌ์ง€ ๋ชจ๋“ˆ๊ณผ ํ•จ๊ป˜ ๊ธฐ๋ณธ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ์ด ์ƒˆ ๋ฒ„์ „์€ ์ถ”- ๊ฐ€ ๋ธŒ๋ฆฌ์ง€์—†์ด Log4j 2.x, SLF4J, JUL (java.util.logging)์„ ์ž๋™์œผ๋กœ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐฉ์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋˜ํ•œ getFile ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•œ isFile ํ‘œ์‹œ๊ธฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” Resource ์ถ”์ƒํ™”๋กœ ์ถ”์ง„๋ ฅ์„ ์–ป์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ์ปจํ…Œ์ด๋„ˆ ์—…๋ฐ์ดํŠธ

  • Spring Framework 5.0์€ ์ด์ œ ํด๋ž˜์Šค ๊ฒฝ๋กœ ์Šค์บ”์˜ ๋Œ€์•ˆ์œผ๋กœ ํ›„๋ณด ์ปดํฌ๋„ŒํŠธ ์ธ๋ฑ์Šค๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ง€์›์€ ํด๋ž˜์Šค ๊ฒฝ๋กœ ์Šค์บ๋„ˆ์—์„œ ํ›„๋ณด ๊ตฌ์„ฑ ์š”์†Œ ์‹๋ณ„ ๋‹จ๊ณ„๋ฅผ ๋ฐ”๋กœ ๊ฐ€๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ƒ‰์ธ์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ๊ฐ ๋ชจ๋“ˆ์— ์•„๋ž˜์˜ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์„ธ์Šค๋Š” ์ธ๋ฑ์Šค ์Šค์บ”์— ํฌํ•จ๋  META-INF / spring.components ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-indexer</artifactId>
        <version>5.0.3.RELEASE</version>
        <optional>true</optional>
    </dependency>
</dependencies>
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นŒ๋“œ ํƒœ์Šคํฌ๋Š” ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ์ž์ฒด META-INF / spring.components ํŒŒ์ผ์„ ์ •์˜ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ์†Œ์Šค ๋ชจ๋ธ์ด ๊ฒ€์‚ฌ๋˜๊ณ  JPA ์—”ํ‹ฐํ‹ฐ์™€ Spring ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ”Œ๋ž˜๊ทธ๋ฉ๋‹ˆ๋‹ค.

  • ํด๋ž˜์Šค ๊ฒฝ๋กœ๋ฅผ ์Šค์บ”ํ•˜์ง€ ์•Š๊ณ  ์ƒ‰์ธ์—์„œ ํ•ญ๋ชฉ์„ ์ฝ๋Š” ๊ฒƒ์€ ํด๋ž˜์Šค๊ฐ€ 200 ๊ฐœ ๋ฏธ๋งŒ์ธ ์†Œ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ ํฐ ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—๋Š” ์ƒ๋‹นํ•œ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ์ธ๋ฑ์Šค๋ฅผ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์€ ์ €๋ ดํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•œ ์‹œ์ž‘ ์‹œ๊ฐ„์€ ํด๋ž˜์Šค ์ˆ˜๊ฐ€ ์ฆ๊ฐ€ํ•จ์— ๋”ฐ๋ผ ์ผ์ •ํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

  • ์ด๊ฒƒ์ด ์šฐ๋ฆฌ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” ๋Œ€๊ทœ๋ชจ Spring ํ”„๋กœ์ ํŠธ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ํฌ๊ฒŒ ๋‹จ์ถ•๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 20 ์ดˆ ๋˜๋Š” 30 ์ดˆ๋Š” ๊ทธ๋ฆฌ ๋งŽ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์ง€๋งŒ ํ•˜๋ฃจ์— ์ˆ˜์‹ญ ๋˜๋Š” ์ˆ˜๋ฐฑ ๋ฒˆ ๊ทธ ์‹œ๊ฐ„์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉด ๋”ํ•ด์ง‘๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ผ์ผ ์ƒ์‚ฐ์„ฑ์— ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค.

  • Spring์˜ Jira ์—์„œ ์ปดํฌ๋„ŒํŠธ ์ธ๋ฑ์Šค ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .

@GetMapping("/")
public String hello(@RequestParam @Nullable String name) {
  return "hello " + name + "!";
}
@Bean
ApplicationRunner applicationRunner(@Nullable PersonService personService) {
  return args -> {
  };
}
  • ์ด์ œ @Nullable ์ฃผ์„์„ ์„ ํƒ์  ์ฃผ์ž… ์ง€์ ์— ๋Œ€ํ•œ ํ‘œ์‹œ๊ธฐ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @Nullable์„ ์‚ฌ์šฉํ•˜๋ฉด ์†Œ๋น„์ž์—๊ฒŒ ๊ฐ’์ด null์ด๋˜๋„๋ก ์ค€๋น„ํ•ด์•ผํ•˜๋Š” ์˜๋ฌด๊ฐ€ ๋ถ€๊ณผ๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ๋Ÿฐํƒ€์ž„์— NullPointerException์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋Œ€์‹  ์ปดํŒŒ์ผ ํƒ€์ž„์— null ๊ฐ’์„ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆด๋ฆฌ์Šค ๋…ธํŠธ์˜ ๋‹ค๋ฅธ ์ƒˆ๋กญ๊ณ  ํ–ฅ์ƒ๋œ ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๊ธฐ๋Šฅ์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ์˜ ๊ตฌํ˜„ GenericApplicationContext ๋ฐ AnnotationConfigApplicationContext.
  • ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ์—์„œ ํŠธ๋žœ์žญ์…˜, ์บ์‹ฑ ๋ฐ ๋น„๋™๊ธฐ ์ฃผ์„์„ ์ผ๊ด€๋˜๊ฒŒ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • XML ๊ตฌ์„ฑ ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค๋Š” ๋ฒ„์ „์—†๋Š” ์Šคํ‚ค๋งˆ๋กœ ๊ฐ„์†Œํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Kotlin์„ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ

  • Spring Framework 5.0์€ JetBrains Kotlin ์–ธ์–ด๋ฅผ ์ง€์› ํ•ฉ๋‹ˆ๋‹ค. Kotlin์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ์„ ์ง€์›ํ•˜๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. Kotlin์€ JVM ์œ„์—์„œ ์‹คํ–‰๋˜์ง€๋งŒ ์ด์— ๊ตญํ•œ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

  • Kotlin ์ง€์›์„ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ๊ธฐ๋Šฅ์ ์ธ Spring ํ”„๋กœ๊ทธ๋ž˜๋ฐ, ํŠนํžˆ ๊ธฐ๋Šฅ์ ์ธ ์›น ์—”๋“œ ํฌ์ธํŠธ ๋ฐ ๋นˆ ๋“ฑ๋ก์— ๋›ฐ์–ด๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Spring Framework 5.0์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์›น ๊ธฐ๋Šฅ API๋ฅผ์œ„ํ•œ ๊น”๋”ํ•˜๊ณ  ๊ด€์šฉ์  ์ธ Kotlin ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

{
( "/ movie"  ๋ฐ  ์ˆ˜๋ฝ ( TEXT_HTML )). nest {
GET ( "/" , movieHandler :: findAllView )
GET ( "/ {card}" , movieHandler :: findOneView )
}
( "/ api / movie"  ๋ฐ  ์ˆ˜๋ฝ ( APPLICATION_JSON )). nest {
GET ( "/" , movieApiHandler :: findAll )
GET ( "/ {id}" , movieApiHandler :: findOne )
}
}

๋นˆ ๋“ฑ๋ก์˜ ๊ฒฝ์šฐ XML ๋˜๋Š” @Configuration ๋ฐ ๋Œ€์‹  @BeanKotlin์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Spring Bean์„ ๋“ฑ๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

val  context  =  GenericApplicationContext {
registerBean ()
registerBean { Cinema ( it . getBean ())}
}

๋ฐ˜์‘ ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ

  • ์ด๋ฒˆ Spring ๋ฆด๋ฆฌ์Šค์˜ ํฅ๋ฏธ๋กœ์šด ๊ธฐ๋Šฅ์€ ์ƒˆ๋กœ์šด ๋ฐ˜์‘ ์Šคํƒ ์›น ํ”„๋ ˆ์ž„ ์›Œํฌ์ž…๋‹ˆ๋‹ค. ์™„์ „ ๋ฐ˜์‘์ ์ด๊ณ  ๋น„ ์ฐจ๋‹จ์ ์ธ์ด ์Šคํƒ์€ ์ ์€ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๋กœ ํ™•์žฅ ํ•  ์ˆ˜์žˆ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„ ์Šคํƒ€์ผ ์ฒ˜๋ฆฌ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

  • Reactive Streams ๋Š” Netflix, Pivotal, Typesafe, Red Hat, Oracle, Twitter ๋ฐ Spray.io์˜ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๊ฐœ๋ฐœ ํ•œ API ์‚ฌ์–‘์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ JPA๊ฐ€ API์ด๊ณ  Hibernate๊ฐ€ ๊ตฌํ˜„ ์ธ Hibernate ์šฉ JPA์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•  ๋ฐ˜์‘ ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ตฌํ˜„์„์œ„ํ•œ ๊ณตํ†ต API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • Reactive Streams API๋Š” ๊ณต์‹์ ์œผ๋กœ Java 9์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. Java 8์—์„œ๋Š” Reactive Streams API ์‚ฌ์–‘์— ๋Œ€ํ•œ ์ข…์†์„ฑ์„ ํฌํ•จํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  • Spring Framework 5.0์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์› ์€ Reactive Streams API ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋Š” Project Reactor๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  • Spring Framework 5.0์—๋Š” ๋ฐ˜์‘ ํ˜• HTTP ๋ฐ WebSocket ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ง€์›ํ•˜๋Š” ์ƒˆ๋กœ์šด spring-webflux ๋ชจ๋“ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค. Spring Framework 5.0์€ REST, HTML ๋ฐ WebSocket ์Šคํƒ€์ผ ์ƒํ˜ธ ์ž‘์šฉ์„ ํฌํ•จํ•˜๋Š” ์„œ๋ฒ„์—์„œ ์‹คํ–‰๋˜๋Š” ๋ฐ˜์‘ ํ˜• ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์ง€์›๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • spring-webflux์˜ ์„œ๋ฒ„ ์ธก์—๋Š” ๋‘ ๊ฐ€์ง€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    • @Controller Spring MVC์˜ ์ฃผ์„ ๊ธฐ๋ฐ˜ ๋ฐ ๊ธฐํƒ€ ์ฃผ์„.
    • Java 8 ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•œ ๊ธฐ๋Šฅ์  ์Šคํƒ€์ผ ๋ผ์šฐํŒ… ๋ฐ ์ฒ˜๋ฆฌ.
@GetMapping("/{id}")
private Mono<Employee> getEmployeeById(@PathVariable String id) {
    return employeeRepository.findEmployeeById(id);
}

@GetMapping
private Flux<Employee> getAllEmployees() {
    return employeeRepository.findAllEmployees();
}
  • RestTemplate ์˜ ๋Œ€์•ˆ์œผ๋กœ Spring ์—์„œ๋Š” WebClient ์‚ฌ์šฉ์„ ๊ฐ•๋ ฅํžˆ ๊ถŒ๊ณ ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
    • Non-blocking I/O
    • Reactive Streams back pressure
    • High concurrency with fewer hardware resources
    • Functional-style, fluent API that takes advantage of Java 8 lambdas
    • Synchronous and asynchronous interactions
    • Streaming up to or streaming down from a server
    • Spring 5.0์—์„œ REST ์—”๋“œ ํฌ์ธํŠธ์˜ WebClient ๊ตฌํ˜„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • (Non-Blocking I/O ๊ธฐ๋ฐ˜์˜ Asynchronous API)
    • (WebClient๋Š” Blocking I/O ๊ธฐ๋ฐ˜์˜ Synchronous API ๋ฐฉ์‹์˜ restTemplate ๋Œ€์•ˆ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.)
    • ์ถœ์ฒ˜: https://ict-nroo.tistory.com/119 [๊ฐœ๋ฐœ์ž์˜ ๊ธฐ๋ก์Šต๊ด€]
@Service
@RequiredArgsConstructor
@Slf4j
public class SomeService implements SomeInterface {

    private final WebClient webClient;
    public Mono<SomeData> getSomething() {
  
    return webClient.mutate()
                    .build()
                    .get()
                    .uri("/resource")
                    .retrieve()
                    .bodyToMono(SomeData.class);
    }
}

์ƒˆ๋กœ์šด WebFlux ๋ชจ๋“ˆ์€ ์šฐ๋ฆฌ์—๊ฒŒ ๋ช‡ ๊ฐ€์ง€ ํฅ๋ฏธ๋กœ์šด ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€๋งŒ, ์ „ํ†ต์ ์ธ Spring MVC๋Š” ์—ฌ์ „ํžˆ Spring Framework 5.0์—์„œ ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฐœ์„ 

  • Spring Framework 5.0์€ JUnit 5 ์—์„œ ํ…Œ์ŠคํŠธ ๋ฐ ํ™•์žฅ์„ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด JUnit 5 Jupiter ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค . ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐ ํ™•์žฅ ๋ชจ๋ธ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ Jupiter ํ•˜์œ„ ํ”„๋กœ์ ํŠธ๋Š” Spring์—์„œ Jupiter ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ์œ„ํ•œ ํ…Œ์ŠคํŠธ ์—”์ง„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

JUnit 5 ๊ฐœ์„ ์‚ฌํ•ญ ์ฐธ๊ณ  : https://javacan.tistory.com/entry/JUnit-5-Intro

  • JUnit 4๊ฐ€ ๋‹จ์ผ jar์˜€๋˜ ๊ฒƒ์— ๋น„ํ•ด, JUnit 5๋Š” ํฌ๊ฒŒ JUnit Platform, JUnit Jupiter, JUnit Vintage ๋ชจ๋“ˆ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

  • ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์ž๋ฅผ ์œ„ํ•œ API ๋ชจ๋“ˆ๊ณผ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์œ„ํ•œ API๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค.

    • ์˜ˆ๋ฅผ ๋“ค์–ด, JUnit Jupiter๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์— ํ•„์š”ํ•œ junit-jupiter-api ๋ชจ๋“ˆ๊ณผ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์œ„ํ•œ junit-jupiter-engine ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค.
  • ์ž๋ฐ” 8 ๋˜๋Š” ๊ทธ ์ด์ƒ ๋ฒ„์ „์„ ์š”๊ตฌํ•œ๋‹ค.

  • ๋˜ํ•œ Spring Framework 5๋Š” Spring TestContext Framework์—์„œ ๋ณ‘๋ ฌ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐ˜์‘ ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ์˜ ๊ฒฝ์šฐ spring-test๋Š” ์ด์ œ Spring WebFlux์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ง€์›์„ ํ†ตํ•ฉํ•˜๊ธฐ์œ„ํ•œ WebTestClient๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. MockMvc์™€ ์œ ์‚ฌํ•œ ์ƒˆ๋กœ์šด WebTestClient์—๋Š” ์‹คํ–‰์ค‘์ธ ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ์˜ ์š”์ฒญ ๋ฐ ์‘๋‹ต์„ ์‚ฌ์šฉํ•˜์—ฌ WebTestClient๋Š” WebFlux ์„œ๋ฒ„ ์ธํ”„๋ผ์— ์ง์ ‘ ๋ฐ”์ธ๋”ฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฌผ๋ก  Spring Framework 5.0์€ ์—ฌ์ „ํžˆ โ€‹โ€‹์šฐ๋ฆฌ์˜ ์˜ค๋žœ ์นœ๊ตฌ ์ธ JUnit 4๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค! ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์—์„œ JUnit 5๋Š” ๊ณง ์ถœ์‹œ ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. JUnit 4์— ๋Œ€ํ•œ ์ง€์›์€ ํ–ฅํ›„ ํ•œ๋™์•ˆ Spring Framework์—์„œ ์ง€์› ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ง€์›

Spring Framework 5.0์€ ์ด์ œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—…๊ทธ๋ ˆ์ด๋“œ ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  • Jackson 2.6 ์ด์ƒ
  • EhCache 2.10+ / 3.0 GA
  • ์ตœ๋Œ€ ์ ˆ์ „ ๋ชจ๋“œ 5.0 ์ด์ƒ
  • JDBC 4.0 ์ด์ƒ
  • XmlUnit 2.x ์ด์ƒ
  • OkHttp 3.x ์ด์ƒ
  • Netty 4.1 ์ด์ƒ

์ค‘๋‹จ ๋œ ์ง€์›

API ์ˆ˜์ค€์—์„œ Spring Framework 5.0์€ ๋‹ค์Œ ํŒจํ‚ค์ง€์— ๋Œ€ํ•œ ์ง€์›์„ ์ค‘๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

  • beans.factory.access

  • jdbc.support.nativejdbc

  • mock.staticmock spring-aspects ๋ชจ๋“ˆ์˜.

  • web.view.tiles2M. ์ด์ œ Tiles 3์ด ์ตœ์†Œ ์š”๊ตฌ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

  • orm.hibernate3 ๋ฐ orm.hibernate4. ์ด์ œ Hibernate 5๊ฐ€ ์ง€์›๋˜๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ์ž…๋‹ˆ๋‹ค.

  • Spring Framework 5.0์€ ๋‹ค์Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์ง€์›๋„ ์ค‘๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ํฌํ‹€๋ฆฟ.

  • ์†๋„.

  • JasperReports.

  • XMLBeans.

  • JDO.

  • ๊ตฌ์•„๋ฐ”. ์ด์ „ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ Spring Framework 4.3.x๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์š”์•ฝ

Spring Framework 5.0์˜ ํ•˜์ด๋ผ์ดํŠธ๋Š” ๋ถ„๋ช… ๋ฆฌ ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ฉฐ ์ด๋Š” ์ค‘์š”ํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„ ์ „ํ™˜์ž…๋‹ˆ๋‹ค. Spring Framework 5.0์„ ๋ฆฌ ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋žจ์˜ ์ดˆ์„ ๋ฆด๋ฆฌ์Šค๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€ 2017 ๋…„๊ณผ ๊ทธ ์ดํ›„์—๋Š” ํ•˜์œ„ ํ”„๋กœ์ ํŠธ๊ฐ€ ๋ฐ˜์‘ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. SpringData, Spring Security, Spring Integration ๋“ฑ์˜ ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์— ์ถ”๊ฐ€ ๋œ ๋ฐ˜์‘ ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋Šฅ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

db lock ์ข…๋ฅ˜์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์‹œ์˜ค

Lock์ด๋ž€?

  • ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์˜ค๋ผํด๊ณผ ๊ฐ™์ด ๊ณ ๊ฐ€์˜ DBMS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฐ์ดํ„ฐ์˜ ๋ฌด๊ฒฐ์„ฑ๊ณผ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๋Šฅ๋ ฅ์ด ๋›ฐ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Lock์˜ ์ข…๋ฅ˜๋Š”?

Lock์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๋กœ ๋‚˜๋ˆ„์–ด ์ง‘๋‹ˆ๋‹ค.

Shared Lock(๊ณต์œ  Lock ๋˜๋Š” Read Lock)

  • ๋ณดํ†ต ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— lock์„ ๊ฑธ์—ˆ์ง€๋งŒ ๋‹ค๋ฅธ ์„ธ์…˜์—์„œ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ณต์œ Lock์„ ์„ค์ •ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€๋กœ ๊ณต์œ Lock์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฐฐํƒ€์  Lock์€ ์„ค์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ฆ‰, ๋‚ด๊ฐ€ ๋ณด๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ณ€๊ฒฝํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

Exclusive Lock(๋ฐฐํƒ€์  Lock ๋˜๋Š” Write lock)

  • ์–ด๋–ค ํŠธ๋žœ์žญ์…˜์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ ์ž ํ•  ๋•Œ(ex . ์“ฐ๊ณ ์ž ํ•  ๋•Œ) ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ํ•ด๋‹น ํ…Œ์ด๋ธ” ํ˜น์€ ๋ ˆ์ฝ”๋“œ(row)๋ฅผ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์ฝ๊ฑฐ๋‚˜ ์“ฐ์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด Exclusive lock์„ ๊ฑธ๊ณ  ํŠธ๋žœ์žญ์…˜์„ ์ง„ํ–‰์‹œํ‚ค๋Š”๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๋ณดํ†ต ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฆ„์—์„œ ๋Š๊ปด์ง€๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ํ•ด๋‹น Lock์ด ํ•ด์ œ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š”, ๋‹ค๋ฅธ ๊ณต์œ Lock, ๋ฐฐํƒ€์ Lock์„ ์„ค์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ฆ‰, ์ฝ๊ธฐ ๊ธฐ์™€ ์“ฐ๊ธฐ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

Blocking ?

๊ฒฝํ•ฉ์œผ๋กœ ์ธํ•œ ์ƒํƒœ์ธ ๋ธ”๋กœํ‚น์— ๋Œ€ํ•˜์—ฌ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

Blocking

๋ธ”๋กœํ‚น์€ Lock๋“ค์˜ ๊ฒฝํ•ฉ(Race condition์ด๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค)์ด ๋ฐœ์ƒํ•˜์—ฌ ํŠน์ • ์„ธ์…˜์ด ์ž‘์—…์„ ์ง„ํ–‰ํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋ฉˆ์ถฐ ์„  ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ณต์œ Lock๊ณผ ๋ฐฐํƒ€์ Lock ๋˜๋Š” ๋ฐฐํƒ€์ Lock๊ณผ ๋ฐฐํƒ€์ Lock๋ผ๋ฆฌ ๋ธ”๋กœํ‚น์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ Transaction commit ๋˜๋Š” rollback ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ฒฝํ•ฉ์ด ๋ฐœ์ƒํ•  ๋•Œ, ๋จผ์ € Lock์„ ์„ค์ •ํ•œ ํŠธ๋žœ์ ์…˜์„ ๊ธฐ๋‹ค๋ ค์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋Ÿฐ ํ˜„์ƒ์ด ๋ฐ˜๋ณต๋˜๋ฉด ๋น ๋ฅธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ๋ฐฉ์•ˆ

SQL ๋ฌธ์žฅ์— ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์‹คํ–‰๋˜๋„๋ก ๋ฆฌํŽ™ํ† ๋งํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๊ธฐ๋ณธ์ด๋ฉฐ ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ํŠธ๋žœ์ ์…˜์„ ๊ฐ€๋Šฅํ•œ ์งง๊ฒŒ ์ •์˜ํ•˜๋ฉด ๊ฒฝํ•ฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋™์‹œ์— ๋ณ€๊ฒฝํ•˜๋Š” ์ž‘์—…์„ ํ•˜์ง€ ์•Š๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํŠธ๋žœ์ ์…˜์ด ํ™œ๋ฐœํ•œ ์ฃผ๊ฐ„์—๋Š” ๋Œ€์šฉ๋Ÿ‰ ๊ฐฑ์‹  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋Œ€์šฉ๋Ÿ‰์ž‘์—…์ด ๋ถˆ๊ฐ€ํ”ผํ•  ๊ฒฝ์šฐ, ์ž‘์—…๋‹จ์œ„๋ฅผ ์ชผ๊ฐœ๊ฑฐ๋‚˜ lock_timeout์„ ์„ค์ •ํ•˜์—ฌ ํ•ด๋‹น Lock์˜ ์ตœ๋Œ€์‹œ๊ฐ„์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

set lock_timeout 3000

Dead Lock์ด๋ž€?

  • deadlock์€ ํŠธ๋žœ์ ์…˜๊ฐ„์˜ ๊ต์ฐฉ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋‘๊ฐœ์˜ ํŠธ๋žœ์ ์…˜๊ฐ„์— ๊ฐ๊ฐ์˜ ํŠธ๋žœ์ ์…˜์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฆฌ์†Œ์Šค์˜ Lock์„ ํš๋“ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ€์žฅ ํ”ํžˆ ๋– ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋Š” deadlock ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. 1๋ฒˆ ํŠธ๋žœ์ ์…˜์—์„œ 2๋ฒˆ ๋ฆฌ์†Œ์Šค์˜ ์ž ๊ธˆ์„ ํš๋“, 2๋ฒˆ ํŠธ๋žœ์ ์…˜์—์„œ๋Š” 1๋ฒˆ ๋ฆฌ์†Œ์Šค์˜ ์ž ๊ธˆ์„ ํš๋“ํ•œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

  • ์ด๋•Œ, ๋™์‹œ์— ์ƒ๋Œ€๋ฐฉ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—‘์„ธ์Šคํ•˜๋ ค๊ณ  ํ• ๋•Œ ๊ธฐ์กด์˜ Lock์ด ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

  • Postgresql์—์„œ๋Š” ์ž๋™์ ์œผ๋กœ deadlock์„ ์ธ์ง€ํ•˜๊ณ  ๊ต์ฐฉ์ƒํƒœ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•˜์—ฌ ํ•˜๋‚˜์˜ ํŠธ๋žœ์ ์…˜์„ ์ทจ์†Œ์‹œํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ์–ด๋–ค ํŠธ๋žœ์ ์…˜์ด ์ทจ์†Œ๋  ์ง€ ํŒ๋‹จํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

Lock Level & Escalation์ด๋ž€?

  • SQL ๋ช…๋ น์–ด์— ๋”ฐ๋ผ์„œ Lock์˜ ์„ค์ •๋Œ€์ƒ์ด ๋ฐ์ดํ„ฐ row์ผ์ง€ database์ผ์ง€ ๋‚˜๋ˆ„์–ด์ง‘๋‹ˆ๋‹ค.
  1. Row level: ๋ณ€๊ฒฝํ•˜๋ ค๋Š” row์—๋งŒ lock์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  2. Page level: ๋ณ€๊ฒฝํ•˜๋ ค๋Š” row๊ฐ€ ๋‹ด๊ธด ๋ฐ์ดํ„ฐ page (๋˜๋Š” ์ธ๋ฑ์Šค ํŽ˜์ด์ง€)์— lock์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ํŽ˜์ด์ง€์— ์†ํ•œ row๋“ค์€ ๋ณ€๊ฒฝ์ž‘์—…๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋ชจ๋‘ lock์— ์˜ํ•ด ์ž ๊น๋‹ˆ๋‹ค. Tabel level: ํ…Œ์ด๋ธ”๊ณผ ์ธ๋ฑ์Šค์— ๋ชจ๋‘ ์ž ๊ธˆ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. Select table, Alter table, Vacuum, Refresh, Index, Drop, Truncate ๋“ฑ์˜ ์ž‘์—…์—์„œ ํ•ด๋‹น๋ ˆ๋ฒจ์˜ ๋ฝ์ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
  3. Database level: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ณต๊ตฌํ•˜๊ฑฐ๋‚˜ ์Šคํ‚ค๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Escalation

  • Lock ๋ฆฌ์†Œ์Šค๊ฐ€ ์ž„๊ณ„์น˜๋ฅผ ๋„˜์œผ๋ฉด Lock ๋ ˆ๋ฒจ์ด ํ™•์žฅ๋˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • Lock ๋ ˆ๋ฒจ์ด ๋‚ฎ์„ ์ˆ˜๋ก ๋™์‹œ์„ฑ์ด ์ข‹์•„์ง€์ง€๋งŒ, ๊ด€๋ฆฌํ•ด์•ผํ•  Lock์ด ๋งŽ์•„์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์€ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.
  • ๋ฐ˜๋Œ€๋กœ Lock๋ ˆ๋ฒจ์ด ๋†’์„ ์ˆ˜๋ก ๊ด€๋ฆฌ๋ฆฌ์†Œ์Šค๋Š” ๋‚ฎ์ง€๋งŒ, ๋™์‹œ์„ฑ์€ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.

rest, restful api์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์‹œ์˜ค.

์ถœ์ฒ˜

REST์˜ ๊ฐœ๋…

REST๋ž€

โ€œRepresentational State Transferโ€ ์˜ ์•ฝ์ž ์ž์›์„ **์ด๋ฆ„(์ž์›์˜ ํ‘œํ˜„)**์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ํ•ด๋‹น ์ž์›์˜ **์ƒํƒœ(์ •๋ณด)**๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ์ž์›(resource)์˜ ํ‘œํ˜„(representation) ์— ์˜ํ•œ ์ƒํƒœ ์ „๋‹ฌ

  • ์ž์›(resource)์˜ ํ‘œํ˜„(representation) ์ž์›: ํ•ด๋‹น ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ -> Ex) ๋ฌธ์„œ, ๊ทธ๋ฆผ, ๋ฐ์ดํ„ฐ, ํ•ด๋‹น ์†Œํ”„ํŠธ์›จ์–ด ์ž์ฒด ๋“ฑ ์ž์›์˜ ํ‘œํ˜„: ๊ทธ ์ž์›์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์ด๋ฆ„ -> Ex) DB์˜ ํ•™์ƒ ์ •๋ณด๊ฐ€ ์ž์›์ผ ๋•Œ, โ€˜studentsโ€™๋ฅผ ์ž์›์˜ ํ‘œํ˜„์œผ๋กœ ์ •ํ•œ๋‹ค.
  • ์ƒํƒœ(์ •๋ณด) ์ „๋‹ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ์š”์ฒญ๋˜์–ด์ง€๋Š” ์‹œ์ ์—์„œ ์ž์›์˜ ์ƒํƒœ(์ •๋ณด)๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. JSON ํ˜น์€ XML๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.
  • ์›”๋“œ ์™€์ด๋“œ ์›น(www)๊ณผ ๊ฐ™์€ ๋ถ„์‚ฐ ํ•˜์ดํผ๋ฏธ๋””์–ด ์‹œ์Šคํ…œ์„ ์œ„ํ•œ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ์•„ํ‚คํ…์ฒ˜์˜ ํ•œ ํ˜•์‹ REST๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์›น์˜ ๊ธฐ์กด ๊ธฐ์ˆ ๊ณผ HTTP ํ”„๋กœํ† ์ฝœ์„ ๊ทธ๋Œ€๋กœ ํ™œ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์›น์˜ ์žฅ์ ์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์ด๋‹ค. REST๋Š” ๋„คํŠธ์›Œํฌ ์ƒ์—์„œ Client์™€ Server ์‚ฌ์ด์˜ ํ†ต์‹  ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. REST์˜ ๊ตฌ์ฒด์ ์ธ ๊ฐœ๋… HTTP URI(Uniform Resource Identifier)๋ฅผ ํ†ตํ•ด ์ž์›(Resource)์„ ๋ช…์‹œํ•˜๊ณ , HTTP Method(POST, GET, PUT, DELETE)๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์ž์›์— ๋Œ€ํ•œ CRUD Operation์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, REST๋Š” ์ž์› ๊ธฐ๋ฐ˜์˜ ๊ตฌ์กฐ(ROA, Resource Oriented Architecture) ์„ค๊ณ„์˜ ์ค‘์‹ฌ์— Resource๊ฐ€ ์žˆ๊ณ  HTTP Method๋ฅผ ํ†ตํ•ด Resource๋ฅผ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค๊ณ„๋œ ์•„ํ‚คํ…์ณ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์›น ์‚ฌ์ดํŠธ์˜ ์ด๋ฏธ์ง€, ํ…์ŠคํŠธ, DB ๋‚ด์šฉ ๋“ฑ์˜ ๋ชจ๋“  ์ž์›์— ๊ณ ์œ ํ•œ ID์ธ HTTP URI๋ฅผ ๋ถ€์—ฌํ•œ๋‹ค.
  • CRUD Operation Create : ์ƒ์„ฑ(POST) Read : ์กฐํšŒ(GET) Update : ์ˆ˜์ •(PUT) Delete : ์‚ญ์ œ(DELETE) HEAD: header ์ •๋ณด ์กฐํšŒ(HEAD)

REST์˜ ์žฅ๋‹จ์ 

์žฅ์ 

  • HTTP ํ”„๋กœํ† ์ฝœ์˜ ์ธํ”„๋ผ๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ REST API ์‚ฌ์šฉ์„ ์œ„ํ•œ ๋ณ„๋„์˜ ์ธํ”„๋ผ๋ฅผ ๊ตฌ์ถœํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • HTTP ํ”„๋กœํ† ์ฝœ์˜ ํ‘œ์ค€์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ์ถ”๊ฐ€์ ์ธ ์žฅ์ ์„ ํ•จ๊ป˜ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
  • HTTP ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ์— ๋”ฐ๋ฅด๋Š” ๋ชจ๋“  ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • Hypermedia API์˜ ๊ธฐ๋ณธ์„ ์ถฉ์‹คํžˆ ์ง€ํ‚ค๋ฉด์„œ ๋ฒ”์šฉ์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค.
  • REST API ๋ฉ”์‹œ์ง€๊ฐ€ ์˜๋„ํ•˜๋Š” ๋ฐ”๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚ด๋ฏ€๋กœ ์˜๋„ํ•˜๋Š” ๋ฐ”๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„œ๋น„์Šค ๋””์ž์ธ์—์„œ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ์ตœ์†Œํ™”ํ•œ๋‹ค.
  • ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์˜ ์—ญํ• ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•œ๋‹ค.

๋‹จ์ 

  • ํ‘œ์ค€์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ 4๊ฐ€์ง€ ๋ฐ–์— ์—†๋‹ค.
  • HTTP Method ํ˜•ํƒœ๊ฐ€ ์ œํ•œ์ ์ด๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธํ•  ์ผ์ด ๋งŽ์€ ์„œ๋น„์Šค๋ผ๋ฉด ์‰ฝ๊ฒŒ ๊ณ ์น  ์ˆ˜ ์žˆ๋Š” URL๋ณด๋‹ค Header ๊ฐ’์ด ์™ ์ง€๋” ์–ด๋ ต๊ฒŒ ๋Š๊ปด์ง„๋‹ค.
  • ๊ตฌํ˜• ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„์ง ์ œ๋Œ€๋กœ ์ง€์›ํ•ด์ฃผ์ง€ ๋ชปํ•˜๋Š” ๋ถ€๋ถ„์ด ์กด์žฌํ•œ๋‹ค.
  • PUT, DELETE๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ์ 
  • pushState๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ 

REST๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

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

REST ๊ตฌ์„ฑ ์š”์†Œ

  • ์ž์›(Resource): URI ๋ชจ๋“  ์ž์›์— ๊ณ ์œ ํ•œ ID๊ฐ€ ์กด์žฌํ•˜๊ณ , ์ด ์ž์›์€ Server์— ์กด์žฌํ•œ๋‹ค. ์ž์›์„ ๊ตฌ๋ณ„ํ•˜๋Š” ID๋Š” โ€˜/groups/:group_idโ€™์™€ ๊ฐ™์€ HTTP URI ๋‹ค. Client๋Š” URI๋ฅผ ์ด์šฉํ•ด์„œ ์ž์›์„ ์ง€์ •ํ•˜๊ณ  ํ•ด๋‹น ์ž์›์˜ ์ƒํƒœ(์ •๋ณด)์— ๋Œ€ํ•œ ์กฐ์ž‘์„ Server์— ์š”์ฒญํ•œ๋‹ค.
  • ํ–‰์œ„(Verb): HTTP Method HTTP ํ”„๋กœํ† ์ฝœ์˜ Method๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. HTTP ํ”„๋กœํ† ์ฝœ์€ GET, POST, PUT, DELETE ์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • ํ‘œํ˜„(Representation of Resource) Client๊ฐ€ ์ž์›์˜ ์ƒํƒœ(์ •๋ณด)์— ๋Œ€ํ•œ ์กฐ์ž‘์„ ์š”์ฒญํ•˜๋ฉด Server๋Š” ์ด์— ์ ์ ˆํ•œ ์‘๋‹ต(Representation)์„ ๋ณด๋‚ธ๋‹ค. REST์—์„œ ํ•˜๋‚˜์˜ ์ž์›์€ JSON, XML, TEXT, RSS ๋“ฑ ์—ฌ๋Ÿฌ ํ˜•ํƒœ์˜ Representation์œผ๋กœ ๋‚˜ํƒ€๋‚ด์–ด ์งˆ ์ˆ˜ ์žˆ๋‹ค. JSON ํ˜น์€ XML๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.

REST ํŠน์ง•

  1. Server-Client(์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ๊ตฌ์กฐ) ์ž์›์ด ์žˆ๋Š” ์ชฝ์ด Server, ์ž์›์„ ์š”์ฒญํ•˜๋Š” ์ชฝ์ด Client๊ฐ€ ๋œ๋‹ค. REST Server: API๋ฅผ ์ œ๊ณตํ•˜๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ ๋ฐ ์ €์žฅ์„ ์ฑ…์ž„์ง„๋‹ค. Client: ์‚ฌ์šฉ์ž ์ธ์ฆ์ด๋‚˜ context(์„ธ์…˜, ๋กœ๊ทธ์ธ ์ •๋ณด) ๋“ฑ์„ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๊ณ  ์ฑ…์ž„์ง„๋‹ค. ์„œ๋กœ ๊ฐ„ ์˜์กด์„ฑ์ด ์ค„์–ด๋“ ๋‹ค.
  2. Stateless(๋ฌด์ƒํƒœ) HTTP ํ”„๋กœํ† ์ฝœ์€ Stateless Protocol์ด๋ฏ€๋กœ REST ์—ญ์‹œ ๋ฌด์ƒํƒœ์„ฑ์„ ๊ฐ–๋Š”๋‹ค. Client์˜ context๋ฅผ Server์— ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, ์„ธ์…˜๊ณผ ์ฟ ํ‚ค์™€ ๊ฐ™์€ context ์ •๋ณด๋ฅผ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๋ฏ€๋กœ ๊ตฌํ˜„์ด ๋‹จ์ˆœํ•ด์ง„๋‹ค. Server๋Š” ๊ฐ๊ฐ์˜ ์š”์ฒญ์„ ์™„์ „ํžˆ ๋ณ„๊ฐœ์˜ ๊ฒƒ์œผ๋กœ ์ธ์‹ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•œ๋‹ค. ๊ฐ API ์„œ๋ฒ„๋Š” Client์˜ ์š”์ฒญ๋งŒ์„ ๋‹จ์ˆœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ฆ‰, ์ด์ „ ์š”์ฒญ์ด ๋‹ค์Œ ์š”์ฒญ์˜ ์ฒ˜๋ฆฌ์— ์—ฐ๊ด€๋˜์–ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ๋ฌผ๋ก  ์ด์ „ ์š”์ฒญ์ด DB๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ DB์— ์˜ํ•ด ๋ฐ”๋€Œ๋Š” ๊ฒƒ์€ ํ—ˆ์šฉํ•œ๋‹ค. Server์˜ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์— ์ผ๊ด€์„ฑ์„ ๋ถ€์—ฌํ•˜๊ณ  ๋ถ€๋‹ด์ด ์ค„์–ด๋“ค๋ฉฐ, ์„œ๋น„์Šค์˜ ์ž์œ ๋„๊ฐ€ ๋†’์•„์ง„๋‹ค.
  3. Cacheable(์บ์‹œ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ) ์›น ํ‘œ์ค€ HTTP ํ”„๋กœํ† ์ฝœ์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์›น์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์กด์˜ ์ธํ”„๋ผ๋ฅผ ๊ทธ๋Œ€๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, HTTP๊ฐ€ ๊ฐ€์ง„ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ํŠน์ง• ์ค‘ ํ•˜๋‚˜์ธ ์บ์‹ฑ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. HTTP ํ”„๋กœํ† ์ฝœ ํ‘œ์ค€์—์„œ ์‚ฌ์šฉํ•˜๋Š” Last-Modified ํƒœ๊ทธ๋‚˜ E-Tag๋ฅผ ์ด์šฉํ•˜๋ฉด ์บ์‹ฑ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋Œ€๋Ÿ‰์˜ ์š”์ฒญ์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์บ์‹œ๊ฐ€ ์š”๊ตฌ๋œ๋‹ค. ์บ์‹œ ์‚ฌ์šฉ์„ ํ†ตํ•ด ์‘๋‹ต์‹œ๊ฐ„์ด ๋นจ๋ผ์ง€๊ณ  REST Server ํŠธ๋žœ์žญ์…˜์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ „์ฒด ์‘๋‹ต์‹œ๊ฐ„, ์„ฑ๋Šฅ, ์„œ๋ฒ„์˜ ์ž์› ์ด์šฉ๋ฅ ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  4. Layered System(๊ณ„์ธตํ™”) Client๋Š” REST API Server๋งŒ ํ˜ธ์ถœํ•œ๋‹ค. REST Server๋Š” ๋‹ค์ค‘ ๊ณ„์ธต์œผ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค. API Server๋Š” ์ˆœ์ˆ˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ทธ ์•ž๋‹จ์— ๋ณด์•ˆ, ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ, ์•”ํ˜ธํ™”, ์‚ฌ์šฉ์ž ์ธ์ฆ ๋“ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ตฌ์กฐ์ƒ์˜ ์œ ์—ฐ์„ฑ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ, ๊ณต์œ  ์บ์‹œ ๋“ฑ์„ ํ†ตํ•ด ํ™•์žฅ์„ฑ๊ณผ ๋ณด์•ˆ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. PROXY, ๊ฒŒ์ดํŠธ์›จ์ด ๊ฐ™์€ ๋„คํŠธ์›Œํฌ ๊ธฐ๋ฐ˜์˜ ์ค‘๊ฐ„ ๋งค์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  5. Code-On-Demand(optional) Server๋กœ๋ถ€ํ„ฐ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ฐ›์•„์„œ Client์—์„œ ์‹คํ–‰ํ•œ๋‹ค. ๋ฐ˜๋“œ์‹œ ์ถฉ์กฑํ•  ํ•„์š”๋Š” ์—†๋‹ค.
  6. Uniform Interface(์ธํ„ฐํŽ˜์ด์Šค ์ผ๊ด€์„ฑ) URI๋กœ ์ง€์ •ํ•œ Resource์— ๋Œ€ํ•œ ์กฐ์ž‘์„ ํ†ต์ผ๋˜๊ณ  ํ•œ์ •์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค. HTTP ํ‘œ์ค€ ํ”„๋กœํ† ์ฝœ์— ๋”ฐ๋ฅด๋Š” ๋ชจ๋“  ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ํŠน์ • ์–ธ์–ด๋‚˜ ๊ธฐ์ˆ ์— ์ข…์†๋˜์ง€ ์•Š๋Š”๋‹ค.

REST API์˜ ๊ฐœ๋…

REST API๋ž€

API(Application Programming Interface)๋ž€

  • ๋ฐ์ดํ„ฐ์™€ ๊ธฐ๋Šฅ์˜ ์ง‘ํ•ฉ์„ ์ œ๊ณตํ•˜์—ฌ ์ปดํ“จํ„ฐ ํ”„๋กœ๊ทธ๋žจ๊ฐ„ ์ƒํ˜ธ ์ž‘์šฉ์„ ์ด‰์ง„ํ•˜๋ฉฐ, ์„œ๋กœ ์ •๋ณด๋ฅผ ๊ตํ™˜๊ฐ€๋Šฅ ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ

REST API์˜ ์ •์˜

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

REST API์˜ ํŠน์ง•

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

REST API ์„ค๊ณ„ ๊ธฐ๋ณธ ๊ทœ์น™

์ฐธ๊ณ  ๋ฆฌ์†Œ์Šค ์›ํ˜•

๋„ํ๋จผํŠธ : ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ ˆ์ฝ”๋“œ์™€ ์œ ์‚ฌํ•œ ๊ฐœ๋… ์ปฌ๋ ‰์…˜ : ์„œ๋ฒ„์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ผ๋Š” ๋ฆฌ์†Œ์Šค ์Šคํ† ์–ด : ํด๋ผ์ด์–ธํŠธ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๋ฆฌ์†Œ์Šค ์ €์žฅ์†Œ URI๋Š” ์ •๋ณด์˜ ์ž์›์„ ํ‘œํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

resource๋Š” ๋™์‚ฌ๋ณด๋‹ค๋Š” ๋ช…์‚ฌ๋ฅผ, ๋Œ€๋ฌธ์ž๋ณด๋‹ค๋Š” ์†Œ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. resource์˜ ๋„ํ๋จผํŠธ ์ด๋ฆ„์œผ๋กœ๋Š” ๋‹จ์ˆ˜ ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. resource์˜ ์ปฌ๋ ‰์…˜ ์ด๋ฆ„์œผ๋กœ๋Š” ๋ณต์ˆ˜ ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. resource์˜ ์Šคํ† ์–ด ์ด๋ฆ„์œผ๋กœ๋Š” ๋ณต์ˆ˜ ๋ช…์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. Ex) GET /Member/1 -> GET /members/1 ์ž์›์— ๋Œ€ํ•œ ํ–‰์œ„๋Š” HTTP Method(GET, PUT, POST, DELETE ๋“ฑ)๋กœ ํ‘œํ˜„ํ•œ๋‹ค. URI์— HTTP Method๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ์•ˆ๋œ๋‹ค. Ex) GET /members/delete/1 -> DELETE /members/1 URI์— ํ–‰์œ„์— ๋Œ€ํ•œ ๋™์‚ฌ ํ‘œํ˜„์ด ๋“ค์–ด๊ฐ€๋ฉด ์•ˆ๋œ๋‹ค. (์ฆ‰, CRUD ๊ธฐ๋Šฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์€ URI์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.) Ex) GET /members/show/1 -> GET /members/1 Ex) GET /members/insert/2 -> POST /members/2

๊ฒฝ๋กœ ๋ถ€๋ถ„ ์ค‘ ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์€ ์œ ์ผํ•œ ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•œ๋‹ค.(์ฆ‰, :id๋Š” ํ•˜๋‚˜์˜ ํŠน์ • resource๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ณ ์œ ๊ฐ’์ด๋‹ค.) Ex) student๋ฅผ ์ƒ์„ฑํ•˜๋Š” route: POST /students Ex) id=12์ธ student๋ฅผ ์‚ญ์ œํ•˜๋Š” route: DELETE /students/12

REST API ์„ค๊ณ„ ๊ทœ์น™

์Šฌ๋ž˜์‹œ ๊ตฌ๋ถ„์ž(/ )๋Š” ๊ณ„์ธต ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š”๋ฐ ์‚ฌ์šฉํ•œ๋‹ค. Ex) http://restapi.example.com/houses/apartments URI ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋กœ ์Šฌ๋ž˜์‹œ(/ )๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค. URI์— ํฌํ•จ๋˜๋Š” ๋ชจ๋“  ๊ธ€์ž๋Š” ๋ฆฌ์†Œ์Šค์˜ ์œ ์ผํ•œ ์‹๋ณ„์ž๋กœ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•˜๋ฉฐ URI๊ฐ€ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์€ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ์—ญ์œผ๋กœ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋‹ค๋ฅด๋ฉด URI๋„ ๋‹ฌ๋ผ์ ธ์•ผ ํ•œ๋‹ค. REST API๋Š” ๋ถ„๋ช…ํ•œ URI๋ฅผ ๋งŒ๋“ค์–ด ํ†ต์‹ ์„ ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜ผ๋™์„ ์ฃผ์ง€ ์•Š๋„๋ก URI ๊ฒฝ๋กœ์˜ ๋งˆ์ง€๋ง‰์—๋Š” ์Šฌ๋ž˜์‹œ(/)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. Ex) http://restapi.example.com/houses/apartments/ (X) ํ•˜์ดํ”ˆ(- )์€ URI ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š”๋ฐ ์‚ฌ์šฉ ๋ถˆ๊ฐ€ํ”ผํ•˜๊ฒŒ ๊ธด URI๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ํ•˜์ดํ”ˆ์„ ์‚ฌ์šฉํ•ด ๊ฐ€๋…์„ฑ์„ ๋†’์ธ๋‹ค. ๋ฐ‘์ค„(_ )์€ URI์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ฐ‘์ค„์€ ๋ณด๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜ ๋ฐ‘์ค„ ๋•Œ๋ฌธ์— ๋ฌธ์ž๊ฐ€ ๊ฐ€๋ ค์ง€๊ธฐ๋„ ํ•˜๋ฏ€๋กœ ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด ๋ฐ‘์ค„์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. URI ๊ฒฝ๋กœ์—๋Š” ์†Œ๋ฌธ์ž๊ฐ€ ์ ํ•ฉํ•˜๋‹ค. URI ๊ฒฝ๋กœ์— ๋Œ€๋ฌธ์ž ์‚ฌ์šฉ์€ ํ”ผํ•˜๋„๋ก ํ•œ๋‹ค. RFC 3986(URI ๋ฌธ๋ฒ• ํ˜•์‹)์€ URI ์Šคํ‚ค๋งˆ์™€ ํ˜ธ์ŠคํŠธ๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•˜๋„๋ก ๊ทœ์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ ํŒŒ์ผํ™•์žฅ์ž๋Š” URI์— ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค. REST API์—์„œ๋Š” ๋ฉ”์‹œ์ง€ ๋ฐ”๋”” ๋‚ด์šฉ์˜ ํฌ๋งท์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•œ ํŒŒ์ผ ํ™•์žฅ์ž๋ฅผ URI ์•ˆ์— ํฌํ•จ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค. Accept header๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. Ex) http://restapi.example.com/members/soccer/345/photo.jpg (X) Ex) GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg (O) ๋ฆฌ์†Œ์Šค ๊ฐ„์—๋Š” ์—ฐ๊ด€ ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ /๋ฆฌ์†Œ์Šค๋ช…/๋ฆฌ์†Œ์Šค ID/๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค๋ช… Ex) GET : /users/{userid}/devices (์ผ๋ฐ˜์ ์œผ๋กœ ์†Œ์œ  โ€˜hasโ€™์˜ ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•  ๋•Œ)

REST API ์„ค๊ณ„ ์˜ˆ์‹œ

์ฐธ๊ณ  ์‘๋‹ต์ƒํƒœ์ฝ”๋“œ

1xx : ์ „์†ก ํ”„๋กœํ† ์ฝœ ์ˆ˜์ค€์˜ ์ •๋ณด ๊ตํ™˜ 2xx : ํด๋ผ์–ด์ธํŠธ ์š”์ฒญ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰๋จ 3xx : ํด๋ผ์ด์–ธํŠธ๋Š” ์š”์ฒญ์„ ์™„๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€์ ์ธ ํ–‰๋™์„ ์ทจํ•ด์•ผ ํ•จ 4xx : ํด๋ผ์ด์–ธํŠธ์˜ ์ž˜๋ชป๋œ ์š”์ฒญ 5xx : ์„œ๋ฒ„์ชฝ ์˜ค๋ฅ˜๋กœ ์ธํ•œ ์ƒํƒœ์ฝ”๋“œ

RESTful์˜ ๊ฐœ๋…

RESTful์ด๋ž€

RESTful์€ ์ผ๋ฐ˜์ ์œผ๋กœ REST๋ผ๋Š” ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์›น ์„œ๋น„์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด์ด๋‹ค. โ€˜REST APIโ€™๋ฅผ ์ œ๊ณตํ•˜๋Š” ์›น ์„œ๋น„์Šค๋ฅผ โ€˜RESTfulโ€™ํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. RESTful์€ REST๋ฅผ REST๋‹ต๊ฒŒ ์“ฐ๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ, ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ณต์‹์ ์œผ๋กœ ๋ฐœํ‘œํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์ฆ‰, REST ์›๋ฆฌ๋ฅผ ๋”ฐ๋ฅด๋Š” ์‹œ์Šคํ…œ์€ RESTful์ด๋ž€ ์šฉ์–ด๋กœ ์ง€์นญ๋œ๋‹ค.

RESTful์˜ ๋ชฉ์ 

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

RESTful ํ•˜์ง€ ๋ชปํ•œ ๊ฒฝ์šฐ

Ex1) CRUD ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ POST๋กœ๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” API Ex2) route์— resource, id ์™ธ์˜ ์ •๋ณด๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ(/students/updateName) https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html

context switching์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์‹œ์˜ค

โš ๏ธ **GitHub.com Fallback** โš ๏ธ