๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Today I Learned(TIL)/์ŠคํŒŒ๋ฅดํƒ€ ๋‚ด์ผ๋ฐฐ์›€์บ ํ”„

[ TIL ] ์ฃผํŠน๊ธฐ ์‹ฌํ™”_Day 4

by carrot0911 2025. 1. 2.

์˜ค๋Š˜ ํ•œ ๊ณต๋ถ€ ๐Ÿง 

  • ๊ฐœ์ธ ๊ณผ์ œ ํ•„์ˆ˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ์ˆ˜์ค€๋ณ„ ํ•™์Šต๋ฐ˜ ์Šคํƒ ๋‹ค๋“œ๋ฐ˜ ์„ธ์…˜ ๋“ฃ๊ธฐ
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹ค์Šต ์„ธ์…˜ ๋“ฃ๊ธฐ
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

 

์˜ค๋Š˜ ์–ป์€ ๋‚ด์šฉ ์ •๋ฆฌ โœ๏ธ 

๊ฐœ์ธ ๊ณผ์ œ ํ•„์ˆ˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„

ํŠœํ„ฐ๋‹˜ ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜ํ•ด์„œ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง

  • Setter๋กœ ๋˜์–ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ช… ๋ฐ”๊พธ๊ธฐ
    • Comment์™€ Todo Entity์˜ setMember, serTodo ๋ฉ”์„œ๋“œ๋ฅผ updateMember, updateTodo๋กœ ๋ฐ”๊ฟ”์ฃผ์—ˆ๋‹ค.
  • Comment ์ƒ์„ฑ์ž์—์„œ User์™€ Todo๋ฅผ ๊ฐ™์ด ๋ฐ›์œผ๋ฉด Comment๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋‘ Entity๋ฅผ ๋„ฃ์ง€ ์•Š๋Š” ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • update ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ์ƒ์„ฑ์ž ์•ˆ์— ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์Œ์œผ๋กœ์จ ๋นผ๋จน๋Š” ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.
    • ์ถ”๊ฐ€์ ์œผ๋กœ Todo์˜ ์ƒ์„ฑ์ž์—๋„ Member๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •ํ–ˆ๋‹ค.
    • ๊ทธ ํ›„ ํ•„์š”์—†์–ด์ง„ update ๋ฉ”์„œ๋“œ๋“ค์„ ๋ชจ๋‘ ์ง€์›Œ๋ฒ„๋ ธ๋‹ค!
  • ๋กœ๊ทธ์ธ์ด ๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ Filter์—์„œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š”๋ฐ 401 Error๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋ณ€๊ฒฝํ–ˆ๋‹ค.
    • GlobalExceptionHandler๋ฅผ ์ด์šฉํ•ด์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ–ˆ๋‹ค.
      Filter์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ์— ๋Œ€ํ•ด์„œ๋Š” ์ ์šฉ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.
           Spring์˜ DispatcherServlet ์ดํ›„ ์ปจํŠธ๋กค๋Ÿฌ ๋ ˆ๋ฒจ์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋™์ž‘ํ•œ๋‹ค.
  • GlobalExceptionHandler๋ฅผ ํ™œ์šฉํ•ด์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ง„ํ–‰ํ–ˆ๋‹ค.
    • AuthService
      • MemberNotFoundException ์ƒ์„ฑ ํ›„ ํšŒ์›์„ ์ฐพ์„ ์ˆ˜ ์—†์„ ๋•Œ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์™„๋ฃŒ
      • InvalidPasswordException ์ƒ์„ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๋•Œ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์™„๋ฃŒ
    • CommentService
      • CommentNotFoundException ์ƒ์„ฑ ํ›„ ๋Œ“๊ธ€์„ ์ฐพ์„ ์ˆ˜ ์—†์„ ๋•Œ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์™„๋ฃŒ
    • MemberService
      • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ „๋ถ€ ์ˆ˜์ • ์™„๋ฃŒ
    • TodoService
      • TodoNotFoundException ์ƒ์„ฑ ํ›„ ์ผ์ •์„ ์ฐพ์„ ์ˆ˜ ์—†์„ ๋•Œ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์™„๋ฃŒ
  • @Valid๋ฅผ ํ†ตํ•ด์„œ ์ƒ์„ฑ๋˜๋Š” ์˜ˆ์™ธ๋„ ์ฒ˜๋ฆฌํ–ˆ๋‹ค.
    • GlobalExceptionHandler์— ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

