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

HashMap ์ถฉ๋Œ ํšŒํ”ผ ๋ฐฉ๋ฒ•

ํ•ด์‹œ ๋ถ„ํฌ์™€ ํ•ด์‹œ ์ถฉ๋Œ

๋™์ผํ•˜์ง€ ์•Š์€ ์–ด๋–ค ๊ฐ์ฒด X์™€ Y๊ฐ€ ์žˆ์„ ๋•Œ, ์ฆ‰ X.equals(Y)๊ฐ€ '๊ฑฐ์ง“'์ผ ๋•Œ X.hashCode() != Y.hashCode()๊ฐ€ ๊ฐ™์ง€ ์•Š๋‹ค๋ฉด, ์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ•ด์‹œ ํ•จ์ˆ˜๋Š” ์™„์ „ํ•œ ํ•ด์‹œ ํ•จ์ˆ˜(perfect hash functions)๋ผ๊ณ  ํ•œ๋‹ค(

https://d2.naver.com/content/images/2015/06/helloworld-831311-2.png

: S๋Š” ๋ชจ๋“  ๊ฐ์ฒด์˜ ์ง‘ํ•ฉ, h๋Š” ํ•ด์‹œ ํ•จ์ˆ˜).

Boolean๊ฐ™์ด ์„œ๋กœ ๊ตฌ๋ณ„๋˜๋Š” ๊ฐ์ฒด์˜ ์ข…๋ฅ˜๊ฐ€ ์ ๊ฑฐ๋‚˜, Integer, Long, Double ๊ฐ™์€ Number ๊ฐ์ฒด๋Š” ๊ฐ์ฒด๊ฐ€ ๋‚˜ํƒ€๋‚ด๋ ค๋Š” ๊ฐ’ ์ž์ฒด๋ฅผ ํ•ด์‹œ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์™„์ „ํ•œ ํ•ด์‹œ ํ•จ์ˆ˜ ๋Œ€์ƒ์œผ๋กœ ์‚ผ์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ String์ด๋‚˜ POJO(plain old java object)์— ๋Œ€ํ•˜์—ฌ ์™„์ „ํ•œ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ์ œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์‹ค์ƒ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

์ ์€ ์—ฐ์‚ฐ๋งŒ์œผ๋กœ ๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ์™„์ „ํ•œ ํ•ด์‹œ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„, ๊ทธ๊ฒƒ์„ HashMap์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. HashMap์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ ๊ฐ์ฒด์˜ hashCode() ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ, ๊ฒฐ๊ณผ ์ž๋ฃŒํ˜•์€ int๋‹ค. 32๋น„ํŠธ ์ •์ˆ˜ ์ž๋ฃŒํ˜•์œผ๋กœ๋Š” ์™„์ „ํ•œ ์ž๋ฃŒ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค. ๋…ผ๋ฆฌ์ ์œผ๋กœ ์ƒ์„ฑ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด์˜ ์ˆ˜๊ฐ€ 232๋ณด๋‹ค ๋งŽ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ, ๋˜ํ•œ ๋ชจ๋“  HashMap ๊ฐ์ฒด์—์„œ O(1)์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋žœ๋ค ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ์›์†Œ๊ฐ€ 232์ธ ๋ฐฐ์—ด์„ ๋ชจ๋“  HashMap์ด ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

@ControllerAdvice, @ExceptionHandler์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์‹œ์˜ค

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ณผ์ • ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ์•„์ฃผ ์ค‘์š”ํ•˜๋ฉด์„œ๋„ ์•„์ฃผ ์–ด๋ ต๋‹ค.

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

์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜๋‹ค.

๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์˜ˆ์™ธ ์ƒํ™ฉ์„ ์˜ˆ์ธกํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” 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 8 HashMap์—์„œ์˜ Separate Chaining

Java 2๋ถ€ํ„ฐ Java 7๊นŒ์ง€์˜ HashMap์—์„œ Separate Chaining ๊ตฌํ˜„ ์ฝ”๋“œ๋Š” ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด์ง€๋งŒ, ๊ตฌํ˜„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž์ฒด๋Š” ๊ฐ™์•˜๋‹ค. ๋งŒ์•ฝ ๊ฐ์ฒด์˜ ํ•ด์‹œ ํ•จ์ˆ˜ ๊ฐ’์ด ๊ท ๋“ฑ ๋ถ„ํฌ(uniform distribution) ์ƒํƒœ๋ผ๊ณ  ํ•  ๋•Œ, get() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์— ๋Œ€ํ•œ ๊ธฐ๋Œ“๊ฐ’์€

https://d2.naver.com/content/images/2015/06/helloworld-831311-5.png

