![article thumbnail](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGbT2r%2Fbtsv90V76Bd%2FU65c5Lbny1y9HfMkeP5ZZk%2Fimg.png)
Spring WebFlux๊ฐ ํฐ ํ์์ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋์ํ๋์ง ์์๋ณด๊ณ ์ ํ๋ค. Spring MVC ์ ๊ฒฝ์ฐ์๋ DispatcherServlet ๊ธฐ๋ฐ์ผ๋ก ์์ฒญ์ ๋ฐ์ ๋ท๋จ์ ์ฒ๋ฆฌ๊ฐ ์ด๋ฃจ์ด์ง๋ค. Spring WebFlux์ ๊ฒฝ์ฐ์๋ DispatcherServlet๊ณผ ๊ฐ์ด front controller ์ ์ญํ ์ ํด์ฃผ๋ ์น๊ตฌ๊ฐ ์กด์ฌํ๋ค. ์ผ๋จ ๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด ๋์ถฉ ๋ถ์ํด๋ณธ ๊ฒ๋ค์ ์์ฝํ์ ๋ ์๋ ๊ฐ์ ๊ทธ๋ฆผ์ด๋ค. (๊ฐ๋จํ๊ฒ ํํํด์ ์๋ต์ด ๋ง์ ์ ์๋ค.) DispatcherHandler (WebHandler์ ๊ตฌํ์ฒด) DispatcherHandler ๋ WebHandler ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ก Spring Webflux์์์ front controller ์ญํ ์ ํ๋ค. ์๋๋ DispatchHandler..
Spring Data ๋? Spring ํ๋ ์์ํฌ์ ํ์ ํ๋ก์ ํธ ์ค ํ๋๋ก ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ํ ๋ฐ์ดํฐ ์ ๊ทผ ๊ธฐ์ ์ ์ง์ํ๋ค. Repository ์ธํฐํ์ด์ค๋ฅผ ํตํด ๊ฐ์ฒด ๋งคํ์ ์ถ์ํ ํํ๋ก ์ง์ํ๊ธฐ ๋๋ฌธ์ ์ข ๋ ์ฝ๊ฒ ๋ฐ์ดํฐ์ ์ ๊ทผ ๋ฐ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. Main Module Spring Data Commons : ๋ชจ๋ Spring Module์ ๋ท๋ฐ์นจํ๋ ํต์ฌ Spring ๊ฐ๋ CrudRepository, PagingAndSortingRepository Spring Data JDBC : spring-jdbc์ ๋ํ Spring Data ์ถ์ํ๋ฅผ ์ ๊ณตํ๋ ๋ชจ๋ CrudRepository๋ฅผ ๊ตฌํํ๋ SimpleJdbcRepository ํด๋์ค Spring Data JPA : JPA๋ฅผ ์ํ ์คํ๋ง ๋ฐ์ดํฐ..
![article thumbnail](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F02BUp%2Fbtsq5Z7341m%2FXkFb4kqwrywzJZB9wJbsd0%2Fimg.png)
MDC ๋? MDC ๋ Mapped Diagnostic Context ์ ์ฝ์๋ก key์ value๋ฅผ ์ ์ฅํ๋ Map ํ์์ผ๋ก slf4j, logback, log4j ๋ฑ ๋ก๊น ํ๋ ์์ํฌ์์ ํ์ํ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค. ThreadLocal ์ ๊ธฐ๋ฐ์ผ๋ก ์ปจํ ์คํธ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ ๋๋ฌธ์ ๋ฉํฐ ์ฐ๋ ๋ ํ๊ฒฝ์์ ์ ์ฉํ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. (๋ฉํฐ ์ฐ๋ ๋ ํ๊ฒฝ์์๋ ๋ก๊ทธ ๋ฉ์์ง์ ๊ฐ ์ฐ๋ ๋์ ๋ํ ๋ก๊ทธ๊ฐ ์์ด๊ธฐ ๋๋ฌธ) ์์ฒญ์ด ์ด๋ค ์ฌ์ฉ์๋ก๋ถํฐ ๋ค์ด์จ ๊ฒ์ธ์ง ์ ์ฅํ๊ฑฐ๋ ์์ฒญ๋ณ๋ก ์๋ณ์๋ฅผ ๋ง๋ค์ด ํน์ ์์ฒญ์ ๋ํ ๋ก๊ทธ๋ง ์ถ์ ํ ์ ์๋ค. ์ฐธ๊ณ : ๋ก๊ทธ์์คํ #4-MDC๋ฅผ ์ด์ฉํ์ฌ ์ฐ๋ ๋๋ณ๋ก ๋ก๊ทธ ๋ถ๋ฅํ๊ธฐ MDC ์ ์ฉํ๊ธฐ Spring Framework๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด AOP๋ฅผ ์ด์ฉํด ์ฝ๊ฒ ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค...
![article thumbnail](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE30at%2FbtrZ77yDivJ%2FdUZSIwSFJNlKACbWshBvXk%2Fimg.png)
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/..
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๊ฐ ์์ ๋ @..
Typically, stubbing argument mismatch indicates user mistake when writing tests. Mockito fails early so that you can debug potential problem easily. However, there are legit scenarios when this exception generates false negative signal: - stubbing the same method multiple times using 'given().will()' or 'when().then()' API Please use 'will().given()' or 'doReturn().when()' API for stubbing. - st..
detached entity passed to persist ๊ด๋ จ ์๋ฌ๊ฐ ๋จ๋ ๊ฒฝ์ฐ ์ด๋ฏธ ์์ฑ๋์ด ์๋ ๊ฐ์ฒด์ ๋ถ๋ถ์ ๋ค์ ํ๋ฒ ๋ ์ค์ ์ ํด์ฃผ๊ฑฐ๋ ์ ์ฅ์ ํด์ฃผ๋ ค๊ณ ํ ๋ ์๊ธฐ๋ ๊ฒ! ์ฆ, ์ํฐํฐ ์ข ์์ฑ ๋ฌธ์ ๊ฑฐ๋ ๊ฐ์ฒด ์์ฑํ ๋ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ !! ์๋ฅผ ๋ค๋ฉด 1) id ํ๋์ @GeneratedValue๋ฅผ ์ฌ์ฉํด์ ์๋์ผ๋ก ๋ง๋ค์ด์ง๋๋ก ํด๋๊ณ ํ ์คํธํ ๋ id ๊ฐ์ ์ค์ ํด์คฌ๋ค๋๊ฐ.. 2) ์ํฐํฐ๋ค์ ์ฐ๊ด๊ด๊ณ๊ฐ ์กด์ฌํ ๋ ํด๋์คA ์ a1, a2 ์ ์ฐ๊ด๋ ํด๋์คB์ b1 ์ด ์์ ๋ (a1 + b1) ์ ์ฅํ๊ณ (a2 + b1) ์ ์ฅ๋์ด ์ค๋ณต์ผ๋ก ์ ์ฅ๋๋ ๊ฒฝ์ฐ (์ด๋ฐ ๊ฒฝ์ฐ์๋ cascade ๊ด๋ จํด์ ์ค์ ์ ์ ๊ฑฐํด์ฃผ๋๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋๊ฒ ํด์ฃผ๋ฉด ๋ ๋ฏ!)
JWT๋? Json Web Token ์ ์ฝ์๋ก json ๊ฐ์ฒด์ ์ฌ์ฉ์์ ์ผ๋ถ ์ ๋ณด๋ฅผ ๋ด๋๋ค. ์ธ์ ๊ณผ ๋ฌ๋ฆฌ ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ๊ฐ ์ค ํ ํฐ์ ๊ฐ์ง๊ณ ์๋ค๊ฐ ํค๋์ ์ค์ด์ ๋ณด๋ด๋ ๋ฐฉ์ (๋จ์ํ๊ฒ ๋งํ๋ฉด ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ ๋ฐฉ์) Header : Signature๋ฅผ ํด์ฑํ๊ธฐ ์ํ ์๊ณ ๋ฆฌ์ฆ ์ ๋ณด๋ค ๋ด๊ฒจ์์ Payload : ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ฃผ๊ณ ๋ฐ๋, ์์คํ ์์ ์ค์ ๋ก ์ฌ์ฉ๋ ์ ๋ณด๋ค์ ๋ํ ๋ด์ฉ ๋ด๊ณ ์์ Signature : ํ ํฐ์ ์ ํจ์ฑ ๊ฒ์ฆ์ ์ํ ๋ฌธ์์ด (์ ํจํ ํ ํฐ์ธ์ง ๊ฒ์ฆ) ์ธ์ ์? ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์ธ์ฆํ ์ ์ ์ ์ ๋ณด๋ฅผ ์ ์ฅํด๋ ! ๊ทธ๋ฆฌ๊ณ ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ฆ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ํต์ ํ๋ ๋ฐฉ์ stateful service๋ ์ธ์ ์ ๋ณด๋ฅผ ์๋ฒ์ ์ ์ฅํ๊ณ ์ธ์ ์ํ์ ๋ฐ๋ฅธ ์๋ต์ ์ฃผ๋ ์๋น์ค! -> EX) ์ธ์ ..
** ๊ธฐ๋ณธ์ ์ผ๋ก security ์ค์ ๊ณผ swagger ์ค์ ์ด ๋ค ๋์ด์์์ ๋ฐํ์ผ๋ก ํ๋ค. SwaggerConfig.java @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .useDefaultResponseMessages(false) .select() .apis(RequestHandlerSelectors.basePackage("com.cherishpet.backend")) .paths(PathSelectors.ant("/api/**")) .build() .apiInfo(metaData()) .securityCon..