week 5 jisoo - GANGNAM-JAVA/JAVA-STUDY GitHub Wiki
๋์ผํ์ง ์์ ์ด๋ค ๊ฐ์ฒด X์ Y๊ฐ ์์ ๋, ์ฆ X.equals(Y)๊ฐ '๊ฑฐ์ง'์ผ ๋ X.hashCode() != Y.hashCode()๊ฐ ๊ฐ์ง ์๋ค๋ฉด, ์ด๋ ์ฌ์ฉํ๋ ํด์ ํจ์๋ ์์ ํ ํด์ ํจ์
(perfect hash functions)๋ผ๊ณ ํ๋ค(
: S๋ ๋ชจ๋ ๊ฐ์ฒด์ ์งํฉ, h๋ ํด์ ํจ์).
Boolean๊ฐ์ด ์๋ก ๊ตฌ๋ณ๋๋ ๊ฐ์ฒด์ ์ข
๋ฅ๊ฐ ์ ๊ฑฐ๋, Integer, Long, Double ๊ฐ์ Number ๊ฐ์ฒด๋ ๊ฐ์ฒด๊ฐ ๋ํ๋ด๋ ค๋ ๊ฐ ์์ฒด๋ฅผ ํด์ ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์์ ํ ํด์ ํจ์ ๋์์ผ๋ก ์ผ์ ์ ์๋ค. ํ์ง๋ง String
์ด๋ POJO(plain old java object)
์ ๋ํ์ฌ ์์ ํ ํด์ ํจ์๋ฅผ ์ ์ํ๋ ๊ฒ์ ์ฌ์ค์ ๋ถ๊ฐ๋ฅํ๋ค.
์ ์ ์ฐ์ฐ๋ง์ผ๋ก ๋น ๋ฅด๊ฒ ๋์ํ ์ ์๋ ์์ ํ ํด์ ํจ์๊ฐ ์๋ค๊ณ ํ๋๋ผ๋, ๊ทธ๊ฒ์ HashMap์์ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ์๋๋ค. HashMap์ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ ๊ฐ์ฒด์ hashCode()
๋ฉ์๋๊ฐ ๋ฐํํ๋ ๊ฐ์ ์ฌ์ฉํ๋ ๋ฐ, ๊ฒฐ๊ณผ ์๋ฃํ์ int
๋ค. 32๋นํธ ์ ์ ์๋ฃํ
์ผ๋ก๋ ์์ ํ ์๋ฃ ํด์ ํจ์๋ฅผ ๋ง๋ค ์ ์๋ค. ๋
ผ๋ฆฌ์ ์ผ๋ก ์์ฑ ๊ฐ๋ฅํ ๊ฐ์ฒด์ ์๊ฐ 232๋ณด๋ค ๋ง์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ฉฐ, ๋ํ ๋ชจ๋ HashMap ๊ฐ์ฒด์์ O(1)์ ๋ณด์ฅํ๊ธฐ ์ํด ๋๋ค ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ฒ ํ๋ ค๋ฉด ์์๊ฐ 232์ธ ๋ฐฐ์ด์ ๋ชจ๋ HashMap์ด ๊ฐ์ง๊ณ ์์ด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
์์ธ ์ฒ๋ฆฌ ๊ณผ์ ํ๋ก๊ทธ๋๋ฐ์์ ์์ธ ์ฒ๋ฆฌ๋ ์์ฃผ ์ค์ํ๋ฉด์๋ ์์ฃผ ์ด๋ ต๋ค.
๊ณผํ๋คํ ๋งํผ ์์ธํ๊ณ ๋ค์ํ๊ฒ ์์ธ๋ฅผ ์ก์ ์ฒ๋ฆฌํด์ค๋ค๋ฉด, ํด๋ผ์ด์ธํธ๋ ๊ทธ๋ ๊ณ ์๋ฒ๋ ๊ทธ๋ ๊ณ ๋ ์์ ์ ์ธ ํ๋ก๊ทธ๋จ์ด ๋ ์ ์๊ฒ ๋์์ค๋ค.
์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ฒฝ์ฐ์ ๋ฐฉ๋ฒ์ ๋ค์ํ๋ค.
๋ฉ์๋ ๋ด์์ ์์ธ ์ํฉ์ ์์ธกํด์ ์ฒ๋ฆฌํ๋ try-catch๋ฌธ์ ์ด์ฉํ๋ ๋ฐฉ๋ฒ ์๊ตฌ์ฌํญ์ ์ํ ์์ธ ์ฒ๋ฆฌ (ex. validation > ํน์ ๊ฐ์ด 0~255๋ฒ์๊ฐ ์๋๋ฉด ์ ํจํ์ง ์์ ๊ฐ์ผ๋ก ํ๋จํ๊ณ ์์ธ ์ฒ๋ฆฌ) ์คํ๋ง ์ํ๋ฆฌํฐ์์ ์ธํฐ์ ํฐ๋ก ์ก์์ UnauthorizedException ๊ฐ์ ์์ธ ์ฒ๋ฆฌ ๊ธฐํ ์ฌ๋ฌ ์์ธ ์ฒ๋ฆฌ๋ค์ ์ ์ฉํ๋ค๋ณด๋ฉด ์ฝ๋๊ฐ ์์ฒญ๋๊ฒ ๋ณต์กํด์ง๋ค.
if๋ฌธ์ผ๋ก ์ก๋ try-catch๋ก ์ก๋ ์์ ๋ฉ์๋๋ก ์์ธ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ ์ฝ๋๋ ๋ณต์กํด์ง๋ค
๊ทธ๋ ๊ฒ ๋๋ฉด ์ ์ง๋ณด์ํ๊ธฐ ์์ฃผ ์ด๋ ค์์ง๋ค.
๋น์ฆ๋์ค ๋ก์ง์ ์ง์คํ๊ธฐ ์ด๋ ต๊ณ , ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๊ด๋ จ๋ ์ฝ๋๋ณด๋ค ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋๊ฐ ๋ ๋ง์์ง๋ ๊ฒฝ์ฐ๋ ์๊ธด๋ค.
์ด๋ฐ ๋ฌธ์ ๋ฅผ ์กฐ๊ธ์ด๋ผ๋ ๊ฐ์ ํ๊ธฐ ์ํด @ExceptionHandler์ @ControllerAdvice๋ฅผ ์ฌ์ฉํ๋ค๊ณ ๋ณด๋ฉด ์ดํด๊ฐ ์ฌ์์ง๋ค.
@ExceptionHandler @ExceptionHandler๊ฐ์ ๊ฒฝ์ฐ๋ @Controller, @RestController๊ฐ ์ ์ฉ๋ Bean๋ด์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ก์์ ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํด์ฃผ๋ ๊ธฐ๋ฅ์ ํ๋ค.
@RestController public class MyRestController { ... ... @ExceptionHandler(NullPointerException.class) public Object nullex(Exception e) { System.err.println(e.getClass()); return "myService"; } } ์์ ๊ฐ์ด ์ ์ฉํ๊ธฐ๋ง ํ๋ฉด ๋๋ค. @ExceptionHandler๋ผ๋ ์ด๋ ธํ ์ด์ ์ ์ฐ๊ณ ์ธ์๋ก ์บ์นํ๊ณ ์ถ์ ์์ธํด๋์ค๋ฅผ ๋ฑ๋กํด์ฃผ๋ฉด ๋๋๋ค.
โ @ExceptionHandler({ Exception1.class, Exception2.class}) ์ด๋ฐ์์ผ๋ก ๋ ๊ฐ ์ด์ ๋ฑ๋ก๋ ๊ฐ๋ฅํ๋ค.
์์ ์์ ์์ ์ฒ๋ผํ๋ฉด MyRestController์ ํด๋นํ๋ Bean์์ NullPointerException์ด ๋ฐ์ํ๋ค๋ฉด, @ExceptionHandler(NullPointerException.class)๊ฐ ์ ์ฉ๋ ๋ฉ์๋๊ฐ ํธ์ถ๋ ๊ฒ์ด๋ค.
์ฃผ์์ฌํญ/์์ ๋ ๊ฒ
Controller, RestController์๋ง ์ ์ฉ๊ฐ๋ฅํ๋ค. (@Service๊ฐ์ ๋น์์๋ ์๋จ.) ๋ฆฌํด ํ์ ์ ์์ ๋กญ๊ฒ ํด๋ ๋๋ค. (Controller๋ด๋ถ์ ์๋ ๋ฉ์๋๋ค์ ์ฌ๋ฌ ํ์ ์ response๋ฅผ ํ ๊ฒ์ด๋ค. ํด๋น ํ์ ๊ณผ ์ ํ๋ค๋ฅธ ๋ฆฌํด ํ์ ์ด์ด๋ ์๊ด์๋ค.) @ExceptionHandler๋ฅผ ๋ฑ๋กํ Controller์๋ง ์ ์ฉ๋๋ค. ๋ค๋ฅธ Controller์์ NullPointerException์ด ๋ฐ์ํ๋๋ผ๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค. ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ก Exception์ ๋ฐ์์๋๋ฐ ์ด๊ฒ ๋ํ ์์ ๋กญ๊ฒ ๋ฐ์์๋ ๋๋ค. ์์ ๋ฅผ ๋ณด๋ฉด์ ํ ์คํธ๋ฅผ ํด๋ณด๋๋กํ์.
@RestController public class MyRestController { @Autowired private MyService myService; @GetMapping("/hello") public String hello() { return "hello";//๋ฌธ์์ด ๋ฐํ } @GetMapping("/myData") public MyData myData() { return new MyData("myName");//object ๋ฐํ } @GetMapping("/service") public String serviceCall() { return myService.serviceMethod();//์ผ๋ฐ์ ์ธ serviceํธ์ถ } @GetMapping("/serviceException") public String serviceException() { return myService.serviceExceptionMethod(); //service์์ ์์ธ๋ฐ์ } @GetMapping("/controllerException") public void controllerException() { throw new NullPointerException();//controller์์ ์์ธ๋ฐ์ } @GetMapping("/customException") public String custom() { throw new CustomException();//custom์์ธ ๋ฐ์ } @ExceptionHandler(NullPointerException.class) public Object nullex(Exception e) { System.err.println(e.getClass()); return "myService"; } } [MyRestController.class]
Stringํ์ ๊ณผ MyData๋ผ๋ ๋๋ง์ ๊ฐ์ฒดํ์ ์ ๋ฆฌํดํ๋ ๋ฉ์๋๋ฑ์ ์กด์ฌํ์ง๋ง ExceptionHandlerํ๋๋ก ๋ค ์ฒ๋ฆฌํ ์ ์๋ค.
myService.serviceExceptionMethod๋ Service์์์ Exception์ด ๋ฐ์ํ๋๋ฐ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์๋น์ค์์ ์์ธ๊ฐ ๋ฐ์ํ์ง๋ง ๊ฒฐ๊ตญ ์ปจํธ๋กค๋ฌ ๋ด์์ ๋ฐ์ํ ๊ฒ๊ณผ ๊ฐ์ผ๋ฏ๋ก ExceptionHandler๊ฐ ์์ธ๋ฅผ ์ก์๋ด์ด "myService"๊ฐ ๋ฆฌํด๋๋ค.
public class CustomException extends RuntimeException{ private static final long serialVersionUID = 1L; } RuntimeException์ ํ์ฅํ ํด๋์ค๋ก CustomException์ ๋ง๋ค์๋ค.
์ด ์์ธ๋ NullPointerException์ด ์๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋๋ผ๋ ExceptionHandler์ ์ํด์ ์ฒ๋ฆฌ๋์ง ์๋๋ค.
๋ง์ฝ ํ๋๋ก ๋ ๋ง์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๊ธธ ์ํ๋ค๋ฉด ๋ชจ๋ ์์ธ์ ๋ถ๋ชจํด๋์ค์ธ Exception.class๋ฅผ ํธ๋ค๋งํ๊ฒํ๋ฉด ๋๋ค.
@ExceptionHandler(Exception.class) @ControllerAdvice @ExceptionHandler๊ฐ ํ๋์ ํด๋์ค์ ๋ํ ๊ฒ์ด๋ผ๋ฉด, @ControllerAdvice๋ ๋ชจ๋ @Controller ์ฆ, ์ ์ญ์์ ๋ฐ์ํ ์ ์๋ ์์ธ๋ฅผ ์ก์ ์ฒ๋ฆฌํด์ฃผ๋ annotation์ด๋ค.
@RestControllerAdvice public class MyAdvice { @ExceptionHandler(CustomException.class) public String custom() { return "hello custom"; } } ์์ ๊ฐ์ด ์๋ก์ด ํด๋์คํ์ผ์ ๋ง๋ค์ด์ annotation์ ๋ถ์ด๊ธฐ๋ง ํ๋ฉด ๋๋ค. ๊ทธ ๋ค์์ @ExceptionHandler๋ก ์ฒ๋ฆฌํ๊ณ ์ถ์ ์์ธ๋ฅผ ์ก์ ์ฒ๋ฆฌํ๋ฉด ๋๋ค.
๋ณ๋์ ์์ฑ๊ฐ์ด ์์ด ์ฌ์ฉํ๋ฉด ๋ชจ๋ ํจํค์ง ์ ์ญ์ ์๋ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ด๋นํ๊ฒ ๋๋ค.
@RestControllerAdvice๋ @ControllerAdvice๊ฐ ์๋๋ฐ ๋ง ๊ทธ๋๋ก @RestControllerAdvice๋ @RestController์์ ๋ฐ์ํ Exception๋ง ์บ์นํ๊ณ , @ControllerAdvice๋ @Controller์์ ๋ฐ์ํ Exception๋ง ์บ์นํ๋ค.
@RestControllerAdvice์ @ControllerAdvice๊ฐ ์กด์ฌํ๋๋ฐ @RestControllerAdvice ์ด๋ ธํ ์ด์ ์ ๋ค์ฌ๋ค๋ณด๋ฉด ์๋์ ๊ฐ์ด ๋์ด์๋ค.
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @ControllerAdvice @ResponseBody public @interface RestControllerAdvice { //... } ์์ ๊ฐ์ด ๋๊ฐ์ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ์ ๋ @RestControllerAdvice๋ฅผ ์ฌ์ฉํ๋ฉด @Controller๋ก ์ ์ฉํ HelloController์์ ๋ฐ์ํ๋ ์์ธ๋ @RestControllerAdvice์์ ์ก์์ฃผ์ง ๋ชปํ๋ค.
@ControllerAdvice์ ๋์ผํ ์ญํ ์ฆ, ์์ธ๋ฅผ ์ก์ ํธ๋ค๋ง ํ ์ ์๋๋ก ํ๋ ๊ธฐ๋ฅ์ ์ํํ๋ฉด์ @ResponseBody๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ ์๋ ์๋ค๋ ์๊ธฐ๋ค.
ViewResolver๋ฅผ ํตํด์ ์์ธ ์ฒ๋ฆฌ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ ์ํค๋ ค๋ฉด @ControllerAdvice๋ง ์จ๋ ๋๊ณ , API์๋ฒ์ฌ์ ์๋ฌ ์๋ต์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํด์ผํ๋ค๋ฉด @ResponseBody ์ด๋ ธํ ์ด์ ์ด ์ถ๊ฐ๋ @RestControllerAdvice๋ฅผ ์ ์ฉํ๋ฉด ๋๋ ๊ฒ์ด๋ค.
@RestController์์ ์์ธ๊ฐ ๋ฐ์ํ๋ @Controller์์ ์์ธ๊ฐ ๋ฐ์ํ๋ @ControllerAdvice + @ExceptionHandler ์กฐํฉ์ผ๋ก ๋ค ์บ์นํ ์ ์๊ณ @ResponseBody์ ํ์ ์ฌ๋ถ์ ๋ฐ๋ผ ์ ์ฉํ๋ฉด ๋๋ค๋ ๊ฒ์ด๋ค. (์ ๋ถ์ฐฐ๋ก ์๋ชป๋ ์ ๋ณด๋ฅผ ๊ณต์ ํ๋ ์ ์ ์์ ํ์์ต๋๋ค.)
๋ํ, ๋ง์ฝ์ ์ ์ญ์ ์์ธ๋ฅผ ์ก๊ธดํ๋ ํจํค์ง ๋จ์๋ก ์ ํํ ์๋์๋ค.
@RestControllerAdvice("com.example.demo.login.controller") login๋ชจ๋์ ์๋ RestController์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ก์ผ๋ ค๋ฉด ์์ ๊ฐ์ด ํ๋ฉด ๋๋ค. (ํจํค์ง ๊ตฌ์ฑ์ ์ํ๋ฉด ์ ์ฉํ๋ค)
์ถ์ฒ: https://jeong-pro.tistory.com/195 [๊ธฐ๋ณธ๊ธฐ๋ฅผ ์๋ ์ ์๋ง์ถ์ด ์ฝ๋ฉ๋ธ๋ก๊ทธ]
๋ฐ๋ผ์ HashMap์ ๋น๋กฏํ ๋ง์ ํด์ ํจ์๋ฅผ ์ด์ฉํ๋ associative array ๊ตฌํ์ฒด์์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ๊ธฐ ์ํ์ฌ ์ค์ ํด์ ํจ์์ ํํ ์ ์ ๋ฒ์ N ๋ณด๋ค ์์ M๊ฐ์ ์์๊ฐ ์๋ ๋ฐฐ์ด๋ง์ ์ฌ์ฉํ๋ค. ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ฒด์ ๋ํ ํด์ ์ฝ๋์ ๋๋จธ์ง ๊ฐ
์ ํด์ ๋ฒํท ์ธ๋ฑ์ค ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ค.
// ์์ 2 ํด์๋ฅผ ์ฌ์ฉํ๋ associative array ๊ตฌํ์ฒด์์ ์ ์ฅ/์กฐํํ ํด์ ๋ฒํท์ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ
int index = X.hashCode() % M;
์ด ์ฝ๋์ ๊ฐ์ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด, ์๋ก ๋ค๋ฅธ ํด์ ์ฝ๋๋ฅผ ๊ฐ์ง๋ ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ 1/M์ ํ๋ฅ ๋ก ๊ฐ์ ํด์ ๋ฒํท์ ์ฌ์ฉํ๊ฒ ๋๋ค. ์ด๋ ํด์ ํจ์๊ฐ ์ผ๋ง๋ ํด์ ์ถฉ๋์ ํํผํ๋๋ก ์ ๊ตฌํ๋์๋๋์ ์๊ด์์ด ๋ฐ์ํ ์ ์๋ ๋ ๋ค๋ฅธ ์ข
๋ฅ์ ํด์ ์ถฉ๋์ด๋ค. ์ด๋ ๊ฒ ํด์ ์ถฉ๋์ด ๋ฐ์ํ๋๋ผ๋ ํค-๊ฐ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ ์ฅํ๊ณ ์กฐํํ ์ ์๊ฒ ํ๋ ๋ฐฉ์์๋ ๋ํ์ ์ผ๋ก ๋ ๊ฐ์ง๊ฐ ์๋๋ฐ, ํ๋๋ Open Addressing
์ด๊ณ , ๋ค๋ฅธ ํ๋๋ Separate Chaining
์ด๋ค. ์ด ๋ ์ธ์๋ ํด์ ์ถฉ๋์ ํด๊ฒฐํ๊ธฐ ์ํ ๋ค์ํ ์๋ฃ ๊ตฌ์กฐ๊ฐ ์์ง๋ง, ๊ฑฐ์ ๋ชจ๋ ์ด ๋์ ์์ฉํ ๊ฒ์ด๋ผ๊ณ ํ ์ ์๋ค.
Open Addressing
์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๋ ค๋ ํด์ ๋ฒํท์ด ์ด๋ฏธ ์ฌ์ฉ ์ค์ธ ๊ฒฝ์ฐ ๋ค๋ฅธ ํด์ ๋ฒํท
์ ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๋ ๋ฐฉ์์ด๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ/์กฐํํ ํด์ ๋ฒํท์ ์ฐพ์ ๋์๋ Linear Probing, Quadratic Probing
๋ฑ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค.
Separate Chaining
์์ ๊ฐ ๋ฐฐ์ด์ ์ธ์๋ ์ธ๋ฑ์ค๊ฐ ๊ฐ์ ํด์ ๋ฒํท์ ์ฐ๊ฒฐํ ๋งํฌ๋ ๋ฆฌ์คํธ์ ์ฒซ ๋ถ๋ถ(head)์ด๋ค.
๋ ๋ชจ๋ Worst Case O(M)
์ด๋ค. ํ์ง๋ง Open Addressing์ ์ฐ์๋ ๊ณต๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ๋๋ฌธ์ Separate Chaining์ ๋นํ์ฌ ์บ์ ํจ์จ์ด ๋๋ค. ๋ฐ๋ผ์ ๋ฐ์ดํฐ ๊ฐ์๊ฐ ์ถฉ๋ถํ ์ ๋ค๋ฉด Open Addressing์ด Separate Chaining๋ณด๋ค ๋ ์ฑ๋ฅ์ด ์ข๋ค. ํ์ง๋ง ๋ฐฐ์ด์ ํฌ๊ธฐ๊ฐ ์ปค์ง์๋ก(M ๊ฐ์ด ์ปค์ง์๋ก) ์บ์ ํจ์จ์ด๋ผ๋ Open Addressing์ ์ฅ์ ์ ์ฌ๋ผ์ง๋ค. ๋ฐฐ์ด์ ํฌ๊ธฐ๊ฐ ์ปค์ง๋ฉด, L1, L2 ์บ์ ์ ์ค๋ฅ (hit ratio)์ด ๋ฎ์์ง๊ธฐ ๋๋ฌธ์ด๋ค.
Java HashMap
์์ ์ฌ์ฉํ๋ ๋ฐฉ์์ Separate Channing
์ด๋ค. Open Addressing์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋ ์ฒ๋ฆฌ๊ฐ ํจ์จ์ ์ด๊ธฐ ์ด๋ ค์ด๋ฐ, HashMap์์ remove() ๋ฉ์๋๋ ๋งค์ฐ ๋น๋ฒํ๊ฒ ํธ์ถ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ฒ๋ค๊ฐ HashMap์ ์ ์ฅ๋ ํค-๊ฐ ์ ๊ฐ์๊ฐ ์ผ์ ๊ฐ์ ์ด์์ผ๋ก ๋ง์์ง๋ฉด, ์ผ๋ฐ์ ์ผ๋ก Open Addressing์ Separate Chaining๋ณด๋ค ๋๋ฆฌ๋ค. Open Addressing์ ๊ฒฝ์ฐ ํด์ ๋ฒํท์ ์ฑ์ด ๋ฐ๋๊ฐ ๋์์ง์๋ก Worst Case ๋ฐ์ ๋น๋๊ฐ ๋ ๋์์ง๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ฉด Separate Chaining ๋ฐฉ์์ ๊ฒฝ์ฐ ํด์ ์ถฉ๋์ด ์ ๋ฐ์ํ์ง ์๋๋ก '์กฐ์ 'ํ ์ ์๋ค๋ฉด Worst Case ๋๋ Worst Case์ ๊ฐ๊น์ด ์ผ์ด ๋ฐ์ํ๋ ๊ฒ์ ์ค์ผ ์ ์๋ค(์ฌ๊ธฐ์ ๋ํด์๋ "๋ณด์กฐ ํด์ ํจ์"์์ ์ค๋ช
ํ๊ฒ ๋ค).
Java 2๋ถํฐ Java 7๊น์ง์ HashMap์์ Separate Chaining ๊ตฌํ ์ฝ๋๋ ์กฐ๊ธ์ฉ ๋ค๋ฅด์ง๋ง, ๊ตฌํ ์๊ณ ๋ฆฌ์ฆ ์์ฒด๋ ๊ฐ์๋ค. ๋ง์ฝ ๊ฐ์ฒด์ ํด์ ํจ์ ๊ฐ์ด ๊ท ๋ฑ ๋ถํฌ(uniform distribution) ์ํ๋ผ๊ณ ํ ๋, get() ๋ฉ์๋ ํธ์ถ์ ๋ํ ๊ธฐ๋๊ฐ์
์ด๋ค. ๊ทธ๋ฌ๋ Java 8์์๋ ์ด๋ณด๋ค ๋ ๋์
์ ๋ณด์ฅํ๋ค. ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ๋ง์์ง๋ฉด, Separate Chaining์์ ๋งํฌ๋ ๋ฆฌ์คํธ ๋์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ๋ง์์ง๋ฉด
๊ณผ
์ ์ฐจ์ด๋ ๋ฌด์ํ ์ ์๋ค. ๊ฒ๋ค๊ฐ ์ค์ ํด์ ๊ฐ์ ๊ท ๋ฑ ๋ถํฌ๊ฐ ์๋๋ฟ๋๋ฌ, ์ค์ฌ ๊ท ๋ฑ ๋ถํฌ๋ฅผ ๋ฐ๋ฅธ๋ค๊ณ ํ๋๋ผ๋ birthday problem์ด ์ค๋ช
ํ๋ฏ ์ผ๋ถ ํด์ ๋ฒํท ๋ช ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์ง์ค๋ ์ ์๋ค. ๊ทธ๋์ ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ์ผ์ ์ด์์ผ ๋์๋ ๋งํฌ๋ ๋ฆฌ์คํธ ๋์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉ
ํ๋ ๊ฒ์ด ์ฑ๋ฅ์ ์ด์ ์ด ์๋ค.
๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ๊ฐ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ๊ฐ์ ๋ํ ๊ธฐ์ค์ ํ๋์ ํด์ ๋ฒํท์ ํ ๋น๋ ํค-๊ฐ ์์ ๊ฐ์์ด๋ค. ์์ 5์์ ๋ณด๋ฏ Java 8 HashMap์์๋ ์์ ํํ๋ก ๊ธฐ์ค์ ์ ํ๊ณ ์๋ค. ์ฆ ํ๋์ ํด์ ๋ฒํท์ 8๊ฐ
์ ํค-๊ฐ ์์ด ๋ชจ์ด๋ฉด ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ํธ๋ฆฌ
๋ก ๋ณ๊ฒฝํ๋ค. ๋ง์ฝ ํด๋น ๋ฒํท์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์
ํ์ฌ ๊ฐ์๊ฐ 6๊ฐ
์ ์ด๋ฅด๋ฉด ๋ค์ ๋งํฌ๋ ๋ฆฌ์คํธ
๋ก ๋ณ๊ฒฝํ๋ค. ํธ๋ฆฌ๋ ๋งํฌ๋ ๋ฆฌ์คํธ๋ณด๋ค ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๋ง๊ณ , ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ์ ์ ๋ ํธ๋ฆฌ์ ๋งํฌ๋ ๋ฆฌ์คํธ์ Worst Case ์ํ ์๊ฐ ์ฐจ์ด ๋น๊ต๋ ์๋ฏธ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. 8๊ณผ 6์ผ๋ก 2 ์ด์์ ์ฐจ์ด๋ฅผ ๋ ๊ฒ์, ๋ง์ฝ ์ฐจ์ด๊ฐ 1์ด๋ผ๋ฉด ์ด๋ค ํ ํค-๊ฐ ์์ด ๋ฐ๋ณต๋์ด ์ฝ์
/์ญ์ ๋๋ ๊ฒฝ์ฐ ๋ถํ์ํ๊ฒ ํธ๋ฆฌ์ ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ๋ณ๊ฒฝํ๋ ์ผ์ด ๋ฐ๋ณต๋์ด ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Java 8 HashMap์์๋ Entry ํด๋์ค ๋์ Node
ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค. Node ํด๋์ค ์์ฒด๋ ์ฌ์ค์ Java 7์ Entry ํด๋์ค์ ๋ด์ฉ์ด ๊ฐ์ง๋ง, ๋งํฌ๋ ๋ฆฌ์คํธ ๋์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํ์ ํด๋์ค์ธ TreeNode
๊ฐ ์๋ค๋ ๊ฒ์ด Java 7 HashMap๊ณผ ๋ค๋ฅด๋ค.
์ด๋ ์ฌ์ฉํ๋ ํธ๋ฆฌ๋ Red-Black Tree
์ธ๋ฐ, Java Collections Framework์ TreeMap๊ณผ ๊ตฌํ์ด ๊ฑฐ์ ๊ฐ๋ค. ํธ๋ฆฌ ์ํ ์ ์ฌ์ฉํ๋ ๋์ ํ๋จ ๊ธฐ์ค
์ ํด์ ํจ์ ๊ฐ
์ด๋ค. ํด์ ๊ฐ์ ๋์ ํ๋จ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉํ๋ฉด Total Ordering์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋๋ฐ, Java 8 HashMap์์๋ ์ด๋ฅผ tieBreakOrder() ๋ฉ์๋๋ก ํด๊ฒฐํ๋ค.
ํด์ ๋ฒํท์ ๊ฐ์๊ฐ ์ ๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์๋ ์ ์์ง๋ง ํด์ ์ถฉ๋๋ก ์ธํด ์ฑ๋ฅ์ ์์ค์ด ๋ฐ์ํ๋ค. ๊ทธ๋์ HashMap์ ํค-๊ฐ ์ ๋ฐ์ดํฐ ๊ฐ์๊ฐ ์ผ์ ๊ฐ์ ์ด์์ด ๋๋ฉด, ํด์ ๋ฒํท์ ๊ฐ์๋ฅผ ๋ ๋ฐฐ๋ก ๋๋ฆฐ๋ค. ์ด๋ ๊ฒ ํด์ ๋ฒํท ๊ฐ์๋ฅผ ๋๋ฆฌ๋ฉด
๊ฐ๋ ์์์ ธ, ํด์ ์ถฉ๋๋ก ์ธํ ์ฑ๋ฅ ์์ค ๋ฌธ์ ๋ฅผ ์ด๋ ์ ๋ ํด๊ฒฐํ ์ ์๋ค.
ํด์ ๋ฒํท ๊ฐ์์ ๊ธฐ๋ณธ๊ฐ์ 16
์ด๊ณ , ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ์๊ณ์ ์ ์ด๋ฅผ ๋๋ง๋ค ํด์ ๋ฒํท ๊ฐ์์ ํฌ๊ธฐ๋ฅผ ๋ ๋ฐฐ์ฉ ์ฆ๊ฐ
์ํจ๋ค. ๋ฒํท์ ์ต๋ ๊ฐ์๋ 230
๊ฐ๋ค. ๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ๋ฒํท ๊ฐ์๊ฐ ๋ ๋ฐฐ๋ก ์ฆ๊ฐํ ๋๋ง๋ค, ๋ชจ๋ ํค-๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ์๋ก์ด Separate Chaining
์ ๊ตฌ์ฑํด์ผ ํ๋ ๋ฌธ์ ๊ฐ ์๋ค. HashMap ์์ฑ์์ ์ธ์๋ก ์ด๊ธฐ ํด์ ๋ฒํท ๊ฐ์
๋ฅผ ์ง์ ํ ์ ์์ผ๋ฏ๋ก, ํด๋น HashMap ๊ฐ์ฒด์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ ์ด๋ ์ ๋์ธ์ง ์์ธก ๊ฐ๋ฅํ ๊ฒฝ์ฐ์๋ ์ด๋ฅผ ์์ฑ์์ ์ธ์๋ก ์ง์ ํ๋ฉด ๋ถํ์ํ๊ฒ Separate Chaining์ ์ฌ๊ตฌ์ฑํ์ง ์๊ฒ ํ ์ ์๋ค.
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ํด์ ๋ฒํท ํฌ๊ธฐ๋ฅผ ๋ ๋ฐฐ๋ก ํ์ฅํ๋ ๊ฒ์๋ ๊ฒฐ์ ์ ์ธ ๋ฌธ์ ๊ฐ ์๋ค. ํด์ ๋ฒํท์ ๊ฐ์ M์ด 2a
ํํ๊ฐ ๋๊ธฐ ๋๋ฌธ์, index = X.hashCode() % M
์ ๊ณ์ฐํ ๋ X.hashCode()์ ํ์ a๊ฐ์ ๋นํธ๋ง ์ฌ์ฉํ๊ฒ ๋๋ค๋ ๊ฒ์ด๋ค. ์ฆ ํด์ ํจ์๊ฐ 32๋นํธ ์์ญ์ ๊ณ ๋ฅด๊ฒ ์ฌ์ฉํ๋๋ก ๋ง๋ค์๋ค ํ๋๋ผ๋ ํด์ ๊ฐ์ 2์ ์น์๋ก ๋๋๋ฉด ํด์ ์ถฉ๋์ด ์ฝ๊ฒ ๋ฐ์ํ ์ ์๋ค.
์ด ๋๋ฌธ์ ๋ณด์กฐ ํด์ ํจ์๊ฐ ํ์ํ๋ค.
index = X.hashCode() % M
์ ๊ณ์ฐํ ๋ ์ฌ์ฉํ๋ M ๊ฐ์ ์์์ผ ๋
index ๊ฐ ๋ถํฌ๊ฐ ๊ฐ์ฅ ๊ท ๋ฑํ ์ ์๋ค. ๊ทธ๋ฌ๋ M ๊ฐ์ด ์์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ด์ฉํ์ฌ index ๊ฐ ๋ถํฌ๊ฐ ๊ฐ๊ธ์ ๊ท ๋ฑํ ์ ์๋๋ก ํด์ผ ํ๋ค.
๋ณด์กฐ ํด์ ํจ์(supplement hash function)์ ๋ชฉ์ ์ 'ํค'์ ํด์ ๊ฐ์ ๋ณํ
ํ์ฌ, ํด์ ์ถฉ๋ ๊ฐ๋ฅ์ฑ์ ์ค์ด๋ ๊ฒ์ด๋ค. ์ด ๋ณด์กฐ ํด์ ํจ์๋ JDK 1.4์ ์ฒ์ ๋ฑ์ฅํ๋ค. Java 5 ~ Java 7์ ๊ฐ์ ๋ฐฉ์์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๊ณ , Java 8๋ถํฐ๋ ๋ค์ ์๋ก์ด ๋ฐฉ์์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค.
final int hash(Object k) {
// Java 7๋ถํฐ๋ JRE๋ฅผ ์คํํ ๋, ๋ฐ์ดํฐ ๊ฐ์๊ฐ ์ผ์ ์ด์์ด๋ฉด
// String ๊ฐ์ฒด์ ๋ํด์ JVM์์ ์ ๊ณตํ๋ ๋ณ๋์ ์ต์
์ผ๋ก
// ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๋๋ก ํ ์ ์๋ค.
// ๋ง์ฝ ์ด ์ต์
์ ์ฌ์ฉํ์ง ์์ผ๋ฉด hashSeed์ ๊ฐ์ 0์ด๋ค.
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
// ํด์ ๋ฒํท์ ๊ฐ์๊ฐ 2a์ด๊ธฐ ๋๋ฌธ์ ํด์ ๊ฐ์ a๋นํธ ๊ฐ๋ง์
// ํด์ ๋ฒํท์ ์ธ๋ฑ์ค๋ก ์ฌ์ฉํ๋ค. ๋ฐ๋ผ์ ์์ ๋นํธ์ ๊ฐ์ด
// ํด์ ๋ฒํท์ ์ธ๋ฑ์ค ๊ฐ์ ๊ฒฐ์ ํ ๋ ๋ฐ์๋ ์ ์๋๋ก
// shift ์ฐ์ฐ๊ณผ XOR ์ฐ์ฐ์ ์ฌ์ฉํ์ฌ, ์๋์ ํด์ ๊ฐ์ด a๋นํธ ๋ด์์
// ์ต๋ํ ๊ฐ์ด ๊ฒน์น์ง ์๊ณ ๊ตฌ๋ณ๋๊ฒ ํ๋ค.
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
๊ทธ๋ฐ๋ฐ Java 8์์๋ Java 7๋ณด๋ค ํจ์ฌ ๋ ๋จ์ํ ํํ์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Java 8 HashMap ๋ณด์กฐ ํด์ ํจ์๋ ์์ 16๋นํธ ๊ฐ์ XOR ์ฐ์ฐ
ํ๋ ๋งค์ฐ ๋จ์ํ ํํ์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๋ค. ์ด์ ๋ก๋ ๋ ๊ฐ์ง๊ฐ ์๋๋ฐ, ์ฒซ ๋ฒ์งธ๋ Java 8์์๋ ํด์ ์ถฉ๋์ด ๋ง์ด ๋ฐ์ํ๋ฉด ๋งํฌ๋ ๋ฆฌ์คํธ ๋์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉ
ํ๋ฏ๋ก ํด์ ์ถฉ๋ ์ ๋ฐ์ํ ์ ์๋ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์ํ๋์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ ๋ฒ์งธ๋ก๋ ์ต๊ทผ์ ํด์ ํจ์๋ ๊ท ๋ฑ ๋ถํฌ๊ฐ ์ ๋๊ฒ ๋ง๋ค์ด์ง๋ ๊ฒฝํฅ์ด ๋ง์, Java 7๊น์ง ์ฌ์ฉํ๋ ๋ณด์กฐ ํด์ ํจ์์ ํจ๊ณผ๊ฐ ํฌ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ ๋ฒ์งธ ์ด์ ๊ฐ ์ข ๋ ๊ฒฐ์ ์ ์ธ ์์ธ์ด ๋์ด Java 8์์๋ ๋ณด์กฐ ํด์ ํจ์์ ๊ตฌํ์ ๋ฐ๊พธ์๋ค.
String ๊ฐ์ฒด์ ๋ํ ํด์ ํจ์ ์ํ ์๊ฐ์ ๋ฌธ์์ด ๊ธธ์ด์ ๋น๋กํ๋ค.
๋๋ฌธ์ JDK 1.1์์๋ String ๊ฐ์ฒด์ ๋ํด์ ๋น ๋ฅด๊ฒ ํด์ ํจ์๋ฅผ ์ํํ๊ธฐ ์ํด, ์ผ์ ๊ฐ๊ฒฉ์ ๋ฌธ์์ ๋ํ ํด์๋ฅผ ๋์ ํ ๊ฐ์ ๋ฌธ์์ด์ ๋ํ ํด์ ํจ์๋ก ์ฌ์ฉํ๋ค.
public int hashCode() {
int hash = 0;
int skip = Math.max(1, length() / 8);
for (int i = 0; i < length(): i+= skip)
hash = s[i] + (37 * hash);
return hash;
}
์์ 10์์ ๋ณผ ์ ์๋ฏ์ด ๋ชจ๋ ๋ฌธ์์ ๋ํ ํด์ ํจ์๋ฅผ ๊ณ์ฐํ๋ ๊ฒ ์๋๋ผ, ๋ฌธ์์ด์ ๊ธธ์ด๊ฐ 16์ ๋์ผ๋ฉด ์ต์ ํ๋์ ๋ฌธ์๋ฅผ ๊ฑด๋๊ฐ๋ฉฐ
(skip) ํด์ ํจ์๋ฅผ ๊ณ์ฐํ๋ค.
๊ทธ๋ฌ๋ ์ด๋ฐ ๋ฐฉ์์ ์ฌ๊ฐํ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํ๋ค. ์น์์ URL์ ๊ธธ์ด๊ฐ ์์ญ ๊ธ์์ ์ด๋ฅด๋ฉด์ ์ ๋ถ๋ถ์ ๋์ผํ๊ฒ ๊ตฌ์ฑ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค. ์ด ๊ฒฝ์ฐ ์๋ก ๋ค๋ฅธ URL์ ํด์ ๊ฐ์ด ๊ฐ์์ง๋ ๋น๋๊ฐ ๋งค์ฐ ๋์์ง ์ ์๋ค๋ ๋ฌธ์ ๊ฐ ์๋ค. (์๋ถ๋ถ์ ๋์ผํ๋ ๋ท๋ถ๋ถ ๋ฌธ์๊ฐ ๋ค๋ฅธ๊ฒฝ์ฐ) ๋ฐ๋ผ์ ์ด๋ฐ ๋ฐฉ์์ ๊ณง ํ๊ธฐ๋์๊ณ , ์์ 11์์ ๋ณด๋ ๋ฐฉ์์ ํ์ฌ์ Java 8๊น์ง๋ ๊ณ์ ์ฌ์ฉํ๊ณ ์๋ค.
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
String ๊ฐ์ฒด ํด์ ํจ์์์ 31
์ ์ฌ์ฉํ๋ ์ด์ ๋, 31์ด ์์
์ด๋ฉฐ ๋ํ ์ด๋ค ์์ 31์ ๊ณฑํ๋ ๊ฒ์ ๋น ๋ฅด๊ฒ ๊ณ์ฐ
ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. 31N=32N-N์ธ๋ฐ, 32๋ 25์ด๋ ์ด๋ค ์์ ๋ํ 32๋ฅผ ๊ณฑํ ๊ฐ์ shift ์ฐ์ฐ์ผ๋ก ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค. ๋ฐ๋ผ์ N์ 31์ ๊ณฑํ ๊ฐ์, (N << 5) โ N๊ณผ ๊ฐ๋ค. 31์ ๊ณฑํ๋ ์ฐ์ฐ์ ์ด๋ ๊ฒ ์ต์ ํ๋ ๋จธ์ ์ฝ๋๋ก ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์, String ํด๋์ค์์ ํด์ ๊ฐ์ ๊ณ์ฐํ ๋์๋ 31์ ์น์๋ก ์ฌ์ฉํ๋ค.
๋ฉํฐ์ฐ๋ ๋ ํ๋ก์ธ์ค์ ๊ฒฝ์ฐ ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๊ฐ์ ํ๋ก์ธ์ค ๋ด์ ์์์ ๊ณต์ ํด์ ์์ ํ๊ธฐ ๋๋ฌธ์ ์๋ก์ ์์ ์ ์ํฅ์ ์ฃผ๊ฒ ๋๋ค. (Heap, Method ์์ญ, Runtime Constant Pool ์์ญ์ ์ค๋ ๋๊ฐ ๊ณต์ ๊ฐ๋ฅํ ์์ญ)
๋ง์ฝ Thread1์ด ์์ ํ๋ ๋์ค ๋ค๋ฅธ Thread2์๊ฒ ์ ์ด๊ถ์ด ๋์ด๊ฐ์ ๋, Thread1์ด ์์ ํ๋ ๊ณต์ ๋ฐ์ดํฐ๋ฅผ Thread2๊ฐ ์์๋ก ๋ณ๊ฒฝํ๋ค๋ฉด, ๋ค์ Thread1์ด ์ ์ด๊ถ์ ๋๊ฒจ๋ฐ์ ๋๋จธ์ง ์์ ์ ๋ง์ณค์ ๋ ์๋ ์๋ํ๋ ๊ฒฐ๊ณผ์ ๋ค๋ฅด๊ฒ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์ ์๋ค.
์ด๋ฌํ ์ผ์ ๋ฐฉ์งํ๊ธฐ ์ํด ํ ์ฐ๋ ๋๊ฐ ํน์ ์์ ์ ๋๋ง์น๊ธฐ ์ ๊น์ง ๋ค๋ฅธ ์ฐ๋ ๋์ ์ํด ๋ฐฉํด๋ฐ์ง ์๋๋ก ํ๋ ๊ฒ์ด ํ์ํ๋ค.
- ์๊ณ ์์ญ : ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋ ์์ญ์ ์ง์
- ๋ฝ : ๊ณต์ ๋ฐ์ดํฐ๊ฐ ๊ฐ์ง๊ณ ์๋ lock์ ํ๋ํ ๋จ ํ๋์ ์ฐ๋ ๋๋ง ์ด ์์ญ ๋ด์ ์ฝ๋ ์ํ ๊ฐ๋ฅ.
๊ณต์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋ ์์ญ์ ์๊ณ ์์ญ
์ผ๋ก ์ง์ ํด๋๊ณ , ๊ณต์ ๋ฐ์ดํฐ๊ฐ ๊ฐ์ง๊ณ ์๋ lock
์ ํ๋ํ ์ฐ๋ ๋๋ ์๊ณ ์์ญ ๋ด์ ๋ชจ๋ ์ฝ๋๋ฅผ ์ํํ๊ณ ๋ฒ์ด๋์ loc
k์ ๋ฐ๋ฉํด์ผ๋ง ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๋ฐ๋ฉ๋ lock
์ ํ๋ํ์ฌ ์๊ณ์์ญ์ ์ฝ๋๋ฅผ ์ํํ ์ ์๊ฒ ํ ์ ์๋ค.
์ด์ฒ๋ผ ํ ์ฐ๋ ๋๊ฐ ์งํ ์ค์ธ ์์ ์ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๊ฐ์ญํ์ง ๋ชปํ๊ฒ ๋ง๋ ๊ฒ์ ๋๊ธฐํ๋ผ๊ณ ํ๋ค.
์ค๋ ๋๋ฅผ ๋๊ธฐํํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋๋ฐ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ synchronized
๋ฅผ ์ด์ฉํด์ ์๊ณ์์ญ์ ์ค์ ํ๋ ๊ฒ์ด๋ค.
๊ฐ์ฅ ๊ฐ๋จํ ๋๊ธฐํ ๋ฐฉ๋ฒ์ด๋ฉฐ, ์ด ํค์๋๋ ์๊ณ ์์ญ์ ์ค์ ํ๋๋ฐ ์ฌ์ฉ๋๋ค. ๋ฉ์๋ ์ ์ฒด๋ฅผ ์๊ณ ์์ญ์ผ๋ก ์ค์ ํ๊ฑฐ๋, ํน์ ์์ญ์ ์๊ณ ์์ญ์ผ๋ก ์ง์ ํ ์ ์๋ค.
public synchronized void calcSum() {
...
}
synchronized(๊ฐ์ฒด์ ์ฐธ์กฐ๋ณ์) {
...
}
- ๋๋ฒ์งธ ๋ฐฉ๋ฒ์ ๋ฉ์๋ ๋ด์ ์ฝ๋ ์ผ๋ถ๋ฅผ ๋ธ๋ญ์ผ๋ก ๊ฐ์ธ๊ณ ๋ธ๋ญ ์์
synchronized(์ฐธ์กฐ๋ณ์)
๋ฅผ ๋ถ์ด๋ ๊ฒ์ด๋ค. ์ด๋ ์ฐธ์กฐ๋ณ์๋ ๋ฝ์ ๊ฑธ๊ณ ์ ํ๋ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์ด์ด์ผ ํ๋ค. - ์ด ๋ธ๋ญ์
synchronized ๋ธ๋ญ
์ด๋ผ๊ณ ๋ถ๋ฅด๋ฉฐ, ์ด ๋ธ๋ญ์ ์์ญ ์์ผ๋ก ๋ค์ด๊ฐ๋ฉด์๋ถํฐ ์ฐ๋ ๋๋ ์ง์ ๋ ๊ฐ์ฒด์ lock์ ์ป๊ฒ ๋๊ณ , ์ด ๋ธ๋ญ์ ๋ฒ์ด๋๋ฉด lock์ ๋ฐ๋ฉํ๋ค. - ๋ ๋ฐฉ๋ฒ ๋ชจ๋ lock์ ํ๋๋ ๋ฐ๋ฉ์ด ์๋์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋ฏ๋ก ์๊ณ ์์ญ๋ง ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
- ๋ชจ๋ ๊ฐ์ฒด๋
lock
์ ํ๋์ฉ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ํด๋น ๊ฐ์ฒด์ lock์ ๊ฐ์ง๊ณ ์๋ ์ฐ๋ ๋๋ง ์๊ณ ์์ญ์ ์ฝ๋๋ฅผ ์ํํ ์ ์๋ค.
-
๋ณ์์ ๊ฐ์์ฑ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ๋ค. ๋ณ์์ ๊ฐ์ CPU ๋ฉ๋ชจ๋ฆฌ์ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋๋ค.
์ด ๊ฐ์
CPU ๋ฉ๋ชจ๋ฆฌ
์ธ์ง๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ
์์ ๊ฐ์ ธ์ค๋ ์ง ์ ์๊ฐ ์๋ค๋ ๋ฌธ์ ๊ฐ ๋ณ์์ ๊ฐ์์ฑ ๋ฌธ์ ์ด๋ค. ์ด๋ ๊ฒ CPU ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ ์ฝ์ด๋ค์ธ๋ค๋ฉด ๋งค์ฐ ์์ ํ์ง ๋ชปํ๋ค.
private volatile int counter; public int getNextUniqueIndex() { return counter++; }
์ถ์ฒ: https://mygumi.tistory.com/112 [๋ง์ด๊ตฌ๋ฏธ์ HelloWorld]
-
volatile
ํค์๋๋ฅผ ๋ณ์ ์์ ์ ์ธํ์ฌ ์ฌ์ฉํ ์ ์๋ค. ์ด๋ก์จ ๊ฐ์์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค. volatile์ ์ฌ์ฉํ๋ฉด counter ๋ณ์๋ฅผ ์ฝ๊ณ ์ฐ๋ ๊ณผ์ ์ ๋ชจ๋ ์ฝ๊ธฐ ์ฐ๊ธฐ ์ฐ์ฐ์๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ
์์๋ง ์ฒ๋ฆฌ๋๋ค. ๋ฐ๋ผ์ ๊ฐ์์ฑ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ค. - ๊ฒฝ์ ์ํ(race condition) - ์ฌ๋ฌ ์ค๋ ๋ ๊ฐ์ ์์ ๋ณ์๋ฅผ ์ฝ๋ ์ํ. - ์ด๋ ํด๊ฒฐ์ด ์๋จ!
- ์ฆ, volatile์ ๊ฒฝ์ฐ๋ ํ๋์ ์ค๋ ๋๊ฐ
์ฐ๊ธฐ ์ฐ์ฐ
์ ํ๊ณ , ๋ค๋ฅธ ์ค๋ ๋์์๋์ฝ๊ธฐ ์ฐ์ฐ
์ ํตํด ์ต์ ๊ฐ์ ๊ฐ์ ธ์ฌ ๊ฒฝ์ฐ. ์ฆ ๋ค๋ฅธ ์ค๋ ๋์์๋ ์ ๋ฐ์ดํธ๋ฅผ ํํ์ง ์์ ๊ฒฝ์ฐ ์ด์ฉํ ์ ์๋ค.
AtomicInteger ํด๋์ค๋ CAS(compare-and-swap)
๊ธฐ๋ฐ์ผ๋ก ๋์ด์๋ค.
CAS
๋ ํน์ ๋ฉ๋ชจ๋ฆฌ ์์น์ ๊ฐ์ด ์ฃผ์ด์ง ๊ฐ์ ๋น๊ตํ์ฌ ๊ฐ์ผ๋ฉด ์๋ก์ด ๊ฐ์ผ๋ก ๋์ฒด๋๋ค.
CAS๋ฅผ c์ธ์ด์ ์ฝ๋๋ก ๋ณด๋ฉด ์ฝ๊ฒ ์ดํด๊ฐ ๊ฐ ๊ฒ์ด๋ค.
Atomic ํด๋์ค
์ ๊ฒฝ์ฐ๋ ์ฌ๋ฌ ์ค๋ ๋์์ ์ฝ๊ธฐ ์ฐ๊ธฐ ๋ชจ๋ ์ด์ฉํ ์ ์๋ค. (CAS)
int compare_and_swap(int* reg, int oldval, int newval)
{
int old_reg_val = *reg;
if (old_reg_val == oldval)
*reg = newval;
return old_reg_val;
}
์ถ์ฒ: https://mygumi.tistory.com/112 [๋ง์ด๊ตฌ๋ฏธ์ HelloWorld]
- JAVA Collection Framework
JAVA์์ ๊ธฐ๋ณธ์ ์ธ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํ ํ๊ฒฝ
JAVA Collection Framework์ ์์ ๊ธฐ๋ณธ ๊ตฌ์กฐ 2. ๊ฐ ์ธํฐํ์ด์ค์ ํน์ง
์ธํฐํ์ด์ค ๊ตฌํ ํด๋์ค ํน์ง List LinkedList
Stack
Vector
ArrayList
์์๊ฐ ์๋ ๋ฐ์ดํฐ์ ์งํฉ, ๋ฐ์ดํฐ์ ์ค๋ณต์ ํ์ฉํจ Set HashSet
TreeSet
์์๋ฅผ ์ ์งํ์ง ์๋ ๋ฐ์ดํฐ์ ์งํฉ, ๋ฐ์ดํฐ์ ์ค๋ณต์ ํ์ฉํ์ง ์์ Map HashMap
TreeMap
HashTable
Properties
ํค(key)์ ๊ฐ(value)์ ์์ผ๋ก ์ด๋ฃจ์ด์ง ๋ฐ์ดํฐ์ ์งํฉ
์์๋ ์ ์ง๋์ง ์๊ณ , ํค๋ ์ค๋ณต์ ํ์ฉํ์ง ์์ผ๋ฉฐ ๊ฐ์ ์ค๋ณต์ ํ์ฉํจ
- Collection ์ธํฐํ์ด์ค๋ค์ ํน์ง
Collection ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ์ List์ Set ์ธํฐํ์ด์ค๊ฐ ๋๋ค. ๊ฐ. List ์ธํฐํ์ด์ค์ ํน์ง
์์๊ฐ ์๋ Collection(์ฌ๊ธฐ์ ์์๋ ์ฝ์ ๋ ์์๋ฅผ ์๋ฏธํ๋ค.) Data๋ฅผ ์ค๋ณตํด์ ํฌํจ ํ ์ ์๋ค. (1). LinkedList์ ํน์ง
LinkedList๋ง ์ ์ํ ๋ด์ฉ์ด ์์ผ๋ ์๋ ์ฃผ์ ์ฐธ๊ณ https://hwan1001.tistory.com/5
[JAVA] ์๋ฃ๊ตฌ์กฐ ํด๋์ค - LinkedList(์ฐ๊ฒฐ๋ฆฌ์คํธ)
- LinkedList(์ฐ๊ฒฐ๋ฆฌ์คํธ) - LinkedList๋ ๊ฐ ๋ ธ๋๊ฐ ๋ฐ์ดํฐ์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ํ ์ค๋ก ์ฐ๊ฒฐ๋์ด ์๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค. - ์ด๋ฆ์์ ๋งํ๋ฏ์ด ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์๋ ๋ ธ๋๋ค์ด ์ฐ๊ฒฐ๋์ด ์..
hwan1001.tistory.com (2). Stack์ ํน์ง
Data์ ์ฝ์ ๊ณผ ์ถ์ถ์ด ํ์ ์ ์ถ(LIFO) ๊ตฌ์กฐ๋ก ๋์ด ์๋ค. push() method : Data ์ฝ์ ํ ๋ ์ฌ์ฉ pop() method : Data ์ถ์ถ ํ ๋ ์ฌ์ฉ peek() method : ์ถ์ถํ Data๋ฅผ ์ญ์ ํ๋ ์๊ณ Data๋ง์ ๊ฐ์ ธ์ฌ ๋ ์ฌ์ฉ search() method : Stack์ผ๋ก๋ถํฐ Data๋ฅผ ๊ฒ์ํ ๋ ์ฌ์ฉ (3). Vector์ ํน์ง
์๋์ผ๋ก ๋๊ธฐํ๋ฅผ ๋ณด์ฅํด ์ค๋ค. ArrayList์ ๋๊ธฐํ๊ฐ ๋ณด์ฅ๋๋๋ก ์ต์ ํํ ํด๋์ค์ด๋ค. addElement() method : Data๋ฅผ ์ฝ์ ํ ๋ ์ฌ์ฉ elementAt() method : Data๋ฅผ ์ถ์ถํ ๋ ์ฌ์ฉ, Index์ ํด๋นํ๋ ๊ฐ์ฒด๋ฅผ ์ป์ด๋ size() method : Vector ๋ด์ ์กด์ฌํ๋ ๊ฐ์ฒด์ ์๋ฅผ ์ป์ด๋ผ ๋ ์ฌ์ฉ insertElementAt() method : Vector ๋ด์ ์ค๊ฐ ์ฝ์ ํ ๋ ์ฌ์ฉ setElementAt() method : Vector ๋ด์ ์กด์ฌํ๋ Data๋ฅผ ์์ ํ ๋ ์ฌ์ฉ indexOf() method : Vector ๋ด์ Data๋ฅผ ๊ฒ์ํ ๋ ์ฌ์ฉ, Index๋ฅผ ๋ฐํ contains() method : Data์ ์กด์ฌ ์ ๋ฌด๋ฅผ ์๊ธฐ ์ํด ์ฌ์ฉ. (4). ArrayList์ ํน์ง
๋๊ธฐํ๋ฅผ ๋ณด์ฅํด์ฃผ์ง ์๋๋ค. ๋ฐฐ์ด์ ๋์ ๋ฉ๋ชจ๋ฆฌ ์ฆ๊ฐ ๊ธฐ๋ฅ์ ๊ตฌํํ ํด๋์ค์ด๋ค. ๋๊ธฐํ ์ง์ ๋ฐฉ๋ฒ : List list = Collections.synchronizeList(new ArrayList(โฆ)); add() method : Data ์ฝ์ ํ ๋ ์ฌ์ฉ get() method : Data ์ถ์ถํ ๋ ์ฌ์ฉ toArray() method : ArrayList๋ก๋ถํฐ ๋ฐฐ์ด์ ์ป์ด๋ผ ๋ ์ฌ์ฉ contains() method : Data์ ์กด์ฌ ์ ๋ฌด๋ฅผ ์๊ธฐ ์ํด ์ฌ์ฉ size() method : ArrayList์ ์์ ๊ฐ์๋ฅผ ์ป์ด๋ผ ๋ ์ฌ์ฉ ๋. Set ์ธํฐํ์ด์ค์ ํน์ง
์งํฉ์ ์ธ ๊ฐ๋ ์ Collection ์์์ ์๋ฏธ๊ฐ ์๋ค. Data๋ฅผ ์ค๋ณตํด์ ํฌํจ ํ ์ ์๋ค. (1). HashSet์ ํน์ง
add() method : Data ์ฝ์ ํ ๋ ์ฌ์ฉ next() method : Data ์ถ์ถํ ๋ ์ฌ์ฉ(HashSet์ Data ์ถ์ถ์ Iterator์ ์ด์ฉํ๋ฉด ๋จ) remove() method : Data๋ฅผ ์ญ์ ํ ๋ ์ฌ์ฉ contains() method : Data์ ํฌํจ์ฌ๋ถ๋ฅผ ์๊ธฐ ์ํด ์ฌ์ฉ size() method : HashSet์ ์์ ๊ฐ์๋ฅผ ์ป์ด๋ผ ๋ ์ฌ์ฉ 4. Map ์ธํฐํ์ด์ค๋ค์ ํน์ง
List์ Set์ด ์์๋ ์งํฉ์ ์ธ ๊ฐ๋ ์ ์ธํฐํ์ด์ค๋ผ๋ฉด Map์ ๊ฒ์์ ๊ฐ๋ ์ด ๊ฐ๋ฏธ๋ ์ธํฐํ์ด์ค๋ค. Map์ธํฐํ์ด์ค๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ ๋ Key์ Value์ ํํ๋ก ์ฝ์ ๋๋ฉฐ, Key๋ฅผ ์ด์ฉํด์ Value๋ฅผ ์ป์ ์ ์๋ค. ๊ฐ. Hashtable, HashMap์ ๊ณตํต์
๋ด๋ถ์ ์ผ๋ก๋ ๋ชจ๋ Hash ๊ธฐ๋ฒ์ ์ด์ฉํ๋ค. Map ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ค. Key์ Value๋ฅผ ์ด์ฉํด์ Data๋ฅผ ๊ด๋ฆฌํ๋ค. ๋. Hashtable, HashMap์ ์ฐจ์ด์
Hashtable์ ๋๊ธฐํ๊ฐ ๋ณด์ฅ๋๋ค. HashMap์ ๋๊ธฐํ๊ฐ ๋ณด์ฅ๋์ง ์๋๋ค. HashMap์ ๋๊ธฐํ ์ง์ ๋ฐฉ๋ฒ : Map m = Collections.synchronizedMap(New HashMap(โฆ)); ๋ค. Hashtable, HashMap๊ณผ HashSet๊ณผ์ ๊ด๊ณ
HashTable๊ณผ HashMap์ ๋ ๋ค Map ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ค. HashSet์ ๋ด๋ถ์ ์ผ๋ก Hash๊ธฐ๋ฒ์ ์ฌ์ฉํ์ง๋ง Set์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ค ๋ผ. HashMap
๊ฐ์ฒด ์์ฑ : Map<String, Integer> map = new HashMap<String, Integer>(); put() method : Data ์ฝ์ ํ ๋ ์ฌ์ฉ get() method : Data๋ฅผ ์ถ์ถํ ๋ ์ฌ์ฉ, argument๊ฐ์ Key๋ฅผ ์ฌ์ฉ ๋ง. HashTable
๊ฐ์ฒด ์์ฑ : Hashtable<String, Object> h = new Hashtable<String, Object>(); put() method : Data ์ฝ์ ํ ๋ ์ฌ์ฉ get() method : Data๋ฅผ ์ถ์ถํ ๋ ์ฌ์ฉ, argument๊ฐ์ Key๋ฅผ ์ฌ์ฉ
- Sorted ์ธํฐํ์ด์ค๋ค์ ํน์ง
Set๊ณผ Map ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ์ ์ ๋ ฌ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋ SortedSet๊ณผ SortedMap ์ธํฐํ์ด์ค๊ฐ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ค์ ๊ฐ๊ฐ TreeSet ํด๋์ค์ TreeMap ํด๋์ค๋ก ๊ตฌ์ฑ๋๋ค. TreeSet๊ณผ TreeMap์ Set๊ณผ Map์ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ผ๋ฉด์ ์ ๋ ฌ ๊ธฐ๋ฅ์ด ๊ฐ๋ฏธ๋์๋ค๋ ๊ฒ์ด ํน์ง์ด๋ค. ๊ฐ. Sorted๋ฅผ ์ง์ํ์ง ์๋ ํด๋์ค
HashSet, HashMap ๋. Sorted๋ฅผ ์ง์ํ๋ ํด๋์ค
TreeSet, TreeMap ๋ค. TreeMap
Key์ Value๋ก Data๋ฅผ ๊ด๋ฆฌ Key๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ๋๋ค. Map ์ธํฐํ์ด์ค๋ฅผ ์์ํ SortedMap ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค ๋ผ. TreeSet
Set ์ธํฐํ์ด์ค๋ฅผ ์์ํ SortedSet ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค ๋ฐ์ดํฐ๋ค์ด ์๋์ผ๋ก ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ๋๋ค. ๋ง. Comparator
TreeSet๊ณผ TreeMap์ ์ฌ์ฉ์๊ฐ ์ง์ ์ ๋ ฌ์ ๋ฐฉ์์ ์ง์ ํ ์ ์๋ค. TreeSet๊ณผ TreeMap์ ์ ๋ ฌ์ ์ํ Comparator ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ฉด ๋๋ค. TreeSet์ Data๋ฅผ ์ง์ด ๋ฃ์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋ฆ์ฐจ์(Ascending) ์ ๋ ฌ์ด ๋์ง๋ง ๊ทธ๊ฒ๋ ๋ฌธ์์ด์ด๋ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์ ๊ณผ ๊ฐ์ ๋จ์ํ ๊ฒ์๋ง ํด๋น๋๋ค. ์ด์ ์ฌ์ฉ์๊ฐ ์ง์ ๋น๊ต๋ฒ์ ๋ฃ์ด์ฃผ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ฒ์ด Comparator ์ธํฐํ์ด์ค์ด๋ค.
์์)
SQL 1๋ฒ
์ผ๋ก 100๋ช
์ ํ์์ ์กฐํํ์๋๋ฐ,
๊ฐ ํ์๋ง๋ค ์ฃผ๋ฌธํ ์ํ์ ์ถ๊ฐ๋ก ์กฐํํ๊ธฐ ์ํด 100๋ฒ
์ SQL์ ์ถ๊ฐ๋ก ์คํํ๋ ์ํฉ์ ๋งํ๋ค.
ํ๋ฒ SQL์ ์คํํด์ ์กฐํ๋ ๊ฒฐ๊ณผ ์๋งํผ N๋ฒ SQL์ ์ถ๊ฐ๋ก ์คํํ๋ค๊ณ ํด์ N+1
๋ฌธ์ ๋ผ ํ๋ค.
N+1
๋ฌธ์ ๋ ์ํฐํฐ ๊ธ๋ก๋ฒ ํ์น์ ๋ต์ ์ฆ์ ๋ก๋ฉ
์ ์ฌ์ฉํ ๋ ๋ฐ์ํ ์ ์๋ค.
JPA๋ฅผ ์ฌ์ฉํ๋ฉด์ ์ฑ๋ฅ์ ๊ฐ์ฅ ์กฐ์ฌํด์ผ ํ๋ ๋ฌธ์ ๊ฐ ๋ฐ๋ก N+1
๋ฌธ์ ์ด๋ค.
em.find()
๋ฉ์๋๋ก ์ํฐํฐ๋ฅผ ์กฐํํ ๋ ์ฐ๊ด๋ ์ํฐํฐ๋ฅผ ๋ก๋ฉํ๋ ์ ๋ต์ด ์ฆ์ ๋ก๋ฉ์ด๋ฉด
๋ฐ์ดํฐ๋ฒ ์ด์ค์ JOIN ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ ํ ๋ฒ์ ์ฐ๊ด๋ ์ํฐํฐ๊น์ง ์กฐํํ๋ค.
Order order = em.find(Order.class, 1L);
// ์ฆ์๋ก๋ฉ์ผ๋ก ์ ์ํฐํฐ๋ฅผ ์ค์ ํ๋ฉด ์คํ๋ SQL์ ๋ค์๊ณผ ๊ฐ๋ค.
/*
select o.*, m.*
from Order o
left outer join Member m on o.MEMBER_ID=m.MEMBER_ID
where o.id=1
*/
์คํ๋ SQL์ ๋ณด๋ฉด ์ฆ์ ๋ก๋ฉ์ผ๋ก ์ค์ ํ member ์ํฐํฐ๋ฅผ JOIN ์ฟผ๋ฆฌ๋ก ํจ๊ป ์กฐํํ๋ค.
์ด ๋ ๋ฌธ์ ๋ JPQL์ ์ฌ์ฉํ ๋ ๋ฐ์ํ๋ค. ์์ ๊ฐ์ ์ํฉ์์ JPQL๋ก ์กฐํํด๋ณด์.
List<Order> orders = em.createQuery("select o from Order o", Order.class).getResultList();
// ์ฐ๊ด๋ ๋ชจ๋ ์ํฐํฐ๋ฅผ ์กฐํํ๋ค.
JPA๊ฐ JPQL์ ๋ถ์ํด์ SQL์ ์์ฑํ ๋๋ ๊ธ๋ก๋ฒ ํ์น ์ ๋ต์ ์ฐธ๊ณ ํ์ง ์๊ณ ์ค์ง JPQL ์์ฒด๋ง ์ฌ์ฉํ๋ค. ๋ฐ๋ผ์ ์ฆ์ ๋ก๋ฉ / ์ง์ฐ ๋ก๋ฉ์ ๊ตฌ๋ถํ์ง ์๊ณ JPQL ์ฟผ๋ฆฌ ์์ฒด์ ์ถฉ์คํ๊ฒ SQL์ ๋ง๋ ๋ค.
-
select o from Order o
JPQL์ ๋ถ์ํด์select * from Order
SQL์ ์์ฑํ๋ค. - DB์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ order ์ํฐํฐ ์ธ์คํด์ค๋ค์ ์์ฑํ๋ค.
- Order.member์ ๊ธ๋ก๋ฒ ํ์น ์ ๋ต์ด
์ฆ์ ๋ก๋ฉ
์ด๋ฏ๋ก order๋ฅผ ๋ก๋ฉํ๋ ์ฆ์ ์ฐ๊ด๋ member๋ ๋ก๋ฉํด์ผ ํ๋ค. - ์ฐ๊ด๋ member๋ฅผ ์์์ฑ ์ปจํ ์คํธ์์ ์ฐพ๋๋ค.
- ๋ง์ฝ ์์์ฑ ์ปจํ
์คํธ์ ์์ผ๋ฉด
SELECT * FROM MEMBER WHERE id=?
SQL์ ์กฐํํ order ์ํฐํฐ ์๋งํผ ์คํํ๋ค. โ ๋ง์ฝ ์กฐํํ order ์ํฐํฐ๊ฐ 10๊ฐ์ด๋ฉด member๋ฅผ ์กฐํํ๋ SQL๋ 10๋ฒ ์คํ๋๋ค.
์ด์ฒ๋ผ ์ฒ์ ์กฐํํ ๋ฐ์ดํฐ ์๋งํผ, ๋ค์ SQL์ ์ฌ์ฉํด์ ์กฐํํ๋ ๊ฒ์ N+1
๋ฌธ์ ๋ผ๊ณ ํ๋ค.
N+1์ด ๋ฐ์ํ๋ฉด SQL์ด ์๋นํ ๋ง์ด ํธ์ถ๋๋ฏ๋ก ์กฐํ ์ฑ๋ฅ์ ์น๋ช ์ ์ด๋ค.
์ด๋ฌํ N+1
๋ฌธ์ ๋ JPQL ํ์น ์กฐ์ธ์ผ๋ก ํด๊ฒฐํ ์ ์๋ค.
๊ธ๋ก๋ฒ ํ์น ์ ๋ต์ ์ฆ์ ๋ก๋ฉ์ผ๋ก ์ค์ ํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์ ์ํฅ์ ์ฃผ๋ฏ๋ก ๋๋ฌด ๋นํจ์จ์ ์ด๋ค. ์ด๋ฒ์๋ JPQL์ ํธ์ถํ๋ ์์ ์ ํจ๊ป ๋ก๋ฉํ ์ํฐํฐ๋ฅผ ์ ํํ ์ ์๋ ํ์น ์กฐ์ธ์ ์์๋ณด์.
์ฆ JPQL๋ง ํ์น ์กฐ์ธ
์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝํด๋ณด์.
// ํ์น ์กฐ์ธ ์ฌ์ฉ ์
JPQL : select 0 from Order o
SQL : select * from Order
// ํ์น ์กฐ์ธ ์ฌ์ฉ ํ
// join ๋ช
๋ น์ด ๋ง์ง๋ง์ fetch๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
JPQL :
select -
from Order o
join fetch o.member
SQL:
select o.*, m.*
from Order o
join Member m on o.MEMBER_ID=m.MEMBER_ID
์ด๋ฌํ JPQL ํ์น ์กฐ์ธ
์ N+1
๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉด์ ํ๋ฉด์ ํ์ํ ์ํฐํฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ฉํ๋ ํ์์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.
ํ์น ์กฐ์ธ์ด ํ์ค์ ์ธ ๋์์ด๊ธด ํ์ง๋ง ๋ฌด๋ถ๋ณํ๊ฒ ์ฌ์ฉํ๋ฉด ํ๋ฉด์ ๋ง์ถ ๋ฆฌํฌ์งํ ๋ฆฌ ๋ฉ์๋๊ฐ ์ฆ๊ฐํ ์ ์๋ค. ๊ฒฐ๊ตญ ํ๋ ์ ํ ์ด์ ๊ณ์ธต(view)์ด ์๊ฒ๋ชจ๋ฅด๊ฒ ๋ฐ์ดํฐ ์ ๊ทผ ๊ณ์ธต(repository)์ ์นจ๋ฒํ๋ ๊ฒ์ด๋ค.
๊ฐ ํ๋ฉด๋ง๋ค ์ฆ์๋ก๋ฉ, ์ง์ฐ ๋ก๋ฉ์ ์๊ตฌ์ฌํญ์ด ๋ค๋ฅด๋ค๋ฉด ๊ฐ๊ฐ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ , ๊ฐ ํ๋ฉด์์ ํ์ํ ๋ฉ์๋๋ง ํธ์ถํ๋ ๋ฐฉ์์ผ๋ก ์ต์ ํ ํ ์ ์์ง๋ง, ๋ทฐ์ ๋ฆฌํฌ์งํ ๋ฆฌ ๊ฐ์ ๋
ผ๋ฆฌ์ ์ธ ์์กด๊ด๊ณ๊ฐ ๋ฐ์ํ๋ค.
์ด๋ด๋ ๋ฌด๋ถ๋ณํ ์ต์ ํ๋ก ํ๋ ์ ํ ์ด์ ๊ณ์ธต๊ณผ ๋ฐ์ดํฐ ์ ๊ทผ ๊ณ์ธต ๊ฐ์ ์์กด๊ด๊ณ๊ฐ ๊ธ๊ฒฉํ๊ฒ ์ฆ๊ฐํ๋ ๊ฒ๋ณด๋ค๋ ์ ์ ํ ์ ์์ ํํ์ ์ ์ฐพ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ด๋ค.
๊ฐ์ ๋ก ์ด๊ธฐํํ๊ธฐ๋ ์์์ฑ ์ปจํ ์คํธ๊ฐ ์ด์์์ ๋ ํ๋ ์ ํ ์ด์ ๊ณ์ธต์ด ํ์ํ ์ฐ๊ด ์ํฐํฐ๋ฅผ ๊ฐ์ ๋ก ์ด๊ธฐํํด์ ๋ฐํํ๋ ๋ฐฉ๋ฒ์ด๋ค. (๊ธ๋ก๋ฒ ํ์น ์ ๋ต์ด ์ง์ฐ ๋ก๋ฉ์ผ ๋ ์ฌ์ฉ)
class OrderService {
@Transactional
public Order findOrder(id) {
Order order = repository.findOrder(id);
order.getMember().getName(); // ํ๋ก์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ๋ก ์ด๊ธฐํํ๋ค.
return order;
}
}
๊ธ๋ก๋ฒ ํ์น ์ ๋ต์ ์ง์ฐ ๋ก๋ฉ์ผ๋ก ์ค์ ํ๋ฉด ์ฐ๊ด๋ ์ํฐํฐ๋ฅผ ์ค์ ์ํฐํฐ๊ฐ ์๋ ํ๋ก์ ๊ฐ์ฒด๋ก ์กฐํํ๋ค. ํ๋ก์ ๊ฐ์ฒด๋ ์ค์ ์ฌ์ฉํ๋ ์์ ์ ์ด๊ธฐํ๋๋ค.
์๋ฅผ ๋ค์ด, order.getMember()
๊น์ง๋ง ํธ์ถํ๋ฉด ๋จ์ํ ํ๋ก์ ๊ฐ์ฒด๋ง ๋ฐํ๋๊ณ ์์ง ์ด๊ธฐํํ์ง ์๋๋ค. ํ๋ก์ ๊ฐ์ฒด๋ member.getName()
์ฒ๋ผ ์ค์ ๊ฐ์ ์ฌ์ฉํ๋ ์์ ์ ์ด๊ธฐํ๋๋ค.
์์ธ ์ฒ๋ฆฌ ๊ณผ์ ํ๋ก๊ทธ๋๋ฐ์์ ์์ธ ์ฒ๋ฆฌ๋ ์์ฃผ ์ค์ํ๋ฉด์๋ ์์ฃผ ์ด๋ ต๋ค.
๊ณผํ๋คํ ๋งํผ ์์ธํ๊ณ ๋ค์ํ๊ฒ ์์ธ๋ฅผ ์ก์ ์ฒ๋ฆฌํด์ค๋ค๋ฉด, ํด๋ผ์ด์ธํธ๋ ๊ทธ๋ ๊ณ ์๋ฒ๋ ๊ทธ๋ ๊ณ ๋ ์์ ์ ์ธ ํ๋ก๊ทธ๋จ์ด ๋ ์ ์๊ฒ ๋์์ค๋ค.
์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ฒฝ์ฐ์ ๋ฐฉ๋ฒ์ ๋ค์ํ๋ค.
๋ฉ์๋ ๋ด์์ ์์ธ ์ํฉ์ ์์ธกํด์ ์ฒ๋ฆฌํ๋ try-catch๋ฌธ์ ์ด์ฉํ๋ ๋ฐฉ๋ฒ ์๊ตฌ์ฌํญ์ ์ํ ์์ธ ์ฒ๋ฆฌ (ex. validation > ํน์ ๊ฐ์ด 0~255๋ฒ์๊ฐ ์๋๋ฉด ์ ํจํ์ง ์์ ๊ฐ์ผ๋ก ํ๋จํ๊ณ ์์ธ ์ฒ๋ฆฌ) ์คํ๋ง ์ํ๋ฆฌํฐ์์ ์ธํฐ์ ํฐ๋ก ์ก์์ UnauthorizedException ๊ฐ์ ์์ธ ์ฒ๋ฆฌ ๊ธฐํ ์ฌ๋ฌ ์์ธ ์ฒ๋ฆฌ๋ค์ ์ ์ฉํ๋ค๋ณด๋ฉด ์ฝ๋๊ฐ ์์ฒญ๋๊ฒ ๋ณต์กํด์ง๋ค.
if๋ฌธ์ผ๋ก ์ก๋ try-catch๋ก ์ก๋ ์์ ๋ฉ์๋๋ก ์์ธ์ฒ๋ฆฌ๋ฅผ ์์ํ๋ ์ฝ๋๋ ๋ณต์กํด์ง๋ค
๊ทธ๋ ๊ฒ ๋๋ฉด ์ ์ง๋ณด์ํ๊ธฐ ์์ฃผ ์ด๋ ค์์ง๋ค.
๋น์ฆ๋์ค ๋ก์ง์ ์ง์คํ๊ธฐ ์ด๋ ต๊ณ , ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๊ด๋ จ๋ ์ฝ๋๋ณด๋ค ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฝ๋๊ฐ ๋ ๋ง์์ง๋ ๊ฒฝ์ฐ๋ ์๊ธด๋ค.
์ด๋ฐ ๋ฌธ์ ๋ฅผ ์กฐ๊ธ์ด๋ผ๋ ๊ฐ์ ํ๊ธฐ ์ํด @ExceptionHandler์ @ControllerAdvice๋ฅผ ์ฌ์ฉํ๋ค๊ณ ๋ณด๋ฉด ์ดํด๊ฐ ์ฌ์์ง๋ค.
@ExceptionHandler @ExceptionHandler๊ฐ์ ๊ฒฝ์ฐ๋ @Controller, @RestController๊ฐ ์ ์ฉ๋ Bean๋ด์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ก์์ ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํด์ฃผ๋ ๊ธฐ๋ฅ์ ํ๋ค.
@RestController public class MyRestController { ... ... @ExceptionHandler(NullPointerException.class) public Object nullex(Exception e) { System.err.println(e.getClass()); return "myService"; } } ์์ ๊ฐ์ด ์ ์ฉํ๊ธฐ๋ง ํ๋ฉด ๋๋ค. @ExceptionHandler๋ผ๋ ์ด๋ ธํ ์ด์ ์ ์ฐ๊ณ ์ธ์๋ก ์บ์นํ๊ณ ์ถ์ ์์ธํด๋์ค๋ฅผ ๋ฑ๋กํด์ฃผ๋ฉด ๋๋๋ค.
โ @ExceptionHandler({ Exception1.class, Exception2.class}) ์ด๋ฐ์์ผ๋ก ๋ ๊ฐ ์ด์ ๋ฑ๋ก๋ ๊ฐ๋ฅํ๋ค.
์์ ์์ ์์ ์ฒ๋ผํ๋ฉด MyRestController์ ํด๋นํ๋ Bean์์ NullPointerException์ด ๋ฐ์ํ๋ค๋ฉด, @ExceptionHandler(NullPointerException.class)๊ฐ ์ ์ฉ๋ ๋ฉ์๋๊ฐ ํธ์ถ๋ ๊ฒ์ด๋ค.
์ฃผ์์ฌํญ/์์ ๋ ๊ฒ
Controller, RestController์๋ง ์ ์ฉ๊ฐ๋ฅํ๋ค. (@Service๊ฐ์ ๋น์์๋ ์๋จ.) ๋ฆฌํด ํ์ ์ ์์ ๋กญ๊ฒ ํด๋ ๋๋ค. (Controller๋ด๋ถ์ ์๋ ๋ฉ์๋๋ค์ ์ฌ๋ฌ ํ์ ์ response๋ฅผ ํ ๊ฒ์ด๋ค. ํด๋น ํ์ ๊ณผ ์ ํ๋ค๋ฅธ ๋ฆฌํด ํ์ ์ด์ด๋ ์๊ด์๋ค.) @ExceptionHandler๋ฅผ ๋ฑ๋กํ Controller์๋ง ์ ์ฉ๋๋ค. ๋ค๋ฅธ Controller์์ NullPointerException์ด ๋ฐ์ํ๋๋ผ๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค. ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ก Exception์ ๋ฐ์์๋๋ฐ ์ด๊ฒ ๋ํ ์์ ๋กญ๊ฒ ๋ฐ์์๋ ๋๋ค. ์์ ๋ฅผ ๋ณด๋ฉด์ ํ ์คํธ๋ฅผ ํด๋ณด๋๋กํ์.
@RestController public class MyRestController { @Autowired private MyService myService; @GetMapping("/hello") public String hello() { return "hello";//๋ฌธ์์ด ๋ฐํ } @GetMapping("/myData") public MyData myData() { return new MyData("myName");//object ๋ฐํ } @GetMapping("/service") public String serviceCall() { return myService.serviceMethod();//์ผ๋ฐ์ ์ธ serviceํธ์ถ } @GetMapping("/serviceException") public String serviceException() { return myService.serviceExceptionMethod(); //service์์ ์์ธ๋ฐ์ } @GetMapping("/controllerException") public void controllerException() { throw new NullPointerException();//controller์์ ์์ธ๋ฐ์ } @GetMapping("/customException") public String custom() { throw new CustomException();//custom์์ธ ๋ฐ์ } @ExceptionHandler(NullPointerException.class) public Object nullex(Exception e) { System.err.println(e.getClass()); return "myService"; } } [MyRestController.class]
Stringํ์ ๊ณผ MyData๋ผ๋ ๋๋ง์ ๊ฐ์ฒดํ์ ์ ๋ฆฌํดํ๋ ๋ฉ์๋๋ฑ์ ์กด์ฌํ์ง๋ง ExceptionHandlerํ๋๋ก ๋ค ์ฒ๋ฆฌํ ์ ์๋ค.
myService.serviceExceptionMethod๋ Service์์์ Exception์ด ๋ฐ์ํ๋๋ฐ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์๋น์ค์์ ์์ธ๊ฐ ๋ฐ์ํ์ง๋ง ๊ฒฐ๊ตญ ์ปจํธ๋กค๋ฌ ๋ด์์ ๋ฐ์ํ ๊ฒ๊ณผ ๊ฐ์ผ๋ฏ๋ก ExceptionHandler๊ฐ ์์ธ๋ฅผ ์ก์๋ด์ด "myService"๊ฐ ๋ฆฌํด๋๋ค.
public class CustomException extends RuntimeException{ private static final long serialVersionUID = 1L; } RuntimeException์ ํ์ฅํ ํด๋์ค๋ก CustomException์ ๋ง๋ค์๋ค.
์ด ์์ธ๋ NullPointerException์ด ์๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋๋ผ๋ ExceptionHandler์ ์ํด์ ์ฒ๋ฆฌ๋์ง ์๋๋ค.
๋ง์ฝ ํ๋๋ก ๋ ๋ง์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๊ธธ ์ํ๋ค๋ฉด ๋ชจ๋ ์์ธ์ ๋ถ๋ชจํด๋์ค์ธ Exception.class๋ฅผ ํธ๋ค๋งํ๊ฒํ๋ฉด ๋๋ค.
@ExceptionHandler(Exception.class) @ControllerAdvice @ExceptionHandler๊ฐ ํ๋์ ํด๋์ค์ ๋ํ ๊ฒ์ด๋ผ๋ฉด, @ControllerAdvice๋ ๋ชจ๋ @Controller ์ฆ, ์ ์ญ์์ ๋ฐ์ํ ์ ์๋ ์์ธ๋ฅผ ์ก์ ์ฒ๋ฆฌํด์ฃผ๋ annotation์ด๋ค.
@RestControllerAdvice public class MyAdvice { @ExceptionHandler(CustomException.class) public String custom() { return "hello custom"; } } ์์ ๊ฐ์ด ์๋ก์ด ํด๋์คํ์ผ์ ๋ง๋ค์ด์ annotation์ ๋ถ์ด๊ธฐ๋ง ํ๋ฉด ๋๋ค. ๊ทธ ๋ค์์ @ExceptionHandler๋ก ์ฒ๋ฆฌํ๊ณ ์ถ์ ์์ธ๋ฅผ ์ก์ ์ฒ๋ฆฌํ๋ฉด ๋๋ค.
๋ณ๋์ ์์ฑ๊ฐ์ด ์์ด ์ฌ์ฉํ๋ฉด ๋ชจ๋ ํจํค์ง ์ ์ญ์ ์๋ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ด๋นํ๊ฒ ๋๋ค.
@RestControllerAdvice๋ @ControllerAdvice๊ฐ ์๋๋ฐ ๋ง ๊ทธ๋๋ก @RestControllerAdvice๋ @RestController์์ ๋ฐ์ํ Exception๋ง ์บ์นํ๊ณ , @ControllerAdvice๋ @Controller์์ ๋ฐ์ํ Exception๋ง ์บ์นํ๋ค.
@RestControllerAdvice์ @ControllerAdvice๊ฐ ์กด์ฌํ๋๋ฐ @RestControllerAdvice ์ด๋ ธํ ์ด์ ์ ๋ค์ฌ๋ค๋ณด๋ฉด ์๋์ ๊ฐ์ด ๋์ด์๋ค.
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @ControllerAdvice @ResponseBody public @interface RestControllerAdvice { //... } ์์ ๊ฐ์ด ๋๊ฐ์ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ์ ๋ @RestControllerAdvice๋ฅผ ์ฌ์ฉํ๋ฉด @Controller๋ก ์ ์ฉํ HelloController์์ ๋ฐ์ํ๋ ์์ธ๋ @RestControllerAdvice์์ ์ก์์ฃผ์ง ๋ชปํ๋ค.
@ControllerAdvice์ ๋์ผํ ์ญํ ์ฆ, ์์ธ๋ฅผ ์ก์ ํธ๋ค๋ง ํ ์ ์๋๋ก ํ๋ ๊ธฐ๋ฅ์ ์ํํ๋ฉด์ @ResponseBody๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ ์๋ ์๋ค๋ ์๊ธฐ๋ค.
ViewResolver๋ฅผ ํตํด์ ์์ธ ์ฒ๋ฆฌ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ ์ํค๋ ค๋ฉด @ControllerAdvice๋ง ์จ๋ ๋๊ณ , API์๋ฒ์ฌ์ ์๋ฌ ์๋ต์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํด์ผํ๋ค๋ฉด @ResponseBody ์ด๋ ธํ ์ด์ ์ด ์ถ๊ฐ๋ @RestControllerAdvice๋ฅผ ์ ์ฉํ๋ฉด ๋๋ ๊ฒ์ด๋ค.
@RestController์์ ์์ธ๊ฐ ๋ฐ์ํ๋ @Controller์์ ์์ธ๊ฐ ๋ฐ์ํ๋ @ControllerAdvice + @ExceptionHandler ์กฐํฉ์ผ๋ก ๋ค ์บ์นํ ์ ์๊ณ @ResponseBody์ ํ์ ์ฌ๋ถ์ ๋ฐ๋ผ ์ ์ฉํ๋ฉด ๋๋ค๋ ๊ฒ์ด๋ค. (์ ๋ถ์ฐฐ๋ก ์๋ชป๋ ์ ๋ณด๋ฅผ ๊ณต์ ํ๋ ์ ์ ์์ ํ์์ต๋๋ค.)
๋ํ, ๋ง์ฝ์ ์ ์ญ์ ์์ธ๋ฅผ ์ก๊ธดํ๋ ํจํค์ง ๋จ์๋ก ์ ํํ ์๋์๋ค.
@RestControllerAdvice("com.example.demo.login.controller") login๋ชจ๋์ ์๋ RestController์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ก์ผ๋ ค๋ฉด ์์ ๊ฐ์ด ํ๋ฉด ๋๋ค. (ํจํค์ง ๊ตฌ์ฑ์ ์ํ๋ฉด ์ ์ฉํ๋ค)
์ถ์ฒ: https://jeong-pro.tistory.com/195 [๊ธฐ๋ณธ๊ธฐ๋ฅผ ์๋ ์ ์๋ง์ถ์ด ์ฝ๋ฉ๋ธ๋ก๊ทธ]
๊ฐ์ธํค = ๋น๋ฐํค = ๋น๊ณต๊ฐํค
๊ณต๊ฐํค ๊ธฐ๋ฒ = ๋น๋์นญํค ๊ธฐ๋ฒ
์ํธํ์ ๋ณตํธํ์ ์ฌ์ฉํ๋ ์ํธํค๊ฐ ๊ฐ์์ง ๋ค๋ฅธ์ง์ ๋ฐ๋ผ ์ํธํ ๊ธฐ๋ฒ์ด ๋์นญํค ๊ธฐ๋ฒ๊ณผ ๋น๋์นญํค ๊ธฐ๋ฒ์ผ๋ก ๋๋์ด ์ง๋ค.
- ๋์นญํค ์ํธ
-
ํ๋์ ๋น๋ฐํค๋ฅผ ์์ชฝ(client & server)๊ฐ ๋ชจ๋ ๊ฐ์ด ์ฌ์ฉ
-
์ํธํ์ ๋ณตํธํ์ ์ฌ์ฉํ๋ ํค๊ฐ ๊ฐ์ ์ํธํ ์๊ณ ๋ฆฌ์ฆ
-
๊ณต๊ฐํค์ ๋น๋ฐํค๋ฅผ ๋ณ๋๋ก ๊ฐ์ง๋ ๊ฒ๊ณผ ๊ตฌ๋ณ๋๋๋ฐ, ์ด์ ๋น๊ตํ๋ฉด ๊ณ์ฐ์๋๊ฐ ๋น ๋ฅด๋ค๋ ์ฅ์
-
๋น๋ฐํค ํ๋๋ง ์์๋ด๋ฉด ์ํธํ๋ ๋ด์ฉ์ ํด๋ ๊ฐ๋ฅ โ ํด์ปค๋ก๋ถํฐ ์์ X
-
๋ํนํค ์ํธ๋ ์ํธํํ๋ ๋จ์์ ๋ฐ๋ผ ์คํธ๋ฆผ์ํธ์ ๋ธ๋ก์ํธ๋ก ๋๋ ์ ์์
ยบ ์คํธ๋ฆผ์ํธ๋ ์ฐ์์ ์ธ ๋นํธ/๋ฐ์ดํธ๋ฅผ ๊ณ์ํด์ ์ ๋ ฅ๋ฐ์, ๊ทธ์ ๋์ํ๋ ์ํธํ ๋นํธ/๋ง์ดํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ์
ยบ ๋ธ๋ก์ํธ๋ ์ ํด์ง ํ ๋จ์(๋ธ๋ก)์ ์ ๋ ฅ๋ฐ์ ๊ทธ์ ๋์ํ๋ ์ํธํ ๋ธ๋ก์ ์์ฑํ๋ ๋ฐฉ์
ยบ ๋ธ๋ก์ํธ์ ๊ฒฝ์ฐ ์ ์ ํ ์ด์ฉ๋ชจ๋๋ฅผ ์กฐํฉํ๋ฉด ๋ธ๋ก ๋จ์๋ณด๋ค ํฐ ์ ๋ ฅ์ ์ฒ๋ฆฌํ ์ ์์. ๋ํ ์คํธ๋ฆผ์ํธ์ ์ ์ฌํ๊ฒ ์ง์์ ์ธ ์ ๋ ฅ์ ๋ํด ๋์ํ ์ ์์. (๋์ ์ ์ถ๋ ฅ ๋จ์๋ ์คํธ๋ฆผ์ํธ๋ณด๋ค ํฐ ๋ธ๋ก ๋จ์๊ฐ ๋จ)
- ๋ํนํค ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ ์ํธ ์๊ณ ๋ฆฌ์ฆ ๋ฐฉ์์ผ๋ก DES, 3-DES, AES, SEED, ARIA, MASK ๋ฑ์ด ์๋ค.
- ๊ณต๊ฐํค ์ํธ
-
๋น๋ฐํค ํ๋ ๋ง ๊ฐ์ง๋ ๋์นญํค ์ํธ ๋ฐฉ๋ฒ๊ณผ ๋ฌ๋ฆฌ, ๊ณต๊ฐํค์ ๋น๋ฐํค ๋ ๊ฐ๊ฐ ์กด์ฌ
-
๊ณต๊ฐํค ์ํธ๋ฅผ ๊ตฌ์ฑํ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋์นญํค ์ํธ ๋ฐฉ์๊ณผ ๋น๊ตํ์ฌ ๋น๋์นญ ์ํธ๋ผ๊ณ ๋ถ๋ฆผ
-
์ํธํ์ ๋ณตํธํ์ ์ฌ์ฉํ๋ ํค๊ฐ ์๋ก ๋ค๋ฆ
-
์ํธํํ ๋์ ํค๋ ๊ณต๊ฐํค(public key), ๋ณตํธํํ ๋์ ํค๋ ๊ฐ์ธํค(private key)
-
๊ณต๊ฐํค๋ ๋๊ตฌ๋ ์ ์ ์์ง๋ง, ๊ทธ์ ๋์ํ๋ ๋น๋ฐํค๋ ํค์ ์์ ์๋ง์ด ์ ์ ์์ด์
ํน์ ํ ๋น๋ฐํค๋ฅผ ๊ฐ์ง๋ ์ฌ์ฉ์๋ง์ด ๋ด์ฉ์ ์ด์ด๋ณผ ์ ์๋๋ก ํ๋ ๋ฐฉ์.
์ก์ ์๋ ์์ ์์ ๊ณต๊ฐํค๋ฅผ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ํธํํ์ฌ
๋คํธ์ํฌ๋ฅผ ํตํด ์๊ฒฉ์ง์ ์ ๋ฌ.
์์ ์๋ ๊ณต๊ฐํค๋ก ์ํธํ๋ ๋ฐ์ดํฐ๋ฅผ ์์ ์ ๊ฐ์ธํค๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณตํธํํ์ฌ ํ๋ฌธ์ ๋ณต์.
-
๊ณต๊ฐํค๋ก ์ํธํํ ๋ฉ์ธ์ง๋ ์์ ์์ ๊ฐ์ธํค๋ก๋ง ํด๋ ํ ์ ์์ผ๋ฏ๋ก ์์ ํ๊ฒ ์๋๋ฐฉ์๊ฒ ๋ฉ์ธ์ง๋ฅผ ์ ๋ฌํด ์ค ์ ์์.
-
๋์นญํค(๋น๋ฐํค)์๊ณ ๋ฆฌ์ฆ์ ๋นํ์ฌ ์๋๊ฐ ๋๋ฆฌ๋ค. (์ฝ 1000๋ฐฐ)
-
์๋๊ฐ ๋๋ฆฌ๊ธฐ ๋๋ฌธ์ ๊ธด๋ฌธ์์ ์ํธํํ๋ ๊ฒฝ์ฐ๋ณด๋ค ๋์นญํค ์๊ณ ๋ฆฌ์ฆ์ ํค๊ฐ์ ๋ํ ์ํธ์ ์ฌ์ฉ.
-
๋ํ์ ์ธ ๊ณต๊ฐํค ์๊ณ ๋ฆฌ์ฆ์ผ๋ก RSA, Elgamal ๋ฑ์ด ์์.
๊ณต๊ฐํค ์ํธํ ๊ฐ๋ ๋
โป ๋น๋ฐํค ์ํธํ์ ๊ณต๊ฐํค ์ํธํ์ ๋น๊ต
์ํ์น ( Apache )
Apache ์๋ฒ๋ ์์ฒญ ํ๋ ๋น ํ๋ก์ธ์ค(๋๋ ์ฐ๋ ๋)๊ฐ ์ฒ๋ฆฌํ๋ ๊ตฌ์กฐ์ ๋๋ค.
์ฆ ์์ฒญ์ด ๋ง์์๋ก CPU์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ด ์ฆ๊ฐํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ ์ ํ๊ฐ ์์ ์ ์์ต๋๋ค.
๋ํ Apache ์๋ฒ์ ํ๋ก์ธ์ค๊ฐ ๋ธ๋กํน( blocking )์ด ๋๋ฉด ์์ฒญ์ ์ฒ๋ฆฌํ์ง ๋ชปํ๊ณ , ์ฒ๋ฆฌ๊ฐ ์๋ฃ ๋ ๋๊น์ง ๊ณ์ ๋๊ธฐํ๋ ์ผ์ด ๋ฐ์ํฉ๋๋ค.
์ด์ ๊ฐ์ ๋ฌธ์ ๋ค์ Keep Alive๋ฅผ ํ์ฑํ ํจ์ผ๋ก์จ ํด๊ฒฐ์ด ๊ฐ๋ฅํ์ง๋ง, Keep Alive ๋๋ฌธ์ ๋๋ ์ ์ ์ ํจ์จ์ด ๊ธ๊ฒฉํ๊ฒ ๋จ์ด์ง๋ ๋ ๋ค๋ฅธ ๋ฌธ์ ์ ์ด ๋ฐ์ํฉ๋๋ค.
์ด๋ฅผ ์ดํดํ๊ธฐ ์ํด์๋ Keep Alive์ ๋ํ ๊ฐ๋ ์ด ํ์ํ๋ฏ๋ก ์ ์ ์ธ๊ธํ๋๋ก ํ๊ฒ ์ต๋๋ค.
Keep Alive
HTTP ํ๋กํ ์ฝ์ ํน์ฑ์ ํ ๋ฒ ํต์ ์ด ์ด๋ฃจ์ด์ง๋ฉด ์ ์์ ๋์ด ๋ฒ๋ฆฌ์ง๋ง, KeepAlive On ์ํ์์๋ KeepAliveTimeOut ์๊ฐ ๋์ ์ ์์ ๋์ง ์๊ณ ๋ค์ ์ ์์ ๊ธฐ๋ค๋ฆฝ๋๋ค.
์ฆ, ํ ๋ฒ ์ฐ๊ฒฐ๋ ํด๋ผ์ด์ธํธ์ ํต์ ์ ์ ์งํ๊ณ ์๊ธฐ ๋๋ฌธ์, ๋ค์ ํต์ ์์ Connection์ ์์ฑํ๊ณ ๋๋ ์์ ์ด ํ์ ์๊ฒ ๋ฉ๋๋ค.
๋ฐ๋ผ์ Keep Alive์ ํ์ฑํ ํจ์ผ๋ก์จ, ์ฑ๋ฅ ํฅ์์ ๊ธฐ๋ ํ ์ ์์ต๋๋ค.
์ ์ ์์( htmlํ์ผ, ์ด๋ฏธ์ง ํ์ผ ๋ฑ )์ผ๋ก๋ง ๊ตฌ์ฑ๋ ์น ์๋ฒ์ KeepAlive On์ผ๋ก ์ค์ ํ ๊ฒฝ์ฐ ์ฝ 50%์ ์ฑ๋ฅ ํฅ์์ ๋ณด์ธ๋ค๊ณ ํฉ๋๋ค.
๋จ ์ด์ ๊ฐ์ ์ฑ๋ฅ ํฅ์์ ๋ณด์ด๋ ค๋ฉด ์๋ฒ๊ฐ ๋ฐ์์ง ์์์ผ ํ๋๋ฐ, ๋ฐ์ ์๋ฒ ํ๊ฒฝ์์ KeepAlive On์ผ๋ก ์ค์ ํด ๋์ ๊ฒฝ์ฐ,
๋ชจ๋ ์์ฒญ ๋ง๋ค ์ฐ๊ฒฐ์ ์ ์งํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํ๋ก์ธ์ค ์๊ฐ ๊ธฐํ๊ธ์์ ์ผ๋ก ๋์ด๋ MaxClient๊ฐ์ ์ด๊ณผํ๊ฒ ๋ฉ๋๋ค.
๋ฐ๋ผ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ฌ์ฉํ๊ฒ ๋๋ฉฐ ์ด๋ ๊ณง ์ฑ๋ฅ ์ ํ์ ์์ธ์ด ๋ฉ๋๋ค. ( ๋๋ ์ ์ ์ ํจ์จ์ด ๋จ์ด์ง )
์ด์ ๋ฐ๋ผ Apache 2.4 ๋ฒ์ ๋ถํฐ Keep Alive์ ๋ํ ๊ณ ๋ฏผ์ ํด๊ฒฐํ๋ ์๋ก์ด MPM ๋ฐฉ์์ธ, Event MPM ๋ฐฉ์์ ์ง์ํฉ๋๋ค.
์ด ๋ฐ์ Apache 2.4 ๋ฒ์ ์์๋ ์ฑ๋ฅ ๊ฐ์ ์ ์ต์ฐ์ ๊ณผ์ ๋ก ์ผ๊ณ , ๋๋ถ์ด์ ์บ์, ํ๋ก์ ๋ชจ๋, ์ธ์ ์ ์ด, ๋น๋๊ธฐ ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ ์ง์ ๊ธฐ๋ฅ์ ๊ฐ์ ํ๋ค๊ณ ํฉ๋๋ค.
Apache๊ฐ ์ฑ๋ฅ ํฅ์์ ํฌ์๋ฅผ ํ ์ด์ ๋, ์ต๊ทผ ์น ์๋ฒ๊ฐ ์ ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ํตํ ์๋ ํฅ์์ ๋ ธ๋ฆฌ๋ ํ๋ก์๋ ์บ์ฑ ์ฒ๋ฆฌ์ฉ ์๋ฒ๋ก ์ฌ์ฉํ๋ ๊ฒฝํฅ์ด ๋๋ฉด์ ์๋์ ๋งค์ฐ ๋ฏผ๊ฐํด์ก๊ธฐ ๋๋ฌธ์ ๋๋ค.
์กฐ๊ธ ๋ค์ ์ดํด ๋ณผ Nginx๊ฐ ์ฑ์ฅํ๊ฒ ๋ ๊ณ๊ธฐ๊ฐ ๋ฐ๋ก Apache๋ณด๋ค ์ฑ๋ฅ์์ ์ฅ์ ์ ๊ฐ๊ณ ์๊ธฐ ๋๋ฌธ์ด์ฃ .
๋จผ์ Apache 2.4๋ฒ์ ์์ ์ด๋ค ๋ณํ๊ฐ ์์๋์ง ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ํ์น 2.4์ ์๋ก์ด ๊ธฐ๋ฅ ( ๊ณต์ ์ฌ์ดํธ - ๋งํฌ )
- ( RUN-TIME ) Loadable MPMS
Apaceh 2.2๊น์ง๋ Multi-Processing Modules ( MPMS )๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ์ปดํ์ผ ์ค์น๋ฅผ ํ ๋ ๊ฒฐ์ ์ง์ด์ผ ํ์ต๋๋ค.
๊ทธ๋ฌ๋ Apache 2.4๋ถํฐ๋ ๋ฐํ์์์ ๊ฒฐ์ ํ ์ ์๋๋ก Loadable Module ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
Apache 2.4 ์ปดํ์ผ ์ค์นํ ๋ ์ํํ๋ Configure์์ โenable-mpms-shared ์ต์ ์ผ๋ก ์ค์ ์ด ๊ฐ๋ฅํฉ๋๋ค.
- Event MPM
Apache 2.2๊น์ง๋ Event Driven ๋ฐฉ์์ ์ง์ํ์ง ์์์ต๋๋ค.
Evnet MPM ๋ฐฉ์์ Keep Alive์ ๋ํ ๊ณ ๋ฏผ์์ ์ถ๋ฐํ ์๋ก์ด MPM ๋ฐฉ์์ ๋๋ค.
์ด ๋ฐฉ์์ ์ฌ์ฉ์ ์์ฒญ๊ณผ Keep Aliveํ Apache์ ์์ฒญ์ ๊ทธ๋๋ก ๋งบ์ด์ฃผ๋ ๊ฒ์ด ์๋๋ผ, ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ฐ๋ ๋๋ฅผ ๋ฐ๋ก ๋์ด ๋ถ์ฐ๋ ์ฒ๋ฆฌ๋ฅผ ํ๋๋ฐ ๊ทธ ๋ชฉ์ ์ ๋๊ณ ์์ต๋๋ค.
- Asynchronous Support
๋น๋๊ธฐ ์ฝ๊ณ /์ฐ๊ธฐ์ ๋ํ ๊ธฐ๋ฅ์ ์ง์ํฉ๋๋ค
(๋ฐ๋ก ์ค์ ํ๊ฑฐ๋ ํ๋ ๊ฒ์ ์๊ณ ๋ด๋ถ ๊ตฌ์กฐ์ ์ผ๋ก ์ง์ํ๋ค๊ณ ํฉ๋๋ค. )
- NameVirtualHost Deprecated
Apache 2.4 ์์๋ NameVirtualHost๊ฐ ์์ผ๋ก ์ฌ์ฉ๋์ง ์๋ ์ต์ ์ผ๋ก ๋ณ๊ฒฝ๋์์ต๋๋ค.
NameVritualHost ๋๋ ํฐ๋ธ๋ ๋ ์ด์ ์ด๋ ํ ์ํฅ์ ์ฃผ์ง ์์ผ๋ฉฐ, ์์ฑ ์ ๊ฒฝ๊ณ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
๋์ ๋ฌต์์ ์ผ๋ก ๋ค๋ฃจ์ด์ง๋ค๊ณ ํ๋๋ฐ, ์ด๋ httpd.conf ํ์ผ์์ ์๋์ ์ฝ๋๋ฅผ ์์ฑํ์ง ์์๋ ๋ฌต์์ ์ผ๋ก ์ธ์ํ๋ค๋ ์๋ฏธ์ ๋๋ค.
NameVirtualHost *:80
- Config File Variables
Apache 2.4 ์์๋ ์ค์ ํ์ผ ๋ด์์ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋์์ต๋๋ค.
Define ํค์๋๋ก ์ด์ฉํด์ ๋ณ์๋ฅผ ์ ์ํฉ๋๋ค.
ex)
Define servername www.example.com
DocumentRoot /var/www/${servername}/htdoc
์์ง์์ค ( Nginx )
Nginx๋ ๋ณด์๊ณผ ์๋๋ฅผ ์ต์ ํ ์ํค๋ ค๋ ๋ ธ๋ ฅ์์ ํ์ํ ์น์๋ฒ์ด๋ฉฐ, ์ฌ์ฉ์ด ๋งค์ฐ ์ฌํํ๊ณ ๊ท๋ชจ๊ฐ ์์ ์๋น์ค์ด๋ฉด์ ์ ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ๋ง์ ์๋น์ค์ ์ ํฉํฉ๋๋ค.
Apache ์์ ์ง์ํ๋ ์๋ง์ ๊ธฐ๋ฅ์ด ํ์ ์๊ณ ์๋ ค์ง ๋ณด์ ๋ฌธ์ ๋ค์ ํน๋ณํ ์ ๋ฐ์ดํธ ์์ด Nginx ์์ฒด์์ ์ฒ๋ฆฌํด์ฃผ๊ณ ์์ต๋๋ค.
Nginx๋ ํ๋ก๊ทธ๋จ์ ํ๋ฆ์ด ์ด๋ฒคํธ์ ์ํด ๊ฒฐ์ ์ด ๋๋ Event Driven ๋ฐฉ์์ ์น ์๋ฒ์ ๋๋ค.
์ฆ ์์ฒญ์ ๋ํ ๊ฐ ์ํ( state )๋ฅผ ์ ํด์, event๊ฐ ๋ฐ์ํ ๋๋ง๋ค event๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
์ ์ ์์ ์ฐ๋ ๋๋ก ํจ์จ์ ์ธ ์ผ ์ฒ๋ฆฌ๋ฅผ ํ๋ฉฐ, ์ฐ๋ ๋๋ฅผ ์ ๊ฒ ์ฌ์ฉ ํ๊ธฐ ๋๋ฌธ์ ์ฐ๋ ๋๋น ํ ๋น๋๋ ๋ฉ๋ชจ๋ฆฌ๋ ์ ๊ฒ ์ฌ์ฉํ๋ ๊ตฌ์กฐ์ ๋๋ค.
๋ํ ์ฐ๋ ๋๋ฅผ ๋ง์ด ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ context switching ๋น์ฉ์ด ์ ๊ณ , ๋ฐ๋ผ์ CPU ์๋ชจ๋ ์ ์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ชจ๋ ๊ฐ๋ฐ์ด ์ด๋ ค์ฐ๋ฉฐ ๋ค์ํ ๋ชจ๋์ด ์๋ค๋ ๊ฒ์ด ๋จ์ ์ ๋๋ค.
Apache์ Nginx ๋น๊ต
Nginx ๋ ๋น๋๊ธฐ ์ด๋ฒคํธ ๊ธฐ๋ฐ์ผ๋ก ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ , Apache ์๋ฒ๋ ์์ฒญ ๋น ์ฐ๋ ๋ ๋๋ ํ๋ก์ธ์ค๊ฐ ์ฒ๋ฆฌํ๋ ๊ตฌ์กฐ ์ ๋๋ค.
์ต๊ทผ ๋์ฉ๋์ ์ ์ ํ์ผ ๋ฐ ํฐ ๊ท๋ชจ์ ์ฌ์ดํธ๊ฐ ๋ง์์ง์ ๋ฐ๋ผ ๋๋ ์ ์์๋ ์ ์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๋ฉฐ ๋น ๋ฅด๊ฒ ์๋น์ค๋ฅผ ํ ์ ์๋ ์น ์ฌ์ดํธ๊ฐ ๋์ธ๊ฐ ๋์๋๋ฐ, ์ด๋ฐ ๋ฉด์์ Nginx๊ฐ ๊ฐ๊ด ๋ฐ๊ธฐ ์์ํ์ต๋๋ค.
์ฑ๋ฅ ๋ฉด์์ Apache 2.2๋ Nginx์ ๋ค์ณ์ก๊ธฐ ๋๋ฌธ์ Nginx๊ฐ ์ฑ์ฅํ๊ฒ ๋์์ต๋๋ค.
๊ทธ๋ฌ๋ค๊ฐ 2012๋ ์ ๋น ๋ฅธ ์๋ต ์๋์ ์ ์ ๋ฆฌ์์ค ์ฌ์ฉ ๋ถ๋ถ์ ๊ฐ์ ํ Apache 2.4๋ฅผ ๋ฐํํ๋ฉด์, Nginx์ ๋์ํ๊ธฐ ์์ ํ์ต๋๋ค.
๊ทธ๋ผ์๋ Nginx๊ฐ ์ฑ๋ฅ ๋ฉด์์๋ Apahce 2.4 ๋ณด๋ค ์ข๋ค๊ณ ํฉ๋๋ค. ( ์์ฒญ ํฐ ์ฐจ์ด๋ ์๋๋๋ค. )
ํ์ง๋ง PHP ๋ชจ๋ ๋ฑ์ ์ง์ ์ ์ฌํ ์ ์๋ Apache๊ฐ ๊ตฌ์กฐ์ ์ด์ ์ด ์๊ธฐ์ ๋ณต์กํ ์น ์ฌ์ดํธ์ ๊ฒฝ์ฐ Apache๊ฐ ์ ํฉํฉ๋๋ค.
์ธ์ ํด๋ฌ์คํฐ๋ง ๊ฐ์ ํน๋ณํ ๋ชฉ์ ์ ์ถ๊ฐ์ ์ผ๋ก ์ํํ๋ ์ธํ ์ ํ ๊ฒฝ์ฐ์๋ ๋ณ๋์ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ๊ธฐ ๋๋ฌธ์,
์ด๋ฌํ ๋ณ๋์ ์์ ์ด ๋ง์ด ํ์ํ ์๋น์ค์ ๊ฒฝ์ฐ์๋ ์ ์ง ๋ณด์ ์ธก๋ฉด์์ Apache๊ฐ ์ ์ฉํฉ๋๋ค.
์ฆ ์์ ์ฑ๊ณผ ํ์ฅ์ฑ, ํธํ์ฑ์์ Apache๊ฐ ์ฐ์ธ, ์ฑ๋ฅ ๋ฉด์์๋ Nginx๊ฐ ์ฐ์ธํ๋ค๋ ๊ฒ์ด ๊ฒฐ๋ก ์ ๋๋ค.
[ ์ฐธ๊ณ ]
http://linux.systemv.pe.kr/apache-2-4-new-features/ - ์ํ์น 2.4
https://prezi.com/romcehawisgh/nginx/ - nginx ํน์ง
https://prezi.com/ymg_mme4iq8m/apache-mpm-event/ - ์ํ์น MPM event ๋ฐฉ์ , nginx