์ฌ์ค ์ค๋ TIL์ด ์๋๋ค....๐คซ ์ต๊ทผ ์คํ๋ฅดํ ์ฝ๋ฉ ํด๋ฝ์์ ์ฃผ๊ดํ๋ ๋ด์ผ๋ฐฐ์์บ ํ์ ์ฐธ์ฌํ๊ฒ ๋์๋ค ๐ Spring ํธ๋์ผ๋ก ์ฐธ์ฌ! ์ด๋ก ๋ถ๋ถ์ ์ข ๋ ํ์ตํ๊ณ , ํ ํ๋ก์ ํธ ๊ฒฝํ์ ์๋ ๊ฒ์ด ๋ชฉ์ โผ๏ธ ๋ชฉ์ ์ฒ๋ผ ๊ฐ๊ฐํ์๋ง์ ํํ, ๊ฐ๋จํ ํ ์๊ฐ ์นํ์ด์ง ๋ง๋ค๊ธฐ ๋์ REST API ์์ฑ์ด๋ผ๋ ์์๊ฐ ์์ด์, spring์ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.. (์ฌ์ค,,,, js๋ฅผ ์ ๋ชป..๐ญ) ํ์๋ถ๋ค์ด spring์ ๋ชจ๋ฅด์
จ๋๋ฐ, ํด๋ณด๊ณ ์ถ์ผ์๋ค๊ณ ํ๋ก crud๋ฅผ ๋ง๋์
จ๋ค..๐ ์ฌ์ค ์ฌ๊ธฐ์ ๋ญ ์จ์ผํ ์ง ๋ชจ๋ฅด๊ฒ ๋ค. ์ค๋ ์์ง ์์นจ์ด๋ผ,,, ํ์ง๋ง ๋ด๋ฐฐ์บ ๋จ์ ์ผ์ ์ ๋ฐํ๋ฟ! ๋ง๋ฌด๋ฆฌ ์ํ๊ณ ๋ญ๊ฐ ๋ ์ฐ๊ณ ์ถ์ผ๋ฉด ์ถ๊ฐํด์ผ์ง์ง์งใ
ใ
ใ
ใ
์ ์ฒด ๊ธ
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..