์Šคํƒ ๋‹ค๋“œ๋ฐ˜ ์„ธ์…˜ ๋“ฃ๊ธฐ

  • @Transactional ๊ฐœ๋… ๋ฐ•์‚ด ๋‚ด๊ธฐ!
    • ์ด๋ฒˆ ์ฃผ ์•ˆ์œผ๋กœ ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•˜๊ธฐ โœ๏ธ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹ค์Šต ์„ธ์…˜ ๋“ฃ๊ธฐ

  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•˜๋Š”์ง€ ํŠœํ„ฐ๋‹˜๊ณผ ํ•จ๊ป˜ ์‹ค์Šต!!
    • ๋…นํ™”๋ณธ ๋‹ค์‹œ ๋ณด๋ฉด์„œ ์ถ”๊ฐ€์ ์ธ ์ดํ•ด ํ•„์š”!

๊ถ๊ธˆํ–ˆ๋˜ ์ 

ํŠœํ„ฐ๋‹˜์˜ ํ”ผ๋“œ๋ฐฑ ์ค‘ ๋‚ด๊ฐ€ ์ดํ•ดํ•œ ๋‚ด์šฉ์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ ํŠœํ„ฐ๋‹˜๊ป˜ ์ฐพ์•„๊ฐ”๋‹ค!

  • Comment ์ƒ์„ฑ์ž์—์„œ User์™€ Todo๋ฅผ ๊ฐ™์ด ๋ฐ›์œผ๋ฉด Comment๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋‘ Entity๋ฅผ ๋„ฃ์ง€ ์•Š๋Š” ์‹ค์ˆ˜๋„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ถ€๋ถ„์ด update ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์ƒ์„ฑ์ž์— ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ฐ€์ ธ๊ฐ์œผ๋กœ์จ ๋น ๋œจ๋ฆฌ๋Š” ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ธ์ง€ ๊ถ๊ธˆํ–ˆ๋‹ค.
    • ๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ ๋ฐฉํ–ฅ์ด ๋งž์•˜๋‹ค!
    • update ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์žก์•„์ค„ ์ˆ˜ ์—†๋‹ค.
    • ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ๋ฌธ์ œ๋ฅผ ์žก์„ ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์šฐ๋ฆฌ์˜ ์ผ์ด๋‹ค!
  • ์ถ”๊ฐ€์ ์œผ๋กœ ControllerAdvice๊ฐ€ ์–ด๋””๊นŒ์ง€์˜ ์˜ˆ์™ธ๋ฅผ ์žก์•„์ค„ ์ˆ˜ ์žˆ๋Š”์ง€ ํ•จ๊ป˜ ์ฐพ์•„๋ณด๋ฉด์„œ ์ง„ํ–‰ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ํ•˜์…จ๋‹ค.

ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

Filter์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ GlobalExceptionHandler๋ฅผ ์ด์šฉํ•ด์„œ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ Postman์„ ์‹คํ–‰ํ–ˆ์„ ๋•Œ 500 Internal Error๊ฐ€ ๊ณ„์† ๋ฐœ์ƒํ–ˆ๋‹ค.

  • @RestControllerAdvice๋Š” Filter์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ์— ๋Œ€ํ•ด์„œ๋Š” ์ ์šฉ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • Spring์˜ DispatcherServlet ์ดํ›„ ์ปจํŠธ๋กค๋Ÿฌ ๋ ˆ๋ฒจ์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋™์ž‘ํ•œ๋‹ค.
  • ์ง์ ‘ ์—์–ด ์ฝ”๋“œ์™€ ๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•ด์„œ ์ถœ๋ ฅ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
if (session == null || session.getAttribute("loginMember") == null) {
    httpResponse.setCharacterEncoding("UTF-8"); // UTF-8๋กœ ์ธ์ฝ”๋”ฉ ์„ค์ •
    httpResponse.setContentType("application/json; charset=UTF-8"); // Content-Type ์„ค์ •
    httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());

    Map<String, String> errorResponse = new HashMap<>();
    errorResponse.put("errorCode", "401 UNAUTHORIZED");
    errorResponse.put("error", "๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ ํ•ด์ฃผ์„ธ์š”.");

    ObjectMapper objectMapper = new ObjectMapper();
    String jsonResponse = objectMapper.writeValueAsString(errorResponse);

    httpResponse.getWriter().write(jsonResponse);

    return;
}

 