์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Java 8์—์„œ๋Š” ์ด๋ณด๋‹ค ๋” ๋‚˜์€

https://d2.naver.com/content/images/2015/06/helloworld-831311-6.png

์„ ๋ณด์žฅํ•œ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด, Separate Chaining์—์„œ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ๋Œ€์‹  ํŠธ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด

https://d2.naver.com/content/images/2015/06/helloworld-831311-7.png

๊ณผ

https://d2.naver.com/content/images/2015/06/helloworld-831311-8.png

์˜ ์ฐจ์ด๋Š” ๋ฌด์‹œํ•  ์ˆ˜ ์—†๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์‹ค์ œ ํ•ด์‹œ ๊ฐ’์€ ๊ท ๋“ฑ ๋ถ„ํฌ๊ฐ€ ์•„๋‹๋ฟ๋”๋Ÿฌ, ์„ค์‚ฌ ๊ท ๋“ฑ ๋ถ„ํฌ๋ฅผ ๋”ฐ๋ฅธ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ 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์€ ํ‚ค-๊ฐ’ ์Œ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ ์ผ์ • ๊ฐœ์ˆ˜ ์ด์ƒ์ด ๋˜๋ฉด, ํ•ด์‹œ ๋ฒ„ํ‚ท์˜ ๊ฐœ์ˆ˜๋ฅผ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฐ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•ด์‹œ ๋ฒ„ํ‚ท ๊ฐœ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๋ฉด

https://d2.naver.com/content/images/2015/06/helloworld-831311-7.png

๊ฐ’๋„ ์ž‘์•„์ ธ, ํ•ด์‹œ ์ถฉ๋Œ๋กœ ์ธํ•œ ์„ฑ๋Šฅ ์†์‹ค ๋ฌธ์ œ๋ฅผ ์–ด๋Š ์ •๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด์‹œ ๋ฒ„ํ‚ท ๊ฐœ์ˆ˜์˜ ๊ธฐ๋ณธ๊ฐ’์€ 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 ๊ฐ์ฒด์— ๋Œ€ํ•œ ํ•ด์‹œ ํ•จ์ˆ˜

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์„ ์Šน์ˆ˜๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

thread safe๋ž€? ํ•ด๊ฒฐ ๋ฐ ํšŒํ”ผ ๋ฐฉ๋ฒ•

์“ฐ๋ ˆ๋“œ์˜ ๋™๊ธฐํ™” ๊ณผ์ •(thread-safe)

๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ”„๋กœ์„ธ์Šค์˜ ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ๋‚ด์˜ ์ž์›์„ ๊ณต์œ ํ•ด์„œ ์ž‘์—…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ์˜ ์ž‘์—…์— ์˜ํ–ฅ์„ ์ฃผ๊ฒŒ ๋œ๋‹ค. (Heap, Method ์˜์—ญ, Runtime Constant Pool ์˜์—ญ์€ ์Šค๋ ˆ๋“œ๊ฐ„ ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ์˜์—ญ)

๋งŒ์•ฝ Thread1์ด ์ž‘์—…ํ•˜๋˜ ๋„์ค‘ ๋‹ค๋ฅธ Thread2์—๊ฒŒ ์ œ์–ด๊ถŒ์ด ๋„˜์–ด๊ฐ”์„ ๋•Œ, Thread1์ด ์ž‘์—…ํ•˜๋˜ ๊ณต์œ ๋ฐ์ดํ„ฐ๋ฅผ Thread2๊ฐ€ ์ž„์˜๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค๋ฉด, ๋‹ค์‹œ Thread1์ด ์ œ์–ด๊ถŒ์„ ๋„˜๊ฒจ๋ฐ›์•„ ๋‚˜๋จธ์ง€ ์ž‘์—…์„ ๋งˆ์ณค์„ ๋•Œ ์›๋ž˜ ์˜๋„ํ–ˆ๋˜ ๊ฒฐ๊ณผ์™€ ๋‹ค๋ฅด๊ฒŒ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ผ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ•œ ์“ฐ๋ ˆ๋“œ๊ฐ€ ํŠน์ • ์ž‘์—…์„ ๋๋งˆ์น˜๊ธฐ ์ „๊นŒ์ง€ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ์— ์˜ํ•ด ๋ฐฉํ•ด๋ฐ›์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”ํ•˜๋‹ค.

  • ์ž„๊ณ„ ์˜์—ญ : ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์˜์—ญ์„ ์ง€์ •
  • ๋ฝ : ๊ณต์œ  ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” lock์„ ํš๋“ํ•œ ๋‹จ ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ๋งŒ ์ด ์˜์—ญ ๋‚ด์˜ ์ฝ”๋“œ ์ˆ˜ํ–‰ ๊ฐ€๋Šฅ.

๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์˜์—ญ์„ ์ž„๊ณ„ ์˜์—ญ์œผ๋กœ ์ง€์ •ํ•ด๋†“๊ณ , ๊ณต์œ  ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” lock์„ ํš๋“ํ•œ ์“ฐ๋ ˆ๋“œ๋Š” ์ž„๊ณ„ ์˜์—ญ ๋‚ด์˜ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋ฒ—์–ด๋‚˜์„œ lock์„ ๋ฐ˜๋‚ฉํ•ด์•ผ๋งŒ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋ฐ˜๋‚ฉ๋œ lock์„ ํš๋“ํ•˜์—ฌ ์ž„๊ณ„์˜์—ญ์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ฒ˜๋Ÿผ ํ•œ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ง„ํ–‰ ์ค‘์ธ ์ž‘์—…์„ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๊ฐ„์„ญํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ๊ฒƒ์„ ๋™๊ธฐํ™”๋ผ๊ณ  ํ•œ๋‹ค.

์Šค๋ ˆ๋“œ๋ฅผ ๋™๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ synchronized๋ฅผ ์ด์šฉํ•ด์„œ ์ž„๊ณ„์˜์—ญ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

synchronized๋ฅผ ์ด์šฉํ•œ ๋™๊ธฐํ™”

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋™๊ธฐํ™” ๋ฐฉ๋ฒ•์ด๋ฉฐ, ์ด ํ‚ค์›Œ๋“œ๋Š” ์ž„๊ณ„ ์˜์—ญ์„ ์„ค์ •ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๋ฉ”์„œ๋“œ ์ „์ฒด๋ฅผ ์ž„๊ณ„ ์˜์—ญ์œผ๋กœ ์„ค์ •ํ•˜๊ฑฐ๋‚˜, ํŠน์ • ์˜์—ญ์„ ์ž„๊ณ„ ์˜์—ญ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

public synchronized void calcSum() {
	...
}

synchronized(๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ณ€์ˆ˜) {
	...
}

  • ๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ๋ฉ”์„œ๋“œ ๋‚ด์˜ ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ๋ธ”๋Ÿญ์œผ๋กœ ๊ฐ์‹ธ๊ณ  ๋ธ”๋Ÿญ ์•ž์— synchronized(์ฐธ์กฐ๋ณ€์ˆ˜) ๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋•Œ ์ฐธ์กฐ๋ณ€์ˆ˜๋Š” ๋ฝ์„ ๊ฑธ๊ณ ์ž ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์ด์–ด์•ผ ํ•œ๋‹ค.
  • ์ด ๋ธ”๋Ÿญ์„ synchronized ๋ธ”๋Ÿญ์ด๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ, ์ด ๋ธ”๋Ÿญ์˜ ์˜์—ญ ์•ˆ์œผ๋กœ ๋“ค์–ด๊ฐ€๋ฉด์„œ๋ถ€ํ„ฐ ์“ฐ๋ ˆ๋“œ๋Š” ์ง€์ •๋œ ๊ฐ์ฒด์˜ lock์„ ์–ป๊ฒŒ ๋˜๊ณ , ์ด ๋ธ”๋Ÿญ์„ ๋ฒ—์–ด๋‚˜๋ฉด lock์„ ๋ฐ˜๋‚ฉํ•œ๋‹ค.
  • ๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ lock์˜ ํš๋“๋œ ๋ฐ˜๋‚ฉ์ด ์ž๋™์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ ์ž„๊ณ„ ์˜์—ญ๋งŒ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ๋ชจ๋“  ๊ฐ์ฒด๋Š” lock์„ ํ•˜๋‚˜์”ฉ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ํ•ด๋‹น ๊ฐ์ฒด์˜ lock์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์“ฐ๋ ˆ๋“œ๋งŒ ์ž„๊ณ„ ์˜์—ญ์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

volatile์„ ์ด์šฉํ•œ ๋™๊ธฐํ™”

  • ๋ณ€์ˆ˜์˜ ๊ฐ€์‹œ์„ฑ ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ๋ณ€์ˆ˜์˜ ๊ฐ’์€ CPU ๋ฉ”๋ชจ๋ฆฌ์™€ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋œ๋‹ค. ์ด ๊ฐ’์„ CPU ๋ฉ”๋ชจ๋ฆฌ์ธ์ง€ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ๋ณ€์ˆ˜์˜ ๊ฐ€์‹œ์„ฑ ๋ฌธ์ œ์ด๋‹ค. ์ด๋ ‡๊ฒŒ CPU ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ’์„ ์ฝ์–ด๋“ค์ธ๋‹ค๋ฉด ๋งค์šฐ ์•ˆ์ „ํ•˜์ง€ ๋ชปํ•œ๋‹ค.
