ํ๋ก์ ํธ (19) ์ธ๋ค์ผํ ๋ฆฌ์คํธํ CompletableFuture๋ฅผ ํ์ฉํด ์ธ๋ถ API ํธ์ถ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ, ์๋ต ์๊ฐ 1๋ถ → 14์ด๋ก ๋จ์ถ ๋ฌธ์ ์ํฉํ๋ก์ ํธ QA์, ์ฃผ๊ฐ ๋ฆฌํฌํธ ๊ธฐ๋ฅ์ ์๋ต ์๊ฐ์ด ์ฌ์ฉ์ 1๋ช ๋น ์ต์ ์ ๊ฒฝ์ฐ 2๋ถ ์ด์, ๋์ฒด๋ก ํ๊ท 1๋ถ ์ด์ ์์๋๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ๋ถ์ํ ๊ฒฐ๊ณผ, DB ์ฟผ๋ฆฌ๋ ์คํ ๊ณํ์ eq_ref ์ ref๋ก ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌ๋๊ณ ์์์ต๋๋ค.์๋ต ์๊ฐ์ด ๊ธธ์ด์ง ์ฃผ์ ์์ธ์ ๋น์ฆ๋์ค ๋ก์ง์์ ์ต๋ 7๋ฒ์ ์ธ๋ถ API ํธ์ถ์ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ณ ์๊ธฐ ๋๋ฌธ์ด์์ต๋๋ค. ์๋ ์ฝ๋์ฒ๋ผ, stream() ๋ด๋ถ์์ ์ฐ์์ ์ธ ์ธ๋ถ API ํธ์ถ์ ์ฒ๋ฆฌํ๋ฉด์ ์ผ์ผ ์๋น์ค์ Clova AI๊ฐ ๋๊ธฐ์ ์ผ๋ก ์์ฒญ๊ณผ ์๋ต์ ์ฃผ๊ณ ๋ฐ๋ ๊ตฌ์กฐ๋ก ๋์ํ๊ณ ์์๊ณ , ์ด๋ฅผ ๊ฐ์ ํ๊ณ ์ ํ์ต๋๋ค.Map> valuesByKey = map.values().stream() ์ธ๋ถ API ํธ์ถ, .. ์ธ๋ถ API ํธ์ถ์ ํธ๋์ญ์ ์์ ๋ถ๋ฆฌํ๊ธฐ ์ํด FACADE ๊ณ์ธต์ ์ฌ์ฉํ๋ค๋ฉด, OSIV ํ์ฑํ ์ฌ๋ถ๋ฅผ ๊ณ ๋ คํ์! ๋ฌธ์ ์ํฉ: ์๋ก ๋ค๋ฅธ ํธ๋์ญ์ ์์ ์ํฐํฐ ๋ณ๊ฒฝ ์ ๋ณ๊ฒฝ๊ฐ์ง๊ฐ ์๋ํ๋๊ฐ? ์ธ๋ถ API ํธ์ถ์ ํธ๋์ญ์ ์์ ๋ถ๋ฆฌํ๊ธฐ ์ํด FACADE ํจํด์ ๋์ ํ์ต๋๋ค.3๊ฐ์ ์๋น์ค๋ฅผ ๋ฆฌํฉํ ๋งํ๋ฉฐ, ํธ๋์ญ์ ๋ฒ์ ๋ฐ์์ ์ธ๋ถ API๋ฅผ ํธ์ถํ๋๋ก ์ค๊ณํ์๊ณ , ์ฝ๋ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์์ต๋๋ค. // ํธ๋์ญ์ ์์ ์ธ๋ถ API ํธ์ถ์ ๋ถ๋ฆฌํ๊ณ ์ ๋ง๋ Facade ๊ฐ์ฒดpublic class Facade { private final Service1 service1; private final Service2 service2; public ... createSomething(...) { // 1๋ฒ ์๋น์ค ํธ๋์ญ์ ์์ EntityA entityA = service1.doSomething(.... OpenFeign์ INFO ๋ ๋ฒจ ๋ก๊ทธ ์ถ๊ฐํ๊ธฐ (2/2): ๋ก๊ทธ ์ค์ ๊ณผ Configuration ๊ณ ๋ฏผ ์ ๋ฒ ๊ธ์์๋ WireMock์ ํ์ฉํด Clova AI(์ธ๋ถ) ์๋ฒ๋ฅผ ๋ชจํนํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ค์ต๋๋ค. ์ด๋ฅผ ํตํด Clova ์๋ฒ๋ฅผ ํธ์ถํ์ง ์์์ผ๋ก์จ ๋น์ฉ ๋ฐ์ ์์ด, @FeignClient ์ logger-level: FULL ์ค์ ์ด ์ ์ ์ฉ ๋์๋์ง๋ฅผ ํ์ธํ๋ ๊ณผ์ ์ ์ดํด๋ดค์ต๋๋ค. ์ด๋ฒ ๊ธ์์๋ INFO ๋ ๋ฒจ์์ Feign ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๋๋ก ์ปค์คํฐ๋ง์ด์งํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๋ ค ํ์ง๋ง, ์ด๋ฏธ ์ด๋ฅผ ๋ค๋ฃฌ ์ข์ ๊ธ๋ค์ด ๋ง์ ํด๋น ์ฃผ์ ๋ฅผ ๊ฐ๋จํ ๋์ด๊ฐ๊ณ , OpenFeign์ @Configuration ์ค๊ณ ๊ณผ์ ์์ ๊ณ ๋ฏผํ๋ ์ ์ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค. Feign ์ปค์คํฐ๋ง์ด์ง ๊ด๋ จ ์ข์ ๊ธ ์ฐ์ํ feign ์ ์ฉ๊ธฐ๋ง๋๋ ๊ฐ๋ฐ์๋์ OpenFeign ์ค๋ช ๊ณผ Github (tistory) FeignClient Log.. OpenFeign์ INFO ๋ ๋ฒจ ๋ก๊ทธ ์ถ๊ฐํ๊ธฐ (1/2): WireMock์ ํ์ฉํ ์ธ๋ถ ์๋ฒ ๋ชจํน ** ์ด๋ฒ ๊ธ์์๋ ํ ์คํธ์์ WireMock์ ํ์ฉํ์ฌ ์ธ๋ถ ์๋ฒ๋ฅผ ๋ชจํนํ๋ ๊ณผ์ ์ ์ค๋ช ํ๋ฉฐ, ๋ค์ ๊ธ์์๋ INFO ๋ ๋ฒจ ๋ก๊ทธ ์ค์ ๋ฐฉ๋ฒ์ ๋ค๋ฃฐ ์์ ์ ๋๋ค. ** Clova AI์ ๋ฐ๋ณต์ ์ธ ์๋ต ์ค๋ฅ ๋ฌธ์ ๊ณ ๋ฏผ ์๋ด ํ๋ซํผ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉฐ ๋ค์ด๋ฒ Clova AI์ ์์ฒญ์ ๋ณด๋ด๋ ์์ ์ ์ํํ์ต๋๋ค. ํ์ง๋ง Clova AI๋ก๋ถํฐ ์ค๋ ์๋ต์ด ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ๋ง์ง ์์ ๋น๋ฒํ๊ฒ ์ค๋ฅ๋ฅผ ๋ฐ์์์ผฐ์ต๋๋ค. ์ด์ ๋ฐ๋ผ, Clova AI ๊ฐ ์ด๋ค ์๋ต์ ์ฃผ๊ณ , ์ด๋ค ์ค๋ฅ๋ฅผ ์ ๋ฐํ๋์ง ์ ํํ ํ์ธํ ํ์๊ฐ ์์์ต๋๋ค.์ด ๊ณผ์ ์์ OpenFeign์ ๋ก๊น ๊ธฐ๋ฅ์ ํ์ฉํ๋ ค ํ์ง๋ง, ๊ธฐ์กด ๋ฐฉ์์ผ๋ก๋ ๋ช ๊ฐ์ง ๋ถํธํจ์ด ์์์ต๋๋ค. logger-level : FULL ์ ์ฌ์ฉํ์ง ์๋ ์ด์ 1. ์ค์ ์ด์ ์๋ฒ์์ F.. Github Actions ์ผ๋ก CI ํ ์คํธ ์๋ํ ์ค ๊ฒช์ ์ด์ ์ ๋ฆฌ (Embedded Redis, Profile, Spring Rest Docs) 210๊ฐ์ ํ ์คํธ ์ฝ๋์ 99% ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง์์ ์์ฝ ํ๋ซํผ์ ๊ฐ๋ฐํ๋ฉฐ ์ด 210์ฌ ๊ฐ์ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ณ , 99% ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ฌ์ฑํ์ต๋๋ค. ํ์ง๋ง ์ฝ๋์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ ๋๋ง๋ค ์ ์ฒด ํ ์คํธ๋ฅผ ์๋์ผ๋ก ์คํํด์ผ ํ๊ณ , ์ด๋ ์ ์ ๋ถํธํ ์์ ์ด ๋์์ต๋๋ค. ๊ทธ๋์ CI/CD ํด์ธ GitHub Actions๋ฅผ ๋์ ํ์ฌ push ๋๋ pull_request๊ฐ ๋ฐ์ํ ๋ ์๋์ผ๋ก ํ ์คํธ๊ฐ ์คํ๋๋๋ก ์ค์ ํ์ต๋๋ค. GitHub Actions๋ฅผ ์ ํํ ์ด์ GitHub Actions๋ฅผ ์ ํํ ์ด์ ๋ ๋จ์ํฉ๋๋ค.Jenkins์ฒ๋ผ ๋ณ๋์ ์๋ฒ๋ฅผ ๊ตฌ์ถํ ํ์๊ฐ ์์ผ๋ฉฐ,๋จ์ํ .github/workflows ๋๋ ํ ๋ฆฌ์ YAML ํ์ผ๋ง ์์ฑํ๋ฉด ๋ฐ๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.๋ํ Groovy์ ๊ฐ์ ์๋ก์ด ๋ฌธ๋ฒ์.. ํธ๋์ญ์ ๋กค๋ฐฑ ์ ๊ฒฐ์ ์ทจ์ ์์ฒญํ๊ธฐ - @TransactionalEventListener & ApplicationEventPublisher ๋ชจํน ์ด์ ๊ฒฐ์ ํ๋ก์ธ์ค๋ฅผ ์ค๊ณํ๋ฉด์, ๊ธฐ์กด์๋ try-catch๋ฅผ ํ์ฉํด ํธ๋์ญ์ ๋ด๋ถ์์ ๋ฐ์ํ๋ ๋ฐํ์ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๊ฒฐ์ ์ทจ์ ์์ฒญ์ ๋ณด๋์ต๋๋ค. ๊ทธ๋ฌ๋, ์ด์ ๋ํ ํ๊ณ๋ฅผ ๋๊ผ๊ณ ํธ๋์ญ์ ๋กค๋ฐฑ ์ ๊ฒฐ์ ์ทจ์ ์์ฒญ์ ๋ช ํํ๊ณ ์ง๊ด์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด @TransactionalEventListener๋ฅผ ๋์ ํ์ต๋๋ค. ๊ธฐ์กด try-catch ๋ฐฉ์์ ํ๊ณ try-catch์์๋ ์ฃผ๋ก DB ์์ธ(์: DataIntegrityViolationException)๋ ๋น์ฆ๋์ค ๋ก์ง์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๊ฒฐ์ ์ทจ์ ์์ฒญ์ ๋ณด๋์ต๋๋ค. ํ์ง๋ง, try-catch๋ฅผ ์ฌ์ฉํ๋ฉด ์์ธ๋ฅผ ์ ์์ ์ธ ํ๋ฆ์ผ๋ก ์ ์ดํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฒ ๋ฉ๋๋ค. ์ด๋ "ํธ๋์ญ์ ์ด ๋กค๋ฐฑ๋์์ ๋ ๊ฒฐ์ ์ทจ์๋ฅผ ์ํํ๋ค"๋ผ๋ ์๋ฏธ๋ฅผ ์ ํํ ํํํ์ง.. ISO 8601 ๊ธฐ์ค์ผ๋ก ํน์ ๋ ์ง์ N์ N์ฃผ์ฐจ๋ฅผ Java 8 ๋ ์ง API๋ก ๊ตฌํ๊ธฐ ISO 8601 ๋ ?ISO 8601์ ๋ ์ง์ ์๊ฐ์ ๊ด๋ จ๋ ๊ตญ์ ํ์ค์ผ๋ก์จ, ์ ์๋ ๋ฐ์ ๋ฐ๋ฅด๋ฉด ๋งค์ฃผ์ ์์์ผ์ ์์์ผ์ด ๋ฉ๋๋ค.๋ํ, ๋งค์์ ์ฒซ ์ฃผ๋ ๊ณผ๋ฐ์ ์ด์์ ์์ผ์ด ํฌํจ๋ ์ฃผ๊ฐ ๊ธฐ์ค์ด ๋ฉ๋๋ค. ISO 8601 ๊ธฐ์ค์ผ๋ก ์ฃผ์ฐจ ๊ณ์ฐ ์์2024๋ 12์ ์์ 2024๋ 12์ 30์ผ, 31์ผ์ ๋ค์๊ณผ ๊ฐ์ ๊ท์น์ ๋ฐ๋ฆ ๋๋ค. 2025๋ 1์ 1~5์ผ(์ด 5์ผ)์ 7์ผ ์ค ๊ณผ๋ฐ์๋ฅผ ๋์ผ๋ฏ๋ก 1์ 1์ฃผ์ฐจ์ ๋๋ค ๋ฐ๋ผ์, 2024๋ 12์ 30์ผ, 31์ผ์ 2025๋ 1์ 1์ฃผ์ฐจ์ ํฌํจ๋ฉ๋๋ค 12์ 2์ผ ~ 12์ 8์ผ -> 12์ 1์ฃผ์ฐจ12์ 9์ผ ~ 12์ 15์ผ -> 12์ 2์ฃผ์ฐจ12์ 16์ผ ~ 12์ 22์ผ -> 12์ 3์ฃผ์ฐจ12์ 23์ผ ~ 12์ 29์ผ -> 12์ 4์ฃผ์ฐจ12์ 30์ผ ~ .. [ํธ๋ฌ๋ธ์ํ ] RestTemplate ๋ก๊น ์ค 404 ์๋ต์ ๋ํ FileNotFoundException ํด๊ฒฐ ๊ฒฐ์ ์น์ธ POST ์์ฒญ ์ RestTemplate ๋ก๊ทธ์์ ๋ฐ์ํ ์ค๋ฅ ๊ฒฐ์ ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๋ฉด์, ๊ฒฐ์ ์น์ธ ์์ฒญ์ ๋ณด๋ด๋ RestTemplate์ ํ์์์์ ์ ์ฉํ๊ณ , ์์ฒญ๊ณผ ์๋ต์ ๋ํ ๋ก๊น ์ ์ถ๊ฐํ๊ณ ์ ํ์ต๋๋ค. Baeldung์ "RestTemplage Logging" ๊ณผ ๋ง๋๋ ๊ฐ๋ฐ์๋์ ๋ก๊น ์ ์ฐธ๊ณ ํด์ RestTemplate ์ ๋ก๊ทธ๋ฅผ ์ถ๊ฐ ํ์ง๋ง ์๋ต์ ๋ฐ์ ๋, FileNotFoundException ์ด ๋ฐ์ํ๋ฉฐ ์๋์ ๊ฐ์ ์คํ ํธ๋ ์ด์ค๋ฅผ ํ์ธํ์ต๋๋ค.java.io.FileNotFoundException: https://api.tosspayments.com/v1/payments/confirmjava.base/sun.net.www.protocol.http.HttpURLConnection.. ์ด์ 1 2 3 ๋ค์