์˜ค๋Š˜ ํ•˜๋ฃจ ์ •๋ฆฌ โœ๏ธ

์ƒ๊ฐ๋ณด๋‹ค ์˜ค๋Š˜ ์‹œ๊ฐ„์ด ๋น ๋ฅด๊ฒŒ ์ง€๋‚˜๊ฐ”๋‹ค.

์˜ค์ „์—๋Š” ๊ฐœ์ธ ๊ณผ์ œ ํ•„์ˆ˜ ๊ธฐ๋Šฅ์„ ์‹œ์ž‘ํ–ˆ๋‹ค!
Lv1์€ ํŠœํ„ฐ๋‹˜์˜ ํ”ผ๋“œ๋ฐฑ์„ ๊ณผ์ œ์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋Š”๋ฐ ํ•„์š” ์—†๋Š” ์ฝ”๋“œ๋Š” ์—†์• ๊ณ  ์‹ค์ˆ˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์„ ํ•˜๋‚˜์˜ ์ฝ”๋“œ๋กœ ํ•ฉ์น˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง์„ ์ง„ํ–‰ํ–ˆ๋‹ค.Lv 2์—์„œ๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์™€ @Valid๋ฅผ ์ด์šฉํ•ด์„œ ๊ธฐ๋Šฅ์„ ๊ฐœ์„ ํ•ด์•ผ ํ–ˆ๋‹ค. Valid ๋ถ€๋ถ„์€ ์ „์— ๊ณผ์ œํ•  ๋•Œ ์ ์šฉํ–ˆ์–ด์„œ ์‰ฝ๊ฒŒ ๋งˆ๋ฌด๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๋ฌธ์ œ๋Š” GlobalExceptionHandler๋ฅผ ์ด์šฉํ•ด์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ถ€๋ถ„์ด์—ˆ๋‹ค. ์•„์ง ํ•œ ๋ฒˆ๋„ ํ•ด๋ณธ ์  ์—†๋Š” ํŒŒํŠธ์—ฌ์„œ ๊ฒ์ด ๋‚ฌ์ง€๋งŒ ์ธํ„ฐ๋„ท์„ ์ฐพ์•„๋ณด๋ฉด์„œ ํ๋ฆ„์„ ์ดํ•ดํ•˜๊ณ  Filter์—์„œ ๋กœ๊ทธ์ธํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ์‹คํ–‰ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ถ€๋ถ„์„ ์žก์œผ๋ ค๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ƒ๊ฐ์ด๋ž‘ ๋‹ค๋ฅด๊ฒŒ ๊ณ„์† ์˜ˆ์™ธ๊ฐ€ ์žกํžˆ์ง€ ์•Š๊ณ  500 Internal Error๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ๋ญ”๊ฐ€ ์ด์ƒํ•จ์„ ๋Š๋ผ๊ณ  ํŠœํ„ฐ๋‹˜์ด ์ถฉ๊ณ ํ•ด ์ฃผ์…จ๋˜ @RestControllerAdvice์˜ ๋ฒ”์œ„๋ฅผ ์ฐพ์•„๋ณด์•˜๋‹ค. ์ด๋Ÿด ์ˆ˜๊ฐ€.... ๋ฒ”์œ„๊ฐ€ Spring์˜ DispatcherServlet ์ดํ›„ ์ปจํŠธ๋กค๋Ÿฌ ๋ ˆ๋ฒจ์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ๋™์ž‘ํ•œ๋‹ค. ์ฆ‰ Filter์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋Š” ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ธํ„ฐ๋„ท์„ ์ฐพ์•„๋ณด๋ฉด์„œ Filter์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ณ  ๊ณผ์ œ์— ์ ์šฉํ–ˆ๋‹ค.