private volatile int counter; public int getNextUniqueIndex() { return counter++; }
์ถœ์ฒ˜: https://mygumi.tistory.com/112 [๋งˆ์ด๊ตฌ๋ฏธ์˜ HelloWorld]
  • volatile ํ‚ค์›Œ๋“œ๋ฅผ ๋ณ€์ˆ˜ ์•ž์— ์„ ์–ธํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋กœ์จ ๊ฐ€์‹œ์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. volatile์„ ์‚ฌ์šฉํ•˜๋ฉด counter ๋ณ€์ˆ˜๋ฅผ ์ฝ๊ณ  ์“ฐ๋Š” ๊ณผ์ •์€ ๋ชจ๋“  ์ฝ๊ธฐ ์“ฐ๊ธฐ ์—ฐ์‚ฐ์„ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ์—์„œ๋งŒ ์ฒ˜๋ฆฌ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ€์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ๋‹ค.
  • ๊ฒฝ์Ÿ ์ƒํƒœ(race condition) - ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ ๊ฐ™์€ ์‹œ์  ๋ณ€์ˆ˜๋ฅผ ์ฝ๋Š” ์ƒํƒœ. - ์ด๋Š” ํ•ด๊ฒฐ์ด ์•ˆ๋จ!
  • ์ฆ‰, volatile์˜ ๊ฒฝ์šฐ๋Š” ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์“ฐ๊ธฐ ์—ฐ์‚ฐ์„ ํ•˜๊ณ , ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ๋Š” ์ฝ๊ธฐ ์—ฐ์‚ฐ์„ ํ†ตํ•ด ์ตœ์‹  ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ๊ฒฝ์šฐ. ์ฆ‰ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ํ–‰ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Atomic

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]

Collection์˜ ์ข…๋ฅ˜์™€ ํŠน์ง•

  1. JAVA Collection Framework

JAVA์—์„œ ๊ธฐ๋ณธ์ ์ธ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•œ ํ™˜๊ฒฝ

JAVA Collection Framework์˜ ์ƒ์† ๊ธฐ๋ณธ ๊ตฌ์กฐ 2. ๊ฐ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํŠน์ง•

์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ํด๋ž˜์Šค ํŠน์ง• List LinkedList

Stack

Vector

ArrayList

์ˆœ์„œ๊ฐ€ ์žˆ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ง‘ํ•ฉ, ๋ฐ์ดํ„ฐ์˜ ์ค‘๋ณต์„ ํ—ˆ์šฉํ•จ Set HashSet

TreeSet

์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ์˜ ์ง‘ํ•ฉ, ๋ฐ์ดํ„ฐ์˜ ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Œ Map HashMap

TreeMap

HashTable

Properties

ํ‚ค(key)์™€ ๊ฐ’(value)์˜ ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐ์ดํ„ฐ์˜ ์ง‘ํ•ฉ

์ˆœ์„œ๋Š” ์œ ์ง€๋˜์ง€ ์•Š๊ณ , ํ‚ค๋Š” ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฉฐ ๊ฐ’์˜ ์ค‘๋ณต์„ ํ—ˆ์šฉํ•จ

  1. Collection ์ธํ„ฐํŽ˜์ด์Šค๋“ค์˜ ํŠน์ง•

Collection ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ List์™€ Set ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋œ๋‹ค. ๊ฐ€. List ์ธํ„ฐํŽ˜์ด์Šค์˜ ํŠน์ง•

์ˆœ์„œ๊ฐ€ ์žˆ๋Š” Collection(์—ฌ๊ธฐ์„œ ์ˆœ์„œ๋Š” ์‚ฝ์ž…๋œ ์ˆœ์„œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.) Data๋ฅผ ์ค‘๋ณตํ•ด์„œ ํฌํ•จ ํ•  ์ˆ˜ ์žˆ๋‹ค. (1). LinkedList์˜ ํŠน์ง•

LinkedList๋งŒ ์ •์˜ํ•œ ๋‚ด์šฉ์ด ์žˆ์œผ๋‹ˆ ์•„๋ž˜ ์ฃผ์†Œ ์ฐธ๊ณ  https://hwan1001.tistory.com/5

[JAVA] ์ž๋ฃŒ๊ตฌ์กฐ ํด๋ž˜์Šค - LinkedList(์—ฐ๊ฒฐ๋ฆฌ์ŠคํŠธ)

  1. 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๋ฅผ ์‚ฌ์šฉ

  1. 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 ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

