week 9 jisoo - GANGNAM-JAVA/JAVA-STUDY GitHub Wiki
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 ๋์ ์ ๋์ฒดํ ๊ฐ์ ์ง์ ํ ์๋ ์์ต๋๋ค.
-
orElse() ๋ฉ์๋ : ์ ์ฅ๋ ๊ฐ์ด ์กด์ฌํ๋ฉด ๊ทธ ๊ฐ์ ๋ฐํํ๊ณ , ๊ฐ์ด ์กด์ฌํ์ง ์์ผ๋ฉด ์ธ์๋ก ์ ๋ฌ๋ ๊ฐ์ ๋ฐํํจ.
-
orElseGet() ๋ฉ์๋ : ์ ์ฅ๋ ๊ฐ์ด ์กด์ฌํ๋ฉด ๊ทธ ๊ฐ์ ๋ฐํํ๊ณ , ๊ฐ์ด ์กด์ฌํ์ง ์์ผ๋ฉด ์ธ์๋ก ์ ๋ฌ๋ ๋๋ค ํํ์์ ๊ฒฐ๊ด๊ฐ์ ๋ฐํํจ.
-
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 ํด๋์ค๋ฅผ ์ ๊ณตํ๊ณ ์์ต๋๋ค.
-
OptionalInt ํด๋์ค
-
OptionalLong ํด๋์ค
-
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 ํด๋์ค์ ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ฉ์๋ ์ค๋ช
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๋ถํฐ ํด๋ก์ ๋ฅผ ์ง์ํ๋ค๋ ๊ธ์ ๋ณด๊ธฐ๋ ํฉ๋๋ค.
- ์๋ฐ์์์ ๋๋ค์ ํด๋ก์ ๋ฅผ ๋ช ํํ ๊ตฌ๋ถํด๋ณด๊ณ ์ ํฉ๋๋ค.
-
๋ณดํต์ ํจ์๋ ์ธ๋ถ์์ ์ธ์๋ฅผ ๋ฐ์์ ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
-
๊ทธ๋ฐ๋ฐ ํด๋ก์ ๋ ์์ ์ ๋๋ฌ์ผ 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();
}
});
}
์ค๋ช ์ด ๊ธธ์๋๋ฐ, ๊ฒฐ๋ก ์ ๋๋ค๋ ํด๋ก์ ๋ฅผ ํฌํจํ๋ ๋ ํฐ ๊ฐ๋ ์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. ๋๋ค๊ฐ ์์ ์ ๋ฒ์ ๋ฐ์ ์๋ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด ๊ทธ๊ฒ์ ๋๋ค์ธ ๋์์ ํด๋ก์ ์ ๋๋ค.
-
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 ์ฝ๋๋ฒ ์ด์ค๋ 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 ๊ตฌ์ฑ ๋ค์ ์คํ์ด์ค๋ ๋ฒ์ ์๋ ์คํค๋ง๋ก ๊ฐ์ํ๋์์ต๋๋ค.
-
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 ๋ฑ์ ํฅํ ๋ฆด๋ฆฌ์ค์ ์ถ๊ฐ ๋ ๋ฐ์ ํ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฅ์ ๋ณผ ์ ์์ต๋๋ค.
- ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๋๋ค. ์ค๋ผํด๊ณผ ๊ฐ์ด ๊ณ ๊ฐ์ DBMS๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๊ฐ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ผ๊ด์ฑ์ ์ ์งํ๋ ๋ฅ๋ ฅ์ด ๋ฐ์ด๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
Lock์ ์ํฉ์ ๋ฐ๋ผ์ ํฌ๊ฒ ๋๊ฐ์ง๋ก ๋๋์ด ์ง๋๋ค.
- ๋ณดํต ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๋ ์ฌ์ฉํฉ๋๋ค. ์ํ๋ ๋ฐ์ดํฐ์ lock์ ๊ฑธ์์ง๋ง ๋ค๋ฅธ ์ธ์ ์์ ์ฝ์ ์ ์์ต๋๋ค.
- ๊ณต์ Lock์ ์ค์ ํ ๊ฒฝ์ฐ ์ถ๊ฐ๋ก ๊ณต์ Lock์ ์ค์ ํ ์ ์์ง๋ง, ๋ฐฐํ์ Lock์ ์ค์ ํ ์ ์์ต๋๋ค.
- ์ฆ, ๋ด๊ฐ ๋ณด๊ณ ์๋ ๋ฐ์ดํฐ๋ ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ๋ณผ ์ ์์ง๋ง, ๋ณ๊ฒฝํ ์๋ ์์ต๋๋ค.
- ์ด๋ค ํธ๋์ญ์ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ ํ ๋(ex . ์ฐ๊ณ ์ ํ ๋) ํด๋น ํธ๋์ญ์ ์ด ์๋ฃ๋ ๋๊น์ง ํด๋น ํ ์ด๋ธ ํน์ ๋ ์ฝ๋(row)๋ฅผ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ์ฝ๊ฑฐ๋ ์ฐ์ง ๋ชปํ๊ฒ ํ๊ธฐ ์ํด Exclusive lock์ ๊ฑธ๊ณ ํธ๋์ญ์ ์ ์งํ์ํค๋๊ฒ์ ๋๋ค.
- ๋ณดํต ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ๋ ์ฌ์ฉํฉ๋๋ค.
- ์ด๋ฆ์์ ๋๊ปด์ง๋ ๊ฒ ์ฒ๋ผ ํด๋น Lock์ด ํด์ ๋๊ธฐ ์ ๊น์ง๋, ๋ค๋ฅธ ๊ณต์ Lock, ๋ฐฐํ์ Lock์ ์ค์ ํ ์ ์์ต๋๋ค.
- ์ฆ, ์ฝ๊ธฐ ๊ธฐ์ ์ฐ๊ธฐ๊ฐ ๋ถ๊ฐ๋ฅํ๋ค๋ ์๋ฏธ์ ๋๋ค.
๊ฒฝํฉ์ผ๋ก ์ธํ ์ํ์ธ ๋ธ๋กํน์ ๋ํ์ฌ ์์๋ด ๋๋ค.
๋ธ๋กํน์ Lock๋ค์ ๊ฒฝํฉ(Race condition์ด๋ผ๊ณ ๋ ํฉ๋๋ค)์ด ๋ฐ์ํ์ฌ ํน์ ์ธ์ ์ด ์์ ์ ์งํํ์ง ๋ชปํ๊ณ ๋ฉ์ถฐ ์ ์ํ๋ฅผ ์๋ฏธํฉ๋๋ค. ๊ณต์ Lock๊ณผ ๋ฐฐํ์ Lock ๋๋ ๋ฐฐํ์ Lock๊ณผ ๋ฐฐํ์ Lock๋ผ๋ฆฌ ๋ธ๋กํน์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ Transaction commit ๋๋ rollback ๋ฟ์ ๋๋ค. ๊ฒฝํฉ์ด ๋ฐ์ํ ๋, ๋จผ์ Lock์ ์ค์ ํ ํธ๋์ ์ ์ ๊ธฐ๋ค๋ ค์ผํ๊ธฐ ๋๋ฌธ์, ์ด๋ฐ ํ์์ด ๋ฐ๋ณต๋๋ฉด ๋น ๋ฅธ ์๋น์ค๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
SQL ๋ฌธ์ฅ์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์คํ๋๋๋ก ๋ฆฌํํ ๋งํ๋ ๊ฒ์ด ๊ฐ์ฅ ๊ธฐ๋ณธ์ด๋ฉฐ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค. ํธ๋์ ์ ์ ๊ฐ๋ฅํ ์งง๊ฒ ์ ์ํ๋ฉด ๊ฒฝํฉ์ ์ค์ผ ์ ์์ต๋๋ค. ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๋์์ ๋ณ๊ฒฝํ๋ ์์ ์ ํ์ง ์๋๋ก ์ค๊ณํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ํ ํธ๋์ ์ ์ด ํ๋ฐํ ์ฃผ๊ฐ์๋ ๋์ฉ๋ ๊ฐฑ์ ์์ ์ ์ํํ๋ฉด ์๋ฉ๋๋ค. ๋์ฉ๋์์ ์ด ๋ถ๊ฐํผํ ๊ฒฝ์ฐ, ์์ ๋จ์๋ฅผ ์ชผ๊ฐ๊ฑฐ๋ lock_timeout์ ์ค์ ํ์ฌ ํด๋น Lock์ ์ต๋์๊ฐ์ ์ค์ ํ ์ ์์ต๋๋ค.
set lock_timeout 3000
-
deadlock์ ํธ๋์ ์ ๊ฐ์ ๊ต์ฐฉ์ํ๋ฅผ ์๋ฏธํฉ๋๋ค. ๋๊ฐ์ ํธ๋์ ์ ๊ฐ์ ๊ฐ๊ฐ์ ํธ๋์ ์ ์ด ๊ฐ์ง๊ณ ์๋ ๋ฆฌ์์ค์ Lock์ ํ๋ํ๋ ค๊ณ ํ ๋ ๋ฐ์ํฉ๋๋ค.
-
๊ฐ์ฅ ํํ ๋ ์ฌ๋ฆด ์ ์๋ deadlock ์ํฉ์ ๋๋ค. 1๋ฒ ํธ๋์ ์ ์์ 2๋ฒ ๋ฆฌ์์ค์ ์ ๊ธ์ ํ๋, 2๋ฒ ํธ๋์ ์ ์์๋ 1๋ฒ ๋ฆฌ์์ค์ ์ ๊ธ์ ํ๋ํ ์ํ์ ๋๋ค.
-
์ด๋, ๋์์ ์๋๋ฐฉ์ ๋ฐ์ดํฐ๋ฅผ ์์ธ์คํ๋ ค๊ณ ํ ๋ ๊ธฐ์กด์ Lock์ด ํด์ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ ์ํฉ์ ๋๋ค.
-
Postgresql์์๋ ์๋์ ์ผ๋ก deadlock์ ์ธ์งํ๊ณ ๊ต์ฐฉ์ํ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ์ฌ ํ๋์ ํธ๋์ ์ ์ ์ทจ์์ํต๋๋ค. ๊ทธ๋ฌ๋, ์ด๋ค ํธ๋์ ์ ์ด ์ทจ์๋ ์ง ํ๋จํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค.
- SQL ๋ช ๋ น์ด์ ๋ฐ๋ผ์ Lock์ ์ค์ ๋์์ด ๋ฐ์ดํฐ row์ผ์ง database์ผ์ง ๋๋์ด์ง๋๋ค.
- Row level: ๋ณ๊ฒฝํ๋ ค๋ row์๋ง lock์ ์ค์ ํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
- Page level: ๋ณ๊ฒฝํ๋ ค๋ row๊ฐ ๋ด๊ธด ๋ฐ์ดํฐ page (๋๋ ์ธ๋ฑ์ค ํ์ด์ง)์ lock์ ์ค์ ํฉ๋๋ค. ๊ฐ์ ํ์ด์ง์ ์ํ row๋ค์ ๋ณ๊ฒฝ์์ ๊ณผ ๋ฌด๊ดํ๊ฒ ๋ชจ๋ lock์ ์ํด ์ ๊น๋๋ค. Tabel level: ํ ์ด๋ธ๊ณผ ์ธ๋ฑ์ค์ ๋ชจ๋ ์ ๊ธ์ ์ค์ ํฉ๋๋ค. Select table, Alter table, Vacuum, Refresh, Index, Drop, Truncate ๋ฑ์ ์์ ์์ ํด๋น๋ ๋ฒจ์ ๋ฝ์ด ์ค์ ๋ฉ๋๋ค.
- Database level: ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ณต๊ตฌํ๊ฑฐ๋ ์คํค๋ง๋ฅผ ๋ณ๊ฒฝํ ๋ ๋ฐ์ํฉ๋๋ค.
- Lock ๋ฆฌ์์ค๊ฐ ์๊ณ์น๋ฅผ ๋์ผ๋ฉด Lock ๋ ๋ฒจ์ด ํ์ฅ๋๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
- Lock ๋ ๋ฒจ์ด ๋ฎ์ ์๋ก ๋์์ฑ์ด ์ข์์ง์ง๋ง, ๊ด๋ฆฌํด์ผํ Lock์ด ๋ง์์ง๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์ ๋จ์ด์ง๋๋ค.
- ๋ฐ๋๋ก Lock๋ ๋ฒจ์ด ๋์ ์๋ก ๊ด๋ฆฌ๋ฆฌ์์ค๋ ๋ฎ์ง๋ง, ๋์์ฑ์ ๋จ์ด์ง๋๋ค.
โ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)
์ฅ์
- HTTP ํ๋กํ ์ฝ์ ์ธํ๋ผ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฏ๋ก REST API ์ฌ์ฉ์ ์ํ ๋ณ๋์ ์ธํ๋ผ๋ฅผ ๊ตฌ์ถํ ํ์๊ฐ ์๋ค.
- HTTP ํ๋กํ ์ฝ์ ํ์ค์ ์ต๋ํ ํ์ฉํ์ฌ ์ฌ๋ฌ ์ถ๊ฐ์ ์ธ ์ฅ์ ์ ํจ๊ป ๊ฐ์ ธ๊ฐ ์ ์๊ฒ ํด์ค๋ค.
- HTTP ํ์ค ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋ ๋ชจ๋ ํ๋ซํผ์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
- Hypermedia API์ ๊ธฐ๋ณธ์ ์ถฉ์คํ ์งํค๋ฉด์ ๋ฒ์ฉ์ฑ์ ๋ณด์ฅํ๋ค.
- REST API ๋ฉ์์ง๊ฐ ์๋ํ๋ ๋ฐ๋ฅผ ๋ช ํํ๊ฒ ๋ํ๋ด๋ฏ๋ก ์๋ํ๋ ๋ฐ๋ฅผ ์ฝ๊ฒ ํ์ ํ ์ ์๋ค.
- ์ฌ๋ฌ๊ฐ์ง ์๋น์ค ๋์์ธ์์ ์๊ธธ ์ ์๋ ๋ฌธ์ ๋ฅผ ์ต์ํํ๋ค.
- ์๋ฒ์ ํด๋ผ์ด์ธํธ์ ์ญํ ์ ๋ช ํํ๊ฒ ๋ถ๋ฆฌํ๋ค.
๋จ์
- ํ์ค์ด ์กด์ฌํ์ง ์๋๋ค.
- ์ฌ์ฉํ ์ ์๋ ๋ฉ์๋๊ฐ 4๊ฐ์ง ๋ฐ์ ์๋ค.
- HTTP Method ํํ๊ฐ ์ ํ์ ์ด๋ค.
- ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ํ ์คํธํ ์ผ์ด ๋ง์ ์๋น์ค๋ผ๋ฉด ์ฝ๊ฒ ๊ณ ์น ์ ์๋ URL๋ณด๋ค Header ๊ฐ์ด ์ ์ง๋ ์ด๋ ต๊ฒ ๋๊ปด์ง๋ค.
- ๊ตฌํ ๋ธ๋ผ์ฐ์ ๊ฐ ์์ง ์ ๋๋ก ์ง์ํด์ฃผ์ง ๋ชปํ๋ ๋ถ๋ถ์ด ์กด์ฌํ๋ค.
- PUT, DELETE๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ ์
- pushState๋ฅผ ์ง์ํ์ง ์๋ ์
- โ์ ํ๋ฆฌ์ผ์ด์ ๋ถ๋ฆฌ ๋ฐ ํตํฉโ
- โ๋ค์ํ ํด๋ผ์ด์ธํธ์ ๋ฑ์ฅโ
- ์ต๊ทผ์ ์๋ฒ ํ๋ก๊ทธ๋จ์ ๋ค์ํ ๋ธ๋ผ์ฐ์ ์ ์๋๋ก์ดํฐ, ์์ดํฐ๊ณผ ๊ฐ์ ๋ชจ๋ฐ์ผ ๋๋ฐ์ด์ค์์๋ ํต์ ์ ํ ์ ์์ด์ผ ํ๋ค. ์ด๋ฌํ ๋ฉํฐ ํ๋ซํผ์ ๋ํ ์ง์์ ์ํด ์๋น์ค ์์์ ๋ํ ์ํคํ ์ฒ๋ฅผ ์ธ์ฐ๊ณ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ชจ์ํ ๊ฒฐ๊ณผ, 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๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
- Server-Client(์๋ฒ-ํด๋ผ์ด์ธํธ ๊ตฌ์กฐ) ์์์ด ์๋ ์ชฝ์ด Server, ์์์ ์์ฒญํ๋ ์ชฝ์ด Client๊ฐ ๋๋ค. REST Server: API๋ฅผ ์ ๊ณตํ๊ณ ๋น์ฆ๋์ค ๋ก์ง ์ฒ๋ฆฌ ๋ฐ ์ ์ฅ์ ์ฑ ์์ง๋ค. Client: ์ฌ์ฉ์ ์ธ์ฆ์ด๋ context(์ธ์ , ๋ก๊ทธ์ธ ์ ๋ณด) ๋ฑ์ ์ง์ ๊ด๋ฆฌํ๊ณ ์ฑ ์์ง๋ค. ์๋ก ๊ฐ ์์กด์ฑ์ด ์ค์ด๋ ๋ค.
- Stateless(๋ฌด์ํ) HTTP ํ๋กํ ์ฝ์ Stateless Protocol์ด๋ฏ๋ก REST ์ญ์ ๋ฌด์ํ์ฑ์ ๊ฐ๋๋ค. Client์ context๋ฅผ Server์ ์ ์ฅํ์ง ์๋๋ค. ์ฆ, ์ธ์ ๊ณผ ์ฟ ํค์ ๊ฐ์ context ์ ๋ณด๋ฅผ ์ ๊ฒฝ์ฐ์ง ์์๋ ๋๋ฏ๋ก ๊ตฌํ์ด ๋จ์ํด์ง๋ค. Server๋ ๊ฐ๊ฐ์ ์์ฒญ์ ์์ ํ ๋ณ๊ฐ์ ๊ฒ์ผ๋ก ์ธ์ํ๊ณ ์ฒ๋ฆฌํ๋ค. ๊ฐ API ์๋ฒ๋ Client์ ์์ฒญ๋ง์ ๋จ์ ์ฒ๋ฆฌํ๋ค. ์ฆ, ์ด์ ์์ฒญ์ด ๋ค์ ์์ฒญ์ ์ฒ๋ฆฌ์ ์ฐ๊ด๋์ด์๋ ์๋๋ค. ๋ฌผ๋ก ์ด์ ์์ฒญ์ด DB๋ฅผ ์์ ํ์ฌ DB์ ์ํด ๋ฐ๋๋ ๊ฒ์ ํ์ฉํ๋ค. Server์ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ผ๊ด์ฑ์ ๋ถ์ฌํ๊ณ ๋ถ๋ด์ด ์ค์ด๋ค๋ฉฐ, ์๋น์ค์ ์์ ๋๊ฐ ๋์์ง๋ค.
- Cacheable(์บ์ ์ฒ๋ฆฌ ๊ฐ๋ฅ) ์น ํ์ค HTTP ํ๋กํ ์ฝ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฏ๋ก ์น์์ ์ฌ์ฉํ๋ ๊ธฐ์กด์ ์ธํ๋ผ๋ฅผ ๊ทธ๋๋ก ํ์ฉํ ์ ์๋ค. ์ฆ, HTTP๊ฐ ๊ฐ์ง ๊ฐ์ฅ ๊ฐ๋ ฅํ ํน์ง ์ค ํ๋์ธ ์บ์ฑ ๊ธฐ๋ฅ์ ์ ์ฉํ ์ ์๋ค. HTTP ํ๋กํ ์ฝ ํ์ค์์ ์ฌ์ฉํ๋ Last-Modified ํ๊ทธ๋ E-Tag๋ฅผ ์ด์ฉํ๋ฉด ์บ์ฑ ๊ตฌํ์ด ๊ฐ๋ฅํ๋ค. ๋๋์ ์์ฒญ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์บ์๊ฐ ์๊ตฌ๋๋ค. ์บ์ ์ฌ์ฉ์ ํตํด ์๋ต์๊ฐ์ด ๋นจ๋ผ์ง๊ณ REST Server ํธ๋์ญ์ ์ด ๋ฐ์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ ์ฒด ์๋ต์๊ฐ, ์ฑ๋ฅ, ์๋ฒ์ ์์ ์ด์ฉ๋ฅ ์ ํฅ์์ํฌ ์ ์๋ค.
- Layered System(๊ณ์ธตํ) Client๋ REST API Server๋ง ํธ์ถํ๋ค. REST Server๋ ๋ค์ค ๊ณ์ธต์ผ๋ก ๊ตฌ์ฑ๋ ์ ์๋ค. API Server๋ ์์ ๋น์ฆ๋์ค ๋ก์ง์ ์ํํ๊ณ ๊ทธ ์๋จ์ ๋ณด์, ๋ก๋๋ฐธ๋ฐ์ฑ, ์ํธํ, ์ฌ์ฉ์ ์ธ์ฆ ๋ฑ์ ์ถ๊ฐํ์ฌ ๊ตฌ์กฐ์์ ์ ์ฐ์ฑ์ ์ค ์ ์๋ค. ๋ํ ๋ก๋๋ฐธ๋ฐ์ฑ, ๊ณต์ ์บ์ ๋ฑ์ ํตํด ํ์ฅ์ฑ๊ณผ ๋ณด์์ฑ์ ํฅ์์ํฌ ์ ์๋ค. PROXY, ๊ฒ์ดํธ์จ์ด ๊ฐ์ ๋คํธ์ํฌ ๊ธฐ๋ฐ์ ์ค๊ฐ ๋งค์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- Code-On-Demand(optional) Server๋ก๋ถํฐ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐ์์ Client์์ ์คํํ๋ค. ๋ฐ๋์ ์ถฉ์กฑํ ํ์๋ ์๋ค.
- Uniform Interface(์ธํฐํ์ด์ค ์ผ๊ด์ฑ) URI๋ก ์ง์ ํ Resource์ ๋ํ ์กฐ์์ ํต์ผ๋๊ณ ํ์ ์ ์ธ ์ธํฐํ์ด์ค๋ก ์ํํ๋ค. HTTP ํ์ค ํ๋กํ ์ฝ์ ๋ฐ๋ฅด๋ ๋ชจ๋ ํ๋ซํผ์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. ํน์ ์ธ์ด๋ ๊ธฐ์ ์ ์ข ์๋์ง ์๋๋ค.
API(Application Programming Interface)๋
-
๋ฐ์ดํฐ์ ๊ธฐ๋ฅ์ ์งํฉ์ ์ ๊ณต
ํ์ฌ ์ปดํจํฐ ํ๋ก๊ทธ๋จ๊ฐ ์ํธ ์์ฉ์ ์ด์งํ๋ฉฐ, ์๋ก ์ ๋ณด๋ฅผ ๊ตํ๊ฐ๋ฅ ํ๋๋ก ํ๋ ๊ฒ
REST ๊ธฐ๋ฐ์ผ๋ก ์๋น์ค API๋ฅผ ๊ตฌํํ ๊ฒ ์ต๊ทผ OpenAPI(๋๊ตฌ๋ ์ฌ์ฉํ ์ ์๋๋ก ๊ณต๊ฐ๋ API: ๊ตฌ๊ธ ๋งต, ๊ณต๊ณต ๋ฐ์ดํฐ ๋ฑ), ๋ง์ดํฌ๋ก ์๋น์ค(ํ๋์ ํฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๊ฐ์ ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ชผ๊ฐ์ด ๋ณ๊ฒฝ๊ณผ ์กฐํฉ์ด ๊ฐ๋ฅํ๋๋ก ๋ง๋ ์ํคํ ์ฒ) ๋ฑ์ ์ ๊ณตํ๋ ์ ์ฒด ๋๋ถ๋ถ์ REST API๋ฅผ ์ ๊ณตํ๋ค.
์ฌ๋ด ์์คํ
๋ค๋ REST ๊ธฐ๋ฐ์ผ๋ก ์์คํ
์ ๋ถ์ฐ
ํด ํ์ฅ์ฑ
๊ณผ ์ฌ์ฌ์ฉ์ฑ
์ ๋์ฌ ์ ์ง๋ณด์ ๋ฐ ์ด์ฉ์ ํธ๋ฆฌํ๊ฒ ํ ์ ์๋ค.
REST๋ HTTP ํ์ค
์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํํ๋ฏ๋ก, HTTP๋ฅผ ์ง์ํ๋ ํ๋ก๊ทธ๋จ ์ธ์ด๋ก ํด๋ผ์ด์ธํธ, ์๋ฒ
๋ฅผ ๊ตฌํํ ์ ์๋ค.
์ฆ, REST API๋ฅผ ์ ์ํ๋ฉด ๋ธํ์ด ํด๋ผ์ด์ธํธ ๋ฟ ์๋๋ผ, ์๋ฐ, C#, ์น ๋ฑ์ ์ด์ฉํด ํด๋ผ์ด์ธํธ๋ฅผ ์ ์ํ ์ ์๋ค.
์ฐธ๊ณ ๋ฆฌ์์ค ์ํ
๋ํ๋จผํธ : ๊ฐ์ฒด ์ธ์คํด์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ์ฝ๋์ ์ ์ฌํ ๊ฐ๋
์ปฌ๋ ์
: ์๋ฒ์์ ๊ด๋ฆฌํ๋ ๋๋ ํฐ๋ฆฌ๋ผ๋ ๋ฆฌ์์ค
์คํ ์ด : ํด๋ผ์ด์ธํธ์์ ๊ด๋ฆฌํ๋ ๋ฆฌ์์ค ์ ์ฅ์
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
์ฌ๋์ ๊ตฌ๋ถ์(/ )๋ ๊ณ์ธต ๊ด๊ณ
๋ฅผ ๋ํ๋ด๋๋ฐ ์ฌ์ฉํ๋ค.
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โ์ ๊ด๊ณ๋ฅผ ํํํ ๋)
์ฐธ๊ณ ์๋ต์ํ์ฝ๋
1xx : ์ ์ก ํ๋กํ ์ฝ ์์ค์ ์ ๋ณด ๊ตํ
2xx : ํด๋ผ์ด์ธํธ ์์ฒญ์ด ์ฑ๊ณต์ ์ผ๋ก ์ํ๋จ
3xx : ํด๋ผ์ด์ธํธ๋ ์์ฒญ์ ์๋ฃํ๊ธฐ ์ํด ์ถ๊ฐ์ ์ธ ํ๋์ ์ทจํด์ผ ํจ
4xx : ํด๋ผ์ด์ธํธ์ ์๋ชป๋ ์์ฒญ
5xx : ์๋ฒ์ชฝ ์ค๋ฅ
๋ก ์ธํ ์ํ์ฝ๋
RESTful์ ์ผ๋ฐ์ ์ผ๋ก REST๋ผ๋ ์ํคํ ์ฒ๋ฅผ ๊ตฌํํ๋ ์น ์๋น์ค๋ฅผ ๋ํ๋ด๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ฉ์ด์ด๋ค. โREST APIโ๋ฅผ ์ ๊ณตํ๋ ์น ์๋น์ค๋ฅผ โRESTfulโํ๋ค๊ณ ํ ์ ์๋ค. RESTful์ REST๋ฅผ REST๋ต๊ฒ ์ฐ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก, ๋๊ตฐ๊ฐ๊ฐ ๊ณต์์ ์ผ๋ก ๋ฐํํ ๊ฒ์ด ์๋๋ค. ์ฆ, REST ์๋ฆฌ๋ฅผ ๋ฐ๋ฅด๋ ์์คํ ์ RESTful์ด๋ ์ฉ์ด๋ก ์ง์นญ๋๋ค.
์ดํดํ๊ธฐ ์ฝ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด REST API๋ฅผ ๋ง๋๋ ๊ฒ RESTfulํ API๋ฅผ ๊ตฌํํ๋ ๊ทผ๋ณธ์ ์ธ ๋ชฉ์ ์ด ์ฑ๋ฅ ํฅ์์ ์๋ ๊ฒ์ด ์๋๋ผ ์ผ๊ด์ ์ธ ์ปจ๋ฒค์ ์ ํตํ API์ ์ดํด๋ ๋ฐ ํธํ์ฑ์ ๋์ด๋ ๊ฒ์ด ์ฃผ ๋๊ธฐ์ด๋, ์ฑ๋ฅ์ด ์ค์ํ ์ํฉ์์๋ ๊ตณ์ด RESTfulํ API๋ฅผ ๊ตฌํํ ํ์๋ ์๋ค.
Ex1) CRUD ๊ธฐ๋ฅ์ ๋ชจ๋ POST๋ก๋ง ์ฒ๋ฆฌํ๋ API Ex2) route์ resource, id ์ธ์ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ(/students/updateName) https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html