์˜ค์ „์—๋Š” ์ด๋ ‡๊ฒŒ ์ •์‹ ์—†์ด ๋ณด๋‚ด๊ณ  ์˜คํ›„์—๋Š” ์„ธ์…˜์˜ ์—ฐ์†์ด์—ˆ๋‹ค.
2์‹œ์— ์Šคํƒ ๋‹ค๋“œ๋ฐ˜ ์„ธ์…˜์„ ๋“ค์—ˆ๋‹ค. @Transactional์— ๋Œ€ํ•œ ๊ฒƒ์„ ์‹ค์Šต๊ณผ ํ•จ๊ป˜ ์•Œ์•„๋ดค๋Š”๋ฐ, ํŠธ๋žœ์žญ์…˜๊ณผ ๊ฐ€๊นŒ์šด ๋“ฏ ๋จผ ๊ทธ๋Ÿฐ ์‚ฌ์ด๊ฐ€ ๋˜์–ด๋ฒ„๋ ธ๋‹ค. ๋ณต์Šต์„ ํ†ตํ•ด ์ข€ ๋” ๊ฐ€๊นŒ์›Œ์งˆ ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•ด์•ผ๊ฒ ๋‹ค. ๐Ÿฅฒ๐Ÿฅฒ
4์‹œ์—๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹ค์Šต ์„ธ์…˜์„ ๋“ค์—ˆ๋‹ค. ์–ด๋–ค ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์ž‘์„ฑ๋˜๋Š”์ง€ ํ๋ฆ„์„ ํ•จ๊ป˜ ๋ณด๋ฉด์„œ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์กŒ๋Š”๋ฐ ์„ธ์…˜์„ ๋“ค์œผ๋ฉด์„œ ๊ฒจ์šฐ๊ฒจ์šฐ ์ฝ”๋“œ๋งŒ ๋”ฐ๋ผ ์น˜๋Š” ๊ผด์ด ๋˜์—ˆ๋‹ค.. ์ค‘๊ฐ„์ค‘๊ฐ„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ ์ดํ•ด๋ฅผ ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์ „์ฒด๋ฅผ ์ดํ•ดํ•˜๊ธฐ์—” ๋ฌด๋ฆฌ์˜€๋‹ค...

๊ทธ๋ž˜์„œ ์ €๋…์„ ๋จน๊ณ  7์‹œ์— ์ถ”๊ฐ€๋กœ ์ง„ํ–‰๋œ ์„ธ์…˜์„ ํ†ตํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•ด ๋ณด๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ๋‹ค! ํŠœํ„ฐ๋‹˜์˜ ์ถ”๊ฐ€์ ์ธ ์„ค๋ช…์„ ํ†ตํ•ด ์–ด๋Š ์ •๋„ ๋” ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์•„์ง ๋งŽ์ด ๋ถ€์กฑํ•œ ๋Š๋‚Œ์ด๋ผ์„œ ๋…นํ™”๋ณธ์„ ๋ณด๋ฉด์„œ ์ถ”๊ฐ€์ ์ธ ๊ณต๋ถ€๊ฐ€ ํ•„์š”ํ•ด ๋ณด์˜€๋‹ค...
ํŠœํ„ฐ๋‹˜๋„ ์•„์ง ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋งˆ์Šคํ„ฐํ•˜์ง€ ๋ชปํ•œ ๊ฑธ ๋ณด๋ฉด.. ์‰ฝ์ง€ ์•Š์€ ๋…€์„์ธ ๊ฒƒ ๊ฐ™๋‹ค.

ํ›„.. ์˜ค๋Š˜๋„ ๋ญ”๊ฐ€ ์ด๊ฒƒ์ €๊ฒƒ ๋งŽ์€ ๊ฒƒ๋“ค์ด ๋จธ๋ฆฟ์†์œผ๋กœ ๋“ค์–ด์˜จ ๋Š๋‚Œ์ด๋‹ค..
๋‹ค ์†Œํ™”ํ•  ์ˆœ ์—†๊ฒ ์ง€๋งŒ ๋…นํ™”๋ณธ์„ ํ™œ์šฉํ•ด์„œ ์ „๋ถ€ ๋‚ด ๊ฒƒ์œผ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๊ณ„์† ๋…ธ๋ ฅํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.
์•„์ง ์ด๋ฒˆ ์ฃผ ๊ธˆ, ํ† , ์ผ์ด ๋‚จ์•„์žˆ์œผ๋‹ˆ๊นŒ ๋˜ ์—ด์‹ฌํžˆ ๊ณต๋ถ€ํ•ด ๋ณด์ž!!! ํŒŒ์ดํŒ…!!!!!!!!!!! ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ

 

๋‚ด์ผ ๊ณ„ํš โฐ

  • ๊ฐœ์ธ ๊ณผ์ œ ๋„์ „ ๊ธฐ๋Šฅ ์‹œ์ž‘!
  • @Transactional์— ๋Œ€ํ•œ ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

+ ์ถ”๊ฐ€๋กœ ๊ณ„ํš์ด ๋” ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šด๋‹ค~_~