n+1 ์ฟผ๋ฆฌ ๋ฌธ์ œ๋ž€?

์˜ˆ์‹œ)

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์„ ๋งŒ๋“ ๋‹ค.

  1. select o from Order o JPQL์„ ๋ถ„์„ํ•ด์„œ select * from Order SQL์„ ์ƒ์„ฑํ•œ๋‹ค.
  2. DB์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ order ์—”ํ‹ฐํ‹ฐ ์ธ์Šคํ„ด์Šค๋“ค์„ ์ƒ์„ฑํ•œ๋‹ค.
  3. Order.member์˜ ๊ธ€๋กœ๋ฒŒ ํŽ˜์น˜ ์ „๋žต์ด ์ฆ‰์‹œ ๋กœ๋”ฉ์ด๋ฏ€๋กœ order๋ฅผ ๋กœ๋”ฉํ•˜๋Š” ์ฆ‰์‹œ ์—ฐ๊ด€๋œ member๋„ ๋กœ๋”ฉํ•ด์•ผ ํ•œ๋‹ค.
  4. ์—ฐ๊ด€๋œ member๋ฅผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ์ฐพ๋Š”๋‹ค.
  5. ๋งŒ์•ฝ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์—†์œผ๋ฉด SELECT * FROM MEMBER WHERE id=? SQL์„ ์กฐํšŒํ•œ order ์—”ํ‹ฐํ‹ฐ ์ˆ˜๋งŒํผ ์‹คํ–‰ํ•œ๋‹ค. โ‡’ ๋งŒ์•ฝ ์กฐํšŒํ•œ order ์—”ํ‹ฐํ‹ฐ๊ฐ€ 10๊ฐœ์ด๋ฉด member๋ฅผ ์กฐํšŒํ•˜๋Š” SQL๋„ 10๋ฒˆ ์‹คํ–‰๋œ๋‹ค.

์ด์ฒ˜๋Ÿผ ์ฒ˜์Œ ์กฐํšŒํ•œ ๋ฐ์ดํ„ฐ ์ˆ˜๋งŒํผ, ๋‹ค์‹œ SQL์„ ์‚ฌ์šฉํ•ด์„œ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์„ N+1 ๋ฌธ์ œ๋ผ๊ณ  ํ•œ๋‹ค.

N+1์ด ๋ฐœ์ƒํ•˜๋ฉด SQL์ด ์ƒ๋‹นํžˆ ๋งŽ์ด ํ˜ธ์ถœ๋˜๋ฏ€๋กœ ์กฐํšŒ ์„ฑ๋Šฅ์— ์น˜๋ช…์ ์ด๋‹ค.

์ด๋Ÿฌํ•œ N+1 ๋ฌธ์ œ๋Š” JPQL ํŽ˜์น˜ ์กฐ์ธ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

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 ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ํ™”๋ฉด์— ํ•„์š”ํ•œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ฏธ๋ฆฌ ๋กœ๋”ฉํ•˜๋Š” ํ˜•์‹์ ์ธ ๋ฐฉ๋ฒ•์ด๋‹ค.

JPQL ํŽ˜์น˜ ์กฐ์ธ์˜ ๋‹จ์ 

ํŽ˜์น˜ ์กฐ์ธ์ด ํ˜„์‹ค์ ์ธ ๋Œ€์•ˆ์ด๊ธด ํ•˜์ง€๋งŒ ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ํ™”๋ฉด์— ๋งž์ถ˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฒฐ๊ตญ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ๊ณ„์ธต(view)์ด ์•Œ๊ฒŒ๋ชจ๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต(repository)์„ ์นจ๋ฒ”ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ฐ ํ™”๋ฉด๋งˆ๋‹ค ์ฆ‰์‹œ๋กœ๋”ฉ, ์ง€์—ฐ ๋กœ๋”ฉ์˜ ์š”๊ตฌ์‚ฌํ•ญ์ด ๋‹ค๋ฅด๋‹ค๋ฉด ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ , ๊ฐ ํ™”๋ฉด์—์„œ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ตœ์ ํ™” ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ทฐ์™€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ฐ„์— ๋…ผ๋ฆฌ์ ์ธ ์˜์กด๊ด€๊ณ„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๋Ÿด๋• ๋ฌด๋ถ„๋ณ„ํ•œ ์ตœ์ ํ™”๋กœ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ๊ณ„์ธต๊ณผ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต ๊ฐ„์— ์˜์กด๊ด€๊ณ„๊ฐ€ ๊ธ‰๊ฒฉํ•˜๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ์ ์ ˆํ•œ ์„ ์—์„œ ํƒ€ํ˜‘์ ์„ ์ฐพ๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด๋‹ค.

