์Šคํ”„๋ง

SimpleJdbcInsert๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, insert๋ฅผ ๊ตฌํ˜„ํ•˜๋˜ ์ค‘ ๋ฌธ์ œ ๋ฐœ์ƒ private Member insert(Member member) { SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate.getJdbcTemplate()) .withTableName("Member") .usingGeneratedKeyColumns("id"); SqlParameterSource params = new BeanPropertySqlParameterSource(member); var id = simpleJdbcInsert.executeAndReturnKey(params).longValue(); return Member.builder() .id(..
QueryDSL gradle ์„ค์ • plugins { id 'java' id 'org.springframework.boot' version '3.0.6' id 'io.spring.dependency-management' version '1.1.0' // id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'dev.be' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation..
QueryDSL ์€ SQL, JPQL ๋“ฑ์„ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋นŒ๋” ์˜คํ”ˆ์†Œ์Šค ํ”„๋ ˆ์ž„์›Œํฌ ์ด๋‹ค. QueryDSL JPA SQL, JPQL์„ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋นŒ๋” API์ด๋‹ค. Entity ํด๋ž˜์Šค์™€ ๋งคํ•‘๋˜๋Š” QClass ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. QClass ? QueryDSL์€ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ QClass๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ JPAAnnotationProcessor๊ฐ€ ์ปดํŒŒ์ผ ์‹œ์ ์— ์ž‘๋™ํ•ด์„œ @Entity ๋“ฑ์˜ ์• ๋…ธํ…Œ์ด์…˜์„ ์ฐพ์•„ ํ•ด๋‹น ํŒŒ์ผ์„ ๋ถ„์„ํ•ด์„œ QClass๋ฅผ ๋งŒ๋“ ๋‹ค. ๐Ÿš€ QClass๋Š” Entity์™€ ํ˜•ํƒœ๊ฐ€ ๋˜‘๊ฐ™์€ static class์ด๋‹ค. ๐Ÿš€ QueryDSL์€ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ, QClass๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ๐Ÿ™‹โ€โ™€๏ธ ์‚ฌ์šฉ ์ด์œ ? EntityCl..
Retry์™€ Recover ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•œ API ํ˜ธ์ถœ์€ ์–ธ์ œ ์–ด๋–ป๊ฒŒ ์‹คํŒจํ• ์ง€ ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๊ฐ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ๊ธฐ์ˆ ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๊ฒŒ ํ‰๊ฐ€๋ฐ›๊ณ  ์žˆ๋‹ค. ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์—์„œ ์„œ๋ฒ„์™€ ์„œ๋ฒ„๊ฐ„ API ํ˜ธ์ถœ ์‹คํŒจ์— ๋Œ€ํ•œ ์žฌ์‹œ๋„๋Š” ๋งค์šฐ ์ค‘์š”ํ•œ ํ–‰์œ„์ด๋‹ค. 1๋ฒˆ์˜ ๋„คํŠธ์›Œํฌ ํ˜ธ์ถœ ์‹คํŒจ๋กœ ์„œ๋น„์Šค์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ชจ๋‘ ์‹คํŒจ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ fallback ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๋ช‡ ๋ฒˆ ๋‹ค์‹œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํฐ ๋ฆฌ์†Œ์Šค ๋‚ญ๋น„๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๐Ÿค” FallBack ์ฒ˜๋ฆฌ??? ์–ด๋–ค ๊ธฐ๋Šฅ์ด ์•ฝํ•ด์ง€๊ฑฐ๋‚˜ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ๋•Œ, ์ด์— ๋Œ€์ฒ˜ํ•˜๋Š” ๊ธฐ๋Šฅ ๋˜๋Š” ๋™์ž‘์„ ๋งํ•œ๋‹ค. fallback์€ API ํ˜ธ์ถœ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค. ์‹คํŒจ์— ๋Œ€ํ•ด์„œ ํ›„์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์„ค์ •ํ•ด๋‘๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ๋˜ํ•œ, DNS ์„œ๋ฒ„, ์Šค์œ„..
CSRF (Cross-Site Request Forgery) ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ์˜ ์–ด๋…ธํ…Œ์ด์…˜์ธ @EnableWebSecurity ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ CSRF ๊ณต๊ฒฉ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ง€์› CSRF ๋ž€? ๐Ÿค” ์‚ฌ์ดํŠธ ๊ฐ„ ์š”์ฒญ ์œ„์กฐ
OSIV (Open Session In View) OSIV ๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ๋ทฐ๊นŒ์ง€ ์—ด์–ด๋‘๋Š” ๊ธฐ๋Šฅ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ ์œ ์ง€๋˜๋ฉด ์—”ํ‹ฐํ‹ฐ๋„ ์˜์† ์ƒํƒœ๋กœ ์œ ์ง€๋จ ๋ทฐ๊นŒ์ง€ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๊ฐ€ ์‚ด์•„์žˆ๋‹ค๋ฉด ๋ทฐ์—์„œ๋„ ์ง€์—ฐ ๋กœ๋”ฉ์„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ OSIV ๋™์ž‘ ์›๋ฆฌ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” OSIV๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๊ณ„์ธต์—์„œ ํŠธ๋žœ์žญ์…˜์„ ์‚ฌ์šฉํ•˜๋Š” OSIV ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋Š” ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ ์‹œ์ ์—์„œ ์ƒ์„ฑ๋˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ํŠธ๋žœ์žญ์…˜์€ ๋น„์ฆˆ๋‹ˆ์Šค ๊ณ„์ธต์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํŠธ๋žœ์žญ์…˜์ด ์ผ์–ด๋‚จ spring.jpa.open-in-view:true ๊ธฐ๋ณธ๊ฐ’ Spring Boot JPA ์˜์กด์„ฑ์„ ์ฃผ์ž…๋ฐ›์•„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•  ๊ฒฝ์šฐ spring.jpa.open-in-view์˜ ๊ธฐ๋ณธ๊ฐ’์ธ true๋กœ ์ง€์ •๋˜์–ด ์žˆ์–ด OSIV๊ฐ€ ์ ์šฉ๋œ ..
Thymeleaf Decoupled Template Logic ๐Ÿค” ํ˜„์žฌ index ์—์„œ ์ปดํฌ๋„ŒํŠธ์˜ ๋ถ„๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ ๊ตฌ๋ฌธ์„ ์ž‘์„ฑํ–ˆ๋Š”๋ฐ, ์ ์ฐจ ๋””์ž์ธ์„ ์ง„ํ–‰ํ•˜๋‹ค๋ณด๋ฉด ์—ฌ๋Ÿฌ ๊ตฌ๋ฌธ๋“ค์ด ๋ถ™์–ด์„œ ์ฝ”๋“œ๊ฐ€ ๋งŽ์ด ์ปค์งˆ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ thymeleaf ๊ตฌ๋ฌธ์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌ์‹œ์ผœ์„œ ์ž‘์„ฑํ•˜๊ณ , index๋ฅผ ์ˆœ์ˆ˜ ๋งˆํฌ์—… ์ƒํƒœ๋กœ ์œ ์ง€์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ• ์ˆœ์ˆ˜ ๋งˆํฌ์—…๊ณผ Thymeleaf ๊ตฌ๋ฌธ์œผ๋กœ ๋”ฐ๋กœ ๋‚˜๋‰จ ์ฐธ์กฐ-thymeleaf ์„ธํŒ… ์Šคํ”„๋ง ๋ถ€ํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœํผํ‹ฐ์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณต๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ธํŒ…์„ ๋”ฐ๋กœ ์ง„ํ–‰ํ•ด์•ผํ•จ ThymeleafConfig package com.example.springboardproject.config; import lombok.Getter; import lombok.RequiredArgsConstruc..
JpaAuditing ๐Ÿค” Java์—์„œ ORM ๊ธฐ์ˆ ์ธ JPA๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋„๋ฉ”์ธ์„ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์— ๋งคํ•‘ํ•  ๋•Œ ๊ณตํ†ต์ ์œผ๋กœ ๋„๋ฉ”์ธ๋“ค์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ•„๋“œ๋‚˜ ์ปฌ๋Ÿผ๋“ค์ด ์กด์žฌํ•˜๋Š”๋ฐ, ๋„๋ฉ”์ธ๋งˆ๋‹ค ๊ณตํ†ต์œผ๋กœ ์กด์žฌํ•œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋œ๋‹ค๋Š” ๋œป์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ˆ„๊ฐ€, ์–ธ์ œํ–ˆ๋Š”๊ฐ€์— ๋Œ€ํ•œ ๊ธฐ๋ก์„ ๋‚จ๊ฒจ๋†“๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•จ ๊ทธ๋ž˜์„œ JPA์—์„œ ๊ฐ์‹œํ•˜๋‹ค๋ผ๋Š” ๋œป์„ ๊ฐ€์ง„ Audit์ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ, Spring Data JPA์—์„œ ์‹œ๊ฐ„์— ๋Œ€ํ•ด์„œ ์ž๋™์œผ๋กœ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.. ๋„๋ฉ”์ธ์„ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์กฐํšŒ๋ฅผ ์ˆ˜ํ–‰ํ•œ ํ›„์— update๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋งค๋ฒˆ ์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•ด์ค˜์•ผํ•˜๋Š”๋ฐ, audit์„ ์ด์šฉํ•˜๋ฉด ์ž๋™์œผ๋กœ ์‹œ๊ฐ„์„ ๋งคํ•‘ํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์— ๋„ฃ์–ด์ฃผ๊ฒŒ ๋จ Article.java && Ar..
KIMHYEYUN
'์Šคํ”„๋ง' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๊ธ€ ๋ชฉ๋ก