{"id":10883,"date":"2025-09-07T12:02:00","date_gmt":"2025-09-07T03:02:00","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=10883"},"modified":"2025-10-13T13:25:20","modified_gmt":"2025-10-13T04:25:20","slug":"transactional-%ea%b3%bc-exception-%ea%b7%b8%eb%a6%ac%ea%b3%a0-%eb%a1%9c%ea%b7%b8-%ec%a0%80%ec%9e%a5","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=10883","title":{"rendered":"Transactional \uacfc Exception \uadf8\ub9ac\uace0 \ub85c\uadf8 \uc800\uc7a5"},"content":{"rendered":"<h1>Transactional \uacfc Exception \uadf8\ub9ac\uace0 \ub85c\uadf8 \uc800\uc7a5<\/h1>\n<p>\uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ub85c\uadf8\ub97c \uc800\uc7a5\ud558\uace0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\ub824 \ud55c\ub2e4.<br \/>\n\ud558\uc9c0\ub9cc \ub85c\uadf8\uac00 \uc800\uc7a5\uc774 \ub418\uc9c0 \uc54a\ub294\ub2e4.<\/p>\n<h2>\uc608\uc81c<\/h2>\n<p>\uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uace0 \ub85c\uadf8\uac00 \uc800\uc7a5\ub420 \uac83\ucc98\ub7fc \ubcf4\uc774\uc9c0\ub9cc \ub85c\uadf8\ub294 \uc800\uc7a5\ub418\uc9c0 \uc54a\ub294\ub2e4.<br \/>\n<code>Transactional<\/code> \uc5d0 \uc758\ud574 DB \uc800\uc7a5\uc774 \ub864\ubc31\ub418\uae30 \ub54c\ubb38\uc774\ub2e4.<\/p>\n<pre><code class=\"language-java\">@Transactional\npublic LoginResponse login(LoginRequest request, String ipAddress, String userAgent) {\n    String email = request.getEmail();\n\n    Optional&lt;User&gt; userOptional = userRepository.findByEmail(email);\n    if (userOptional.isEmpty()) {\n        loginLogService.logFailedLogin(email, ipAddress, userAgent, &quot;\uc874\uc7ac\ud558\uc9c0 \uc54a\ub294 \uc774\uba54\uc77c&quot;);\n        throw new LoginFailedException(&quot;\uc774\uba54\uc77c \ub610\ub294 \ube44\ubc00\ubc88\ud638\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.&quot;);\n    }\n\n    \/\/ ......\n}\n\n@Transactional\npublic void logFailedLogin(String email, String ipAddress, String userAgent, String failureReason) {\n    LoginLog loginLog = LoginLog.builder()\n            .email(email)\n            .ipAddress(ipAddress)\n            .userAgent(userAgent)\n            .status(LoginLog.LoginStatus.FAILURE)\n            .failureReason(failureReason)\n            .build();\n\n    loginLogRepository.save(loginLog);\n    log.warn(&quot;Failed login logged for email: {}, IP: {}, Reason: {}&quot;, email, ipAddress, failureReason);\n}<\/code><\/pre>\n<h2>\ud574\uacb0<\/h2>\n<p><code>REQUIRES_NEW<\/code> \ub97c \uc774\uc6a9\ud574 \uc544\uc608 \ubcc4\ub3c4\uc758 DB \uc5f0\uacb0\ub85c \ubd84\ub9ac\ud574 \uc8fc\uc5b4\uc57c \ud55c\ub2e4.<br \/>\n\ub2e4\ub9cc \ubcc4\ub3c4\uc758 DB \uc5f0\uacb0\uc774 \ub41c\ub2e4\ub294 \uc758\ubbf8\ub294 \ud55c\uac1c\uc758 DB \uc5f0\uacb0\uc774 \uc544\ub2c8\ub77c \ub450\uac1c\uc758 DB \uc5f0\uacb0\uc744 \ud544\uc694\ub85c \ud55c\ub2e4\ub294 \uc758\ubbf8\uac00 \ub41c\ub2e4.<\/p>\n<pre><code class=\"language-java\">@Transactional(propagation = Propagation.REQUIRES_NEW)\npublic void logFailedLogin(String email, String ipAddress, String userAgent, String failureReason) {\n    \/\/ ......\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Transactional \uacfc Exception \uadf8\ub9ac\uace0 \ub85c\uadf8 \uc800\uc7a5 \uc608\uc678\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ub85c\uadf8\ub97c \uc800\uc7a5\ud558\uace0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\ub824 \ud55c\ub2e4. \ud558\uc9c0\ub9cc \ub85c\uadf8\uac00 \uc800\uc7a5\uc774 \ub418\uc9c0 \uc54a\ub294\ub2e4. \uc608\uc81c \uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uace0 \ub85c\uadf8\uac00 \uc800\uc7a5\ub420 \uac83\ucc98\ub7fc \ubcf4\uc774\uc9c0\ub9cc \ub85c\uadf8\ub294 \uc800\uc7a5\ub418\uc9c0 \uc54a\ub294\ub2e4. Transactional \uc5d0 \uc758\ud574 DB \uc800\uc7a5\uc774 \ub864\ubc31\ub418\uae30 \ub54c\ubb38\uc774\ub2e4. @Transactional public LoginResponse login(LoginRequest request, String ipAddress, String userAgent) { String email = request.getEmail(); Optional&lt;User&gt; userOptional = userRepository.findByEmail(email); if\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=10883\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-10883","post","type-post","status-publish","format-standard","hentry","category-spring-boot"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/10883","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10883"}],"version-history":[{"count":2,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/10883\/revisions"}],"predecessor-version":[{"id":10903,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/10883\/revisions\/10903"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10883"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}