๊ฐ•์ œ๋กœ ์ดˆ๊ธฐํ™”

๊ฐ•์ œ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ ์‚ด์•„์žˆ์„ ๋•Œ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ๊ณ„์ธต์ด ํ•„์š”ํ•œ ์—ฐ๊ด€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ฐ•์ œ๋กœ ์ดˆ๊ธฐํ™”ํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. (๊ธ€๋กœ๋ฒŒ ํŽ˜์น˜ ์ „๋žต์ด ์ง€์—ฐ ๋กœ๋”ฉ์ผ ๋•Œ ์‚ฌ์šฉ)

class OrderService {
	@Transactional
	public Order findOrder(id) {
		Order order = repository.findOrder(id);
		order.getMember().getName();  // ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ๊ฐ•์ œ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
		return order;
	}
}

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

์˜ˆ๋ฅผ ๋“ค์–ด, order.getMember() ๊นŒ์ง€๋งŒ ํ˜ธ์ถœํ•˜๋ฉด ๋‹จ์ˆœํžˆ ํ”„๋ก์‹œ ๊ฐ์ฒด๋งŒ ๋ฐ˜ํ™˜๋˜๊ณ  ์•„์ง ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” member.getName() ์ฒ˜๋Ÿผ ์‹ค์ œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ์‹œ์ ์— ์ดˆ๊ธฐํ™”๋œ๋‹ค.

@ControllerAdvice, @ExceptionHandler์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์‹œ์˜ค

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๊ณผ์ • ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ์•„์ฃผ ์ค‘์š”ํ•˜๋ฉด์„œ๋„ ์•„์ฃผ ์–ด๋ ต๋‹ค.

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

์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๋ฐฉ๋ฒ•์€ ๋‹ค์–‘ํ•˜๋‹ค.

๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์˜ˆ์™ธ ์ƒํ™ฉ์„ ์˜ˆ์ธกํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” 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 [๊ธฐ๋ณธ๊ธฐ๋ฅผ ์Œ“๋Š” ์ •์•„๋งˆ์ถ”์–ด ์ฝ”๋”ฉ๋ธ”๋กœ๊ทธ]

๋Œ€์นญํ‚ค ์•”ํ˜ธํ™”์™€ ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๋ฐฉ์‹์˜ ์ฐจ์ด

๊ฐœ์ธํ‚ค = ๋น„๋ฐ€ํ‚ค = ๋น„๊ณต๊ฐœํ‚ค

๊ณต๊ฐœํ‚ค ๊ธฐ๋ฒ• = ๋น„๋Œ€์นญํ‚ค ๊ธฐ๋ฒ•

์•”ํ˜ธํ™”์™€ ๋ณตํ˜ธํ™”์— ์‚ฌ์šฉํ•˜๋Š” ์•”ํ˜ธํ‚ค๊ฐ€ ๊ฐ™์€์ง€ ๋‹ค๋ฅธ์ง€์— ๋”ฐ๋ผ ์•”ํ˜ธํ™” ๊ธฐ๋ฒ•์ด ๋Œ€์นญํ‚ค ๊ธฐ๋ฒ•๊ณผ ๋น„๋Œ€์นญํ‚ค ๊ธฐ๋ฒ•์œผ๋กœ ๋‚˜๋‰˜์–ด ์ง„๋‹ค.

  1. ๋Œ€์นญํ‚ค ์•”ํ˜ธ
  • ํ•˜๋‚˜์˜ ๋น„๋ฐ€ํ‚ค๋ฅผ ์–‘์ชฝ(client & server)๊ฐ€ ๋ชจ๋‘ ๊ฐ™์ด ์‚ฌ์šฉ

  • ์•”ํ˜ธํ™”์™€ ๋ณตํ˜ธํ™”์— ์‚ฌ์šฉํ•˜๋Š” ํ‚ค๊ฐ€ ๊ฐ™์€ ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๊ณต๊ฐœํ‚ค์™€ ๋น„๋ฐ€ํ‚ค๋ฅผ ๋ณ„๋„๋กœ ๊ฐ€์ง€๋Š” ๊ฒƒ๊ณผ ๊ตฌ๋ณ„๋˜๋Š”๋ฐ, ์ด์™€ ๋น„๊ตํ•˜๋ฉด ๊ณ„์‚ฐ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค๋Š” ์žฅ์ 

  • ๋น„๋ฐ€ํ‚ค ํ•˜๋‚˜๋งŒ ์•Œ์•„๋‚ด๋ฉด ์•”ํ˜ธํ™”๋œ ๋‚ด์šฉ์„ ํ•ด๋… ๊ฐ€๋Šฅ โ†’ ํ•ด์ปค๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ X

  • ๋Œ€ํ‚นํ‚ค ์•”ํ˜ธ๋Š” ์•”ํ˜ธํ™”ํ•˜๋Š” ๋‹จ์œ„์— ๋”ฐ๋ผ ์ŠคํŠธ๋ฆผ์•”ํ˜ธ์™€ ๋ธ”๋ก์•”ํ˜ธ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Œ

