๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ตฌ์กฐ ๋ณ๊ฒฝ์ด ๋ง์ ๊ฒฝ์ฐ - ๊ธฐ์กด ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๊ผญ dump ๋ ๋๊ธฐ (ํ ์ด๋ธ์ ๊ฑด๋ค๊ฒ ๋๋ค๋ฉด ๋ฌด์์ ํ๋ ๊ผญ ์ฒซ๋ฒ์งธ๋ก ํ์) - ๊ธฐ์กด ์ปฌ๋ผ(old column)์ ์ ์งํ๊ณ ์๋ก์ด ์ปฌ๋ผ(new column)์ ํจ๊ป ๋ง๋ค๊ธฐ, ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ์์์ ํ์ธํ๋ฉด ์กฐ๊ธ์ฉ ์ด์ ์ปฌ๋ผ ์ง์๋๊ฐ๊ธฐ - ์ปฌ๋ผ ๋ช๊ฐ์ ๋์ฒด๋ณด๋ค ๋ ํฐ ๊ตฌ์กฐ์ ๋ง์ด๊ทธ๋ ์ด์ ์ด ํ์ํ๋ค๋ฉด ํ ์ด๋ธ ๋ณต์ ๋ฅผ ํตํด ์๋ก์ด ํ ์ด๋ธ์ ๋ง๋ค๊ณ ์์ ํ ํ ์ด๋ธ์ ๊ต์ฒดํ๊ธฐ (๊ธฐ์กด ํ ์ด๋ธ์์ ์์ ํ๋ค๋ณด๋ฉด ์ด์ ๋ฐ์ดํฐ๋ฅผ ๋ ๋ ค๋ฒ๋ฆด ์ ์๋ ์ํ ์ํฉ์ ๋์ผ ์ ์๋ค..ใ ) API ์ ๋ฒ์ ๊ต์ฒด๊ฐ ํ์ํ ๊ฒฝ์ฐ - API ๊ธฐ์กด ๋ฒ์ ๋ ์ฌ์ ํ ๋์ ๊ฐ๋ฅํด์ผ ํ๋ค. ํด๋น API๋ฅผ ์ฌ์ฉํ๋ ๊ณณ์ ์ ๋ถ ์ถ์ ํ๊ณ ๋ฐ๊พธ๋๋ก ์์ฒญํ ์๋ ์๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด API๋ ๋์ ๊ฐ๋ฅ..
์ฃผ๋์ด ๊ฐ๋ฐ์์ ์๋ฐ๊ธฐ ํ๊ณ ์๊ฐ์ด ์ ๋ง ๋นจ๋ฆฌ๊ฐ๋ค. ๋ฒ์จ 1๋ ์ค ์ ๋ฐ์ด ์ง๋ฌ๋ค๋๊ฒ ๋ฏฟ๊ธฐ์ง ์๋๋ค ๐ฅน ์ ์ฌ๋ฅผ ๊ฒฐ์ ํ๋ฉฐ ํผ์ ๋์๊ฒผ๋ ์๊ฐ๋ค์ด ์๋ค. 1. ์ฃผ์ด์ง ์ ๋ฌด๋งํผ์ ์ ๋๋ก ์ดํดํ๊ณ ๋๊น์ง ๋งก์ ์ญํ ์ ์ถฉ์คํ ํด๋ด๊ธฐ 2. ์์ฌ ์ํต์ ํ๋ฐํ ํ๊ธฐ 3. ๋ฌด์กฐ๊ฑด์ ์ธ ์์ฉ๋ณด๋ค๋ ๋ด ์ฃผ๊ด์ ๊ฐ์ง๊ณ ๋๋ ทํ๊ฒ ์๊ฒฌ์ ํํํ๊ธฐ ์๊ฐ์ ๋ค๋์๋ณด๋ ๊ทธ๋๋ ๊ฝค ์ค์ฒํ๋ฉฐ ์ด์ฌํ ํ์ฌ์ํ์ ํ๋ค๋ ์๊ฐ์ด ๋ ๋ค. ์ธํด์ ํ ๋๋ณด๋ค ์ ๋ฌด์ ๋์ด๋๊ฐ ๋์์ก๊ณ ์๋ง์ ๋ ๊ฑฐ์ ์ฝ๋๋ค์ ๋ง๋๊ธฐ๋ ํ๊ณ ํฌ๊ณ ์์ ์ฑ๋ฆฐ์ง๋ค์ด ์์๋ค. ๋ฌธ์ ๋ค์ ํ๋์ฉ ํด๊ฒฐํด๋๊ฐ๋ฉฐ ์ค์ค๋ก ์ป๋ ๊นจ๋ฌ์๋ ์์๊ณ ์ด๋์ ๋ ๋ ธํ์ฐ๊ฐ ์๊ธด ๊ฒ ๊ฐ๊ธฐ๋ ํ๋ค. ํ์๋ถ๋ค์ด ๋์์ฃผ์ ์ ์ ๋ฌด์ ์ ์ ์ํ ์ ์์๊ณ ์ถํ์ ๋๊ตฐ๊ฐ ๋ค์ด์จ๋ค๋ฉด ๋๋ ๋ฐ์ ๋์์ ๋จ๋ค์๊ฒ ๋ง..
collections API ์ค ํ๋๋ก ์ปฌ๋ ์ ์ Map ํํ๋ก ๋ณํ์์ผ์ฃผ๋ API ์ด๋ค. associateBy ํจ์์ groupBy ํจ์๋ ์ง์ ๋ key์ ์ํด ์ธ๋ฑ์ฑ๋ ์ปฌ๋ ์ ์ ์์๋ก๋ถํฐ Map์ ๋ง๋ค์ด์ค๋ค. associateBy public inline fun Iterable.associateBy(keySelector: (T) -> K): Map { val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16) return associateByTo(LinkedHashMap(capacity), keySelector) } ๋งค๊ฐ๋ณ์์๋ T๋ฅผ ์ ๋ฌํ๊ณ key๋ฅผ ๋ฆฌํดํ๋ ๋๋คํจ์ keySelector๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค. ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ key..
Programming Models 1. Annotated Controller Spring MVC์์ ์ฌ์ฉํ๋ ๋ฐฉ์์ WebFlux ์์ ๊ทธ๋๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. @RequestMapping, @PathVariable, @RestController, @GetMapping ๋ฑ 2. Functional Endpoints Java8์ lambda style routing๊ณผ handling ๋ฐฉ์ (ํจ์ํ ๋ชจ๋ธ) RouterFunction: ์ด๋ค ํธ๋ค๋ฌ๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ ์ง ๊ฒฐ์ HandlerFunction: ๋ฐ์ธ๋ฉ ๋ถํฐ HTTP ์์ฒญ ์๋ต์ฒ๋ฆฌ ServerRequest์ ServerResponse๋ก ์๋ต์ ํ๋ฉฐ ์๋ธ๋ฆฟ ์ ์ฝ์ด ์๊ณ ๋ฆฌ์กํฐ๋ธ ํ์ ์ ์ง์ํ๋ค. Spring WebFlux์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ 2๊ฐ์ ๊ฐ๋ฐ ..
Spring Actuator๋? ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ๋ชจ๋ํฐ๋ง, Metric ์์ง์ ์ํ Http Endpoint๋ฅผ ์ ๊ณตํด์ฃผ๋ ๋ชจ๋์ด๋ค. (์์ฝํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํ๋ฅผ ์ ์ฒด์ ์ผ๋ก ์ ์ ์๋๋ก ๋์์ฃผ๋ ๊ธฐ๋ฅ!) // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator implementation 'org.springframework.boot:spring-boot-starter-actuator:3.0.1' ๋ค์๊ณผ ๊ฐ์ด dependency๋ง ์ถ๊ฐํด์ฃผ๋ฉด ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. Ex) spring ์ค์ yaml ํ์ผ์ ์๋์ ๊ฐ์ด ์ด๋ค endpoint๋ค์ ํฌํจํ ์ง ๋ช ์ํด์ฃผ๋ฉด ๋๋ค. management: endp..
๊ธฐ์กด์ ํ๋ ๊ฒ ์ฒ๋ผ http.requestMatchers("/h2-console/**").permitAll() ๋ก h2-console์ ๋ํ ์ ๊ทผ์ ํ์ฉํด์ฃผ๋ ค๊ณ ํ์ง๋ง ๊ณ์ํด์ 403(forbidden) ์๋ฌ๊ฐ ๋ฌ๋ค. ๊ตฌ๊ธ๋ง์ ํตํด ํด๊ฒฐํ ๊ฒฐ๊ณผ @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests() .requestMatchers("/users/**").permitAll() .and() .authorizeHttpRequests(auth -> auth .requestMatchers(AntPathRequestMatcher.antMatcher("/h2-console/..
Coroutine Context ์ฝ๋ฃจํด์ ํญ์ Coroutine Context๋ก ๊ตฌ์ฑ๋ ์ฝํ ์คํธ ์์์ ์คํ๋๋๋ฐ, ์ด ์ฝํ ์คํธ๋ Dispatchers์ Job์ผ๋ก ๊ตฌ์ฑ๋๋ค. Dispatchers๋ ์ฝ๋ฃจํด์ด ์คํ๋ ์ค๋ ๋๋ฅผ ์ง์ ํ๋ ์ญํ Default : CPU์์ ๋ง์ ์ฐ์ฐ์ด ํ์ํ ์ฒ๋ฆฌ ๋์์์ ๊ฐ๋ฅํ ์ต๋ ๊ฐ์๋ CPU ์ฝ์ด ์์ ๊ฐ๋ค. IO : ํ์ผ ์ ์ถ๋ ฅ, ๋คํธ์ํฌ ์ฝ ๋ฑ ์ค๋ ๋๊ธฐํ๋ ์ํฉ์ผ ๋ Blocking IO์ฉ ๊ณต์ ์ค๋ ๋ํ์์ ๋์ Default์ ์ค๋ ๋๋ฅผ ๊ณต์ ํ๋ฏ๋ก withContext์์ Dispatcher ๋ณ๊ฒฝ ์, ์ปจํ ์คํธ ์ค์์นญ ํ์ง ์๊ณ ๋์ผํ ์ค๋ ๋์์ ์คํ๋จ Main: ์ฝ๋ฃจํด์์ ์ฒ๋ฆฌ๋ ๊ฐ์ UI์ ๋ฐ์ํ ๋ ๋ฉ์ธ์ค๋ ๋์์ ๋์ UnConfined ๋ฉ์ธ์ค๋ ๋์์ ๋์ C..
Reified ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๋ค๋ฆญ ํจ์์์ Runtime์ ํ์ ์ ๋ณด๋ฅผ ์ ์ ์๋ค. (๋ณดํต์ ์ปดํ์ผ ์์๋ง ํ์ ์ ์ ์ ์๊ณ ๋ฐํ์์์ ํ์ ์ ๋ณด๋ ์กด์ฌํ์ง ์๊ฒ ๋๋ค.) ์ฆ, ๋ฐํ์์์๋ ํ์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ์ธ์คํด์ค๋ฅผ ์ฐพ๊ธฐ๊ฐ ์ฝ๋ค. reified ๋ inline fun๊ณผ ํจ๊ป ์ฌ์ฉ๋๋ฉฐ ํจ์์ ๋งค๊ฐ๋ณ์๋ก T ํ์ ํด๋์ค๋ฅผ ๋ฐ๋ ๊ฒ์ ์๋ตํ ์ ์๋ค. ์ถ๊ฐ์ ์ผ๋ก T ํด๋์ค๋ฅผ ๋๊ฒจ์ค ํ์๊ฐ ์๋ค๋ ์ ์ด ์ข์ ๊ฒ ๊ฐ๋ค. ๋ค์์ R2dbcEntityTemplate ์ฟผ๋ฆฌ ์คํ์ ์ํ ํจ์์ด๋ค. ๊ธฐ์กด ์ฝ๋) private fun executeQuery(build: Select, entityClass: KClass): Flow = r2dbcEntityTemplate.query( QueryBuil..
Kotest์๋ ์ ํ์ฒ๋ฆฌ๋ฅผ ์ํ ์ฌ๋ฌ๊ฐ์ ์ธํฐํ์ด์ค ํจ์๋ค์ด ์กด์ฌํ๋๋ฐ ๋ํ์ ์ผ๋ก @beforeSpec @beforeContainer @beforeTest @beforeEach .. ๋ฑ์ด ์กด์ฌํ๋ค. ํ ์คํธ ์๋ช ์ฃผ๊ธฐ์ ์ด๋ ํ ์ ํ ์ธํ ์ ํด์ฃผ์ด์ผ ํ๋๊ฒฝ์ฐ ์ฌ์ฉํ๋ค. ์๋ฅผ ๋ค๋ฉด ํ ์คํธ ์ปจํ ์ด๋ ์คํ, ๋ฐ์ดํฐ ์ฝ์ ๋ฑ๋ฑ! ์ด๋ค function์ ์ฌ์ฉํ๋์ ๋ฐ๋ผ ํ ์คํธ ๊ณผ์ ๊ณผ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง ์ ์๊ธฐ ๋๋ฌธ์ ํ์์ ๋ง๊ฒ ๊ณจ๋ผ ์ฌ์ฉํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค. Function Description @beforeEach ๊ฐ testcase ๋ง๋ค ํธ์ถ๋๋ค. @beforeTest ๊ฐ testcase ๋ง๋ค ํธ์ถ๋๋ค. @beforeContainer ๊ฑฑ context๋ง๋ค ํธ์ถ๋๋ค. @beforeSpec ํ๋์ ํ ์คํธ spec (FunS..
์ฐ๊ด๋ ์ํฐํฐ์ ๋ํด ์ง์ฐ๋ก๋ฉ์ผ๋ก ์ค์ ์ ํด์ฃผ๋ฉด ์ผ๋ฐ์ ์ธ ์กฐํ ์ฟผ๋ฆฌ์์๋ ์ฐ๊ด๋ ์ํฐํฐ๊น์ง ์กฐํํด์ค์ง ์๊ณ ์ฐ๊ด๋ ์ํฐํฐ๋ ๊ฐ์ง ํ๋ก์ ๊ฐ์ฒด๋ก ์ค์ ์ด ๋๋ค. ์ด๋ ๊ฒ ๋๋ฉด ์ฐ๊ด๋ ์ํฐํฐ์ ๊ฐ์ ์ ๊ทผํด์ผํ ๋ ๋ฐ์ดํฐ๋ง๋ค ์ฟผ๋ฆฌ๊ฐ ํ๋ฒ์ฉ ๋ ์คํ๋์ด N+1 ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฒ์ด Fetch Join ์ด๋ค. ์ฐ๊ด๋ ๊ฒ๋ค์ ํ๋ฒ์ ๋ค ๊ฐ์ ธ์ค๋ ๊ฒ์ผ๋ก ๊ฐ์ง ํ๋ก์ ๊ฐ์ฒด๊ฐ ์๋๋ผ ์ฐ๊ด๋ ์ํฐํฐ๊น์ง ์ค์ ๊ฐ์ผ๋ก ์ ๋ถ ์ฑ์์ค๋ค. (์ฆ, ์กฐ์ธ๋ง ํ๋ ๊ฒ์ด ์๋๋ผ select ์ ์ ์๋ ๊ฐ๋ค๋ ์ ๋ถ ๋ฃ์ด์ฃผ๋ ๊ฒ) EntityGraph - data jpa๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ fetch join ์ jpql ์์ด ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค. JpaRepository๋ฅผ ์์๋ฐ๋ repository๊ฐ ์์ ๋ @..