ยบ ์ŠคํŠธ๋ฆผ์•”ํ˜ธ๋Š” ์—ฐ์†์ ์ธ ๋น„ํŠธ/๋ฐ”์ดํŠธ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ž…๋ ฅ๋ฐ›์•„, ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” ์•”ํ˜ธํ™” ๋น„ํŠธ/๋งˆ์ดํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹

ยบ ๋ธ”๋ก์•”ํ˜ธ๋Š” ์ •ํ•ด์ง„ ํ•œ ๋‹จ์œ„(๋ธ”๋ก)์„ ์ž…๋ ฅ๋ฐ›์•„ ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” ์•”ํ˜ธํ™” ๋ธ”๋ก์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹

ยบ ๋ธ”๋ก์•”ํ˜ธ์˜ ๊ฒฝ์šฐ ์ ์ ˆํ•œ ์šด์šฉ๋ชจ๋“œ๋ฅผ ์กฐํ•ฉํ•˜๋ฉด ๋ธ”๋ก ๋‹จ์œ„๋ณด๋‹ค ํฐ ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ. ๋˜ํ•œ ์ŠคํŠธ๋ฆผ์•”ํ˜ธ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ง€์†์ ์ธ ์ž…๋ ฅ์— ๋Œ€ํ•ด ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Œ. (๋Œ€์‹  ์ž…์ถœ๋ ฅ ๋‹จ์œ„๋Š” ์ŠคํŠธ๋ฆผ์•”ํ˜ธ๋ณด๋‹ค ํฐ ๋ธ”๋ก ๋‹จ์œ„๊ฐ€ ๋จ)

  • ๋Œ€ํ‚นํ‚ค ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ์•”ํ˜ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฐฉ์‹์œผ๋กœ DES, 3-DES, AES, SEED, ARIA, MASK ๋“ฑ์ด ์žˆ๋‹ค.
  1. ๊ณต๊ฐœํ‚ค ์•”ํ˜ธ
  • ๋น„๋ฐ€ํ‚ค ํ•˜๋‚˜ ๋งŒ ๊ฐ€์ง€๋Š” ๋Œ€์นญํ‚ค ์•”ํ˜ธ ๋ฐฉ๋ฒ•๊ณผ ๋‹ฌ๋ฆฌ, ๊ณต๊ฐœํ‚ค์™€ ๋น„๋ฐ€ํ‚ค ๋‘ ๊ฐœ๊ฐ€ ์กด์žฌ

  • ๊ณต๊ฐœํ‚ค ์•”ํ˜ธ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋Œ€์นญํ‚ค ์•”ํ˜ธ ๋ฐฉ์‹๊ณผ ๋น„๊ตํ•˜์—ฌ ๋น„๋Œ€์นญ ์•”ํ˜ธ๋ผ๊ณ  ๋ถˆ๋ฆผ

  • ์•”ํ˜ธํ™”์™€ ๋ณตํ˜ธํ™”์— ์‚ฌ์šฉํ•˜๋Š” ํ‚ค๊ฐ€ ์„œ๋กœ ๋‹ค๋ฆ„

  • ์•”ํ˜ธํ™”ํ•  ๋•Œ์˜ ํ‚ค๋Š” ๊ณต๊ฐœํ‚ค(public key), ๋ณตํ˜ธํ™”ํ•  ๋•Œ์˜ ํ‚ค๋Š” ๊ฐœ์ธํ‚ค(private key)

  • ๊ณต๊ฐœํ‚ค๋Š” ๋ˆ„๊ตฌ๋‚˜ ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” ๋น„๋ฐ€ํ‚ค๋Š” ํ‚ค์˜ ์†Œ์œ ์ž๋งŒ์ด ์•Œ ์ˆ˜ ์žˆ์–ด์„œ

    ํŠน์ •ํ•œ ๋น„๋ฐ€ํ‚ค๋ฅผ ๊ฐ€์ง€๋Š” ์‚ฌ์šฉ์ž๋งŒ์ด ๋‚ด์šฉ์„ ์—ด์–ด๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ฐฉ์‹.

์†ก์‹ ์ž๋Š” ์ˆ˜์‹ ์ž์˜ ๊ณต๊ฐœํ‚ค๋ฅผ ๋ฐ›์•„ ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”ํ•˜์—ฌ

๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์›๊ฒฉ์ง€์— ์ „๋‹ฌ.

์ˆ˜์‹ ์ž๋Š” ๊ณต๊ฐœํ‚ค๋กœ ์•”ํ˜ธํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ž์‹ ์˜ ๊ฐœ์ธํ‚ค๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณตํ˜ธํ™”ํ•˜์—ฌ ํ‰๋ฌธ์„ ๋ณต์›.

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

  • ๋Œ€์นญํ‚ค(๋น„๋ฐ€ํ‚ค)์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋น„ํ•˜์—ฌ ์†๋„๊ฐ€ ๋Š๋ฆฌ๋‹ค. (์•ฝ 1000๋ฐฐ)

  • ์†๋„๊ฐ€ ๋Š๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ๊ธด๋ฌธ์„œ์˜ ์•”ํ˜ธํ™”ํ•˜๋Š” ๊ฒฝ์šฐ๋ณด๋‹ค ๋Œ€์นญํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ‚ค๊ฐ’์— ๋Œ€ํ•œ ์•”ํ˜ธ์— ์‚ฌ์šฉ.

  • ๋Œ€ํ‘œ์ ์ธ ๊ณต๊ฐœํ‚ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ RSA, Elgamal ๋“ฑ์ด ์žˆ์Œ.

๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™” ๊ฐœ๋…๋„

โ€ป ๋น„๋ฐ€ํ‚ค ์•”ํ˜ธํ™”์™€ ๊ณต๊ฐœํ‚ค ์•”ํ˜ธํ™”์˜ ๋น„๊ต

NginX์™€ Apache ๋น„๊ต

์•„ํŒŒ์น˜ ( 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์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ( ๊ณต์‹ ์‚ฌ์ดํŠธ - ๋งํฌ )

  1. ( RUN-TIME ) Loadable MPMS

Apaceh 2.2๊นŒ์ง€๋Š” Multi-Processing Modules ( MPMS )๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ปดํŒŒ์ผ ์„ค์น˜๋ฅผ ํ•  ๋•Œ ๊ฒฐ์ •์ง€์–ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ Apache 2.4๋ถ€ํ„ฐ๋Š” ๋Ÿฐํƒ€์ž„์—์„œ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก Loadable Module ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Apache 2.4 ์ปดํŒŒ์ผ ์„ค์น˜ํ•  ๋•Œ ์ˆ˜ํ–‰ํ•˜๋Š” Configure์—์„œ โ€“enable-mpms-shared ์˜ต์…˜์œผ๋กœ ์„ค์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  1. Event MPM

Apache 2.2๊นŒ์ง€๋Š” Event Driven ๋ฐฉ์‹์„ ์ง€์›ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

Evnet MPM ๋ฐฉ์‹์€ Keep Alive์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์—์„œ ์ถœ๋ฐœํ•œ ์ƒˆ๋กœ์šด MPM ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์ด ๋ฐฉ์‹์€ ์‚ฌ์šฉ์ž ์š”์ฒญ๊ณผ Keep Aliveํ•œ Apache์˜ ์š”์ฒญ์„ ๊ทธ๋Œ€๋กœ ๋งบ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์“ฐ๋ ˆ๋“œ๋ฅผ ๋”ฐ๋กœ ๋‘์–ด ๋ถ„์‚ฐ๋œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š”๋ฐ ๊ทธ ๋ชฉ์ ์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  1. Asynchronous Support

๋น„๋™๊ธฐ ์ฝ๊ณ /์“ฐ๊ธฐ์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค

(๋”ฐ๋กœ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ํ•˜๋Š” ๊ฒƒ์€ ์—†๊ณ  ๋‚ด๋ถ€ ๊ตฌ์กฐ์ ์œผ๋กœ ์ง€์›ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. )

  1. NameVirtualHost Deprecated

Apache 2.4 ์—์„œ๋Š” NameVirtualHost๊ฐ€ ์•ž์œผ๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ์˜ต์…˜์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

NameVritualHost ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” ๋” ์ด์ƒ ์–ด๋– ํ•œ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉฐ, ์ž‘์„ฑ ์‹œ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๋Œ€์‹  ๋ฌต์‹œ์ ์œผ๋กœ ๋‹ค๋ฃจ์–ด์ง„๋‹ค๊ณ  ํ•˜๋Š”๋ฐ, ์ด๋Š” httpd.conf ํŒŒ์ผ์—์„œ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋ฌต์‹œ์ ์œผ๋กœ ์ธ์‹ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

NameVirtualHost *:80

  1. 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

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