diff --git a/2022-retrospective.html b/2022-retrospective.html index 5994d7318..1a65d048c 100644 --- a/2022-retrospective.html +++ b/2022-retrospective.html @@ -13,12 +13,12 @@ - - + +
-
본문으로 건너뛰기

2022년 회고

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
+

2022년 회고

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

조금 더 미래에 대한 생각을 해볼걸 그랬다.
전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

자바

전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
@@ -33,7 +33,7 @@ 적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

2023년에는

마음의 여유가 없었던 2022년이었던 것 같다.
하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

- - + + \ No newline at end of file diff --git a/404.html b/404.html index 52448ba26..f1b20907e 100644 --- a/404.html +++ b/404.html @@ -13,13 +13,13 @@ - - + +

페이지를 찾을 수 없습니다.

원하는 페이지를 찾을 수 없습니다.

사이트 관리자에게 링크가 깨진 것을 알려주세요.

- - + + \ No newline at end of file diff --git a/accidental-duplication.html b/accidental-duplication.html index c1cfab741..a8b2b39da 100644 --- a/accidental-duplication.html +++ b/accidental-duplication.html @@ -13,12 +13,12 @@ - - + +
-

중복과 우발적 중복

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
+

중복과 우발적 중복

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
요청에 담긴 Body를 통해 전달받은 값을 DTO로 매핑하여 추가와 수정을 했다.

장바구니 미션에서의 상품 추가 및 수정

중복1

클래스명을 제외하고 필드와 검증로직 그 외 모든게 같은 DTO를 보며 중복이라고 생각했다.
하지만 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
위 경우는 중복일까? 중복이 아닐까?

이 부분에 대해서 다음과 같은 리뷰를 받았다.

ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

질문에 대해 아래와 같이 답변을 했다.

저장과 수정할 때 필요한 필드값이 동일하여 현재 구조에서는 하나로 사용해도 된다고 생각을 하지만, 말씀해주신대로 요구사항이 변경된다면 달라질 가능성이 높다고 판단하였습니다!

중복과 우발적 중복

로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러가지 종류로 나누어 설명하고 있다.

  • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
  • 거짓된 중복, 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.

추가와 수정은 초기에는 중복으로 보이지만 초기 생성시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다. @@ -32,7 +32,7 @@ 상황에 맞춰 적재적소에 의존 역전을 이용해보는 것도 좋을 것 같다.

참고 자료

클린 아키텍처 16장 독립성, 로버트 C. 마틴
https://techblog.woowahan.com/2647/
https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

- - + + \ No newline at end of file diff --git a/assets/js/0462f8fc.d191c72d.js b/assets/js/0462f8fc.b80201e1.js similarity index 98% rename from assets/js/0462f8fc.d191c72d.js rename to assets/js/0462f8fc.b80201e1.js index 3fffdf598..ca7ce50a5 100644 --- a/assets/js/0462f8fc.d191c72d.js +++ b/assets/js/0462f8fc.b80201e1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4481],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>f});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=n.createContext({}),c=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=c(e.components);return n.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=c(r),f=a,m=d["".concat(p,".").concat(f)]||d[f]||u[f]||i;return r?n.createElement(m,l(l({ref:t},s),{},{components:r})):n.createElement(m,l({ref:t},s))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const i={title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",slug:"/test/benefit",tags:["test"]},l=void 0,o={unversionedId:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd",id:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd",title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",description:"\ub514\ubc84\uae45 \uac10\uc18c",source:"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/benefit",permalink:"/docs/test/benefit",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",slug:"/test/benefit",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"TDD heuristics",permalink:"/docs/test/heuristics"}},p={},c=[{value:"\ub514\ubc84\uae45 \uac10\uc18c",id:"\ub514\ubc84\uae45-\uac10\uc18c",level:3},{value:"\uc790\uc2e0 \uc788\uac8c \ubcc0\uacbd",id:"\uc790\uc2e0-\uc788\uac8c-\ubcc0\uacbd",level:3},{value:"\ub354 \ub098\uc740 \ubb38\uc11c \uc790\ub8cc",id:"\ub354-\ub098\uc740-\ubb38\uc11c-\uc790\ub8cc",level:3},{value:"\ub354 \ub2e8\uc21c\ud55c \ub9ac\ubdf0",id:"\ub354-\ub2e8\uc21c\ud55c-\ub9ac\ubdf0",level:3},{value:"\uc0ac\ub824 \uae4a\uc740 \uc124\uacc4",id:"\uc0ac\ub824-\uae4a\uc740-\uc124\uacc4",level:3},{value:"\uace0\ud488\uc9c8\uc758 \ub9b4\ub9ac\uc2a4\ub97c \ube60\ub974\uac8c",id:"\uace0\ud488\uc9c8\uc758-\ub9b4\ub9ac\uc2a4\ub97c-\ube60\ub974\uac8c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ub514\ubc84\uae45-\uac10\uc18c"},"\ub514\ubc84\uae45 \uac10\uc18c"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub97c \ud55c \ubc88 \uc791\uc131\ud574\ub450\uba74 \ud504\ub85c\uc81d\ud2b8\uc758 \uc0dd\uc874 \uc8fc\uae30\ub3d9\uc548 \uac12\ube44\uc2fc \uacb0\ud568\uc744 \uc608\ubc29\ud574 \uc900\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud568\uc774 \ud574\uacb0\ub418\uc5b4 \ub514\ubc84\uae45\uc5d0\uc11c \ud574\ubc29\uc2dc\ucf1c\uc900\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30\uc5d0\uc11c \uc5b8\uae09\ub41c ",(0,a.kt)("inlineCode",{parentName:"p"},"TDD heuristics 15. \ub514\ubc84\uac70 \uc0ac\uc6a9\uc744 \ud53c\ud558\ub77c")," \uc640 \uc5f0\uacb0\ub418\ub294 \ub0b4\uc6a9\uc774\ub2e4."),(0,a.kt)("h3",{id:"\uc790\uc2e0-\uc788\uac8c-\ubcc0\uacbd"},"\uc790\uc2e0 \uc788\uac8c \ubcc0\uacbd"),(0,a.kt)("p",null,"\uc18c\ud504\ud2b8\uc6e8\uc5b4\ub294 \ud56d\uc0c1 \ubcc0\uacbd\ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub9ac\ud329\ud130\ub9c1\ud560 \ub54c \uc790\uc2e0\uac10\uc744 \uac00\uc9c0\uace0 \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\ub354-\ub098\uc740-\ubb38\uc11c-\uc790\ub8cc"},"\ub354 \ub098\uc740 \ubb38\uc11c \uc790\ub8cc"),(0,a.kt)("p",null,"\ud558\ub098\uc758 \ud589\uc704\ub9cc \uc9d1\uc911\ud574 \uac80\uc99d\ud558\ub294 \ud14c\uc2a4\ud2b8\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ubb38\uc11c\uc640 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc774 \ub54c \ud14c\uc2a4\ud2b8\ub294 \uba85\ud655\ud558\uace0 \uac04\uacb0\ud574\uc57c\uc9c0\ub9cc \ubb38\uc11c \uc790\ub8cc\ub85c\uc11c\uc758 \uc5ed\ud560\uc744 \ud6cc\ub96d\ud788 \uc218\ud589\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\ub354-\ub2e8\uc21c\ud55c-\ub9ac\ubdf0"},"\ub354 \ub2e8\uc21c\ud55c \ub9ac\ubdf0"),(0,a.kt)("p",null,"\uc815\ud655\uc131, \uadf9\ub2e8 \uc0c1\ud669, \uc624\ub958 \uc0c1\ud669 \ub4f1\uc758 \ub2e4\uc591\ud55c \uce21\uba74\uc5d0\uc11c \ucf54\ub4dc\ub97c \uac80\uc0ac\ud574\uc8fc\ub294 \ud14c\uc2a4\ud2b8\uac00 \uc900\ube44\ub418\uc5b4 \uc788\ub2e4\uba74 \ub9ac\ubdf0\uc5b4\uac00 \uac80\uc99d\ud558\ub294 \uc2dc\uac04\uc744 \ud06c\uac8c \uc904\uc5ec\uc900\ub2e4. "),(0,a.kt)("h3",{id:"\uc0ac\ub824-\uae4a\uc740-\uc124\uacc4"},"\uc0ac\ub824 \uae4a\uc740 \uc124\uacc4"),(0,a.kt)("p",null,"\uc0c8\ub85c \uc791\uc131\ud55c \ucf54\ub4dc\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uc77c\uc740 \uc2e4\uc9c8\uc801\uc73c\ub85c \ud574\ub2f9 \ucf54\ub4dc\uc758 API\uac00 \uc798 \uc124\uacc4\ub418\uc5b4 \uc788\ub294\uc9c0\ub97c \uc2dc\ud5d8\ud558\ub294 \ud589\uc704\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud14c\uc2a4\ud2b8\ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\ub294 \ub108\ubb34 \ub9ce\uc740 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac70\ub098, \uc758\uc874\uc131\uc774 \ubcf5\uc7a1\ud55c \uacbd\uc6b0\uac00 \ub9ce\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc798 \uc124\uacc4\ub41c \ucf54\ub4dc\ub77c\uba74 \ubaa8\ub4c8\ud654\uac00 \uc798 \ub418\uc5b4\uc788\uc5b4\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\uace0\ud488\uc9c8\uc758-\ub9b4\ub9ac\uc2a4\ub97c-\ube60\ub974\uac8c"},"\uace0\ud488\uc9c8\uc758 \ub9b4\ub9ac\uc2a4\ub97c \ube60\ub974\uac8c"),(0,a.kt)("p",null,"\uc790\ub3d9\ud654\ub41c \ud14c\uc2a4\ud2b8\ub97c \uac16\ucd98\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ubc84\uc804\uc744 \ub9b4\ub9ac\uc2a4\ud560 \ub54c \ubd88\uc548\uc5d0 \ub5a8\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uad6c\uae00 \uc5d4\uc9c0\ub2c8\uc5b4\ub294 \uc774\ub807\uac8c \uc77c\ud55c\ub2e4, \ud0c0\uc774\ud130\uc2a4 \uc708\ud130\uc2a4, \ud1b0 \ub9e8\uc26c\ub809, \ud558\uc774\ub7fc \ub77c\uc774\ud2b8 p.288"))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[4481],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>f});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=n.createContext({}),c=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=c(e.components);return n.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=c(r),f=a,m=d["".concat(p,".").concat(f)]||d[f]||u[f]||i;return r?n.createElement(m,l(l({ref:t},s),{},{components:r})):n.createElement(m,l({ref:t},s))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const i={title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",slug:"/test/benefit",tags:["test"]},l=void 0,o={unversionedId:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd",id:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd",title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",description:"\ub514\ubc84\uae45 \uac10\uc18c",source:"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/benefit",permalink:"/docs/test/benefit",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",slug:"/test/benefit",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"TDD heuristics",permalink:"/docs/test/heuristics"}},p={},c=[{value:"\ub514\ubc84\uae45 \uac10\uc18c",id:"\ub514\ubc84\uae45-\uac10\uc18c",level:3},{value:"\uc790\uc2e0 \uc788\uac8c \ubcc0\uacbd",id:"\uc790\uc2e0-\uc788\uac8c-\ubcc0\uacbd",level:3},{value:"\ub354 \ub098\uc740 \ubb38\uc11c \uc790\ub8cc",id:"\ub354-\ub098\uc740-\ubb38\uc11c-\uc790\ub8cc",level:3},{value:"\ub354 \ub2e8\uc21c\ud55c \ub9ac\ubdf0",id:"\ub354-\ub2e8\uc21c\ud55c-\ub9ac\ubdf0",level:3},{value:"\uc0ac\ub824 \uae4a\uc740 \uc124\uacc4",id:"\uc0ac\ub824-\uae4a\uc740-\uc124\uacc4",level:3},{value:"\uace0\ud488\uc9c8\uc758 \ub9b4\ub9ac\uc2a4\ub97c \ube60\ub974\uac8c",id:"\uace0\ud488\uc9c8\uc758-\ub9b4\ub9ac\uc2a4\ub97c-\ube60\ub974\uac8c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ub514\ubc84\uae45-\uac10\uc18c"},"\ub514\ubc84\uae45 \uac10\uc18c"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub97c \ud55c \ubc88 \uc791\uc131\ud574\ub450\uba74 \ud504\ub85c\uc81d\ud2b8\uc758 \uc0dd\uc874 \uc8fc\uae30\ub3d9\uc548 \uac12\ube44\uc2fc \uacb0\ud568\uc744 \uc608\ubc29\ud574 \uc900\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud568\uc774 \ud574\uacb0\ub418\uc5b4 \ub514\ubc84\uae45\uc5d0\uc11c \ud574\ubc29\uc2dc\ucf1c\uc900\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30\uc5d0\uc11c \uc5b8\uae09\ub41c ",(0,a.kt)("inlineCode",{parentName:"p"},"TDD heuristics 15. \ub514\ubc84\uac70 \uc0ac\uc6a9\uc744 \ud53c\ud558\ub77c")," \uc640 \uc5f0\uacb0\ub418\ub294 \ub0b4\uc6a9\uc774\ub2e4."),(0,a.kt)("h3",{id:"\uc790\uc2e0-\uc788\uac8c-\ubcc0\uacbd"},"\uc790\uc2e0 \uc788\uac8c \ubcc0\uacbd"),(0,a.kt)("p",null,"\uc18c\ud504\ud2b8\uc6e8\uc5b4\ub294 \ud56d\uc0c1 \ubcc0\uacbd\ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub9ac\ud329\ud130\ub9c1\ud560 \ub54c \uc790\uc2e0\uac10\uc744 \uac00\uc9c0\uace0 \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\ub354-\ub098\uc740-\ubb38\uc11c-\uc790\ub8cc"},"\ub354 \ub098\uc740 \ubb38\uc11c \uc790\ub8cc"),(0,a.kt)("p",null,"\ud558\ub098\uc758 \ud589\uc704\ub9cc \uc9d1\uc911\ud574 \uac80\uc99d\ud558\ub294 \ud14c\uc2a4\ud2b8\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ubb38\uc11c\uc640 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc774 \ub54c \ud14c\uc2a4\ud2b8\ub294 \uba85\ud655\ud558\uace0 \uac04\uacb0\ud574\uc57c\uc9c0\ub9cc \ubb38\uc11c \uc790\ub8cc\ub85c\uc11c\uc758 \uc5ed\ud560\uc744 \ud6cc\ub96d\ud788 \uc218\ud589\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\ub354-\ub2e8\uc21c\ud55c-\ub9ac\ubdf0"},"\ub354 \ub2e8\uc21c\ud55c \ub9ac\ubdf0"),(0,a.kt)("p",null,"\uc815\ud655\uc131, \uadf9\ub2e8 \uc0c1\ud669, \uc624\ub958 \uc0c1\ud669 \ub4f1\uc758 \ub2e4\uc591\ud55c \uce21\uba74\uc5d0\uc11c \ucf54\ub4dc\ub97c \uac80\uc0ac\ud574\uc8fc\ub294 \ud14c\uc2a4\ud2b8\uac00 \uc900\ube44\ub418\uc5b4 \uc788\ub2e4\uba74 \ub9ac\ubdf0\uc5b4\uac00 \uac80\uc99d\ud558\ub294 \uc2dc\uac04\uc744 \ud06c\uac8c \uc904\uc5ec\uc900\ub2e4. "),(0,a.kt)("h3",{id:"\uc0ac\ub824-\uae4a\uc740-\uc124\uacc4"},"\uc0ac\ub824 \uae4a\uc740 \uc124\uacc4"),(0,a.kt)("p",null,"\uc0c8\ub85c \uc791\uc131\ud55c \ucf54\ub4dc\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uc77c\uc740 \uc2e4\uc9c8\uc801\uc73c\ub85c \ud574\ub2f9 \ucf54\ub4dc\uc758 API\uac00 \uc798 \uc124\uacc4\ub418\uc5b4 \uc788\ub294\uc9c0\ub97c \uc2dc\ud5d8\ud558\ub294 \ud589\uc704\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud14c\uc2a4\ud2b8\ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\ub294 \ub108\ubb34 \ub9ce\uc740 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac70\ub098, \uc758\uc874\uc131\uc774 \ubcf5\uc7a1\ud55c \uacbd\uc6b0\uac00 \ub9ce\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc798 \uc124\uacc4\ub41c \ucf54\ub4dc\ub77c\uba74 \ubaa8\ub4c8\ud654\uac00 \uc798 \ub418\uc5b4\uc788\uc5b4\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\uace0\ud488\uc9c8\uc758-\ub9b4\ub9ac\uc2a4\ub97c-\ube60\ub974\uac8c"},"\uace0\ud488\uc9c8\uc758 \ub9b4\ub9ac\uc2a4\ub97c \ube60\ub974\uac8c"),(0,a.kt)("p",null,"\uc790\ub3d9\ud654\ub41c \ud14c\uc2a4\ud2b8\ub97c \uac16\ucd98\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ubc84\uc804\uc744 \ub9b4\ub9ac\uc2a4\ud560 \ub54c \ubd88\uc548\uc5d0 \ub5a8\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uad6c\uae00 \uc5d4\uc9c0\ub2c8\uc5b4\ub294 \uc774\ub807\uac8c \uc77c\ud55c\ub2e4, \ud0c0\uc774\ud130\uc2a4 \uc708\ud130\uc2a4, \ud1b0 \ub9e8\uc26c\ub809, \ud558\uc774\ub7fc \ub77c\uc774\ud2b8 p.288"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/04644f5f.b526cda7.js b/assets/js/04644f5f.478842f3.js similarity index 98% rename from assets/js/04644f5f.b526cda7.js rename to assets/js/04644f5f.478842f3.js index b530d2f5c..446e4126c 100644 --- a/assets/js/04644f5f.b526cda7.js +++ b/assets/js/04644f5f.478842f3.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2625],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>d});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=r.createContext({}),p=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,c=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),s=p(n),d=a,f=s["".concat(c,".").concat(d)]||s[d]||m[d]||l;return n?r.createElement(f,i(i({ref:t},u),{},{components:n})):r.createElement(f,i({ref:t},u))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=s;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var p=2;p{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>o,toc:()=>p});var r=n(87462),a=(n(67294),n(3905));const l={title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",slug:"/etc/communication",tags:["etc"]},i=void 0,o={unversionedId:"\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",id:"\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",description:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798 \ud558\ub294 \uac1c\ubc1c\uc790?",source:"@site/docs/\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/communication",permalink:"/docs/etc/communication",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",slug:"/etc/communication",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",permalink:"/docs/etc/experience-and-self-question"},next:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",permalink:"/docs/network/load-balancing-algorithm"}},c={},p=[{value:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798 \ud558\ub294 \uac1c\ubc1c\uc790?",id:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158-\uc798-\ud558\ub294-\uac1c\ubc1c\uc790",level:3},{value:"\ubcc0\ud654\ub97c \ub9cc\ub4e4\ub824\uba74 \uc2b5\uad00\uc774 \ud544\uc694\ud558\ub2e4.",id:"\ubcc0\ud654\ub97c-\ub9cc\ub4e4\ub824\uba74-\uc2b5\uad00\uc774-\ud544\uc694\ud558\ub2e4",level:3},{value:"\uc88b\uc740 \uc2b5\uad00 4\uac00\uc9c0",id:"\uc88b\uc740-\uc2b5\uad00-4\uac00\uc9c0",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:p};function m(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158-\uc798-\ud558\ub294-\uac1c\ubc1c\uc790"},"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798 \ud558\ub294 \uac1c\ubc1c\uc790?"),(0,a.kt)("p",null,"\uc2a4\ud399 \uad6c\ud604\ud615 \uac1c\ubc1c\uc790 vs \ubb38\uc81c \ud574\uacb0\ud615 \uac1c\ubc1c\uc790 "),(0,a.kt)("p",null,"\uac1c\ubc1c\uc790 != \uc2a4\ud399\uc744 \uc8fc\uba74 \uc798 \uad6c\ud604\ud558\ub294 \uc0ac\ub78c",(0,a.kt)("br",{parentName:"p"}),"\n","\uad6c\ud604\uc5d0 \uc9d1\uc911\ud55c\ub2e4\uba74 \uc77c\uc758 \uc2dc\uc57c\uac00 \uc881\uc544\uc9c4\ub2e4. "),(0,a.kt)("p",null,"\uc758\ub3c4\uc640 \ub9e5\ub77d\uc744 \uc774\ud574\ud574\uc11c, \ub354 \uc88b\uc740 \uc2a4\ud399\uc744 \ub9cc\ub4e4\uc5b4\ub0b4\ub824\uace0 \ud558\ub294 \uac1c\ubc1c\uc790\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\ubcc0\ud654\ub97c-\ub9cc\ub4e4\ub824\uba74-\uc2b5\uad00\uc774-\ud544\uc694\ud558\ub2e4"},"\ubcc0\ud654\ub97c \ub9cc\ub4e4\ub824\uba74 \uc2b5\uad00\uc774 \ud544\uc694\ud558\ub2e4."),(0,a.kt)("p",null,"\uc8fc\ub2c8\uc5b4 \uac1c\ubc1c\uc790\ub294 \uc2a4\ud399 \uad6c\ud604 \uac1c\ubc1c\uc790\uc5d0\uc11c \uc2dc\uc791\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ubcc0\ud654\ub97c \uc704\ud574 \uc2e4\uc81c\ub85c \ud589\ub3d9\ud558\ub294 ",(0,a.kt)("inlineCode",{parentName:"p"},"\uc2b5\uad00"),"\uc774 \ud544\uc694\ud558\ub2e4. "),(0,a.kt)("h3",{id:"\uc88b\uc740-\uc2b5\uad00-4\uac00\uc9c0"},"\uc88b\uc740 \uc2b5\uad00 4\uac00\uc9c0"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\ud574\uacb0\ud558\ub824\ub294 ",(0,a.kt)("inlineCode",{parentName:"li"},"\ubb38\uc81c"),"\uc640 ",(0,a.kt)("inlineCode",{parentName:"li"},"\uc758\ub3c4/\uc0c1\ud669"),"\uc5d0 \ub300\ud574 \ubb3b\ub294\ub2e4. "),(0,a.kt)("li",{parentName:"ol"},"\uc0c1\ub300\ubc29\uc758 \ub9d0\uc744 \ub4e3\uace0 ",(0,a.kt)("inlineCode",{parentName:"li"},"\ub0b4\uac00")," \uc774\ud574\ud55c \ubc14\ub97c \uc694\uc57d\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4. ",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\ud55c \ubc88 \uc815\ub9ac\ud55c\ub2e4\uba74 1... 2... \uc774\ub807\uac8c \uc774\ud574\ud588\ub294\ub370 \ub9de\uc744\uae4c\uc694?"))),(0,a.kt)("li",{parentName:"ol"},"\uc548 \ub41c\ub2e4\uace0 \ub9d0\ud560 \ub54c\ub294 \uc0c1\ub300\ubc29\uc5d0 \uad00\uc810\uc5d0\uc11c \ub300\uc548\uc744 \uc81c\uc2dc\ud55c\ub2e4. ",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\uc81c\uc57d\uc744 \ub35c \ubc1b\ub294 \ub2e4\ub978 \ubc29\ud5a5\uc131/\ub300\uc548 \uc81c\uc2dc"))),(0,a.kt)("li",{parentName:"ol"},"\ubb38\uc81c\ub97c \ud574\uacb0\ud560 \ub610 \ub2e4\ub978 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubcf8\ub2e4. ",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\ub2e8\uc815\ub300\uc2e0 \ud55c \ubc88 \ub354 \uc9c8\ubb38\ud558\uace0 \uc0dd\uac01")))),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00 - \uc1a1\ubc94\uadfc, INFCON 2023"))}m.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2625],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>d});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=r.createContext({}),p=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=p(e.components);return r.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},s=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,c=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),s=p(n),d=a,f=s["".concat(c,".").concat(d)]||s[d]||m[d]||l;return n?r.createElement(f,i(i({ref:t},u),{},{components:n})):r.createElement(f,i({ref:t},u))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=s;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var p=2;p{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>l,metadata:()=>o,toc:()=>p});var r=n(87462),a=(n(67294),n(3905));const l={title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",slug:"/etc/communication",tags:["etc"]},i=void 0,o={unversionedId:"\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",id:"\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",description:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798 \ud558\ub294 \uac1c\ubc1c\uc790?",source:"@site/docs/\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/communication",permalink:"/docs/etc/communication",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",slug:"/etc/communication",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",permalink:"/docs/etc/experience-and-self-question"},next:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",permalink:"/docs/network/load-balancing-algorithm"}},c={},p=[{value:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798 \ud558\ub294 \uac1c\ubc1c\uc790?",id:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158-\uc798-\ud558\ub294-\uac1c\ubc1c\uc790",level:3},{value:"\ubcc0\ud654\ub97c \ub9cc\ub4e4\ub824\uba74 \uc2b5\uad00\uc774 \ud544\uc694\ud558\ub2e4.",id:"\ubcc0\ud654\ub97c-\ub9cc\ub4e4\ub824\uba74-\uc2b5\uad00\uc774-\ud544\uc694\ud558\ub2e4",level:3},{value:"\uc88b\uc740 \uc2b5\uad00 4\uac00\uc9c0",id:"\uc88b\uc740-\uc2b5\uad00-4\uac00\uc9c0",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:p};function m(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158-\uc798-\ud558\ub294-\uac1c\ubc1c\uc790"},"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798 \ud558\ub294 \uac1c\ubc1c\uc790?"),(0,a.kt)("p",null,"\uc2a4\ud399 \uad6c\ud604\ud615 \uac1c\ubc1c\uc790 vs \ubb38\uc81c \ud574\uacb0\ud615 \uac1c\ubc1c\uc790 "),(0,a.kt)("p",null,"\uac1c\ubc1c\uc790 != \uc2a4\ud399\uc744 \uc8fc\uba74 \uc798 \uad6c\ud604\ud558\ub294 \uc0ac\ub78c",(0,a.kt)("br",{parentName:"p"}),"\n","\uad6c\ud604\uc5d0 \uc9d1\uc911\ud55c\ub2e4\uba74 \uc77c\uc758 \uc2dc\uc57c\uac00 \uc881\uc544\uc9c4\ub2e4. "),(0,a.kt)("p",null,"\uc758\ub3c4\uc640 \ub9e5\ub77d\uc744 \uc774\ud574\ud574\uc11c, \ub354 \uc88b\uc740 \uc2a4\ud399\uc744 \ub9cc\ub4e4\uc5b4\ub0b4\ub824\uace0 \ud558\ub294 \uac1c\ubc1c\uc790\uac00 \ub418\uc5b4\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\ubcc0\ud654\ub97c-\ub9cc\ub4e4\ub824\uba74-\uc2b5\uad00\uc774-\ud544\uc694\ud558\ub2e4"},"\ubcc0\ud654\ub97c \ub9cc\ub4e4\ub824\uba74 \uc2b5\uad00\uc774 \ud544\uc694\ud558\ub2e4."),(0,a.kt)("p",null,"\uc8fc\ub2c8\uc5b4 \uac1c\ubc1c\uc790\ub294 \uc2a4\ud399 \uad6c\ud604 \uac1c\ubc1c\uc790\uc5d0\uc11c \uc2dc\uc791\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ubcc0\ud654\ub97c \uc704\ud574 \uc2e4\uc81c\ub85c \ud589\ub3d9\ud558\ub294 ",(0,a.kt)("inlineCode",{parentName:"p"},"\uc2b5\uad00"),"\uc774 \ud544\uc694\ud558\ub2e4. "),(0,a.kt)("h3",{id:"\uc88b\uc740-\uc2b5\uad00-4\uac00\uc9c0"},"\uc88b\uc740 \uc2b5\uad00 4\uac00\uc9c0"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"\ud574\uacb0\ud558\ub824\ub294 ",(0,a.kt)("inlineCode",{parentName:"li"},"\ubb38\uc81c"),"\uc640 ",(0,a.kt)("inlineCode",{parentName:"li"},"\uc758\ub3c4/\uc0c1\ud669"),"\uc5d0 \ub300\ud574 \ubb3b\ub294\ub2e4. "),(0,a.kt)("li",{parentName:"ol"},"\uc0c1\ub300\ubc29\uc758 \ub9d0\uc744 \ub4e3\uace0 ",(0,a.kt)("inlineCode",{parentName:"li"},"\ub0b4\uac00")," \uc774\ud574\ud55c \ubc14\ub97c \uc694\uc57d\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4. ",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\ud55c \ubc88 \uc815\ub9ac\ud55c\ub2e4\uba74 1... 2... \uc774\ub807\uac8c \uc774\ud574\ud588\ub294\ub370 \ub9de\uc744\uae4c\uc694?"))),(0,a.kt)("li",{parentName:"ol"},"\uc548 \ub41c\ub2e4\uace0 \ub9d0\ud560 \ub54c\ub294 \uc0c1\ub300\ubc29\uc5d0 \uad00\uc810\uc5d0\uc11c \ub300\uc548\uc744 \uc81c\uc2dc\ud55c\ub2e4. ",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\uc81c\uc57d\uc744 \ub35c \ubc1b\ub294 \ub2e4\ub978 \ubc29\ud5a5\uc131/\ub300\uc548 \uc81c\uc2dc"))),(0,a.kt)("li",{parentName:"ol"},"\ubb38\uc81c\ub97c \ud574\uacb0\ud560 \ub610 \ub2e4\ub978 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubcf8\ub2e4. ",(0,a.kt)("ul",{parentName:"li"},(0,a.kt)("li",{parentName:"ul"},"\ub2e8\uc815\ub300\uc2e0 \ud55c \ubc88 \ub354 \uc9c8\ubb38\ud558\uace0 \uc0dd\uac01")))),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00 - \uc1a1\ubc94\uadfc, INFCON 2023"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0d47646f.04fe4885.js b/assets/js/0d47646f.e8fba6bf.js similarity index 98% rename from assets/js/0d47646f.04fe4885.js rename to assets/js/0d47646f.e8fba6bf.js index b877436cf..a1d2ff47f 100644 --- a/assets/js/0d47646f.04fe4885.js +++ b/assets/js/0d47646f.e8fba6bf.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2342],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),c=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(r),d=o,f=m["".concat(p,".").concat(d)]||m[d]||s[d]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>a,default:()=>s,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(87462),o=(r(67294),r(3905));const i={title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"/monitoring/intro",tags:["monitoring"]},a=void 0,l={unversionedId:"\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131",id:"\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131",title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",description:"\ubaa8\ub2c8\ud130\ub9c1 3\ub2e8\uacc4",source:"@site/docs/\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131.mdx",sourceDirName:"\ubaa8\ub2c8\ud130\ub9c1",slug:"/monitoring/intro",permalink:"/docs/monitoring/intro",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131.mdx",tags:[{label:"monitoring",permalink:"/docs/tags/monitoring"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"/monitoring/intro",tags:["monitoring"]},sidebar:"tutorialSidebar",previous:{title:"\ud130\ubbf8\ub110 \uc258 \ud504\ub86c\ud504\ud2b8 \uc124\uc815",permalink:"/docs/linux/shell"},next:{title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",permalink:"/docs/culture/postmortem"}},p={},c=[{value:"\ubaa8\ub2c8\ud130\ub9c1 3\ub2e8\uacc4",id:"\ubaa8\ub2c8\ud130\ub9c1-3\ub2e8\uacc4",level:3},{value:"\ubaa8\ub2c8\ud130\ub9c1 \ub300\uc0c1",id:"\ubaa8\ub2c8\ud130\ub9c1-\ub300\uc0c1",level:3},{value:"\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucd94\uc801",id:"\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ucd94\uc801",level:3},{value:"\ub85c\uadf8",id:"\ub85c\uadf8",level:3},{value:"\ubaa8\ub2c8\ud130\ub9c1",id:"\ubaa8\ub2c8\ud130\ub9c1",level:3},{value:"\uc54c\ub78c",id:"\uc54c\ub78c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"\ubaa8\ub2c8\ud130\ub9c1-3\ub2e8\uacc4"},"\ubaa8\ub2c8\ud130\ub9c1 3\ub2e8\uacc4"),(0,o.kt)("p",null,"\ub300\uc2dc\ubcf4\ub4dc",(0,o.kt)("br",{parentName:"p"}),"\n","\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucd94\uc801 - \ud540\ud3ec\uc778\ud2b8",(0,o.kt)("br",{parentName:"p"}),"\n","\ub85c\uadf8 "),(0,o.kt)("h3",{id:"\ubaa8\ub2c8\ud130\ub9c1-\ub300\uc0c1"},"\ubaa8\ub2c8\ud130\ub9c1 \ub300\uc0c1"),(0,o.kt)("p",null,"\uc2dc\uc2a4\ud15c \uba54\ud2b8\ub9ad(CPU, \uba54\ubaa8\ub9ac)",(0,o.kt)("br",{parentName:"p"}),"\n","\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uba54\ud2b8\ub9ad(Thread Pool, Connection Pool, \ud638\ucd9c \uc218)",(0,o.kt)("br",{parentName:"p"}),"\n","\ube44\uc988\ub2c8\uc2a4 \uba54\ud2b8\ub9ad"),(0,o.kt)("h3",{id:"\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ucd94\uc801"},"\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucd94\uc801"),(0,o.kt)("p",null,"\uac01\uac01\uc758 HTTP \uc694\uccad \ucd94\uc801",(0,o.kt)("br",{parentName:"p"}),"\n","\ud540\ud3ec\uc778\ud2b8, \uc2a4\uce74\uc6b0\ud2b8, \uc640\ud0ed, \uc81c\ub2c8\ud37c "),(0,o.kt)("h3",{id:"\ub85c\uadf8"},"\ub85c\uadf8"),(0,o.kt)("p",null,"\uac00\uc7a5 \uc138\uc138\ud55c \ucd94\uc801",(0,o.kt)("br",{parentName:"p"}),"\n","\uac19\uc740 HTTP \uc694\uccad\uc744 \ubb36\uc5b4\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \uc911\uc694\ud558\ub2e4.",(0,o.kt)("br",{parentName:"p"}),"\n","MDC(Mapped Diagnostic Context) \uc801\uc6a9"),(0,o.kt)("p",null,"\ud30c\uc77c\ub85c \uc9c1\uc811 \ub85c\uadf8\ub97c \ub0a8\uae30\ub294 \uacbd\uc6b0 \u2192 \uc77c\ubc18 \ub85c\uadf8\uc640 \uc5d0\ub7ec \ub85c\uadf8 \ud30c\uc77c\uc744 \uad6c\ubd84\ud574\uc11c \ub0a8\uaca8\uc57c \ud55c\ub2e4.",(0,o.kt)("br",{parentName:"p"}),"\n","\ud074\ub77c\uc6b0\ub4dc\uc5d0 \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0 \u2192 \uac80\uc0c9\uc774 \uc798 \ub418\ub3c4\ub85d \uad6c\ubd84\ud55c\ub2e4. "),(0,o.kt)("h3",{id:"\ubaa8\ub2c8\ud130\ub9c1"},"\ubaa8\ub2c8\ud130\ub9c1"),(0,o.kt)("p",null,"\uad00\ucc30\uc758 \uacbd\uc6b0 \uc804\uccb4 \u2192 \uc881\uac8c"),(0,o.kt)("h3",{id:"\uc54c\ub78c"},"\uc54c\ub78c"),(0,o.kt)("p",null,"\uc54c\ub78c\uc758 \uacbd\uc6b0 2\uac00\uc9c0 \uc885\ub958(\uacbd\uace0, \uc2ec\uac01)\ub85c \uad6c\ubd84\ud574\uc11c \uad00\ub9ac\ud55c\ub2e4."),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ud575\uc2ec \uc6d0\ub9ac\uc640 \ud65c\uc6a9, \uae40\uc601\ud55c"))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2342],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),c=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,p=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(r),d=o,f=m["".concat(p,".").concat(d)]||m[d]||s[d]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:o,a[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>a,default:()=>s,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(87462),o=(r(67294),r(3905));const i={title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"/monitoring/intro",tags:["monitoring"]},a=void 0,l={unversionedId:"\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131",id:"\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131",title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",description:"\ubaa8\ub2c8\ud130\ub9c1 3\ub2e8\uacc4",source:"@site/docs/\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131.mdx",sourceDirName:"\ubaa8\ub2c8\ud130\ub9c1",slug:"/monitoring/intro",permalink:"/docs/monitoring/intro",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131.mdx",tags:[{label:"monitoring",permalink:"/docs/tags/monitoring"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",slug:"/monitoring/intro",tags:["monitoring"]},sidebar:"tutorialSidebar",previous:{title:"\ud130\ubbf8\ub110 \uc258 \ud504\ub86c\ud504\ud2b8 \uc124\uc815",permalink:"/docs/linux/shell"},next:{title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",permalink:"/docs/culture/postmortem"}},p={},c=[{value:"\ubaa8\ub2c8\ud130\ub9c1 3\ub2e8\uacc4",id:"\ubaa8\ub2c8\ud130\ub9c1-3\ub2e8\uacc4",level:3},{value:"\ubaa8\ub2c8\ud130\ub9c1 \ub300\uc0c1",id:"\ubaa8\ub2c8\ud130\ub9c1-\ub300\uc0c1",level:3},{value:"\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucd94\uc801",id:"\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ucd94\uc801",level:3},{value:"\ub85c\uadf8",id:"\ub85c\uadf8",level:3},{value:"\ubaa8\ub2c8\ud130\ub9c1",id:"\ubaa8\ub2c8\ud130\ub9c1",level:3},{value:"\uc54c\ub78c",id:"\uc54c\ub78c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"\ubaa8\ub2c8\ud130\ub9c1-3\ub2e8\uacc4"},"\ubaa8\ub2c8\ud130\ub9c1 3\ub2e8\uacc4"),(0,o.kt)("p",null,"\ub300\uc2dc\ubcf4\ub4dc",(0,o.kt)("br",{parentName:"p"}),"\n","\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucd94\uc801 - \ud540\ud3ec\uc778\ud2b8",(0,o.kt)("br",{parentName:"p"}),"\n","\ub85c\uadf8 "),(0,o.kt)("h3",{id:"\ubaa8\ub2c8\ud130\ub9c1-\ub300\uc0c1"},"\ubaa8\ub2c8\ud130\ub9c1 \ub300\uc0c1"),(0,o.kt)("p",null,"\uc2dc\uc2a4\ud15c \uba54\ud2b8\ub9ad(CPU, \uba54\ubaa8\ub9ac)",(0,o.kt)("br",{parentName:"p"}),"\n","\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uba54\ud2b8\ub9ad(Thread Pool, Connection Pool, \ud638\ucd9c \uc218)",(0,o.kt)("br",{parentName:"p"}),"\n","\ube44\uc988\ub2c8\uc2a4 \uba54\ud2b8\ub9ad"),(0,o.kt)("h3",{id:"\uc560\ud50c\ub9ac\ucf00\uc774\uc158-\ucd94\uc801"},"\uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucd94\uc801"),(0,o.kt)("p",null,"\uac01\uac01\uc758 HTTP \uc694\uccad \ucd94\uc801",(0,o.kt)("br",{parentName:"p"}),"\n","\ud540\ud3ec\uc778\ud2b8, \uc2a4\uce74\uc6b0\ud2b8, \uc640\ud0ed, \uc81c\ub2c8\ud37c "),(0,o.kt)("h3",{id:"\ub85c\uadf8"},"\ub85c\uadf8"),(0,o.kt)("p",null,"\uac00\uc7a5 \uc138\uc138\ud55c \ucd94\uc801",(0,o.kt)("br",{parentName:"p"}),"\n","\uac19\uc740 HTTP \uc694\uccad\uc744 \ubb36\uc5b4\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \uc911\uc694\ud558\ub2e4.",(0,o.kt)("br",{parentName:"p"}),"\n","MDC(Mapped Diagnostic Context) \uc801\uc6a9"),(0,o.kt)("p",null,"\ud30c\uc77c\ub85c \uc9c1\uc811 \ub85c\uadf8\ub97c \ub0a8\uae30\ub294 \uacbd\uc6b0 \u2192 \uc77c\ubc18 \ub85c\uadf8\uc640 \uc5d0\ub7ec \ub85c\uadf8 \ud30c\uc77c\uc744 \uad6c\ubd84\ud574\uc11c \ub0a8\uaca8\uc57c \ud55c\ub2e4.",(0,o.kt)("br",{parentName:"p"}),"\n","\ud074\ub77c\uc6b0\ub4dc\uc5d0 \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0 \u2192 \uac80\uc0c9\uc774 \uc798 \ub418\ub3c4\ub85d \uad6c\ubd84\ud55c\ub2e4. "),(0,o.kt)("h3",{id:"\ubaa8\ub2c8\ud130\ub9c1"},"\ubaa8\ub2c8\ud130\ub9c1"),(0,o.kt)("p",null,"\uad00\ucc30\uc758 \uacbd\uc6b0 \uc804\uccb4 \u2192 \uc881\uac8c"),(0,o.kt)("h3",{id:"\uc54c\ub78c"},"\uc54c\ub78c"),(0,o.kt)("p",null,"\uc54c\ub78c\uc758 \uacbd\uc6b0 2\uac00\uc9c0 \uc885\ub958(\uacbd\uace0, \uc2ec\uac01)\ub85c \uad6c\ubd84\ud574\uc11c \uad00\ub9ac\ud55c\ub2e4."),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ud575\uc2ec \uc6d0\ub9ac\uc640 \ud65c\uc6a9, \uae40\uc601\ud55c"))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/302370be.bdf8f944.js b/assets/js/302370be.9c65bb4a.js similarity index 98% rename from assets/js/302370be.bdf8f944.js rename to assets/js/302370be.9c65bb4a.js index 036fabf1f..488582d21 100644 --- a/assets/js/302370be.bdf8f944.js +++ b/assets/js/302370be.9c65bb4a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1883],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>f});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=n.createContext({}),s=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},c=function(e){var t=s(e.components);return n.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,p=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),u=s(r),f=a,m=u["".concat(p,".").concat(f)]||u[f]||d[f]||l;return r?n.createElement(m,i(i({ref:t},c),{},{components:r})):n.createElement(m,i({ref:t},c))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,i=new Array(l);i[0]=u;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var s=2;s{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>s});var n=r(87462),a=(r(67294),r(3905));const l={title:"FIRST",slug:"/test/first",tags:["test"]},i=void 0,o={unversionedId:"\ud14c\uc2a4\ud2b8/FIRST",id:"\ud14c\uc2a4\ud2b8/FIRST",title:"FIRST",description:"FIRST\ub780?",source:"@site/docs/\ud14c\uc2a4\ud2b8/FIRST.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/first",permalink:"/docs/test/first",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/FIRST.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"FIRST",slug:"/test/first",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",permalink:"/docs/performance/types"},next:{title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",permalink:"/docs/test/stairstep"}},p={},s=[{value:"FIRST\ub780?",id:"first\ub780",level:3},{value:"Fast(\ube60\ub974\uac8c)",id:"fast\ube60\ub974\uac8c",level:3},{value:"Independent(\ub3c5\ub9bd\uc801\uc73c\ub85c)",id:"independent\ub3c5\ub9bd\uc801\uc73c\ub85c",level:3},{value:"Repeatable(\ubc18\ubcf5 \uac00\ub2a5\ud55c)",id:"repeatable\ubc18\ubcf5-\uac00\ub2a5\ud55c",level:3},{value:"Self-Validating(\uc790\uac00 \uac80\uc99d\ud558\ub294)",id:"self-validating\uc790\uac00-\uac80\uc99d\ud558\ub294",level:3},{value:"Timely(\uc801\uc2dc\uc5d0)",id:"timely\uc801\uc2dc\uc5d0",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}],c={toc:s};function d(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"first\ub780"},"FIRST\ub780?"),(0,a.kt)("p",null,"Fast, Independent, Repeatable, Self-Validating, Timely\uc758 \uc57d\uc790\ub85c \uc88b\uc740 \ub2e8\uc704 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294\ub370 \ub3c4\uc6c0\uc774 \ub418\ub294 \uc6d0\uce59\ub4e4\uc774\ub2e4."),(0,a.kt)("h3",{id:"fast\ube60\ub974\uac8c"},"Fast(\ube60\ub974\uac8c)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\uac00 \ube60\ub974\uac8c \ub3cc\uc544\uac00\uc9c0 \uc54a\uc73c\uba74, \ud14c\uc2a4\ud2b8\ub97c \ub9e4 \uc21c\uac04 \uc2e4\ud589\ud558\uc9c0 \uc54a\uc744 \uac83\uc774\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud14c\uc2a4\ud2b8\ub97c \uc790\uc8fc \uc2e4\ud589\ud558\uc9c0 \uc54a\uc73c\uba74, \ubc84\uadf8\ub97c \ub193\uce60 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub530\ub77c\uc11c \ube60\ub974\uac8c \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ud53c\ub4dc\ubc31 \ubc1b\ub294 \uc8fc\uae30\ub97c \uc9e7\uac8c \ub9cc\ub4dc\ub294 \uac83\uc774 \uc88b\ub2e4. "),(0,a.kt)("h3",{id:"independent\ub3c5\ub9bd\uc801\uc73c\ub85c"},"Independent(\ub3c5\ub9bd\uc801\uc73c\ub85c)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548\ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4. "),(0,a.kt)("h3",{id:"repeatable\ubc18\ubcf5-\uac00\ub2a5\ud55c"},"Repeatable(\ubc18\ubcf5 \uac00\ub2a5\ud55c)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub294 \uc5b4\ub5a0\ud55c \ud658\uacbd\uc5d0\uc11c\ub77c\ub3c4 \ubc18\ubcf5 \uac00\ub2a5\ud574\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \ubc18\ubcf5\uc801\uc73c\ub85c \uc218\ud589\ud574\ub3c4 \uac19\uc740 \uacb0\uacfc\ub97c \ub0bc \uc218 \uc788\uc5b4\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"self-validating\uc790\uac00-\uac80\uc99d\ud558\ub294"},"Self-Validating(\uc790\uac00 \uac80\uc99d\ud558\ub294)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub294 \uc131\uacf5 \ub610\ub294 \uc2e4\ud328\ub85c bool \uac12\uc73c\ub85c \uacb0\uacfc\ub97c \ub0b4\uc5b4 \uc790\uccb4\uc801\uc73c\ub85c \uac80\uc99d\ud574\uc57c \ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","JUnit\uacfc \uac19\uc740 \uc790\ub3d9\ud654\ub41c \ud14c\uc2a4\ud2b8 \ub3c4\uad6c\ub97c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"timely\uc801\uc2dc\uc5d0"},"Timely(\uc801\uc2dc\uc5d0)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub294 \uc801\uc2dc\uc5d0 \uc791\uc131\ud574\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e8\uc704 \ud14c\uc2a4\ud2b8\ub294 \ud14c\uc2a4\ud2b8 \ud558\ub824\ub294 \uc2e4\uc81c \ucf54\ub4dc\ub97c \uad6c\ud604\ud558\uae30 \uc9c1\uc804\uc5d0 \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.(TDD)",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e4\uc81c \ucf54\ub4dc\ub97c \uad6c\ud604\ud55c \ub2e4\uc74c\uc5d0 \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud55c\ub2e4\uba74, \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4\ub294 \uac83\uc744 \ub4a4\ub2a6\uac8c \ubc1c\uacac\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h2",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://tddmanifesto.com/a-clean-test/"},"A clean test, TDD Manifasto"),(0,a.kt)("br",{parentName:"p"}),"\n","Clean Code 9\uc7a5 \ub2e8\uc704\ud14c\uc2a4\ud2b8, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4"))}d.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1883],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>f});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=n.createContext({}),s=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},c=function(e){var t=s(e.components);return n.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,p=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),u=s(r),f=a,m=u["".concat(p,".").concat(f)]||u[f]||d[f]||l;return r?n.createElement(m,i(i({ref:t},c),{},{components:r})):n.createElement(m,i({ref:t},c))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,i=new Array(l);i[0]=u;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var s=2;s{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>s});var n=r(87462),a=(r(67294),r(3905));const l={title:"FIRST",slug:"/test/first",tags:["test"]},i=void 0,o={unversionedId:"\ud14c\uc2a4\ud2b8/FIRST",id:"\ud14c\uc2a4\ud2b8/FIRST",title:"FIRST",description:"FIRST\ub780?",source:"@site/docs/\ud14c\uc2a4\ud2b8/FIRST.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/first",permalink:"/docs/test/first",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/FIRST.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"FIRST",slug:"/test/first",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",permalink:"/docs/performance/types"},next:{title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",permalink:"/docs/test/stairstep"}},p={},s=[{value:"FIRST\ub780?",id:"first\ub780",level:3},{value:"Fast(\ube60\ub974\uac8c)",id:"fast\ube60\ub974\uac8c",level:3},{value:"Independent(\ub3c5\ub9bd\uc801\uc73c\ub85c)",id:"independent\ub3c5\ub9bd\uc801\uc73c\ub85c",level:3},{value:"Repeatable(\ubc18\ubcf5 \uac00\ub2a5\ud55c)",id:"repeatable\ubc18\ubcf5-\uac00\ub2a5\ud55c",level:3},{value:"Self-Validating(\uc790\uac00 \uac80\uc99d\ud558\ub294)",id:"self-validating\uc790\uac00-\uac80\uc99d\ud558\ub294",level:3},{value:"Timely(\uc801\uc2dc\uc5d0)",id:"timely\uc801\uc2dc\uc5d0",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:2}],c={toc:s};function d(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"first\ub780"},"FIRST\ub780?"),(0,a.kt)("p",null,"Fast, Independent, Repeatable, Self-Validating, Timely\uc758 \uc57d\uc790\ub85c \uc88b\uc740 \ub2e8\uc704 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub294\ub370 \ub3c4\uc6c0\uc774 \ub418\ub294 \uc6d0\uce59\ub4e4\uc774\ub2e4."),(0,a.kt)("h3",{id:"fast\ube60\ub974\uac8c"},"Fast(\ube60\ub974\uac8c)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\uac00 \ube60\ub974\uac8c \ub3cc\uc544\uac00\uc9c0 \uc54a\uc73c\uba74, \ud14c\uc2a4\ud2b8\ub97c \ub9e4 \uc21c\uac04 \uc2e4\ud589\ud558\uc9c0 \uc54a\uc744 \uac83\uc774\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud14c\uc2a4\ud2b8\ub97c \uc790\uc8fc \uc2e4\ud589\ud558\uc9c0 \uc54a\uc73c\uba74, \ubc84\uadf8\ub97c \ub193\uce60 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub530\ub77c\uc11c \ube60\ub974\uac8c \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ud53c\ub4dc\ubc31 \ubc1b\ub294 \uc8fc\uae30\ub97c \uc9e7\uac8c \ub9cc\ub4dc\ub294 \uac83\uc774 \uc88b\ub2e4. "),(0,a.kt)("h3",{id:"independent\ub3c5\ub9bd\uc801\uc73c\ub85c"},"Independent(\ub3c5\ub9bd\uc801\uc73c\ub85c)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub07c\ub9ac \uc11c\ub85c \uc758\uc874\ud558\uba74 \uc548\ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc11c\ub85c \uc758\uc874\ud558\uac8c \ub41c\ub2e4\uba74 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \ub54c, \ub610 \ub2e4\ub978 \ud558\ub098\uc758 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc5d0 \uc758\uc874\ud558\uc9c0 \uc54a\uace0, \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \ud14c\uc2a4\ud2b8\uac00 \uc88b\uc740 \ud14c\uc2a4\ud2b8\ub2e4. "),(0,a.kt)("h3",{id:"repeatable\ubc18\ubcf5-\uac00\ub2a5\ud55c"},"Repeatable(\ubc18\ubcf5 \uac00\ub2a5\ud55c)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub294 \uc5b4\ub5a0\ud55c \ud658\uacbd\uc5d0\uc11c\ub77c\ub3c4 \ubc18\ubcf5 \uac00\ub2a5\ud574\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \ubc18\ubcf5\uc801\uc73c\ub85c \uc218\ud589\ud574\ub3c4 \uac19\uc740 \uacb0\uacfc\ub97c \ub0bc \uc218 \uc788\uc5b4\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"self-validating\uc790\uac00-\uac80\uc99d\ud558\ub294"},"Self-Validating(\uc790\uac00 \uac80\uc99d\ud558\ub294)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub294 \uc131\uacf5 \ub610\ub294 \uc2e4\ud328\ub85c bool \uac12\uc73c\ub85c \uacb0\uacfc\ub97c \ub0b4\uc5b4 \uc790\uccb4\uc801\uc73c\ub85c \uac80\uc99d\ud574\uc57c \ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","JUnit\uacfc \uac19\uc740 \uc790\ub3d9\ud654\ub41c \ud14c\uc2a4\ud2b8 \ub3c4\uad6c\ub97c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"timely\uc801\uc2dc\uc5d0"},"Timely(\uc801\uc2dc\uc5d0)"),(0,a.kt)("p",null,"\ud14c\uc2a4\ud2b8\ub294 \uc801\uc2dc\uc5d0 \uc791\uc131\ud574\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e8\uc704 \ud14c\uc2a4\ud2b8\ub294 \ud14c\uc2a4\ud2b8 \ud558\ub824\ub294 \uc2e4\uc81c \ucf54\ub4dc\ub97c \uad6c\ud604\ud558\uae30 \uc9c1\uc804\uc5d0 \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.(TDD)",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e4\uc81c \ucf54\ub4dc\ub97c \uad6c\ud604\ud55c \ub2e4\uc74c\uc5d0 \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ub97c \uc791\uc131\ud55c\ub2e4\uba74, \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\ub97c \uc791\uc131\ud588\ub2e4\ub294 \uac83\uc744 \ub4a4\ub2a6\uac8c \ubc1c\uacac\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h2",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://tddmanifesto.com/a-clean-test/"},"A clean test, TDD Manifasto"),(0,a.kt)("br",{parentName:"p"}),"\n","Clean Code 9\uc7a5 \ub2e8\uc704\ud14c\uc2a4\ud2b8, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4"))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/366ddb85.905cf70f.js b/assets/js/366ddb85.bba0b200.js similarity index 99% rename from assets/js/366ddb85.905cf70f.js rename to assets/js/366ddb85.bba0b200.js index 46533878e..f7f61f013 100644 --- a/assets/js/366ddb85.905cf70f.js +++ b/assets/js/366ddb85.bba0b200.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3691],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=c(r),m=a,f=d["".concat(i,".").concat(m)]||d[m]||s[m]||o;return r?n.createElement(f,p(p({ref:t},u),{},{components:r})):n.createElement(f,p({ref:t},u))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,p=new Array(o);p[0]=d;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,p[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>p,default:()=>s,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",slug:"/etc/develop-with-spring",tags:["etc"]},p=void 0,l={unversionedId:"\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",id:"\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",description:"\uc5b4\ub5a4 \uae30\uc220\uc744 \ud1b5\ud574\uc11c\ub3c4 \uc131\uc7a5\ud560 \uc218 \uc788\ub2e4.",source:"@site/docs/\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/develop-with-spring",permalink:"/docs/etc/develop-with-spring",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",slug:"/etc/develop-with-spring",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",permalink:"/docs/etc/healthful-growth"},next:{title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",permalink:"/docs/etc/experience-and-self-question"}},i={},c=[{value:"\uc2e4\uc804 \uc0ac\uc6a9",id:"\uc2e4\uc804-\uc0ac\uc6a9",level:3},{value:"\uc9c8\ubb38\uacfc \ud0d0\uad6c",id:"\uc9c8\ubb38\uacfc-\ud0d0\uad6c",level:3},{value:"\ud6c8\ub828\uacfc \uac1c\uc120",id:"\ud6c8\ub828\uacfc-\uac1c\uc120",level:3},{value:"\uacf5\uc720\uc640 \ub17c\uc7c1",id:"\uacf5\uc720\uc640-\ub17c\uc7c1",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"\uc5b4\ub5a4 \uae30\uc220\uc744 \ud1b5\ud574\uc11c\ub3c4 \uc131\uc7a5\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\uc2e4\uc804-\uc0ac\uc6a9"},"\uc2e4\uc804 \uc0ac\uc6a9"),(0,a.kt)("p",null,"\ub2e8\uc21c \uae30\uc220\uc758 \uc0ac\uc6a9\uc73c\ub85c\ub294 \uc131\uc7a5\uc774 \uc5b4\ub835\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e4\uc804 \uc801\uc6a9\uc73c\ub85c \uc131\uc7a5\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\uc9c8\ubb38\uacfc-\ud0d0\uad6c"},"\uc9c8\ubb38\uacfc \ud0d0\uad6c"),(0,a.kt)("p",null,"\ub0b4\uac00 \uc0ac\uc6a9\ud558\ub294 \uae30\uc220\uc740 \uc65c \uc774\ub807\uac8c \ub9cc\ub4e4\uc5b4\uc84c\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \uc65c \uc774\ub807\uac8c \uc124\uacc4\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud574\uc57c \ud558\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\uc7a5\ub2e8\uc810\uc740 \ubb34\uc5c7\uc778\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\ub978 \ub300\uc548\uc740 \uc5c6\uc744\uae4c?",(0,a.kt)("br",{parentName:"p"}),"\n","\uc9c0\uae08\ub3c4 \uc88b\uae34\ud55c\ub370 \ub2e4\uc74c\uc5d0\ub294 \uac1c\uc120\ud560 \ubd80\ubd84\uc774 \uc788\uc744\uae4c? "),(0,a.kt)("h3",{id:"\ud6c8\ub828\uacfc-\uac1c\uc120"},"\ud6c8\ub828\uacfc \uac1c\uc120"),(0,a.kt)("p",null,"\ubc30\uc6b4 \uac83\uc744 \uc751\uc6a9\ud574\ubcf4\ub294 \ucf54\ub529\uc744 \uafb8\uc900\ud788",(0,a.kt)("br",{parentName:"p"}),"\n","\ud29c\ud1a0\ub9ac\uc5bc \uc608\uc81c\ub97c \ubc18\ubcf5\ud574\uc11c \uc791\uc131",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0c8\ub85c\uc6b4 \uae30\ub2a5\uc744 \ucd94\uac00\ud558\uace0 \uc124\uacc4 \uad6c\uc870\ub97c \ubcc0\uacbd\ud574\ubcf4\ub294 \uc2dc\ub3c4",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e4\ubb34\uc5d0\uc11c \uc0ac\uc6a9\ud558\uc9c0 \ubabb\ud588\ub358 \uae30\uc220 \ub3c4\uc785",(0,a.kt)("br",{parentName:"p"}),"\n","\uc5f0\uc2b5\uc6a9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\uc0c1\ud558\uace0 \uc124\uacc4",(0,a.kt)("br",{parentName:"p"}),"\n","\ucd08\uae30 \uac1c\ubc1c \uc0dd\uc0b0\uc131, \ubcc0\uacbd \uc6a9\uc774\uc131 \ub4f1\uc744 \uad00\ucc30 "),(0,a.kt)("h3",{id:"\uacf5\uc720\uc640-\ub17c\uc7c1"},"\uacf5\uc720\uc640 \ub17c\uc7c1"),(0,a.kt)("p",null,"\ubb38\uc11c, \ubc1c\ud45c \uc790\ub8cc\ub85c \uc815\ub9ac",(0,a.kt)("br",{parentName:"p"}),"\n","\uc815\ub9ac\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc774\uba74 \ud6a8\uc728\uc131\uc774 \ub5a8\uc5b4\uc9c0\uae30\uc5d0 \uc911\uc694\ud55c \ubd80\ubd84\ub9cc \uc815\ub9ac",(0,a.kt)("br",{parentName:"p"}),"\n","\uac04\ub2e8\ud55c \uc791\uc131, \uac80\uc0c9\uc774 \uac00\ub2a5\ud55c \ub3c4\uad6c \ud65c\uc6a9",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub9cc\uc758 \uc815\uc758\uc640 \uc124\uba85\uc744 \ub9cc\ub4e4\uc5b4\uac00\uae30 -> \ud55c \ubb38\uc7a5, \ud55c \ubb38\ub2e8, 5\ubd84\uac04 \uc124\uba85, \uc810\uc810 \ub298\ub824\uac00\uba70"),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30 - \ud1a0\ube44, INFCON 2023"))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3691],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=c(r),m=a,f=d["".concat(i,".").concat(m)]||d[m]||s[m]||o;return r?n.createElement(f,p(p({ref:t},u),{},{components:r})):n.createElement(f,p({ref:t},u))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,p=new Array(o);p[0]=d;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,p[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>p,default:()=>s,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",slug:"/etc/develop-with-spring",tags:["etc"]},p=void 0,l={unversionedId:"\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",id:"\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",description:"\uc5b4\ub5a4 \uae30\uc220\uc744 \ud1b5\ud574\uc11c\ub3c4 \uc131\uc7a5\ud560 \uc218 \uc788\ub2e4.",source:"@site/docs/\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/develop-with-spring",permalink:"/docs/etc/develop-with-spring",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",slug:"/etc/develop-with-spring",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",permalink:"/docs/etc/healthful-growth"},next:{title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",permalink:"/docs/etc/experience-and-self-question"}},i={},c=[{value:"\uc2e4\uc804 \uc0ac\uc6a9",id:"\uc2e4\uc804-\uc0ac\uc6a9",level:3},{value:"\uc9c8\ubb38\uacfc \ud0d0\uad6c",id:"\uc9c8\ubb38\uacfc-\ud0d0\uad6c",level:3},{value:"\ud6c8\ub828\uacfc \uac1c\uc120",id:"\ud6c8\ub828\uacfc-\uac1c\uc120",level:3},{value:"\uacf5\uc720\uc640 \ub17c\uc7c1",id:"\uacf5\uc720\uc640-\ub17c\uc7c1",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"\uc5b4\ub5a4 \uae30\uc220\uc744 \ud1b5\ud574\uc11c\ub3c4 \uc131\uc7a5\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\uc2e4\uc804-\uc0ac\uc6a9"},"\uc2e4\uc804 \uc0ac\uc6a9"),(0,a.kt)("p",null,"\ub2e8\uc21c \uae30\uc220\uc758 \uc0ac\uc6a9\uc73c\ub85c\ub294 \uc131\uc7a5\uc774 \uc5b4\ub835\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e4\uc804 \uc801\uc6a9\uc73c\ub85c \uc131\uc7a5\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\uc9c8\ubb38\uacfc-\ud0d0\uad6c"},"\uc9c8\ubb38\uacfc \ud0d0\uad6c"),(0,a.kt)("p",null,"\ub0b4\uac00 \uc0ac\uc6a9\ud558\ub294 \uae30\uc220\uc740 \uc65c \uc774\ub807\uac8c \ub9cc\ub4e4\uc5b4\uc84c\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \uc65c \uc774\ub807\uac8c \uc124\uacc4\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud574\uc57c \ud558\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\uc7a5\ub2e8\uc810\uc740 \ubb34\uc5c7\uc778\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\ub978 \ub300\uc548\uc740 \uc5c6\uc744\uae4c?",(0,a.kt)("br",{parentName:"p"}),"\n","\uc9c0\uae08\ub3c4 \uc88b\uae34\ud55c\ub370 \ub2e4\uc74c\uc5d0\ub294 \uac1c\uc120\ud560 \ubd80\ubd84\uc774 \uc788\uc744\uae4c? "),(0,a.kt)("h3",{id:"\ud6c8\ub828\uacfc-\uac1c\uc120"},"\ud6c8\ub828\uacfc \uac1c\uc120"),(0,a.kt)("p",null,"\ubc30\uc6b4 \uac83\uc744 \uc751\uc6a9\ud574\ubcf4\ub294 \ucf54\ub529\uc744 \uafb8\uc900\ud788",(0,a.kt)("br",{parentName:"p"}),"\n","\ud29c\ud1a0\ub9ac\uc5bc \uc608\uc81c\ub97c \ubc18\ubcf5\ud574\uc11c \uc791\uc131",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0c8\ub85c\uc6b4 \uae30\ub2a5\uc744 \ucd94\uac00\ud558\uace0 \uc124\uacc4 \uad6c\uc870\ub97c \ubcc0\uacbd\ud574\ubcf4\ub294 \uc2dc\ub3c4",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e4\ubb34\uc5d0\uc11c \uc0ac\uc6a9\ud558\uc9c0 \ubabb\ud588\ub358 \uae30\uc220 \ub3c4\uc785",(0,a.kt)("br",{parentName:"p"}),"\n","\uc5f0\uc2b5\uc6a9 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uad6c\uc0c1\ud558\uace0 \uc124\uacc4",(0,a.kt)("br",{parentName:"p"}),"\n","\ucd08\uae30 \uac1c\ubc1c \uc0dd\uc0b0\uc131, \ubcc0\uacbd \uc6a9\uc774\uc131 \ub4f1\uc744 \uad00\ucc30 "),(0,a.kt)("h3",{id:"\uacf5\uc720\uc640-\ub17c\uc7c1"},"\uacf5\uc720\uc640 \ub17c\uc7c1"),(0,a.kt)("p",null,"\ubb38\uc11c, \ubc1c\ud45c \uc790\ub8cc\ub85c \uc815\ub9ac",(0,a.kt)("br",{parentName:"p"}),"\n","\uc815\ub9ac\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc774\uba74 \ud6a8\uc728\uc131\uc774 \ub5a8\uc5b4\uc9c0\uae30\uc5d0 \uc911\uc694\ud55c \ubd80\ubd84\ub9cc \uc815\ub9ac",(0,a.kt)("br",{parentName:"p"}),"\n","\uac04\ub2e8\ud55c \uc791\uc131, \uac80\uc0c9\uc774 \uac00\ub2a5\ud55c \ub3c4\uad6c \ud65c\uc6a9",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub9cc\uc758 \uc815\uc758\uc640 \uc124\uba85\uc744 \ub9cc\ub4e4\uc5b4\uac00\uae30 -> \ud55c \ubb38\uc7a5, \ud55c \ubb38\ub2e8, 5\ubd84\uac04 \uc124\uba85, \uc810\uc810 \ub298\ub824\uac00\uba70"),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30 - \ud1a0\ube44, INFCON 2023"))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/3b0d95bc.bbfd78b6.js b/assets/js/3b0d95bc.428f526d.js similarity index 98% rename from assets/js/3b0d95bc.bbfd78b6.js rename to assets/js/3b0d95bc.428f526d.js index fda192d87..2d1d7a3f6 100644 --- a/assets/js/3b0d95bc.bbfd78b6.js +++ b/assets/js/3b0d95bc.428f526d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5140],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),u=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=u(e.components);return r.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,p=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),d=u(n),m=a,E=d["".concat(p,".").concat(m)]||d[m]||s[m]||l;return n?r.createElement(E,i(i({ref:t},c),{},{components:n})):r.createElement(E,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var u=2;u{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>s,frontMatter:()=>l,metadata:()=>o,toc:()=>u});var r=n(87462),a=(n(67294),n(3905));const l={title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",slug:"/jpa/key",tags:["JPA"]},i=void 0,o={unversionedId:"JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551",id:"JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551",title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",description:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",source:"@site/docs/JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551.mdx",sourceDirName:"JPA",slug:"/jpa/key",permalink:"/docs/jpa/key",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551.mdx",tags:[{label:"JPA",permalink:"/docs/tags/jpa"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",slug:"/jpa/key",tags:["JPA"]},sidebar:"tutorialSidebar",next:{title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",permalink:"/docs/nginx/command"}},p={},u=[{value:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",id:"\uae30\ubcf8-\ud0a4-\ub9e4\ud551",level:3},{value:"\uc9c1\uc811 \ud560\ub2f9",id:"\uc9c1\uc811-\ud560\ub2f9",level:3},{value:"IDENTITY",id:"identity",level:3},{value:"SEQUENCE",id:"sequence",level:3},{value:"TABLE",id:"table",level:3},{value:"AUTO",id:"auto",level:3},{value:"UUID",id:"uuid",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],c={toc:u};function s(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uae30\ubcf8-\ud0a4-\ub9e4\ud551"},"\uae30\ubcf8 \ud0a4 \ub9e4\ud551"),(0,a.kt)("p",null,"\uae30\ubcf8 \ud0a4 \ub9e4\ud551 \uc804\ub7b5\uc5d0\ub294 \uc9c1\uc811 \ud560\ub2f9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uace0 \uc790\ub3d9 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc790\ub3d9 \uc0dd\uc131\uc744 \uc120\ud0dd\ud55c\ub2e4\uba74 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \ud0a4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc9c1\uc811 \ud560\ub2f9\ud558\uc9c0 \uc54a\uace0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc0dd\uc131\ud574\uc8fc\ub294 \uac12\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\uc9c1\uc811-\ud560\ub2f9"},"\uc9c1\uc811 \ud560\ub2f9"),(0,a.kt)("p",null,"\uae30\ubcf8 \ud0a4\ub97c \uc9c1\uc811 \ud560\ub2f9\ud558\ub294 \uacbd\uc6b0\uc5d0 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Id"),"\ub9cc \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc790\ub3d9 \ud560\ub2f9\ud558\ub294 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Id"),"\uc5d0 \ucd94\uac00\uc801\uc73c\ub85c ",(0,a.kt)("inlineCode",{parentName:"p"},"@GeneratedValue"),"\ub97c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"identity"},"IDENTITY"),(0,a.kt)("p",null,"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc0dd\uc131\ud55c \ud0a4\ub97c \uc0ac\uc6a9\ud558\ub294 \uc804\ub7b5",(0,a.kt)("br",{parentName:"p"}),"\n","MySQL, PostgreSQL\uacfc \uac19\uc740 DB\uc5d0\uc11c \uc8fc\ub85c \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","Hibernate\ub294 JDBC3\uc5d0 \ucd94\uac00\ub41c ",(0,a.kt)("inlineCode",{parentName:"p"},"Statement.getGeneratedKeys()"),"\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc0dd\uc131\uacfc \ub3d9\uc2dc\uc5d0 \ud0a4 \uac12\uc744 \uc5bb\uc5b4 \uc62c \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.IDENTITY)\n private Long id;\n}\n")),(0,a.kt)("h3",{id:"sequence"},"SEQUENCE"),(0,a.kt)("p",null,"\uc2dc\ud000\uc2a4\ub294 \uc720\uc77c\ud55c \uac12\uc744 \uc21c\uc11c\ub300\ub85c \uc0dd\uc131\ud558\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc624\ube0c\uc81d\ud2b8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","IDENTITY\uc758 \uacbd\uc6b0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud55c \ud6c4 \uc2dd\ubcc4\uc790\ub97c \uc870\ud68c\ud574\uc11c \uc5d4\ud2f0\ud2f0\uc758 \uc2dd\ubcc4\uc790\uc5d0 \ud560\ub2f9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","SEQUENCE\uc758 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"call next value for member_seq"),"\uc640 \uac19\uc774 \uc2dc\ud000\uc2a4\ub97c \uc0ac\uc6a9\ud574\uc11c \uc2dd\ubcc4\uc790\ub97c "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},'@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@SequenceGenerator(\n name = "MEMBER_SEQ_GENERATOR",\n sequenceName = "MEMBER_SEQ",\n initialValue = 1,\n allocationSize = 1\n)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")\n private Long id;\n}\n')),(0,a.kt)("h3",{id:"table"},"TABLE"),(0,a.kt)("p",null,"\ud0a4 \uc0dd\uc131\uc6a9 \ud14c\uc774\ube14\uc744 \ubcc4\ub3c4\ub85c \ub450\uc5b4 \uc2dc\ud000\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \uc2dd\ubcc4\uc790 \ud0a4\ub97c \uc5bb\ub294 \uc804\ub7b5\uc774\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc870\ud68c\uc640 \uc5c5\ub370\uc774\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},'@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@TableGenerator(\n name = "MEMBER_SEQ_GENERATOR",\n table = "MEMBER_SEQUENCES",\n pkColumnValue = "MEMBER_SEQ",\n allocationSize = 1\n)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")\n private Long id;\n}\n')),(0,a.kt)("h3",{id:"auto"},"AUTO"),(0,a.kt)("p",null,"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub530\ub77c \uc704\uc5d0 \uc5b8\uae09\ub41c \uc804\ub7b5 \uc911 \ud558\ub098\ub97c \uc790\ub3d9\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","MySQL\uc758 \uacbd\uc6b0 IDENTITY Oracle\uc758 \uacbd\uc6b0 SEQUENCE\ub97c \uc120\ud0dd\ud55c\ub2e4. "),(0,a.kt)("h3",{id:"uuid"},"UUID"),(0,a.kt)("p",null,"JPA 3.1.0 UUID \uc0dd\uc131 \uc804\ub7b5\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","Hibernate 6.2\ubd80\ud130 JPA 3.1.0\uc744 \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1 \uc774\uc0c1\uc778 \uacbd\uc6b0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.UUID)\n @UuidGenerator(style = Style.RANDOM)\n private Long id;\n}\n")),(0,a.kt)("p",null,"UuidGenerator\ub97c \uc774\uc6a9\ud558\uc5ec UUID \uc0dd\uc131 \ubc29\uc2dd\ub3c4 \uc124\uc815\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0dd\uc131 \ubc29\uc2dd\uc740 3\uac00\uc9c0\uac00 \uc788\ub2e4."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"RANDOM - \ub09c\uc218 \uae30\ubc18 UUID \uc0dd\uc131(uuid v4)"),(0,a.kt)("li",{parentName:"ul"},"TIME \u2013 \uc2dc\uac04 \uae30\ubc18 UUID \uc0dd\uc131(uuid v1)"),(0,a.kt)("li",{parentName:"ul"},"AUTO \u2013 \uae30\ubcf8 \uc635\uc158, RANDOM\uacfc \ub3d9\uc77c")),(0,a.kt)("p",null,"UUID\uc758 \uacbd\uc6b0 \ub9ce\uc740 \uc591\uc758 \uc800\uc7a5 \uacf5\uac04\uc744 \ud544\uc694\ub85c \ud558\uace0, \uc131\ub2a5 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\uae30\uc5d0 UUID\ub97c \uc0ac\uc6a9\ud574\uc57c \ud558\ub294 \uacbd\uc6b0 TSID\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc790\ubc14 ORM \ud45c\uc900 JPA \ud504\ub85c\uadf8\ub798\ubc0d, \uae40\uc601\ud55c p.131 ~ p.144",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://www.baeldung.com/java-hibernate-uuid-primary-key"},"Generate UUIDs as Primary Keys With Hibernate")))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5140],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),u=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=u(e.components);return r.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,p=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),d=u(n),m=a,E=d["".concat(p,".").concat(m)]||d[m]||s[m]||l;return n?r.createElement(E,i(i({ref:t},c),{},{components:n})):r.createElement(E,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=d;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:a,i[1]=o;for(var u=2;u{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>s,frontMatter:()=>l,metadata:()=>o,toc:()=>u});var r=n(87462),a=(n(67294),n(3905));const l={title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",slug:"/jpa/key",tags:["JPA"]},i=void 0,o={unversionedId:"JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551",id:"JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551",title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",description:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",source:"@site/docs/JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551.mdx",sourceDirName:"JPA",slug:"/jpa/key",permalink:"/docs/jpa/key",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551.mdx",tags:[{label:"JPA",permalink:"/docs/tags/jpa"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",slug:"/jpa/key",tags:["JPA"]},sidebar:"tutorialSidebar",next:{title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",permalink:"/docs/nginx/command"}},p={},u=[{value:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",id:"\uae30\ubcf8-\ud0a4-\ub9e4\ud551",level:3},{value:"\uc9c1\uc811 \ud560\ub2f9",id:"\uc9c1\uc811-\ud560\ub2f9",level:3},{value:"IDENTITY",id:"identity",level:3},{value:"SEQUENCE",id:"sequence",level:3},{value:"TABLE",id:"table",level:3},{value:"AUTO",id:"auto",level:3},{value:"UUID",id:"uuid",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],c={toc:u};function s(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uae30\ubcf8-\ud0a4-\ub9e4\ud551"},"\uae30\ubcf8 \ud0a4 \ub9e4\ud551"),(0,a.kt)("p",null,"\uae30\ubcf8 \ud0a4 \ub9e4\ud551 \uc804\ub7b5\uc5d0\ub294 \uc9c1\uc811 \ud560\ub2f9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uace0 \uc790\ub3d9 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc790\ub3d9 \uc0dd\uc131\uc744 \uc120\ud0dd\ud55c\ub2e4\uba74 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \ud0a4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc9c1\uc811 \ud560\ub2f9\ud558\uc9c0 \uc54a\uace0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc0dd\uc131\ud574\uc8fc\ub294 \uac12\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\uc9c1\uc811-\ud560\ub2f9"},"\uc9c1\uc811 \ud560\ub2f9"),(0,a.kt)("p",null,"\uae30\ubcf8 \ud0a4\ub97c \uc9c1\uc811 \ud560\ub2f9\ud558\ub294 \uacbd\uc6b0\uc5d0 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Id"),"\ub9cc \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc790\ub3d9 \ud560\ub2f9\ud558\ub294 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Id"),"\uc5d0 \ucd94\uac00\uc801\uc73c\ub85c ",(0,a.kt)("inlineCode",{parentName:"p"},"@GeneratedValue"),"\ub97c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"identity"},"IDENTITY"),(0,a.kt)("p",null,"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc0dd\uc131\ud55c \ud0a4\ub97c \uc0ac\uc6a9\ud558\ub294 \uc804\ub7b5",(0,a.kt)("br",{parentName:"p"}),"\n","MySQL, PostgreSQL\uacfc \uac19\uc740 DB\uc5d0\uc11c \uc8fc\ub85c \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","Hibernate\ub294 JDBC3\uc5d0 \ucd94\uac00\ub41c ",(0,a.kt)("inlineCode",{parentName:"p"},"Statement.getGeneratedKeys()"),"\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc0dd\uc131\uacfc \ub3d9\uc2dc\uc5d0 \ud0a4 \uac12\uc744 \uc5bb\uc5b4 \uc62c \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.IDENTITY)\n private Long id;\n}\n")),(0,a.kt)("h3",{id:"sequence"},"SEQUENCE"),(0,a.kt)("p",null,"\uc2dc\ud000\uc2a4\ub294 \uc720\uc77c\ud55c \uac12\uc744 \uc21c\uc11c\ub300\ub85c \uc0dd\uc131\ud558\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc624\ube0c\uc81d\ud2b8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","IDENTITY\uc758 \uacbd\uc6b0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud55c \ud6c4 \uc2dd\ubcc4\uc790\ub97c \uc870\ud68c\ud574\uc11c \uc5d4\ud2f0\ud2f0\uc758 \uc2dd\ubcc4\uc790\uc5d0 \ud560\ub2f9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","SEQUENCE\uc758 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"call next value for member_seq"),"\uc640 \uac19\uc774 \uc2dc\ud000\uc2a4\ub97c \uc0ac\uc6a9\ud574\uc11c \uc2dd\ubcc4\uc790\ub97c "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},'@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@SequenceGenerator(\n name = "MEMBER_SEQ_GENERATOR",\n sequenceName = "MEMBER_SEQ",\n initialValue = 1,\n allocationSize = 1\n)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")\n private Long id;\n}\n')),(0,a.kt)("h3",{id:"table"},"TABLE"),(0,a.kt)("p",null,"\ud0a4 \uc0dd\uc131\uc6a9 \ud14c\uc774\ube14\uc744 \ubcc4\ub3c4\ub85c \ub450\uc5b4 \uc2dc\ud000\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \uc2dd\ubcc4\uc790 \ud0a4\ub97c \uc5bb\ub294 \uc804\ub7b5\uc774\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc870\ud68c\uc640 \uc5c5\ub370\uc774\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},'@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@TableGenerator(\n name = "MEMBER_SEQ_GENERATOR",\n table = "MEMBER_SEQUENCES",\n pkColumnValue = "MEMBER_SEQ",\n allocationSize = 1\n)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")\n private Long id;\n}\n')),(0,a.kt)("h3",{id:"auto"},"AUTO"),(0,a.kt)("p",null,"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ub530\ub77c \uc704\uc5d0 \uc5b8\uae09\ub41c \uc804\ub7b5 \uc911 \ud558\ub098\ub97c \uc790\ub3d9\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","MySQL\uc758 \uacbd\uc6b0 IDENTITY Oracle\uc758 \uacbd\uc6b0 SEQUENCE\ub97c \uc120\ud0dd\ud55c\ub2e4. "),(0,a.kt)("h3",{id:"uuid"},"UUID"),(0,a.kt)("p",null,"JPA 3.1.0 UUID \uc0dd\uc131 \uc804\ub7b5\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","Hibernate 6.2\ubd80\ud130 JPA 3.1.0\uc744 \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1 \uc774\uc0c1\uc778 \uacbd\uc6b0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"@Getter\n@NoArgsConstructor(access = AccessLevel.PROTECTED)\n@Entity\npublic class Member {\n\n @Id\n @GeneratedValue(strategy = GenerationType.UUID)\n @UuidGenerator(style = Style.RANDOM)\n private Long id;\n}\n")),(0,a.kt)("p",null,"UuidGenerator\ub97c \uc774\uc6a9\ud558\uc5ec UUID \uc0dd\uc131 \ubc29\uc2dd\ub3c4 \uc124\uc815\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0dd\uc131 \ubc29\uc2dd\uc740 3\uac00\uc9c0\uac00 \uc788\ub2e4."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"RANDOM - \ub09c\uc218 \uae30\ubc18 UUID \uc0dd\uc131(uuid v4)"),(0,a.kt)("li",{parentName:"ul"},"TIME \u2013 \uc2dc\uac04 \uae30\ubc18 UUID \uc0dd\uc131(uuid v1)"),(0,a.kt)("li",{parentName:"ul"},"AUTO \u2013 \uae30\ubcf8 \uc635\uc158, RANDOM\uacfc \ub3d9\uc77c")),(0,a.kt)("p",null,"UUID\uc758 \uacbd\uc6b0 \ub9ce\uc740 \uc591\uc758 \uc800\uc7a5 \uacf5\uac04\uc744 \ud544\uc694\ub85c \ud558\uace0, \uc131\ub2a5 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\uae30\uc5d0 UUID\ub97c \uc0ac\uc6a9\ud574\uc57c \ud558\ub294 \uacbd\uc6b0 TSID\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc790\ubc14 ORM \ud45c\uc900 JPA \ud504\ub85c\uadf8\ub798\ubc0d, \uae40\uc601\ud55c p.131 ~ p.144",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://www.baeldung.com/java-hibernate-uuid-primary-key"},"Generate UUIDs as Primary Keys With Hibernate")))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/3fc16fd0.5d70fe41.js b/assets/js/3fc16fd0.2fbb0d17.js similarity index 98% rename from assets/js/3fc16fd0.5d70fe41.js rename to assets/js/3fc16fd0.2fbb0d17.js index 66cfe236f..7f677dd81 100644 --- a/assets/js/3fc16fd0.5d70fe41.js +++ b/assets/js/3fc16fd0.2fbb0d17.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3886],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>k});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),c=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},s=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,l=e.originalType,p=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=c(r),k=o,d=s["".concat(p,".").concat(k)]||s[k]||m[k]||l;return r?n.createElement(d,a(a({ref:t},u),{},{components:r})):n.createElement(d,a({ref:t},u))}));function k(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=r.length,a=new Array(l);a[0]=s;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>a,default:()=>m,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var n=r(87462),o=(r(67294),r(3905));const l={title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",slug:"/book/getting-out-of-the-box",tags:["book"]},a=void 0,i={unversionedId:"\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30",id:"\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30",title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",description:"\u26a0\ufe0f \uc790\uae30\ubc30\ubc18\uc758 \uc6d0\ub9ac",source:"@site/docs/\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30.mdx",sourceDirName:"\ub3c4\uc11c",slug:"/book/getting-out-of-the-box",permalink:"/docs/book/getting-out-of-the-box",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30.mdx",tags:[{label:"book",permalink:"/docs/tags/book"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",slug:"/book/getting-out-of-the-box",tags:["book"]},sidebar:"tutorialSidebar",previous:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",permalink:"/docs/network/load-balancing"},next:{title:"Swap \uba54\ubaa8\ub9ac \uc124\uc815",permalink:"/docs/linux/swap"}},p={},c=[{value:"\u26a0\ufe0f \uc790\uae30\ubc30\ubc18\uc758 \uc6d0\ub9ac",id:"\ufe0f-\uc790\uae30\ubc30\ubc18\uc758-\uc6d0\ub9ac",level:3},{value:"\u274c \uc0c1\uc790 \uc548\uc5d0\uc11c \uc18c\uc6a9\uc5c6\ub294 \uc77c",id:"-\uc0c1\uc790-\uc548\uc5d0\uc11c-\uc18c\uc6a9\uc5c6\ub294-\uc77c",level:3},{value:"\ud83d\udcd6 \ud559\uc2b5\uc790\ub8cc",id:"-\ud559\uc2b5\uc790\ub8cc",level:3},{value:"\ud83c\udfc3 \uc2e4\ucc9c\ud558\uae30",id:"-\uc2e4\ucc9c\ud558\uae30",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function m(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"\ufe0f-\uc790\uae30\ubc30\ubc18\uc758-\uc6d0\ub9ac"},"\u26a0\ufe0f \uc790\uae30\ubc30\ubc18\uc758 \uc6d0\ub9ac"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \ubb34\uc5c7\uc778\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uacfc \ub290\ub08c\uc5d0 \ub300\ud574 \ubc18\ud558\ub294 \ud589\uc704\ub97c \uc790\uae30\ubc30\ubc18\uc774\ub77c\uace0 \ud55c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\ub0b4\uac00 \uc790\uae30\ubc30\ubc18\ud560 \ub54c, \ub098\ub294 \uc790\uae30\ubc30\ubc18\uc744 \uc815\ub2f9\ud654\uc2dc\ud0a4\ub294 \ubc29\uc2dd\uc73c\ub85c \uc138\uc0c1\uc744 \ubcf4\uae30 \uc2dc\uc791\ud55c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc790\uc2e0\uc744 \uc815\ub2f9\ud654\uc2dc\ud0a4\ub294 \ubc29\uc2dd\uc73c\ub85c \uc138\uc0c1\uc744 \ubcfc \ub54c, \uc0ac\uc2e4\uc744 \ubcf4\ub294 \ub098\uc758 \uc2dc\uac01\uc740 \uc65c\uace1\ub41c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc790\uae30\ubc30\ubc18\ud560 \ub54c, \ub098\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac00\uac8c \ub41c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc5b4\ub5a4 \uc0c1\uc790\ub4e4\uc740 \ub098\uc758 \ud2b9\uc131\uc774 \ub418\uace0 \uc77c\uc0c1\uc801\uc73c\ub85c \ub098\ub294 \uadf8 \uc0c1\uc790\ub4e4\uc744 \uc9c0\ub2c8\uace0 \ub2e4\ub2cc\ub2e4."),(0,o.kt)("li",{parentName:"ol"},"\ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\uc74c\uc73c\ub85c \uc778\ud558\uc5ec, \ub098\ub294 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\ub3c4 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac00\ub3c4\ub85d \uc774\ub04c\uac8c \ub41c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc0c1\uc790 \uc548\uc5d0\uc11c \uc6b0\ub9ac\ub294 \uc11c\ub85c \uc798\ubabb \ub300\ud558\ub294 \uac83\uc744 \ubd80\ucd94\uae30\uace0 \uc0c1\ud638 \uc815\ub2f9\ud654\ub97c \uc5bb\uac8c \ub41c\ub2e4. \uc6b0\ub9ac\ub294 \uc11c\ub85c\uc5d0\uac8c \uc0c1\uc790 \uc548\uc5d0 \uba38\ubb3c\uae30 \uc704\ud55c \uc774\uc720\ub97c \uc8fc\ub3c4\ub85d \uacf5\ubaa8\ud55c\ub2e4. ")),(0,o.kt)("h3",{id:"-\uc0c1\uc790-\uc548\uc5d0\uc11c-\uc18c\uc6a9\uc5c6\ub294-\uc77c"},"\u274c \uc0c1\uc790 \uc548\uc5d0\uc11c \uc18c\uc6a9\uc5c6\ub294 \uc77c"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc744 \ubcc0\ud654\uc2dc\ud0a4\ub824\uace0 \ud558\ub294 \uac83"),(0,o.kt)("li",{parentName:"ol"},'\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c "\ub9de\ucdb0\uc8fc\uae30" \uc704\ud574 \ucd5c\uc120\uc744 \ub2e4\ud558\uae30'),(0,o.kt)("li",{parentName:"ol"},"\ub450\uace0 \ub5a0\ub098\uae30"),(0,o.kt)("li",{parentName:"ol"},"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158"),(0,o.kt)("li",{parentName:"ol"},"\uc0c8\ub85c\uc6b4 \uae30\uc220\uc774\ub098 \ud14c\ud06c\ub2c9 \ud65c\uc6a9\ud558\uae30"),(0,o.kt)("li",{parentName:"ol"},"\ub098\uc758 \ud589\ub3d9\uc744 \ubcc0\ud654\uc2dc\ud0a4\ub294 \uac83")),(0,o.kt)("h3",{id:"-\ud559\uc2b5\uc790\ub8cc"},"\ud83d\udcd6 \ud559\uc2b5\uc790\ub8cc"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},'\uc790\uae30\ubc30\ubc18\uc740 \uc790\uae30\uae30\ub9cc\uacfc "\uc0c1\uc790"\uc548\uc73c\ub85c \uc774\ub048\ub2e4. '),(0,o.kt)("li",{parentName:"ol"},"\uc0c1\uc790 \uc548\uc5d0 \uc788\uc744 \ub54c, \ub2f9\uc2e0\uc740 \uacb0\uacfc(\uc131\uacfc)\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc5c6\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\ub2f9\uc2e0\uc758 \uc601\ud5a5\ub825\uacfc \uc131\uacf5\uc758 \ud06c\uae30\ub294 \uc5bc\ub9c8\ub098 \uc0c1\uc790 \ubc16\uc5d0 \uc874\uc7ac\ud558\ub290\ub0d0\uc5d0 \ub2ec\ub824\uc788\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \uc800\ud56d\ud558\ub294 \uac83\uc744 \uadf8\ub9cc\ub458 \ub54c \ub2f9\uc2e0\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\uac8c \ub41c\ub2e4. ")),(0,o.kt)("h3",{id:"-\uc2e4\ucc9c\ud558\uae30"},"\ud83c\udfc3 \uc2e4\ucc9c\ud558\uae30"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\uc644\ubcbd\ud574\uc9c0\ub824\uace0 \ub178\ub825\ud558\uc9c0 \ub9d0\uace0, \uc9c0\uae08\ubcf4\ub2e4 \ub354 \uc88b\uc544\uc9c0\ub824\uace0 \ub178\ub825\ud558\ub77c. "),(0,o.kt)("li",{parentName:"ol"},"\uc544\uc9c1 \ud559\uc2b5\ub0b4\uc6a9\uc744 \uc54c\uc9c0 \ubabb\ud558\ub294 \uc0ac\ub78c\ub4e4\uc5d0\uac8c '\uc0c1\uc790'\ub098 \uae30\ud0c0 \ub2e8\uc5b4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc9c0 \ub9c8\ub77c. \ub2e4\ub9cc \ub2f9\uc2e0 \uc790\uc2e0\uc758 \uc0b6\uc5d0\uc11c \uadf8 \uc6d0\ub9ac\ub4e4\uc744 \uc801\uc6a9\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc0c1\uc790\ub97c \ucc3e\uc9c0 \ub9d0\uace0, \uba3c\uc800 \ub2f9\uc2e0 \uc790\uc2e0\uc758 \uc0c1\uc790\ub97c \ucc3e\uc544\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub2e4\uace0 \ud790\ub09c\ud558\uc9c0 \ub9d0\uace0, \ub2f9\uc2e0\uc774 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub3c4\ub85d \ub178\ub825\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2f9\uc2e0\uc774 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub2e4\ub294 \uac83\uc744 \ubc1c\uacac\ud588\uc744 \ub54c \uc790\uc2e0\uc5d0 \ub300\ud574 \ud3ec\uae30\ud558\uc9c0 \ub9c8\ub77c. \uacc4\uc18d \ub178\ub825\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2f9\uc2e0\uc774 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub2e4\ub294 \uac83\uc744 \ubd80\uc778\ud558\uc9c0 \ub9c8\ub77c. \uc0ac\uacfc\ud558\uace0, \uacc4\uc18d\ud574\uc11c \uc804\uc9c4\ud558\ub77c. \ubbf8\ub798\uc5d0 \ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \ub354 \ub3c4\uc6c0\uc774 \ub418\ub3c4\ub85d \ub178\ub825\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc798\ubabb\ud558\uace0 \uc788\ub294 \uac83\uc5d0 \ucd08\uc810\uc744 \ub9de\ucd94\uc9c0 \ub9c8\ub77c. \uadf8\ub4e4\uc744 \ub3d5\uae30 \uc704\ud574 \ub2f9\uc2e0\uc774 \uc62c\ubc14\ub974\uac8c \ud589\ud560 \uc218 \uc788\ub294 \uc77c\uc5d0 \ucd08\uc810\uc744 \ub9de\ucdb0\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \ub2f9\uc2e0\uc744 \ub3d5\uace0 \uc788\ub294\uc9c0\uc5d0 \ub300\ud574 \uc5fc\ub824\ud558\uc9c0 \ub9c8\ub77c. \ub2f9\uc2e0\uc774 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc744 \ub3d5\uace0 \uc788\ub294\uc9c0\uc5d0 \ub300\ud574 \uac71\uc815\ud558\ub77c. ")),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c, \uc544\ube48\uc800\uc5f0\uad6c\uc18c"))}m.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3886],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>k});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),c=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},s=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,l=e.originalType,p=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=c(r),k=o,d=s["".concat(p,".").concat(k)]||s[k]||m[k]||l;return r?n.createElement(d,a(a({ref:t},u),{},{components:r})):n.createElement(d,a({ref:t},u))}));function k(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var l=r.length,a=new Array(l);a[0]=s;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>a,default:()=>m,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var n=r(87462),o=(r(67294),r(3905));const l={title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",slug:"/book/getting-out-of-the-box",tags:["book"]},a=void 0,i={unversionedId:"\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30",id:"\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30",title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",description:"\u26a0\ufe0f \uc790\uae30\ubc30\ubc18\uc758 \uc6d0\ub9ac",source:"@site/docs/\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30.mdx",sourceDirName:"\ub3c4\uc11c",slug:"/book/getting-out-of-the-box",permalink:"/docs/book/getting-out-of-the-box",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30.mdx",tags:[{label:"book",permalink:"/docs/tags/book"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",slug:"/book/getting-out-of-the-box",tags:["book"]},sidebar:"tutorialSidebar",previous:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",permalink:"/docs/network/load-balancing"},next:{title:"Swap \uba54\ubaa8\ub9ac \uc124\uc815",permalink:"/docs/linux/swap"}},p={},c=[{value:"\u26a0\ufe0f \uc790\uae30\ubc30\ubc18\uc758 \uc6d0\ub9ac",id:"\ufe0f-\uc790\uae30\ubc30\ubc18\uc758-\uc6d0\ub9ac",level:3},{value:"\u274c \uc0c1\uc790 \uc548\uc5d0\uc11c \uc18c\uc6a9\uc5c6\ub294 \uc77c",id:"-\uc0c1\uc790-\uc548\uc5d0\uc11c-\uc18c\uc6a9\uc5c6\ub294-\uc77c",level:3},{value:"\ud83d\udcd6 \ud559\uc2b5\uc790\ub8cc",id:"-\ud559\uc2b5\uc790\ub8cc",level:3},{value:"\ud83c\udfc3 \uc2e4\ucc9c\ud558\uae30",id:"-\uc2e4\ucc9c\ud558\uae30",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function m(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"\ufe0f-\uc790\uae30\ubc30\ubc18\uc758-\uc6d0\ub9ac"},"\u26a0\ufe0f \uc790\uae30\ubc30\ubc18\uc758 \uc6d0\ub9ac"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \ubb34\uc5c7\uc778\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uacfc \ub290\ub08c\uc5d0 \ub300\ud574 \ubc18\ud558\ub294 \ud589\uc704\ub97c \uc790\uae30\ubc30\ubc18\uc774\ub77c\uace0 \ud55c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\ub0b4\uac00 \uc790\uae30\ubc30\ubc18\ud560 \ub54c, \ub098\ub294 \uc790\uae30\ubc30\ubc18\uc744 \uc815\ub2f9\ud654\uc2dc\ud0a4\ub294 \ubc29\uc2dd\uc73c\ub85c \uc138\uc0c1\uc744 \ubcf4\uae30 \uc2dc\uc791\ud55c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc790\uc2e0\uc744 \uc815\ub2f9\ud654\uc2dc\ud0a4\ub294 \ubc29\uc2dd\uc73c\ub85c \uc138\uc0c1\uc744 \ubcfc \ub54c, \uc0ac\uc2e4\uc744 \ubcf4\ub294 \ub098\uc758 \uc2dc\uac01\uc740 \uc65c\uace1\ub41c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc790\uae30\ubc30\ubc18\ud560 \ub54c, \ub098\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac00\uac8c \ub41c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc5b4\ub5a4 \uc0c1\uc790\ub4e4\uc740 \ub098\uc758 \ud2b9\uc131\uc774 \ub418\uace0 \uc77c\uc0c1\uc801\uc73c\ub85c \ub098\ub294 \uadf8 \uc0c1\uc790\ub4e4\uc744 \uc9c0\ub2c8\uace0 \ub2e4\ub2cc\ub2e4."),(0,o.kt)("li",{parentName:"ol"},"\ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\uc74c\uc73c\ub85c \uc778\ud558\uc5ec, \ub098\ub294 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\ub3c4 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac00\ub3c4\ub85d \uc774\ub04c\uac8c \ub41c\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\uc0c1\uc790 \uc548\uc5d0\uc11c \uc6b0\ub9ac\ub294 \uc11c\ub85c \uc798\ubabb \ub300\ud558\ub294 \uac83\uc744 \ubd80\ucd94\uae30\uace0 \uc0c1\ud638 \uc815\ub2f9\ud654\ub97c \uc5bb\uac8c \ub41c\ub2e4. \uc6b0\ub9ac\ub294 \uc11c\ub85c\uc5d0\uac8c \uc0c1\uc790 \uc548\uc5d0 \uba38\ubb3c\uae30 \uc704\ud55c \uc774\uc720\ub97c \uc8fc\ub3c4\ub85d \uacf5\ubaa8\ud55c\ub2e4. ")),(0,o.kt)("h3",{id:"-\uc0c1\uc790-\uc548\uc5d0\uc11c-\uc18c\uc6a9\uc5c6\ub294-\uc77c"},"\u274c \uc0c1\uc790 \uc548\uc5d0\uc11c \uc18c\uc6a9\uc5c6\ub294 \uc77c"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc744 \ubcc0\ud654\uc2dc\ud0a4\ub824\uace0 \ud558\ub294 \uac83"),(0,o.kt)("li",{parentName:"ol"},'\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c "\ub9de\ucdb0\uc8fc\uae30" \uc704\ud574 \ucd5c\uc120\uc744 \ub2e4\ud558\uae30'),(0,o.kt)("li",{parentName:"ol"},"\ub450\uace0 \ub5a0\ub098\uae30"),(0,o.kt)("li",{parentName:"ol"},"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158"),(0,o.kt)("li",{parentName:"ol"},"\uc0c8\ub85c\uc6b4 \uae30\uc220\uc774\ub098 \ud14c\ud06c\ub2c9 \ud65c\uc6a9\ud558\uae30"),(0,o.kt)("li",{parentName:"ol"},"\ub098\uc758 \ud589\ub3d9\uc744 \ubcc0\ud654\uc2dc\ud0a4\ub294 \uac83")),(0,o.kt)("h3",{id:"-\ud559\uc2b5\uc790\ub8cc"},"\ud83d\udcd6 \ud559\uc2b5\uc790\ub8cc"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},'\uc790\uae30\ubc30\ubc18\uc740 \uc790\uae30\uae30\ub9cc\uacfc "\uc0c1\uc790"\uc548\uc73c\ub85c \uc774\ub048\ub2e4. '),(0,o.kt)("li",{parentName:"ol"},"\uc0c1\uc790 \uc548\uc5d0 \uc788\uc744 \ub54c, \ub2f9\uc2e0\uc740 \uacb0\uacfc(\uc131\uacfc)\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc5c6\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\ub2f9\uc2e0\uc758 \uc601\ud5a5\ub825\uacfc \uc131\uacf5\uc758 \ud06c\uae30\ub294 \uc5bc\ub9c8\ub098 \uc0c1\uc790 \ubc16\uc5d0 \uc874\uc7ac\ud558\ub290\ub0d0\uc5d0 \ub2ec\ub824\uc788\ub2e4. "),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \uc800\ud56d\ud558\ub294 \uac83\uc744 \uadf8\ub9cc\ub458 \ub54c \ub2f9\uc2e0\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\uac8c \ub41c\ub2e4. ")),(0,o.kt)("h3",{id:"-\uc2e4\ucc9c\ud558\uae30"},"\ud83c\udfc3 \uc2e4\ucc9c\ud558\uae30"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},"\uc644\ubcbd\ud574\uc9c0\ub824\uace0 \ub178\ub825\ud558\uc9c0 \ub9d0\uace0, \uc9c0\uae08\ubcf4\ub2e4 \ub354 \uc88b\uc544\uc9c0\ub824\uace0 \ub178\ub825\ud558\ub77c. "),(0,o.kt)("li",{parentName:"ol"},"\uc544\uc9c1 \ud559\uc2b5\ub0b4\uc6a9\uc744 \uc54c\uc9c0 \ubabb\ud558\ub294 \uc0ac\ub78c\ub4e4\uc5d0\uac8c '\uc0c1\uc790'\ub098 \uae30\ud0c0 \ub2e8\uc5b4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc9c0 \ub9c8\ub77c. \ub2e4\ub9cc \ub2f9\uc2e0 \uc790\uc2e0\uc758 \uc0b6\uc5d0\uc11c \uadf8 \uc6d0\ub9ac\ub4e4\uc744 \uc801\uc6a9\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc0c1\uc790\ub97c \ucc3e\uc9c0 \ub9d0\uace0, \uba3c\uc800 \ub2f9\uc2e0 \uc790\uc2e0\uc758 \uc0c1\uc790\ub97c \ucc3e\uc544\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub2e4\uace0 \ud790\ub09c\ud558\uc9c0 \ub9d0\uace0, \ub2f9\uc2e0\uc774 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub3c4\ub85d \ub178\ub825\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2f9\uc2e0\uc774 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub2e4\ub294 \uac83\uc744 \ubc1c\uacac\ud588\uc744 \ub54c \uc790\uc2e0\uc5d0 \ub300\ud574 \ud3ec\uae30\ud558\uc9c0 \ub9c8\ub77c. \uacc4\uc18d \ub178\ub825\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2f9\uc2e0\uc774 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub2e4\ub294 \uac83\uc744 \ubd80\uc778\ud558\uc9c0 \ub9c8\ub77c. \uc0ac\uacfc\ud558\uace0, \uacc4\uc18d\ud574\uc11c \uc804\uc9c4\ud558\ub77c. \ubbf8\ub798\uc5d0 \ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \ub354 \ub3c4\uc6c0\uc774 \ub418\ub3c4\ub85d \ub178\ub825\ud558\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc798\ubabb\ud558\uace0 \uc788\ub294 \uac83\uc5d0 \ucd08\uc810\uc744 \ub9de\ucd94\uc9c0 \ub9c8\ub77c. \uadf8\ub4e4\uc744 \ub3d5\uae30 \uc704\ud574 \ub2f9\uc2e0\uc774 \uc62c\ubc14\ub974\uac8c \ud589\ud560 \uc218 \uc788\ub294 \uc77c\uc5d0 \ucd08\uc810\uc744 \ub9de\ucdb0\ub77c."),(0,o.kt)("li",{parentName:"ol"},"\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \ub2f9\uc2e0\uc744 \ub3d5\uace0 \uc788\ub294\uc9c0\uc5d0 \ub300\ud574 \uc5fc\ub824\ud558\uc9c0 \ub9c8\ub77c. \ub2f9\uc2e0\uc774 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc744 \ub3d5\uace0 \uc788\ub294\uc9c0\uc5d0 \ub300\ud574 \uac71\uc815\ud558\ub77c. ")),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c, \uc544\ube48\uc800\uc5f0\uad6c\uc18c"))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/459bd227.d754b82a.js b/assets/js/459bd227.420144d0.js similarity index 98% rename from assets/js/459bd227.d754b82a.js rename to assets/js/459bd227.420144d0.js index 7dbb89602..035ac8669 100644 --- a/assets/js/459bd227.d754b82a.js +++ b/assets/js/459bd227.420144d0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9094],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),m=c(r),d=a,b=m["".concat(i,".").concat(d)]||m[d]||s[d]||l;return r?n.createElement(b,p(p({ref:t},u),{},{components:r})):n.createElement(b,p({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,p=new Array(l);p[0]=m;var o={};for(var i in t)hasOwnProperty.call(t,i)&&(o[i]=t[i]);o.originalType=e,o.mdxType="string"==typeof e?e:a,p[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>p,default:()=>s,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const l={title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",slug:"/etc/healthful-growth",tags:["etc"]},p=void 0,o={unversionedId:"\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30",id:"\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30",title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",description:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 4\uc6d4 19\uc77c",source:"@site/docs/\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/healthful-growth",permalink:"/docs/etc/healthful-growth",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",slug:"/etc/healthful-growth",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\ubb38\uc11c",permalink:"/docs/"},next:{title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",permalink:"/docs/etc/develop-with-spring"}},i={},c=[{value:"\uc790\uc874\uac10 \uae30\ub465 \ub9cc\ub4e4\uae30",id:"\uc790\uc874\uac10-\uae30\ub465-\ub9cc\ub4e4\uae30",level:3},{value:"\ub098\ub9cc\uc758 \ud559\uc2b5 \ubc29\ubc95 \ucc3e\uae30",id:"\ub098\ub9cc\uc758-\ud559\uc2b5-\ubc29\ubc95-\ucc3e\uae30",level:3},{value:"\uc0c8\ub85c\uc6b4 \ud658\uacbd\uc744 \uc798 \ubc30\uc6b0\ub294 \ubc29\ubc95",id:"\uc0c8\ub85c\uc6b4-\ud658\uacbd\uc744-\uc798-\ubc30\uc6b0\ub294-\ubc29\ubc95",level:3},{value:"\ud559\uc2b5 \uc8fc\uc81c",id:"\ud559\uc2b5-\uc8fc\uc81c",level:3},{value:"\uc0b0\ub9cc\ud568 \uad00\ub9ac\ud558\uae30",id:"\uc0b0\ub9cc\ud568-\uad00\ub9ac\ud558\uae30",level:3},{value:"\uac70\uc778\uc5d0 \uc5b4\uae68\uc704\uc5d0 \uc62c\ub77c\ud0c0\uae30",id:"\uac70\uc778\uc5d0-\uc5b4\uae68\uc704\uc5d0-\uc62c\ub77c\ud0c0\uae30",level:3},{value:"\ubcf4\uc0c1",id:"\ubcf4\uc0c1",level:3},{value:"\ub0a8\uc744 \uc124\ub4dd\ud558\ub294 \ubc29\ubc95 \ubc30\uc6b0\uae30",id:"\ub0a8\uc744-\uc124\ub4dd\ud558\ub294-\ubc29\ubc95-\ubc30\uc6b0\uae30",level:3}],u={toc:c};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 4\uc6d4 19\uc77c",(0,a.kt)("br",{parentName:"p"}),"\n","\uc774\ub3d9\uc6b1\ub2d8 \ud2b9\uac15"),(0,a.kt)("h3",{id:"\uc790\uc874\uac10-\uae30\ub465-\ub9cc\ub4e4\uae30"},"\uc790\uc874\uac10 \uae30\ub465 \ub9cc\ub4e4\uae30"),(0,a.kt)("p",null,"\ub6f0\uc5b4\ub09c \ub3d9\ub8cc, \uc0c8\ub85c\uc6b4 \ud658\uacbd \uadf8\ub9ac\uace0 \ud504\ub85c\uc81d\ud2b8\ub97c \uc2e4\ud328\ud558\uba74\uc11c \uc790\uc874\uac10\uc774 \ub5a8\uc5b4\uc9c8 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc790\uc874\uac10\uc774 \ubb34\ub108\uc9c0\uc9c0 \uc54a\ub3c4\ub85d \ub098\ub97c \uc9c0\ud0f1\ud560 \uc218 \uc788\ub294 \uae30\ub465\uc774 \ud544\uc694\ud558\ub2e4. (\ud55c \uac1c\uac00 \uc544\ub2cc \uc5ec\ub7ec \uac1c) "),(0,a.kt)("h3",{id:"\ub098\ub9cc\uc758-\ud559\uc2b5-\ubc29\ubc95-\ucc3e\uae30"},"\ub098\ub9cc\uc758 \ud559\uc2b5 \ubc29\ubc95 \ucc3e\uae30"),(0,a.kt)("p",null,"\ud68c\uc0ac \uc77c\uc744 \uc9c0\uc18d\uc801\uc73c\ub85c \ud55c\ub2e4\uba74 \ud68c\uc0ac \uc77c\uc758 \uc219\ub828\uc790\uac00 \ub418\uc9c0\ub9cc, \uac1c\ubc1c \uc804\ubb38\uac00\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc8fc\ub2c8\uc5b4 \uc77c\ub54c\ub294 \uc131\uacfc\uac00 \uc544\ub2cc \ud559\uc2b5\uc73c\ub85c!",(0,a.kt)("br",{parentName:"p"}),"\n","\uc9c0\uc18d\uc801\uc73c\ub85c \uc131\uc7a5\ud560 \uc218 \uc788\ub294 \uc0ac\ub78c\uc778\uc9c0? \uace0\ubbfc\ud558\uae30"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\ub3d9\uc6b1\ub2d8\uc774 \uadf8\ub3d9\uc548 \uc2dc\ub3c4\ud55c \ubc29\ubc95")),(0,a.kt)("p",null,"\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8 \uc9c4\ud589\ud558\uae30 \u2192 A-Z \uad6c\ud604 \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ucc45 \uc2a4\ud130\ub514 \u2192 \ub192\uc740 \uc644\uc8fc\uc728, \ud558\uc9c0\ub9cc \ub0b4\uac00 \ubc1c\ud45c\ud55c \uc8fc\uc81c\ub9cc \uae30\uc5b5\uc5d0 \ub0a8\ub294\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uac15\uc758 \uc900\ube44 \u2192 100% \ub0b4\uc6a9 \uc2b5\ub4dd, \ub0ae\uc740 \uc2dc\uac04 \uac00\uc131\ube44, \uac15\uc758 \uc678\uc801\uc778 \ubd80\uac00\uc791\uc5c5",(0,a.kt)("br",{parentName:"p"}),"\n","\ube14\ub85c\uadf8 \u2192 \uc628\ub77c\uc778 \ubaa8\ub450\uac00 \ub9ac\ubdf0\uc5b4, \ub3d9\ub8cc\uc640 \uacf5\uc720 \uac00\ub2a5, \ud53c\ub4dc\ubc31\uc758 \ubd80\ub044\ub7ec\uc6c0 \ud83d\ude33 "),(0,a.kt)("p",null,"\uc2e4\ud328\ud558\uac70\ub098, \uc798\ubabb \uc801\uc5b4\ub3c4 \ub0a8\ub4e4\uc758 \uc2dc\uc120\ubcf4\ub2e8 \ub098 \uc790\uc2e0\uc758 \uc131\uc7a5\uc774 \uc911\uc694\ud558\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uac00\ub2a5\ud558\uba74 \uc778\uc99d\ub418\uace0, \uc815\uc81c\ub41c \uc790\ub8cc\ub85c \uc2b5\ub4dd\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\uc5d0\uac8c \ub9de\ub294 \uac00\uc7a5 \ud6a8\uc728\uc774 \uc88b\uc740 \ud559\uc2b5 \ubc29\ubc95\uc73c\ub85c \ucc3e\uace0, \uc218\uc2dc\ub85c \uc810\uac80\ud558\uc5ec \ub354 \uc88b\uc740 \ubc29\ubc95\uc744 \ucc3e\uace0 \uc2dc\ub3c4\ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\uc0c8\ub85c\uc6b4-\ud658\uacbd\uc744-\uc798-\ubc30\uc6b0\ub294-\ubc29\ubc95"},"\uc0c8\ub85c\uc6b4 \ud658\uacbd\uc744 \uc798 \ubc30\uc6b0\ub294 \ubc29\ubc95"),(0,a.kt)("p",null,"\uc2dc\uac04 > \ub3c8\uc774\uae30 \ub54c\ubb38\uc5d0 \uc2dc\uac04\uc744 \ub3c8\uc73c\ub85c \uad6c\ub9e4\ud558\uc790.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e0\ub8b0\ud560\ub9cc\ud55c \ubd84\uaed8 \uc9c8\ubb38 \ub610\ub294 \ucf54\ub4dc \ub9ac\ubdf0\uac00 \uac00\ub2a5\ud55c \uac15\uc758\ub97c \uad6c\ub9e4\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc5b4\ub5a4 \ud559\uc2b5 \ubc29\uc2dd, \uc5b8\uc81c \uc9d1\uc911\uc774 \uc798 \ub418\ub294\uc9c0, \uc5b4\ub5a4 \ud658\uacbd\uc5d0\uc11c \uc9d1\uc911\uc774 \uc798 \ub418\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\ud559\uc2b5-\uc8fc\uc81c"},"\ud559\uc2b5 \uc8fc\uc81c"),(0,a.kt)("p",null,"\ud68c\uc0ac \uc5c5\ubb34\uc5d0\uc11c \ub9cc\ub09c \ubb38\uc81c\ub97c \uc5f0\uad6c, \uc815\ub9ac, \ud574\uacb0\ud574\uc11c \ucee4\ubba4\ub2c8\ud2f0\uc5d0 \uacf5\uc720\ud558\uace0 \ud53c\ub4dc\ubc31\uc744 \ubc1b\ub294\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc8fc\ubcc0 \ub3d9\ub8cc\ub4e4\uc5d0\uac8c \uc778\uc815\ubc1b\ub294\uac8c \uc6b0\uc120\uc774\ub2e4. "),(0,a.kt)("h3",{id:"\uc0b0\ub9cc\ud568-\uad00\ub9ac\ud558\uae30"},"\uc0b0\ub9cc\ud568 \uad00\ub9ac\ud558\uae30"),(0,a.kt)("p",null,"\ucee8\ud14d\uc2a4\ud2b8 \uc2a4\uc704\uce6d\uc774 \uc790\uc8fc \uc77c\uc5b4\ub098\uba74 \uc0b0\ub9cc\ud574\uc9c0\uae30 \ub54c\ubb38\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \uac00\uc838\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","ex) \uc9d1\uc911\uc774 \uc798 \ub418\ub294 \ud658\uacbd \uad6c\uc131\ud558\uae30, \ucd9c\uadfc \uc804 1~2\uc2dc\uac04 \uc9d1\uc911\ud558\uace0 \ucd9c\uadfc\ud558\uae30, \uc810\uc2ec \uc800\ub141 \uc0b0\ucc45\ud558\uae30, \uc8fc 2~3\ud68c \uc6b4\ub3d9\ud558\uae30"),(0,a.kt)("h3",{id:"\uac70\uc778\uc5d0-\uc5b4\uae68\uc704\uc5d0-\uc62c\ub77c\ud0c0\uae30"},"\uac70\uc778\uc5d0 \uc5b4\uae68\uc704\uc5d0 \uc62c\ub77c\ud0c0\uae30"),(0,a.kt)("p",null,"\ub6f0\uc5b4\ub09c \uc0ac\ub78c \uc606\uc5d0\uc11c \ubc30\uc6cc\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","C\ub808\ubca8, \ud14c\ud06c \ub9ac\ub4dc\uc640 \uac19\uc774 \uc77c\ud560 \uc218 \uc788\ub294 \uac83\uc740 \ud070 \uae30\ud68c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \ubc29\ubc95, \uc2e0\ub8b0 \uc790\uc0b0\uc744 \ud655\ubcf4\ud558\ub294 \ubc29\ubc95, \ubb38\ud654\ub97c \ub9cc\ub4e4\uc5b4\uac00\ub294 \ubc29\ubc95, \uacb0\uc815\uc758 \uae30\uc900\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \ud559\uc2b5\ud560 \uc218 \uc788\ub2e4."),(0,a.kt)("h3",{id:"\ubcf4\uc0c1"},"\ubcf4\uc0c1"),(0,a.kt)("p",null,"\uc2dc\ub828 \ub4a4\uc5d0\ub294 \ud56d\uc0c1 \ubcf4\ubb3c\uc774 \uae30\ub2e4\ub9ac\uace0 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ubcf4\uc0c1\uc744 \ud1b5\ud574 \uafb8\uc900\ud568\uc744 \uc720\uc9c0\ud560 \uc218 \uc788\ub3c4\ub85d \ub9cc\ub4e4\uc5b4\ub77c. "),(0,a.kt)("h3",{id:"\ub0a8\uc744-\uc124\ub4dd\ud558\ub294-\ubc29\ubc95-\ubc30\uc6b0\uae30"},"\ub0a8\uc744 \uc124\ub4dd\ud558\ub294 \ubc29\ubc95 \ubc30\uc6b0\uae30"),(0,a.kt)("p",null,"\ud300\uc6d0\ub4e4\uc774 \ub9e4\ubc88 \ub0b4 \uc758\uacac\uc744 \ubc18\ub300\ud55c\ub2e4\uba74 \uc644\ubcbd\ud55c \ub17c\ub9ac\uac00 \uc911\uc694\ud55c\uac8c \uc544\ub2c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc5b4\ub5bb\uac8c \ud558\uba74 \uc2e0\ub8b0 \uc790\uc0b0\uc744 \ud655\ubcf4\ud560 \uc218 \uc788\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ucee4\ubba4\ub2c8\ucf00\uc774\uc158, \ud611\uc5c5, \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0\uc11c \ubd80\uc871\ud568\uc774 \uc788\uc73c\uba74 \uc548\ub41c\ub2e4."))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9094],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=n.createContext({}),c=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),m=c(r),d=a,b=m["".concat(i,".").concat(d)]||m[d]||s[d]||l;return r?n.createElement(b,p(p({ref:t},u),{},{components:r})):n.createElement(b,p({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=r.length,p=new Array(l);p[0]=m;var o={};for(var i in t)hasOwnProperty.call(t,i)&&(o[i]=t[i]);o.originalType=e,o.mdxType="string"==typeof e?e:a,p[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>p,default:()=>s,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const l={title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",slug:"/etc/healthful-growth",tags:["etc"]},p=void 0,o={unversionedId:"\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30",id:"\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30",title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",description:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 4\uc6d4 19\uc77c",source:"@site/docs/\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/healthful-growth",permalink:"/docs/etc/healthful-growth",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",slug:"/etc/healthful-growth",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\ubb38\uc11c",permalink:"/docs/"},next:{title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",permalink:"/docs/etc/develop-with-spring"}},i={},c=[{value:"\uc790\uc874\uac10 \uae30\ub465 \ub9cc\ub4e4\uae30",id:"\uc790\uc874\uac10-\uae30\ub465-\ub9cc\ub4e4\uae30",level:3},{value:"\ub098\ub9cc\uc758 \ud559\uc2b5 \ubc29\ubc95 \ucc3e\uae30",id:"\ub098\ub9cc\uc758-\ud559\uc2b5-\ubc29\ubc95-\ucc3e\uae30",level:3},{value:"\uc0c8\ub85c\uc6b4 \ud658\uacbd\uc744 \uc798 \ubc30\uc6b0\ub294 \ubc29\ubc95",id:"\uc0c8\ub85c\uc6b4-\ud658\uacbd\uc744-\uc798-\ubc30\uc6b0\ub294-\ubc29\ubc95",level:3},{value:"\ud559\uc2b5 \uc8fc\uc81c",id:"\ud559\uc2b5-\uc8fc\uc81c",level:3},{value:"\uc0b0\ub9cc\ud568 \uad00\ub9ac\ud558\uae30",id:"\uc0b0\ub9cc\ud568-\uad00\ub9ac\ud558\uae30",level:3},{value:"\uac70\uc778\uc5d0 \uc5b4\uae68\uc704\uc5d0 \uc62c\ub77c\ud0c0\uae30",id:"\uac70\uc778\uc5d0-\uc5b4\uae68\uc704\uc5d0-\uc62c\ub77c\ud0c0\uae30",level:3},{value:"\ubcf4\uc0c1",id:"\ubcf4\uc0c1",level:3},{value:"\ub0a8\uc744 \uc124\ub4dd\ud558\ub294 \ubc29\ubc95 \ubc30\uc6b0\uae30",id:"\ub0a8\uc744-\uc124\ub4dd\ud558\ub294-\ubc29\ubc95-\ubc30\uc6b0\uae30",level:3}],u={toc:c};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 4\uc6d4 19\uc77c",(0,a.kt)("br",{parentName:"p"}),"\n","\uc774\ub3d9\uc6b1\ub2d8 \ud2b9\uac15"),(0,a.kt)("h3",{id:"\uc790\uc874\uac10-\uae30\ub465-\ub9cc\ub4e4\uae30"},"\uc790\uc874\uac10 \uae30\ub465 \ub9cc\ub4e4\uae30"),(0,a.kt)("p",null,"\ub6f0\uc5b4\ub09c \ub3d9\ub8cc, \uc0c8\ub85c\uc6b4 \ud658\uacbd \uadf8\ub9ac\uace0 \ud504\ub85c\uc81d\ud2b8\ub97c \uc2e4\ud328\ud558\uba74\uc11c \uc790\uc874\uac10\uc774 \ub5a8\uc5b4\uc9c8 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc790\uc874\uac10\uc774 \ubb34\ub108\uc9c0\uc9c0 \uc54a\ub3c4\ub85d \ub098\ub97c \uc9c0\ud0f1\ud560 \uc218 \uc788\ub294 \uae30\ub465\uc774 \ud544\uc694\ud558\ub2e4. (\ud55c \uac1c\uac00 \uc544\ub2cc \uc5ec\ub7ec \uac1c) "),(0,a.kt)("h3",{id:"\ub098\ub9cc\uc758-\ud559\uc2b5-\ubc29\ubc95-\ucc3e\uae30"},"\ub098\ub9cc\uc758 \ud559\uc2b5 \ubc29\ubc95 \ucc3e\uae30"),(0,a.kt)("p",null,"\ud68c\uc0ac \uc77c\uc744 \uc9c0\uc18d\uc801\uc73c\ub85c \ud55c\ub2e4\uba74 \ud68c\uc0ac \uc77c\uc758 \uc219\ub828\uc790\uac00 \ub418\uc9c0\ub9cc, \uac1c\ubc1c \uc804\ubb38\uac00\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc8fc\ub2c8\uc5b4 \uc77c\ub54c\ub294 \uc131\uacfc\uac00 \uc544\ub2cc \ud559\uc2b5\uc73c\ub85c!",(0,a.kt)("br",{parentName:"p"}),"\n","\uc9c0\uc18d\uc801\uc73c\ub85c \uc131\uc7a5\ud560 \uc218 \uc788\ub294 \uc0ac\ub78c\uc778\uc9c0? \uace0\ubbfc\ud558\uae30"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\ub3d9\uc6b1\ub2d8\uc774 \uadf8\ub3d9\uc548 \uc2dc\ub3c4\ud55c \ubc29\ubc95")),(0,a.kt)("p",null,"\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8 \uc9c4\ud589\ud558\uae30 \u2192 A-Z \uad6c\ud604 \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ucc45 \uc2a4\ud130\ub514 \u2192 \ub192\uc740 \uc644\uc8fc\uc728, \ud558\uc9c0\ub9cc \ub0b4\uac00 \ubc1c\ud45c\ud55c \uc8fc\uc81c\ub9cc \uae30\uc5b5\uc5d0 \ub0a8\ub294\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uac15\uc758 \uc900\ube44 \u2192 100% \ub0b4\uc6a9 \uc2b5\ub4dd, \ub0ae\uc740 \uc2dc\uac04 \uac00\uc131\ube44, \uac15\uc758 \uc678\uc801\uc778 \ubd80\uac00\uc791\uc5c5",(0,a.kt)("br",{parentName:"p"}),"\n","\ube14\ub85c\uadf8 \u2192 \uc628\ub77c\uc778 \ubaa8\ub450\uac00 \ub9ac\ubdf0\uc5b4, \ub3d9\ub8cc\uc640 \uacf5\uc720 \uac00\ub2a5, \ud53c\ub4dc\ubc31\uc758 \ubd80\ub044\ub7ec\uc6c0 \ud83d\ude33 "),(0,a.kt)("p",null,"\uc2e4\ud328\ud558\uac70\ub098, \uc798\ubabb \uc801\uc5b4\ub3c4 \ub0a8\ub4e4\uc758 \uc2dc\uc120\ubcf4\ub2e8 \ub098 \uc790\uc2e0\uc758 \uc131\uc7a5\uc774 \uc911\uc694\ud558\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uac00\ub2a5\ud558\uba74 \uc778\uc99d\ub418\uace0, \uc815\uc81c\ub41c \uc790\ub8cc\ub85c \uc2b5\ub4dd\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\uc5d0\uac8c \ub9de\ub294 \uac00\uc7a5 \ud6a8\uc728\uc774 \uc88b\uc740 \ud559\uc2b5 \ubc29\ubc95\uc73c\ub85c \ucc3e\uace0, \uc218\uc2dc\ub85c \uc810\uac80\ud558\uc5ec \ub354 \uc88b\uc740 \ubc29\ubc95\uc744 \ucc3e\uace0 \uc2dc\ub3c4\ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\uc0c8\ub85c\uc6b4-\ud658\uacbd\uc744-\uc798-\ubc30\uc6b0\ub294-\ubc29\ubc95"},"\uc0c8\ub85c\uc6b4 \ud658\uacbd\uc744 \uc798 \ubc30\uc6b0\ub294 \ubc29\ubc95"),(0,a.kt)("p",null,"\uc2dc\uac04 > \ub3c8\uc774\uae30 \ub54c\ubb38\uc5d0 \uc2dc\uac04\uc744 \ub3c8\uc73c\ub85c \uad6c\ub9e4\ud558\uc790.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc2e0\ub8b0\ud560\ub9cc\ud55c \ubd84\uaed8 \uc9c8\ubb38 \ub610\ub294 \ucf54\ub4dc \ub9ac\ubdf0\uac00 \uac00\ub2a5\ud55c \uac15\uc758\ub97c \uad6c\ub9e4\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc5b4\ub5a4 \ud559\uc2b5 \ubc29\uc2dd, \uc5b8\uc81c \uc9d1\uc911\uc774 \uc798 \ub418\ub294\uc9c0, \uc5b4\ub5a4 \ud658\uacbd\uc5d0\uc11c \uc9d1\uc911\uc774 \uc798 \ub418\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. "),(0,a.kt)("h3",{id:"\ud559\uc2b5-\uc8fc\uc81c"},"\ud559\uc2b5 \uc8fc\uc81c"),(0,a.kt)("p",null,"\ud68c\uc0ac \uc5c5\ubb34\uc5d0\uc11c \ub9cc\ub09c \ubb38\uc81c\ub97c \uc5f0\uad6c, \uc815\ub9ac, \ud574\uacb0\ud574\uc11c \ucee4\ubba4\ub2c8\ud2f0\uc5d0 \uacf5\uc720\ud558\uace0 \ud53c\ub4dc\ubc31\uc744 \ubc1b\ub294\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc8fc\ubcc0 \ub3d9\ub8cc\ub4e4\uc5d0\uac8c \uc778\uc815\ubc1b\ub294\uac8c \uc6b0\uc120\uc774\ub2e4. "),(0,a.kt)("h3",{id:"\uc0b0\ub9cc\ud568-\uad00\ub9ac\ud558\uae30"},"\uc0b0\ub9cc\ud568 \uad00\ub9ac\ud558\uae30"),(0,a.kt)("p",null,"\ucee8\ud14d\uc2a4\ud2b8 \uc2a4\uc704\uce6d\uc774 \uc790\uc8fc \uc77c\uc5b4\ub098\uba74 \uc0b0\ub9cc\ud574\uc9c0\uae30 \ub54c\ubb38\uc5d0 \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \uac00\uc838\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","ex) \uc9d1\uc911\uc774 \uc798 \ub418\ub294 \ud658\uacbd \uad6c\uc131\ud558\uae30, \ucd9c\uadfc \uc804 1~2\uc2dc\uac04 \uc9d1\uc911\ud558\uace0 \ucd9c\uadfc\ud558\uae30, \uc810\uc2ec \uc800\ub141 \uc0b0\ucc45\ud558\uae30, \uc8fc 2~3\ud68c \uc6b4\ub3d9\ud558\uae30"),(0,a.kt)("h3",{id:"\uac70\uc778\uc5d0-\uc5b4\uae68\uc704\uc5d0-\uc62c\ub77c\ud0c0\uae30"},"\uac70\uc778\uc5d0 \uc5b4\uae68\uc704\uc5d0 \uc62c\ub77c\ud0c0\uae30"),(0,a.kt)("p",null,"\ub6f0\uc5b4\ub09c \uc0ac\ub78c \uc606\uc5d0\uc11c \ubc30\uc6cc\uc57c \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","C\ub808\ubca8, \ud14c\ud06c \ub9ac\ub4dc\uc640 \uac19\uc774 \uc77c\ud560 \uc218 \uc788\ub294 \uac83\uc740 \ud070 \uae30\ud68c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \ubc29\ubc95, \uc2e0\ub8b0 \uc790\uc0b0\uc744 \ud655\ubcf4\ud558\ub294 \ubc29\ubc95, \ubb38\ud654\ub97c \ub9cc\ub4e4\uc5b4\uac00\ub294 \ubc29\ubc95, \uacb0\uc815\uc758 \uae30\uc900\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \ud559\uc2b5\ud560 \uc218 \uc788\ub2e4."),(0,a.kt)("h3",{id:"\ubcf4\uc0c1"},"\ubcf4\uc0c1"),(0,a.kt)("p",null,"\uc2dc\ub828 \ub4a4\uc5d0\ub294 \ud56d\uc0c1 \ubcf4\ubb3c\uc774 \uae30\ub2e4\ub9ac\uace0 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ubcf4\uc0c1\uc744 \ud1b5\ud574 \uafb8\uc900\ud568\uc744 \uc720\uc9c0\ud560 \uc218 \uc788\ub3c4\ub85d \ub9cc\ub4e4\uc5b4\ub77c. "),(0,a.kt)("h3",{id:"\ub0a8\uc744-\uc124\ub4dd\ud558\ub294-\ubc29\ubc95-\ubc30\uc6b0\uae30"},"\ub0a8\uc744 \uc124\ub4dd\ud558\ub294 \ubc29\ubc95 \ubc30\uc6b0\uae30"),(0,a.kt)("p",null,"\ud300\uc6d0\ub4e4\uc774 \ub9e4\ubc88 \ub0b4 \uc758\uacac\uc744 \ubc18\ub300\ud55c\ub2e4\uba74 \uc644\ubcbd\ud55c \ub17c\ub9ac\uac00 \uc911\uc694\ud55c\uac8c \uc544\ub2c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc5b4\ub5bb\uac8c \ud558\uba74 \uc2e0\ub8b0 \uc790\uc0b0\uc744 \ud655\ubcf4\ud560 \uc218 \uc788\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ucee4\ubba4\ub2c8\ucf00\uc774\uc158, \ud611\uc5c5, \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0\uc11c \ubd80\uc871\ud568\uc774 \uc788\uc73c\uba74 \uc548\ub41c\ub2e4."))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/48bd1d32.00513cdb.js b/assets/js/48bd1d32.8f931e51.js similarity index 98% rename from assets/js/48bd1d32.00513cdb.js rename to assets/js/48bd1d32.8f931e51.js index 85218fe44..a36823ab5 100644 --- a/assets/js/48bd1d32.00513cdb.js +++ b/assets/js/48bd1d32.8f931e51.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9563],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(67294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=c(r),d=i,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||a;return r?n.createElement(f,o(o({ref:t},p),{},{components:r})):n.createElement(f,o({ref:t},p))}));function d(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(87462),i=(r(67294),r(3905));const a={title:"TDD heuristics",slug:"/test/heuristics",tags:["test"]},o=void 0,l={unversionedId:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59",id:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59",title:"TDD heuristics",description:"TDD heuristics",source:"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/heuristics",permalink:"/docs/test/heuristics",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"TDD heuristics",slug:"/test/heuristics",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",permalink:"/docs/test/stairstep"},next:{title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",permalink:"/docs/test/benefit"}},s={},c=[{value:"TDD heuristics",id:"tdd-heuristics",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h3",{id:"tdd-heuristics"},"TDD heuristics"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"\uc5ec\ub7ec\ubd84\uc774 \uc791\uc131\ud558\uace0 \uc2f6\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub3c4\ub85d \ub9cc\ub4dc\ub294 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\uc2e4\ud328\uc2dc\ucf1c\ub77c. \ud1b5\uacfc\uc2dc\ucf1c\ub77c. \uadf8\ub9ac\uace0 \uc815\ub9ac\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ucd5c\uc0c1\uc758 \uacb0\uacfc\ub97c \ucd94\uad6c\ud558\uc9c0 \ub9d0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\uc2e4\ud328\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud558\uace0, \uac00\uc7a5 \uad6c\uccb4\uc801\uc774\uba70, \uac00\uc7a5 \ud1f4\ud654\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\uac00\ub2a5\ud558\uba74 \uc77c\ubc18\ud654\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ucf54\ub4dc\uac00 \ud2c0\ub838\ub2e4\uace0 \ub290\uaef4\uc9c0\uba74 \uc7a0\uc2dc \uba48\ucdb0\uc11c \uc124\uacc4\ub97c \uace0\uccd0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ub354 \ubcf5\uc7a1\ud55c \ub2e4\uc74c \uacbd\uc6b0\ub85c \ub118\uc5b4\uac00\uae30 \uc804, \uc9c0\uae08 \ub2e4\ub8e8\uace0 \uc788\ub294 \ub354 \ub2e8\uc21c\ud55c \uacbd\uc6b0\ub97c \ubaa8\uc870\ub9ac \ud14c\uc2a4\ud2b8\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud604\uc7ac \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\uc2dc\ud0a4\uae30 \uc704\ud574 \ub108\ubb34 \ub9ce\uc740 \uad6c\ud604\uc744 \ud574\uc57c \ud55c\ub2e4\uba74, \ud14c\uc2a4\ud2b8\ub97c \uc9c0\uc6b0\uace0 \ub354 \uc27d\uac8c \ud1b5\uacfc\ud560 \uc218 \uc788\ub294 \ub354 \ub2e8\uc21c\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8 \uacf5\uac04(test space)\uc744 \uc804\ubd80 \ud3ec\uad04\ud558\ub294 \uc2e0\uc911\ud558\uace0 \uc810\uc9c4\uc801\uc778 \ud328\ud134\uc744 \ub530\ub974\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud544\uc694 \uc5c6\ub294 \uac83\uc744 \uc5ec\ub7ec\ubd84\uc758 \ud14c\uc2a4\ud2b8\uc5d0 \ub123\uc9c0 \ub9d0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8\uc5d0 \uc2e4\uc81c \uc11c\ube44\uc2a4 \ub370\uc774\ud130\ub97c \uc0ac\uc6a9\ud558\uc9c0 \ub9d0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8 \uad6c\uc870\ub97c \uc81c\ud488 \ucf54\ub4dc \uad6c\uc870\ub85c\ubd80\ud130 \ubd84\ub9ac\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8\uac00 \uad6c\uccb4\uc801(specific)\uc774 \ub420\uc218\ub85d \ucf54\ub4dc\ub294 \uc77c\ubc18\uc801(generic)\uc774 \ub41c\ub2e4."),(0,i.kt)("li",{parentName:"ol"},"\ubcc0\ud658\uc744 \uc801\uc6a9\ud55c \uacb0\uacfc \ucd5c\uc801\uc774 \uc544\ub2cc \ud574\ub2f5\uc5d0 \ub3c4\ub2ec\ud588\ub2e4\uba74 \ub2e4\ub978 \ubcc0\ud658\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ub514\ubc84\uac70 \uc0ac\uc6a9\uc744 \ud53c\ud558\ub77c")),(0,i.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,i.kt)("p",null,"\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 p.44 ~ p.209"))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9563],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(67294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=c(r),d=i,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||a;return r?n.createElement(f,o(o({ref:t},p),{},{components:r})):n.createElement(f,o({ref:t},p))}));function d(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(87462),i=(r(67294),r(3905));const a={title:"TDD heuristics",slug:"/test/heuristics",tags:["test"]},o=void 0,l={unversionedId:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59",id:"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59",title:"TDD heuristics",description:"TDD heuristics",source:"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/heuristics",permalink:"/docs/test/heuristics",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"TDD heuristics",slug:"/test/heuristics",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",permalink:"/docs/test/stairstep"},next:{title:"\ud14c\uc2a4\ud2b8 \ucf54\ub4dc\uac00 \uc8fc\ub294 \ud61c\ud0dd",permalink:"/docs/test/benefit"}},s={},c=[{value:"TDD heuristics",id:"tdd-heuristics",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h3",{id:"tdd-heuristics"},"TDD heuristics"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"\uc5ec\ub7ec\ubd84\uc774 \uc791\uc131\ud558\uace0 \uc2f6\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub3c4\ub85d \ub9cc\ub4dc\ub294 \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\uc2e4\ud328\uc2dc\ucf1c\ub77c. \ud1b5\uacfc\uc2dc\ucf1c\ub77c. \uadf8\ub9ac\uace0 \uc815\ub9ac\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ucd5c\uc0c1\uc758 \uacb0\uacfc\ub97c \ucd94\uad6c\ud558\uc9c0 \ub9d0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\uc2e4\ud328\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud558\uace0, \uac00\uc7a5 \uad6c\uccb4\uc801\uc774\uba70, \uac00\uc7a5 \ud1f4\ud654\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\uac00\ub2a5\ud558\uba74 \uc77c\ubc18\ud654\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ucf54\ub4dc\uac00 \ud2c0\ub838\ub2e4\uace0 \ub290\uaef4\uc9c0\uba74 \uc7a0\uc2dc \uba48\ucdb0\uc11c \uc124\uacc4\ub97c \uace0\uccd0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ub354 \ubcf5\uc7a1\ud55c \ub2e4\uc74c \uacbd\uc6b0\ub85c \ub118\uc5b4\uac00\uae30 \uc804, \uc9c0\uae08 \ub2e4\ub8e8\uace0 \uc788\ub294 \ub354 \ub2e8\uc21c\ud55c \uacbd\uc6b0\ub97c \ubaa8\uc870\ub9ac \ud14c\uc2a4\ud2b8\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud604\uc7ac \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\uc2dc\ud0a4\uae30 \uc704\ud574 \ub108\ubb34 \ub9ce\uc740 \uad6c\ud604\uc744 \ud574\uc57c \ud55c\ub2e4\uba74, \ud14c\uc2a4\ud2b8\ub97c \uc9c0\uc6b0\uace0 \ub354 \uc27d\uac8c \ud1b5\uacfc\ud560 \uc218 \uc788\ub294 \ub354 \ub2e8\uc21c\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8 \uacf5\uac04(test space)\uc744 \uc804\ubd80 \ud3ec\uad04\ud558\ub294 \uc2e0\uc911\ud558\uace0 \uc810\uc9c4\uc801\uc778 \ud328\ud134\uc744 \ub530\ub974\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud544\uc694 \uc5c6\ub294 \uac83\uc744 \uc5ec\ub7ec\ubd84\uc758 \ud14c\uc2a4\ud2b8\uc5d0 \ub123\uc9c0 \ub9d0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8\uc5d0 \uc2e4\uc81c \uc11c\ube44\uc2a4 \ub370\uc774\ud130\ub97c \uc0ac\uc6a9\ud558\uc9c0 \ub9d0\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8 \uad6c\uc870\ub97c \uc81c\ud488 \ucf54\ub4dc \uad6c\uc870\ub85c\ubd80\ud130 \ubd84\ub9ac\ud558\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ud14c\uc2a4\ud2b8\uac00 \uad6c\uccb4\uc801(specific)\uc774 \ub420\uc218\ub85d \ucf54\ub4dc\ub294 \uc77c\ubc18\uc801(generic)\uc774 \ub41c\ub2e4."),(0,i.kt)("li",{parentName:"ol"},"\ubcc0\ud658\uc744 \uc801\uc6a9\ud55c \uacb0\uacfc \ucd5c\uc801\uc774 \uc544\ub2cc \ud574\ub2f5\uc5d0 \ub3c4\ub2ec\ud588\ub2e4\uba74 \ub2e4\ub978 \ubcc0\ud658\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub77c."),(0,i.kt)("li",{parentName:"ol"},"\ub514\ubc84\uac70 \uc0ac\uc6a9\uc744 \ud53c\ud558\ub77c")),(0,i.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,i.kt)("p",null,"\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 p.44 ~ p.209"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/814f3328.11618e69.js b/assets/js/814f3328.11618e69.js deleted file mode 100644 index 64d71caca..000000000 --- a/assets/js/814f3328.11618e69.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2535],{45641:e=>{e.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac","permalink":"/async-exception"},{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"},{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"},{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"},{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"}]}')}}]); \ No newline at end of file diff --git a/assets/js/814f3328.e89f70ff.js b/assets/js/814f3328.e89f70ff.js new file mode 100644 index 000000000..afbc489d5 --- /dev/null +++ b/assets/js/814f3328.e89f70ff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2535],{45641:e=>{e.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","permalink":"/log-async-exception"},{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"},{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"},{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"},{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"}]}')}}]); \ No newline at end of file diff --git a/assets/js/87070fc3.0f052f4b.js b/assets/js/87070fc3.5b3591e0.js similarity index 99% rename from assets/js/87070fc3.0f052f4b.js rename to assets/js/87070fc3.5b3591e0.js index f90809d21..bd3436855 100644 --- a/assets/js/87070fc3.0f052f4b.js +++ b/assets/js/87070fc3.5b3591e0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6124],{3905:(t,e,r)=>{r.d(e,{Zo:()=>s,kt:()=>d});var n=r(67294);function a(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function l(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,n)}return r}function o(t){for(var e=1;e=0||(a[r]=t[r]);return a}(t,e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(a[r]=t[r])}return a}var i=n.createContext({}),c=function(t){var e=n.useContext(i),r=e;return t&&(r="function"==typeof t?t(e):o(o({},e),t)),r},s=function(t){var e=c(t.components);return n.createElement(i.Provider,{value:e},t.children)},u={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},m=n.forwardRef((function(t,e){var r=t.components,a=t.mdxType,l=t.originalType,i=t.parentName,s=p(t,["components","mdxType","originalType","parentName"]),m=c(r),d=a,f=m["".concat(i,".").concat(d)]||m[d]||u[d]||l;return r?n.createElement(f,o(o({ref:e},s),{},{components:r})):n.createElement(f,o({ref:e},s))}));function d(t,e){var r=arguments,a=e&&e.mdxType;if("string"==typeof t||a){var l=r.length,o=new Array(l);o[0]=m;var p={};for(var i in e)hasOwnProperty.call(e,i)&&(p[i]=e[i]);p.originalType=t,p.mdxType="string"==typeof t?t:a,o[1]=p;for(var c=2;c{r.r(e),r.d(e,{assets:()=>i,contentTitle:()=>o,default:()=>u,frontMatter:()=>l,metadata:()=>p,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const l={title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",slug:"/performance/types",tags:["performance","test"]},o=void 0,p={unversionedId:"\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8",id:"\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8",title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",description:"| \ud14c\uc2a4\ud2b8 | \uc124\uba85 |",source:"@site/docs/\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",sourceDirName:"\uc131\ub2a5",slug:"/performance/types",permalink:"/docs/performance/types",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",tags:[{label:"performance",permalink:"/docs/tags/performance"},{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",slug:"/performance/types",tags:["performance","test"]},sidebar:"tutorialSidebar",previous:{title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",permalink:"/docs/performance/throughput-latency"},next:{title:"FIRST",permalink:"/docs/test/first"}},i={},c=[{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:c};function u(t){let{components:e,...r}=t;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("table",null,(0,a.kt)("thead",{parentName:"table"},(0,a.kt)("tr",{parentName:"thead"},(0,a.kt)("th",{parentName:"tr",align:null},"\ud14c\uc2a4\ud2b8"),(0,a.kt)("th",{parentName:"tr",align:null},"\uc124\uba85"))),(0,a.kt)("tbody",{parentName:"table"},(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc9c0\uc5f0 \ud14c\uc2a4\ud2b8(latency test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc694\uccad\uc5d0 \ub300\ud55c \uc751\ub2f5 \uc2dc\uac04\uc744 \uce21\uc815")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\ucc98\ub9ac\uc728 \ud14c\uc2a4\ud2b8(throughput test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc2dc\uc2a4\ud15c \uc131\ub2a5\uc774 \uae09\ub77d\ud558\uae30 \uc9c1\uc804, \ucd5c\ub300 \ucc98\ub9ac\uc728 \uc218\uce58\ub97c \uce21\uc815")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\ubd80\ud558 \ud14c\uc2a4\ud2b8(load test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\ube44\uc988\ub2c8\uc2a4 \uc774\ubca4\ud2b8\ub97c \ub300\ube44\ud574 \ud2b8\ub798\ud53d\uc744 \uacac\ub51c \uc218 \uc788\ub294\uc9c0 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(stress test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc2dc\uc2a4\ud15c\uc758 \ud55c\uacc4\uc810\uc744 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(endurance test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc7a5\uc2dc\uac04 \uc2e4\ud589\ud560 \uacbd\uc6b0 \uc131\ub2a5 \uc774\uc0c1\uc774 \ubc1c\uc0dd\ud558\ub294\uc9c0 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc6a9\ub7c9 \uacc4\ud68d \ud14c\uc2a4\ud2b8(capacity planning test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\ub9ac\uc18c\uc2a4\ub97c \ucd94\uac00\ud55c \ub9cc\ud07c \uc2dc\uc2a4\ud15c\uc774 \ud655\uc7a5\ub418\ub294\uc9c0 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc800\ud558 \ud14c\uc2a4\ud2b8(degradation test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc2dc\uc2a4\ud15c\uc774 \ubd80\ubd84\uc801\uc73c\ub85c \uc2e4\ud328\ud560 \uacbd\uc6b0 \uc5b4\ub5a4 \uc77c\uc774 \ubc1c\uc0dd\ud558\ub294\uc9c0 \ud655\uc778(\uc7a5\uc560 \ubcf5\uad6c \ubc0f \ud68c\ubcf5 \ub4f1)")))),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc"))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[6124],{3905:(t,e,r)=>{r.d(e,{Zo:()=>s,kt:()=>d});var n=r(67294);function a(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function l(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(t);e&&(n=n.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),r.push.apply(r,n)}return r}function o(t){for(var e=1;e=0||(a[r]=t[r]);return a}(t,e);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(t);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(t,r)&&(a[r]=t[r])}return a}var i=n.createContext({}),c=function(t){var e=n.useContext(i),r=e;return t&&(r="function"==typeof t?t(e):o(o({},e),t)),r},s=function(t){var e=c(t.components);return n.createElement(i.Provider,{value:e},t.children)},u={inlineCode:"code",wrapper:function(t){var e=t.children;return n.createElement(n.Fragment,{},e)}},m=n.forwardRef((function(t,e){var r=t.components,a=t.mdxType,l=t.originalType,i=t.parentName,s=p(t,["components","mdxType","originalType","parentName"]),m=c(r),d=a,f=m["".concat(i,".").concat(d)]||m[d]||u[d]||l;return r?n.createElement(f,o(o({ref:e},s),{},{components:r})):n.createElement(f,o({ref:e},s))}));function d(t,e){var r=arguments,a=e&&e.mdxType;if("string"==typeof t||a){var l=r.length,o=new Array(l);o[0]=m;var p={};for(var i in e)hasOwnProperty.call(e,i)&&(p[i]=e[i]);p.originalType=t,p.mdxType="string"==typeof t?t:a,o[1]=p;for(var c=2;c{r.r(e),r.d(e,{assets:()=>i,contentTitle:()=>o,default:()=>u,frontMatter:()=>l,metadata:()=>p,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const l={title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",slug:"/performance/types",tags:["performance","test"]},o=void 0,p={unversionedId:"\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8",id:"\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8",title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",description:"| \ud14c\uc2a4\ud2b8 | \uc124\uba85 |",source:"@site/docs/\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",sourceDirName:"\uc131\ub2a5",slug:"/performance/types",permalink:"/docs/performance/types",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",tags:[{label:"performance",permalink:"/docs/tags/performance"},{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",slug:"/performance/types",tags:["performance","test"]},sidebar:"tutorialSidebar",previous:{title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",permalink:"/docs/performance/throughput-latency"},next:{title:"FIRST",permalink:"/docs/test/first"}},i={},c=[{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:c};function u(t){let{components:e,...r}=t;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:e,mdxType:"MDXLayout"}),(0,a.kt)("table",null,(0,a.kt)("thead",{parentName:"table"},(0,a.kt)("tr",{parentName:"thead"},(0,a.kt)("th",{parentName:"tr",align:null},"\ud14c\uc2a4\ud2b8"),(0,a.kt)("th",{parentName:"tr",align:null},"\uc124\uba85"))),(0,a.kt)("tbody",{parentName:"table"},(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc9c0\uc5f0 \ud14c\uc2a4\ud2b8(latency test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc694\uccad\uc5d0 \ub300\ud55c \uc751\ub2f5 \uc2dc\uac04\uc744 \uce21\uc815")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\ucc98\ub9ac\uc728 \ud14c\uc2a4\ud2b8(throughput test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc2dc\uc2a4\ud15c \uc131\ub2a5\uc774 \uae09\ub77d\ud558\uae30 \uc9c1\uc804, \ucd5c\ub300 \ucc98\ub9ac\uc728 \uc218\uce58\ub97c \uce21\uc815")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\ubd80\ud558 \ud14c\uc2a4\ud2b8(load test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\ube44\uc988\ub2c8\uc2a4 \uc774\ubca4\ud2b8\ub97c \ub300\ube44\ud574 \ud2b8\ub798\ud53d\uc744 \uacac\ub51c \uc218 \uc788\ub294\uc9c0 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(stress test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc2dc\uc2a4\ud15c\uc758 \ud55c\uacc4\uc810\uc744 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\ub0b4\uad6c \ud14c\uc2a4\ud2b8(endurance test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc7a5\uc2dc\uac04 \uc2e4\ud589\ud560 \uacbd\uc6b0 \uc131\ub2a5 \uc774\uc0c1\uc774 \ubc1c\uc0dd\ud558\ub294\uc9c0 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc6a9\ub7c9 \uacc4\ud68d \ud14c\uc2a4\ud2b8(capacity planning test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\ub9ac\uc18c\uc2a4\ub97c \ucd94\uac00\ud55c \ub9cc\ud07c \uc2dc\uc2a4\ud15c\uc774 \ud655\uc7a5\ub418\ub294\uc9c0 \ud655\uc778")),(0,a.kt)("tr",{parentName:"tbody"},(0,a.kt)("td",{parentName:"tr",align:null},"\uc800\ud558 \ud14c\uc2a4\ud2b8(degradation test)"),(0,a.kt)("td",{parentName:"tr",align:null},"\uc2dc\uc2a4\ud15c\uc774 \ubd80\ubd84\uc801\uc73c\ub85c \uc2e4\ud328\ud560 \uacbd\uc6b0 \uc5b4\ub5a4 \uc77c\uc774 \ubc1c\uc0dd\ud558\ub294\uc9c0 \ud655\uc778(\uc7a5\uc560 \ubcf5\uad6c \ubc0f \ud68c\ubcf5 \ub4f1)")))),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/905ecccc.11052f62.js b/assets/js/905ecccc.11052f62.js new file mode 100644 index 000000000..9d4feabf5 --- /dev/null +++ b/assets/js/905ecccc.11052f62.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2939],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var u=r.createContext({}),c=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=c(e.components);return r.createElement(u.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,g=m["".concat(u,".").concat(d)]||m[d]||p[d]||o;return n?r.createElement(g,i(i({ref:t},s),{},{components:n})):r.createElement(g,i({ref:t},s))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c{n.d(t,{Z:()=>i});var r=n(67294),a=n(86010);const o="tabItem_Ymn6";function i(e){let{children:t,hidden:n,className:i}=e;return r.createElement("div",{role:"tabpanel",className:(0,a.Z)(o,i),hidden:n},t)}},74866:(e,t,n)=>{n.d(t,{Z:()=>S});var r=n(87462),a=n(67294),o=n(86010),i=n(12466),l=n(16550),u=n(91980),c=n(67392),s=n(50012);function p(e){return function(e){return a.Children.map(e,(e=>{if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))}(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:a}}=e;return{value:t,label:n,attributes:r,default:a}}))}function m(e){const{values:t,children:n}=e;return(0,a.useMemo)((()=>{const e=t??p(n);return function(e){const t=(0,c.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function d(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function g(e){let{queryString:t=!1,groupId:n}=e;const r=(0,l.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,u._X)(o),(0,a.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(r.location.search);t.set(o,e),r.replace({...r.location,search:t.toString()})}),[o,r])]}function k(e){const{defaultValue:t,queryString:n=!1,groupId:r}=e,o=m(e),[i,l]=(0,a.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!d({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=n.find((e=>e.default))??n[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:o}))),[u,c]=g({queryString:n,groupId:r}),[p,k]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,o]=(0,s.Nk)(n);return[r,(0,a.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:r}),f=(()=>{const e=u??p;return d({value:e,tabValues:o})?e:null})();(0,a.useEffect)((()=>{f&&l(f)}),[f]);return{selectedValue:i,selectValue:(0,a.useCallback)((e=>{if(!d({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),c(e),k(e)}),[c,k,o]),tabValues:o}}var f=n(72389);const b="tabList__CuJ",h="tabItem_LNqP";function N(e){let{className:t,block:n,selectedValue:l,selectValue:u,tabValues:c}=e;const s=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),m=e=>{const t=e.currentTarget,n=s.indexOf(t),r=c[n].value;r!==l&&(p(t),u(r))},d=e=>{let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{const n=s.indexOf(e.currentTarget)+1;t=s[n]??s[0];break}case"ArrowLeft":{const n=s.indexOf(e.currentTarget)-1;t=s[n]??s[s.length-1];break}}t?.focus()};return a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},c.map((e=>{let{value:t,label:n,attributes:i}=e;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:l===t?0:-1,"aria-selected":l===t,key:t,ref:e=>s.push(e),onKeyDown:d,onClick:m},i,{className:(0,o.Z)("tabs__item",h,i?.className,{"tabs__item--active":l===t})}),n??t)})))}function v(e){let{lazy:t,children:n,selectedValue:r}=e;if(t){const e=n.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return a.createElement("div",{className:"margin-top--md"},n.map(((e,t)=>(0,a.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function C(e){const t=k(e);return a.createElement("div",{className:(0,o.Z)("tabs-container",b)},a.createElement(N,(0,r.Z)({},e,t)),a.createElement(v,(0,r.Z)({},e,t)))}function S(e){const t=(0,f.Z)();return a.createElement(C,(0,r.Z)({key:String(t)},e))}},1057:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>u,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>p});var r=n(87462),a=(n(67294),n(3905)),o=n(74866),i=n(85162);const l={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},u=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"\ud1b0\ucea3 \uad6c\ud604",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.27,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},s={authorsImageUrls:[]},p=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],m={toc:p};function d(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ud1b0\ucea3-\uad6c\ud604"},"\ud1b0\ucea3 \uad6c\ud604"),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. "),(0,a.kt)("p",null,"\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. "),(0,a.kt)("h3",{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"},"\ub2e4\uc774\uc5b4\uadf8\ub7a8"),(0,a.kt)("p",null,"Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. "),(0,a.kt)("mermaid",{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),(0,a.kt)("h3",{id:"\ucf54\ub4dc-\ub9ac\ubdf0"},"\ucf54\ub4dc \ub9ac\ubdf0"),(0,a.kt)("p",null,"\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"sessionconfig"},"SessionConfig"),(0,a.kt)("p",null,"\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/apache/tomcat/pull/660"},"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. "),(0,a.kt)("p",null,"\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. "),(0,a.kt)("p",null,"\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. "),(0,a.kt)(o.Z,{mdxType:"Tabs"},(0,a.kt)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"))),(0,a.kt)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"))),(0,a.kt)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n")))),(0,a.kt)("h3",{id:"http-\uc218\uc5c5"},"HTTP \uc218\uc5c5"),(0,a.kt)("p",null,"\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yml"},"server:\n compression:\n enabled: true\n")),(0,a.kt)("p",null,"\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/spring-projects/spring-boot/issues/21369"},"issue"),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. "),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.")),(0,a.kt)("p",null,"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("admonition",{title:"ETag",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","MDN")),(0,a.kt)("h3",{id:"thread-\uc218\uc5c5"},"Thread \uc218\uc5c5"),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"threads.max"),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"max-connections"),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"accept-count"),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. "),(0,a.kt)("mermaid",{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),(0,a.kt)("h3",{id:"\ub9c8\uce58\uba70"},"\ub9c8\uce58\uba70"),(0,a.kt)("p",null,"\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag"},"ETag, mdn"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html"},"Apache Tomcat 8 Configuration Reference"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://bcho.tistory.com/788"},"Apache Tomcat Tuning, Terry Cho"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://dev-ws.tistory.com/96"},"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/905ecccc.806a92d0.js b/assets/js/905ecccc.806a92d0.js deleted file mode 100644 index 94096a9ef..000000000 --- a/assets/js/905ecccc.806a92d0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2939],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var u=r.createContext({}),c=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=c(e.components);return r.createElement(u.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,g=m["".concat(u,".").concat(d)]||m[d]||p[d]||o;return n?r.createElement(g,i(i({ref:t},s),{},{components:n})):r.createElement(g,i({ref:t},s))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c{n.d(t,{Z:()=>i});var r=n(67294),a=n(86010);const o="tabItem_Ymn6";function i(e){let{children:t,hidden:n,className:i}=e;return r.createElement("div",{role:"tabpanel",className:(0,a.Z)(o,i),hidden:n},t)}},74866:(e,t,n)=>{n.d(t,{Z:()=>S});var r=n(87462),a=n(67294),o=n(86010),i=n(12466),l=n(16550),u=n(91980),c=n(67392),s=n(50012);function p(e){return function(e){return a.Children.map(e,(e=>{if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))}(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:a}}=e;return{value:t,label:n,attributes:r,default:a}}))}function m(e){const{values:t,children:n}=e;return(0,a.useMemo)((()=>{const e=t??p(n);return function(e){const t=(0,c.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function d(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function g(e){let{queryString:t=!1,groupId:n}=e;const r=(0,l.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,u._X)(o),(0,a.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(r.location.search);t.set(o,e),r.replace({...r.location,search:t.toString()})}),[o,r])]}function k(e){const{defaultValue:t,queryString:n=!1,groupId:r}=e,o=m(e),[i,l]=(0,a.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!d({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=n.find((e=>e.default))??n[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:o}))),[u,c]=g({queryString:n,groupId:r}),[p,k]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,o]=(0,s.Nk)(n);return[r,(0,a.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:r}),f=(()=>{const e=u??p;return d({value:e,tabValues:o})?e:null})();(0,a.useEffect)((()=>{f&&l(f)}),[f]);return{selectedValue:i,selectValue:(0,a.useCallback)((e=>{if(!d({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),c(e),k(e)}),[c,k,o]),tabValues:o}}var f=n(72389);const b="tabList__CuJ",h="tabItem_LNqP";function N(e){let{className:t,block:n,selectedValue:l,selectValue:u,tabValues:c}=e;const s=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),m=e=>{const t=e.currentTarget,n=s.indexOf(t),r=c[n].value;r!==l&&(p(t),u(r))},d=e=>{let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{const n=s.indexOf(e.currentTarget)+1;t=s[n]??s[0];break}case"ArrowLeft":{const n=s.indexOf(e.currentTarget)-1;t=s[n]??s[s.length-1];break}}t?.focus()};return a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},c.map((e=>{let{value:t,label:n,attributes:i}=e;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:l===t?0:-1,"aria-selected":l===t,key:t,ref:e=>s.push(e),onKeyDown:d,onClick:m},i,{className:(0,o.Z)("tabs__item",h,i?.className,{"tabs__item--active":l===t})}),n??t)})))}function v(e){let{lazy:t,children:n,selectedValue:r}=e;if(t){const e=n.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return a.createElement("div",{className:"margin-top--md"},n.map(((e,t)=>(0,a.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function C(e){const t=k(e);return a.createElement("div",{className:(0,o.Z)("tabs-container",b)},a.createElement(N,(0,r.Z)({},e,t)),a.createElement(v,(0,r.Z)({},e,t)))}function S(e){const t=(0,f.Z)();return a.createElement(C,(0,r.Z)({key:String(t)},e))}},1057:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>u,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>p});var r=n(87462),a=(n(67294),n(3905)),o=n(74866),i=n(85162);const l={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},u=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"\ud1b0\ucea3 \uad6c\ud604",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.27,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",permalink:"/async-exception"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},s={authorsImageUrls:[]},p=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],m={toc:p};function d(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ud1b0\ucea3-\uad6c\ud604"},"\ud1b0\ucea3 \uad6c\ud604"),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. "),(0,a.kt)("p",null,"\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. "),(0,a.kt)("h3",{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"},"\ub2e4\uc774\uc5b4\uadf8\ub7a8"),(0,a.kt)("p",null,"Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. "),(0,a.kt)("mermaid",{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),(0,a.kt)("h3",{id:"\ucf54\ub4dc-\ub9ac\ubdf0"},"\ucf54\ub4dc \ub9ac\ubdf0"),(0,a.kt)("p",null,"\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"sessionconfig"},"SessionConfig"),(0,a.kt)("p",null,"\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/apache/tomcat/pull/660"},"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. "),(0,a.kt)("p",null,"\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. "),(0,a.kt)("p",null,"\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. "),(0,a.kt)(o.Z,{mdxType:"Tabs"},(0,a.kt)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"))),(0,a.kt)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"))),(0,a.kt)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n")))),(0,a.kt)("h3",{id:"http-\uc218\uc5c5"},"HTTP \uc218\uc5c5"),(0,a.kt)("p",null,"\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yml"},"server:\n compression:\n enabled: true\n")),(0,a.kt)("p",null,"\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/spring-projects/spring-boot/issues/21369"},"issue"),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. "),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.")),(0,a.kt)("p",null,"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("admonition",{title:"ETag",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","MDN")),(0,a.kt)("h3",{id:"thread-\uc218\uc5c5"},"Thread \uc218\uc5c5"),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"threads.max"),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"max-connections"),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"accept-count"),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. "),(0,a.kt)("mermaid",{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),(0,a.kt)("h3",{id:"\ub9c8\uce58\uba70"},"\ub9c8\uce58\uba70"),(0,a.kt)("p",null,"\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag"},"ETag, mdn"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html"},"Apache Tomcat 8 Configuration Reference"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://bcho.tistory.com/788"},"Apache Tomcat Tuning, Terry Cho"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://dev-ws.tistory.com/96"},"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/981f7647.3ede4ce8.js b/assets/js/981f7647.43a0ab0d.js similarity index 97% rename from assets/js/981f7647.3ede4ce8.js rename to assets/js/981f7647.43a0ab0d.js index 02c55cc97..905b4c536 100644 --- a/assets/js/981f7647.3ede4ce8.js +++ b/assets/js/981f7647.43a0ab0d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2947],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>f});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=p(r),f=a,g=d["".concat(c,".").concat(f)]||d[f]||s[f]||o;return r?n.createElement(g,l(l({ref:t},u),{},{components:r})):n.createElement(g,l({ref:t},u))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,l=new Array(o);l[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>s,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var n=r(87462),a=(r(67294),r(3905));const o={title:"\ud328\ud0a4\uc9c0",slug:"/design/package",tags:["package"]},l=void 0,i={unversionedId:"\uc124\uacc4/\ud328\ud0a4\uc9c0",id:"\uc124\uacc4/\ud328\ud0a4\uc9c0",title:"\ud328\ud0a4\uc9c0",description:"\uacc4\uce35 \uae30\ubc18 \ud328\ud0a4\uc9c0",source:"@site/docs/\uc124\uacc4/\ud328\ud0a4\uc9c0.mdx",sourceDirName:"\uc124\uacc4",slug:"/design/package",permalink:"/docs/design/package",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc124\uacc4/\ud328\ud0a4\uc9c0.mdx",tags:[{label:"package",permalink:"/docs/tags/package"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ud328\ud0a4\uc9c0",slug:"/design/package",tags:["package"]},sidebar:"tutorialSidebar",previous:{title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",permalink:"/docs/culture/postmortem"},next:{title:"Throughput \ubaa9\ud46f\uac12",permalink:"/docs/performance/throughput"}},c={},p=[{value:"\uacc4\uce35 \uae30\ubc18 \ud328\ud0a4\uc9c0",id:"\uacc4\uce35-\uae30\ubc18-\ud328\ud0a4\uc9c0",level:3},{value:"\uae30\ub2a5 \uae30\ubc18 \ud328\ud0a4\uc9c0",id:"\uae30\ub2a5-\uae30\ubc18-\ud328\ud0a4\uc9c0",level:3},{value:"\ud3ec\ud2b8\uc640 \uc5b4\ub311\ud130",id:"\ud3ec\ud2b8\uc640-\uc5b4\ub311\ud130",level:3},{value:"\ucef4\ud3ec\ub10c\ud2b8 \uae30\ubc18 \ud328\ud0a4\uc9c0",id:"\ucef4\ud3ec\ub10c\ud2b8-\uae30\ubc18-\ud328\ud0a4\uc9c0",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:p};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uacc4\uce35-\uae30\ubc18-\ud328\ud0a4\uc9c0"},"\uacc4\uce35 \uae30\ubc18 \ud328\ud0a4\uc9c0"),(0,a.kt)("p",null,"\uc804\ud1b5\uc801\uc778 \uc218\ud3c9 \uacc4\uce35\ud615 \uc544\ud0a4\ud14d\ucc98",(0,a.kt)("br",{parentName:"p"}),"\n","\uae30\uc220\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ud574\ub2f9 \ucf54\ub4dc\uac00 \ud558\ub294 \uc77c\uc5d0 \uae30\ubc18\ud574 \ucf54\ub4dc\ub97c \ubd84\ud560"),(0,a.kt)("h3",{id:"\uae30\ub2a5-\uae30\ubc18-\ud328\ud0a4\uc9c0"},"\uae30\ub2a5 \uae30\ubc18 \ud328\ud0a4\uc9c0"),(0,a.kt)("p",null,"\uc11c\ub85c \uc5f0\uad00\ub41c \uae30\ub2a5, \ub3c4\uba54\uc778 \uac1c\ub150, \ub610\ub294 Aggregate Root\uc5d0 \uae30\ubc18\ud558\uc5ec \uc218\uc9c1\uc758 \uc587\uc740 \uc870\uac01\uc73c\ub85c \ucf54\ub4dc\ub97c \ub098\ub204\ub294 \ubc29\uc2dd"),(0,a.kt)("h3",{id:"\ud3ec\ud2b8\uc640-\uc5b4\ub311\ud130"},"\ud3ec\ud2b8\uc640 \uc5b4\ub311\ud130"),(0,a.kt)("p",null,"\uc5c5\ubb34/\ub3c4\uba54\uc778\uc5d0 \ucd08\uc810\uc744 \ub454 \ucf54\ub4dc\uac00 \ud504\ub808\uc784\uc6cc\ud06c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac19\uc740 \uae30\uc220\uc801\uc778 \uc138\ubd80 \uad6c\ud604\uacfc \ub3c5\ub9bd\uc801\uc774\uba70 \ubd84\ub9ac\ub41c \uc544\ud0a4\ud14d\ucc98\ub97c \ub9cc\ub4e4\uae30 \uc704\ud574 \uc0ac\uc6a9"),(0,a.kt)("h3",{id:"\ucef4\ud3ec\ub10c\ud2b8-\uae30\ubc18-\ud328\ud0a4\uc9c0"},"\ucef4\ud3ec\ub10c\ud2b8 \uae30\ubc18 \ud328\ud0a4\uc9c0"),(0,a.kt)("p",null,"\ud070 \ub2e8\uc704\uc758 \ub2e8\uc77c \ucef4\ud3ec\ub10c\ud2b8\uc640 \uad00\ub828\ub41c \ubaa8\ub4e0 \ucc45\uc784\uc744 \ud558\ub098\uc758 \uc790\ubc14 \ud328\ud0a4\uc9c0\ub85c \ubb36\ub294 \ub370 \uc8fc\uc548\uc810\uc744 \ub460",(0,a.kt)("br",{parentName:"p"}),"\n","\ubaa8\ub178\ub9ac\ud2f1 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \ucef4\ud3ec\ub10c\ud2b8\ub97c \uc798 \uc815\uc758\ud558\uba74 MSA\ub85c \uac00\uae30 \uc704\ud55c \ubc1c\ud310\uc73c\ub85c \uc0bc\uc744 \uc218 \uc788\uc74c"),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 p.316"))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2947],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>f});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=p(r),f=a,g=d["".concat(c,".").concat(f)]||d[f]||s[f]||o;return r?n.createElement(g,l(l({ref:t},u),{},{components:r})):n.createElement(g,l({ref:t},u))}));function f(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,l=new Array(o);l[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>s,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var n=r(87462),a=(r(67294),r(3905));const o={title:"\ud328\ud0a4\uc9c0",slug:"/design/package",tags:["package"]},l=void 0,i={unversionedId:"\uc124\uacc4/\ud328\ud0a4\uc9c0",id:"\uc124\uacc4/\ud328\ud0a4\uc9c0",title:"\ud328\ud0a4\uc9c0",description:"\uacc4\uce35 \uae30\ubc18 \ud328\ud0a4\uc9c0",source:"@site/docs/\uc124\uacc4/\ud328\ud0a4\uc9c0.mdx",sourceDirName:"\uc124\uacc4",slug:"/design/package",permalink:"/docs/design/package",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc124\uacc4/\ud328\ud0a4\uc9c0.mdx",tags:[{label:"package",permalink:"/docs/tags/package"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ud328\ud0a4\uc9c0",slug:"/design/package",tags:["package"]},sidebar:"tutorialSidebar",previous:{title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",permalink:"/docs/culture/postmortem"},next:{title:"Throughput \ubaa9\ud46f\uac12",permalink:"/docs/performance/throughput"}},c={},p=[{value:"\uacc4\uce35 \uae30\ubc18 \ud328\ud0a4\uc9c0",id:"\uacc4\uce35-\uae30\ubc18-\ud328\ud0a4\uc9c0",level:3},{value:"\uae30\ub2a5 \uae30\ubc18 \ud328\ud0a4\uc9c0",id:"\uae30\ub2a5-\uae30\ubc18-\ud328\ud0a4\uc9c0",level:3},{value:"\ud3ec\ud2b8\uc640 \uc5b4\ub311\ud130",id:"\ud3ec\ud2b8\uc640-\uc5b4\ub311\ud130",level:3},{value:"\ucef4\ud3ec\ub10c\ud2b8 \uae30\ubc18 \ud328\ud0a4\uc9c0",id:"\ucef4\ud3ec\ub10c\ud2b8-\uae30\ubc18-\ud328\ud0a4\uc9c0",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:p};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uacc4\uce35-\uae30\ubc18-\ud328\ud0a4\uc9c0"},"\uacc4\uce35 \uae30\ubc18 \ud328\ud0a4\uc9c0"),(0,a.kt)("p",null,"\uc804\ud1b5\uc801\uc778 \uc218\ud3c9 \uacc4\uce35\ud615 \uc544\ud0a4\ud14d\ucc98",(0,a.kt)("br",{parentName:"p"}),"\n","\uae30\uc220\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ud574\ub2f9 \ucf54\ub4dc\uac00 \ud558\ub294 \uc77c\uc5d0 \uae30\ubc18\ud574 \ucf54\ub4dc\ub97c \ubd84\ud560"),(0,a.kt)("h3",{id:"\uae30\ub2a5-\uae30\ubc18-\ud328\ud0a4\uc9c0"},"\uae30\ub2a5 \uae30\ubc18 \ud328\ud0a4\uc9c0"),(0,a.kt)("p",null,"\uc11c\ub85c \uc5f0\uad00\ub41c \uae30\ub2a5, \ub3c4\uba54\uc778 \uac1c\ub150, \ub610\ub294 Aggregate Root\uc5d0 \uae30\ubc18\ud558\uc5ec \uc218\uc9c1\uc758 \uc587\uc740 \uc870\uac01\uc73c\ub85c \ucf54\ub4dc\ub97c \ub098\ub204\ub294 \ubc29\uc2dd"),(0,a.kt)("h3",{id:"\ud3ec\ud2b8\uc640-\uc5b4\ub311\ud130"},"\ud3ec\ud2b8\uc640 \uc5b4\ub311\ud130"),(0,a.kt)("p",null,"\uc5c5\ubb34/\ub3c4\uba54\uc778\uc5d0 \ucd08\uc810\uc744 \ub454 \ucf54\ub4dc\uac00 \ud504\ub808\uc784\uc6cc\ud06c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac19\uc740 \uae30\uc220\uc801\uc778 \uc138\ubd80 \uad6c\ud604\uacfc \ub3c5\ub9bd\uc801\uc774\uba70 \ubd84\ub9ac\ub41c \uc544\ud0a4\ud14d\ucc98\ub97c \ub9cc\ub4e4\uae30 \uc704\ud574 \uc0ac\uc6a9"),(0,a.kt)("h3",{id:"\ucef4\ud3ec\ub10c\ud2b8-\uae30\ubc18-\ud328\ud0a4\uc9c0"},"\ucef4\ud3ec\ub10c\ud2b8 \uae30\ubc18 \ud328\ud0a4\uc9c0"),(0,a.kt)("p",null,"\ud070 \ub2e8\uc704\uc758 \ub2e8\uc77c \ucef4\ud3ec\ub10c\ud2b8\uc640 \uad00\ub828\ub41c \ubaa8\ub4e0 \ucc45\uc784\uc744 \ud558\ub098\uc758 \uc790\ubc14 \ud328\ud0a4\uc9c0\ub85c \ubb36\ub294 \ub370 \uc8fc\uc548\uc810\uc744 \ub460",(0,a.kt)("br",{parentName:"p"}),"\n","\ubaa8\ub178\ub9ac\ud2f1 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \ucef4\ud3ec\ub10c\ud2b8\ub97c \uc798 \uc815\uc758\ud558\uba74 MSA\ub85c \uac00\uae30 \uc704\ud55c \ubc1c\ud310\uc73c\ub85c \uc0bc\uc744 \uc218 \uc788\uc74c"),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 p.316"))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9e477a5e.85b777bc.js b/assets/js/9e477a5e.8e1eb79d.js similarity index 98% rename from assets/js/9e477a5e.85b777bc.js rename to assets/js/9e477a5e.8e1eb79d.js index 04c2db9c8..fc452e4a8 100644 --- a/assets/js/9e477a5e.85b777bc.js +++ b/assets/js/9e477a5e.8e1eb79d.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8312],{3905:(e,t,r)=>{r.d(t,{Zo:()=>m,kt:()=>d});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),c=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},m=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,m=i(e,["components","mdxType","originalType","parentName"]),u=c(r),d=o,f=u["".concat(l,".").concat(d)]||u[d]||s[d]||a;return r?n.createElement(f,p(p({ref:t},m),{},{components:r})):n.createElement(f,p({ref:t},m))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,p=new Array(a);p[0]=u;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:o,p[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>p,default:()=>s,frontMatter:()=>a,metadata:()=>i,toc:()=>c});var n=r(87462),o=(r(67294),r(3905));const a={title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",slug:"/culture/postmortem",tags:["postmortem"]},p=void 0,i={unversionedId:"\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c",id:"\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c",title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",description:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c(Postmortem)",source:"@site/docs/\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c.mdx",sourceDirName:"\ubb38\ud654",slug:"/culture/postmortem",permalink:"/docs/culture/postmortem",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c.mdx",tags:[{label:"postmortem",permalink:"/docs/tags/postmortem"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",slug:"/culture/postmortem",tags:["postmortem"]},sidebar:"tutorialSidebar",previous:{title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/docs/monitoring/intro"},next:{title:"\ud328\ud0a4\uc9c0",permalink:"/docs/design/package"}},l={},c=[{value:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c(Postmortem)",id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15cpostmortem",level:3},{value:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c\uc5d0 \ub2f4\uaca8\uc57c \ud558\ub294 \ub0b4\uc6a9",id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15c\uc5d0-\ub2f4\uaca8\uc57c-\ud558\ub294-\ub0b4\uc6a9",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],m={toc:c};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},m,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15cpostmortem"},"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c(Postmortem)"),(0,o.kt)("p",null,"\uc2e4\ud328\ud55c \uadfc\ubcf8 \uc6d0\uc778\uc744 \ubd84\uc11d\ud558\uc5ec \ubb38\uc11c\ub85c \ub0a8\uae30\ub294 \uac83"),(0,o.kt)("h3",{id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15c\uc5d0-\ub2f4\uaca8\uc57c-\ud558\ub294-\ub0b4\uc6a9"},"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c\uc5d0 \ub2f4\uaca8\uc57c \ud558\ub294 \ub0b4\uc6a9"),(0,o.kt)("p",null,"\uc0ac\uac74\uc758 \uac1c\uc694",(0,o.kt)("br",{parentName:"p"}),"\n","\uc0ac\uac74\uc744 \uc778\uc9c0\ud558\uace0 \ud574\uacb0\uc5d0 \uc774\ub974\uae30\uae4c\uc9c0\uc758 \ud0c0\uc784\ub77c\uc778",(0,o.kt)("br",{parentName:"p"}),"\n","\uc0ac\uac74\uc758 \uadfc\ubcf8 \uc6d0\uc778",(0,o.kt)("br",{parentName:"p"}),"\n","\uc601\ud5a5\uacfc \ud53c\ud574 \ud3c9\uac00",(0,o.kt)("br",{parentName:"p"}),"\n","\ubb38\uc81c\ub97c \uc989\uc2dc \ud574\uacb0\ud558\uae30 \uc704\ud55c \uc870\uce58 \ud56d\ubaa9(\uc18c\uc720\uc790 \uba85\uc2dc)",(0,o.kt)("br",{parentName:"p"}),"\n","\uac1c\ubc1c \ubc29\uc9c0\ub97c \uc704\ud55c \uc870\uce58 \ud56d\ubaa9",(0,o.kt)("br",{parentName:"p"}),"\n","\ud574\ub2f9 \uacbd\ud5d8\uc5d0\uc11c \uc5bb\uc740 \uad50\ud6c8 "),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uad6c\uae00 \uc5d4\uc9c0\ub2c8\uc5b4\ub294 \uc774\ub807\uac8c \uc77c\ud55c\ub2e4, \ud0c0\uc774\ud130\uc2a4 \uc708\ud130\uc2a4, \ud1b0 \ub9e8\uc26c\ub809, \ud558\uc774\ub7fc \ub77c\uc774\ud2b8 p.86",(0,o.kt)("br",{parentName:"p"}),"\n",(0,o.kt)("a",{parentName:"p",href:"https://techblog.woowahan.com/4886/"},"\uc6b0\uc544\ud55c \uc7a5\uc560\ub300\uc751")))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8312],{3905:(e,t,r)=>{r.d(t,{Zo:()=>m,kt:()=>d});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),c=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},m=function(e){var t=c(e.components);return n.createElement(l.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,m=i(e,["components","mdxType","originalType","parentName"]),u=c(r),d=o,f=u["".concat(l,".").concat(d)]||u[d]||s[d]||a;return r?n.createElement(f,p(p({ref:t},m),{},{components:r})):n.createElement(f,p({ref:t},m))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,p=new Array(a);p[0]=u;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:o,p[1]=i;for(var c=2;c{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>p,default:()=>s,frontMatter:()=>a,metadata:()=>i,toc:()=>c});var n=r(87462),o=(r(67294),r(3905));const a={title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",slug:"/culture/postmortem",tags:["postmortem"]},p=void 0,i={unversionedId:"\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c",id:"\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c",title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",description:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c(Postmortem)",source:"@site/docs/\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c.mdx",sourceDirName:"\ubb38\ud654",slug:"/culture/postmortem",permalink:"/docs/culture/postmortem",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c.mdx",tags:[{label:"postmortem",permalink:"/docs/tags/postmortem"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c",slug:"/culture/postmortem",tags:["postmortem"]},sidebar:"tutorialSidebar",previous:{title:"\ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131",permalink:"/docs/monitoring/intro"},next:{title:"\ud328\ud0a4\uc9c0",permalink:"/docs/design/package"}},l={},c=[{value:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c(Postmortem)",id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15cpostmortem",level:3},{value:"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c\uc5d0 \ub2f4\uaca8\uc57c \ud558\ub294 \ub0b4\uc6a9",id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15c\uc5d0-\ub2f4\uaca8\uc57c-\ud558\ub294-\ub0b4\uc6a9",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],m={toc:c};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},m,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15cpostmortem"},"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c(Postmortem)"),(0,o.kt)("p",null,"\uc2e4\ud328\ud55c \uadfc\ubcf8 \uc6d0\uc778\uc744 \ubd84\uc11d\ud558\uc5ec \ubb38\uc11c\ub85c \ub0a8\uae30\ub294 \uac83"),(0,o.kt)("h3",{id:"\ud3ec\uc2a4\ud2b8-\ubaa8\ud15c\uc5d0-\ub2f4\uaca8\uc57c-\ud558\ub294-\ub0b4\uc6a9"},"\ud3ec\uc2a4\ud2b8 \ubaa8\ud15c\uc5d0 \ub2f4\uaca8\uc57c \ud558\ub294 \ub0b4\uc6a9"),(0,o.kt)("p",null,"\uc0ac\uac74\uc758 \uac1c\uc694",(0,o.kt)("br",{parentName:"p"}),"\n","\uc0ac\uac74\uc744 \uc778\uc9c0\ud558\uace0 \ud574\uacb0\uc5d0 \uc774\ub974\uae30\uae4c\uc9c0\uc758 \ud0c0\uc784\ub77c\uc778",(0,o.kt)("br",{parentName:"p"}),"\n","\uc0ac\uac74\uc758 \uadfc\ubcf8 \uc6d0\uc778",(0,o.kt)("br",{parentName:"p"}),"\n","\uc601\ud5a5\uacfc \ud53c\ud574 \ud3c9\uac00",(0,o.kt)("br",{parentName:"p"}),"\n","\ubb38\uc81c\ub97c \uc989\uc2dc \ud574\uacb0\ud558\uae30 \uc704\ud55c \uc870\uce58 \ud56d\ubaa9(\uc18c\uc720\uc790 \uba85\uc2dc)",(0,o.kt)("br",{parentName:"p"}),"\n","\uac1c\ubc1c \ubc29\uc9c0\ub97c \uc704\ud55c \uc870\uce58 \ud56d\ubaa9",(0,o.kt)("br",{parentName:"p"}),"\n","\ud574\ub2f9 \uacbd\ud5d8\uc5d0\uc11c \uc5bb\uc740 \uad50\ud6c8 "),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uad6c\uae00 \uc5d4\uc9c0\ub2c8\uc5b4\ub294 \uc774\ub807\uac8c \uc77c\ud55c\ub2e4, \ud0c0\uc774\ud130\uc2a4 \uc708\ud130\uc2a4, \ud1b0 \ub9e8\uc26c\ub809, \ud558\uc774\ub7fc \ub77c\uc774\ud2b8 p.86",(0,o.kt)("br",{parentName:"p"}),"\n",(0,o.kt)("a",{parentName:"p",href:"https://techblog.woowahan.com/4886/"},"\uc6b0\uc544\ud55c \uc7a5\uc560\ub300\uc751")))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a43f2942.90e79db4.js b/assets/js/a43f2942.66ee91f6.js similarity index 98% rename from assets/js/a43f2942.90e79db4.js rename to assets/js/a43f2942.66ee91f6.js index dd4f3bab7..255167b2e 100644 --- a/assets/js/a43f2942.90e79db4.js +++ b/assets/js/a43f2942.66ee91f6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[104],{3905:(e,t,r)=>{r.d(t,{Zo:()=>l,kt:()=>d});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},l=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,l=i(e,["components","mdxType","originalType","parentName"]),f=p(r),d=a,m=f["".concat(c,".").concat(d)]||f[d]||u[d]||o;return r?n.createElement(m,s(s({ref:t},l),{},{components:r})):n.createElement(m,s({ref:t},l))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,s=new Array(o);s[0]=f;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",slug:"/test/stairstep",tags:["test"]},s=void 0,i={unversionedId:"\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8",id:"\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8",title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",description:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8(Stairstep Test)",source:"@site/docs/\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/stairstep",permalink:"/docs/test/stairstep",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",slug:"/test/stairstep",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"FIRST",permalink:"/docs/test/first"},next:{title:"TDD heuristics",permalink:"/docs/test/heuristics"}},c={},p=[{value:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8(Stairstep Test)",id:"\uacc4\ub2e8-\ud14c\uc2a4\ud2b8stairstep-test",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],l={toc:p};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},l,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uacc4\ub2e8-\ud14c\uc2a4\ud2b8stairstep-test"},"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8(Stairstep Test)"),(0,a.kt)("p",null,"\ucd94\ud6c4\uc5d0 \ud544\uc694\ub85c \ud560 \ud074\ub798\uc2a4, \ud568\uc218, \ub2e4\ub978 \uad6c\uc870\ub97c \ub9cc\ub4e4\ub3c4\ub85d \uac15\uc81c\ud558\uae30 \uc704\ud574 \uc791\uc131\ud558\ub294 \ud14c\uc2a4\ud2b8",(0,a.kt)("br",{parentName:"p"}),"\n","\uc544\ubb34\ub7f0 \ub2e8\uc815\ubb38\uc774 \uc5c6\uc744 \uc218\ub3c4 \uc788\uace0, \uae30\ub2a5\uc774 \uc870\uae08 \ub354 \uad6c\ud604\ub41c\ub2e4\uba74 \uc81c\uac70\ud558\uace0 \ud3ec\uad04\uc801\uc778 \ud14c\uc2a4\ud2b8\ub85c \ub300\uc2e0\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ubcf5\uc7a1\ub3c4\ub97c \ud544\uc694\ud55c \uc218\uc900\uae4c\uc9c0 \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0ac \uc218 \uc788\uac8c \ub3c4\uc640\uc8fc\ub294 \uacc4\ub2e8 \uc5ed\ud560\uc744 \ud558\uae30 \ub54c\ubb38\uc5d0 \uacc4\ub2e8 \ud14c\uc2a4\ud2b8\ub77c\uace0 \ubd80\ub978\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 p.74"))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[104],{3905:(e,t,r)=>{r.d(t,{Zo:()=>l,kt:()=>d});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function s(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):s(s({},t),e)),r},l=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,l=i(e,["components","mdxType","originalType","parentName"]),f=p(r),d=a,m=f["".concat(c,".").concat(d)]||f[d]||u[d]||o;return r?n.createElement(m,s(s({ref:t},l),{},{components:r})):n.createElement(m,s({ref:t},l))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,s=new Array(o);s[0]=f;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",slug:"/test/stairstep",tags:["test"]},s=void 0,i={unversionedId:"\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8",id:"\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8",title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",description:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8(Stairstep Test)",source:"@site/docs/\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8.mdx",sourceDirName:"\ud14c\uc2a4\ud2b8",slug:"/test/stairstep",permalink:"/docs/test/stairstep",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8.mdx",tags:[{label:"test",permalink:"/docs/tags/test"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8",slug:"/test/stairstep",tags:["test"]},sidebar:"tutorialSidebar",previous:{title:"FIRST",permalink:"/docs/test/first"},next:{title:"TDD heuristics",permalink:"/docs/test/heuristics"}},c={},p=[{value:"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8(Stairstep Test)",id:"\uacc4\ub2e8-\ud14c\uc2a4\ud2b8stairstep-test",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],l={toc:p};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},l,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uacc4\ub2e8-\ud14c\uc2a4\ud2b8stairstep-test"},"\uacc4\ub2e8 \ud14c\uc2a4\ud2b8(Stairstep Test)"),(0,a.kt)("p",null,"\ucd94\ud6c4\uc5d0 \ud544\uc694\ub85c \ud560 \ud074\ub798\uc2a4, \ud568\uc218, \ub2e4\ub978 \uad6c\uc870\ub97c \ub9cc\ub4e4\ub3c4\ub85d \uac15\uc81c\ud558\uae30 \uc704\ud574 \uc791\uc131\ud558\ub294 \ud14c\uc2a4\ud2b8",(0,a.kt)("br",{parentName:"p"}),"\n","\uc544\ubb34\ub7f0 \ub2e8\uc815\ubb38\uc774 \uc5c6\uc744 \uc218\ub3c4 \uc788\uace0, \uae30\ub2a5\uc774 \uc870\uae08 \ub354 \uad6c\ud604\ub41c\ub2e4\uba74 \uc81c\uac70\ud558\uace0 \ud3ec\uad04\uc801\uc778 \ud14c\uc2a4\ud2b8\ub85c \ub300\uc2e0\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ubcf5\uc7a1\ub3c4\ub97c \ud544\uc694\ud55c \uc218\uc900\uae4c\uc9c0 \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0ac \uc218 \uc788\uac8c \ub3c4\uc640\uc8fc\ub294 \uacc4\ub2e8 \uc5ed\ud560\uc744 \ud558\uae30 \ub54c\ubb38\uc5d0 \uacc4\ub2e8 \ud14c\uc2a4\ud2b8\ub77c\uace0 \ubd80\ub978\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 p.74"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a710d533.a76e7019.js b/assets/js/a710d533.a76e7019.js deleted file mode 100644 index b9bf7ae54..000000000 --- a/assets/js/a710d533.a76e7019.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1711],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var u=r.createContext({}),c=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=c(e.components);return r.createElement(u.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,g=m["".concat(u,".").concat(d)]||m[d]||p[d]||o;return n?r.createElement(g,i(i({ref:t},s),{},{components:n})):r.createElement(g,i({ref:t},s))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c{n.d(t,{Z:()=>i});var r=n(67294),a=n(86010);const o="tabItem_Ymn6";function i(e){let{children:t,hidden:n,className:i}=e;return r.createElement("div",{role:"tabpanel",className:(0,a.Z)(o,i),hidden:n},t)}},74866:(e,t,n)=>{n.d(t,{Z:()=>S});var r=n(87462),a=n(67294),o=n(86010),i=n(12466),l=n(16550),u=n(91980),c=n(67392),s=n(50012);function p(e){return function(e){return a.Children.map(e,(e=>{if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))}(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:a}}=e;return{value:t,label:n,attributes:r,default:a}}))}function m(e){const{values:t,children:n}=e;return(0,a.useMemo)((()=>{const e=t??p(n);return function(e){const t=(0,c.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function d(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function g(e){let{queryString:t=!1,groupId:n}=e;const r=(0,l.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,u._X)(o),(0,a.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(r.location.search);t.set(o,e),r.replace({...r.location,search:t.toString()})}),[o,r])]}function k(e){const{defaultValue:t,queryString:n=!1,groupId:r}=e,o=m(e),[i,l]=(0,a.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!d({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=n.find((e=>e.default))??n[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:o}))),[u,c]=g({queryString:n,groupId:r}),[p,k]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,o]=(0,s.Nk)(n);return[r,(0,a.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:r}),f=(()=>{const e=u??p;return d({value:e,tabValues:o})?e:null})();(0,a.useEffect)((()=>{f&&l(f)}),[f]);return{selectedValue:i,selectValue:(0,a.useCallback)((e=>{if(!d({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),c(e),k(e)}),[c,k,o]),tabValues:o}}var f=n(72389);const b="tabList__CuJ",h="tabItem_LNqP";function N(e){let{className:t,block:n,selectedValue:l,selectValue:u,tabValues:c}=e;const s=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),m=e=>{const t=e.currentTarget,n=s.indexOf(t),r=c[n].value;r!==l&&(p(t),u(r))},d=e=>{let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{const n=s.indexOf(e.currentTarget)+1;t=s[n]??s[0];break}case"ArrowLeft":{const n=s.indexOf(e.currentTarget)-1;t=s[n]??s[s.length-1];break}}t?.focus()};return a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},c.map((e=>{let{value:t,label:n,attributes:i}=e;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:l===t?0:-1,"aria-selected":l===t,key:t,ref:e=>s.push(e),onKeyDown:d,onClick:m},i,{className:(0,o.Z)("tabs__item",h,i?.className,{"tabs__item--active":l===t})}),n??t)})))}function v(e){let{lazy:t,children:n,selectedValue:r}=e;if(t){const e=n.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return a.createElement("div",{className:"margin-top--md"},n.map(((e,t)=>(0,a.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function C(e){const t=k(e);return a.createElement("div",{className:(0,o.Z)("tabs-container",b)},a.createElement(N,(0,r.Z)({},e,t)),a.createElement(v,(0,r.Z)({},e,t)))}function S(e){const t=(0,f.Z)();return a.createElement(C,(0,r.Z)({key:String(t)},e))}},95220:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>u,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>p});var r=n(87462),a=(n(67294),n(3905)),o=n(74866),i=n(85162);const l={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},u=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"\ud1b0\ucea3 \uad6c\ud604",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.27,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",permalink:"/async-exception"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},s={authorsImageUrls:[]},p=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],m={toc:p};function d(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ud1b0\ucea3-\uad6c\ud604"},"\ud1b0\ucea3 \uad6c\ud604"),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. "),(0,a.kt)("p",null,"\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. "),(0,a.kt)("h3",{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"},"\ub2e4\uc774\uc5b4\uadf8\ub7a8"),(0,a.kt)("p",null,"Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. "),(0,a.kt)("mermaid",{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),(0,a.kt)("h3",{id:"\ucf54\ub4dc-\ub9ac\ubdf0"},"\ucf54\ub4dc \ub9ac\ubdf0"),(0,a.kt)("p",null,"\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"sessionconfig"},"SessionConfig"),(0,a.kt)("p",null,"\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/apache/tomcat/pull/660"},"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. "),(0,a.kt)("p",null,"\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. "),(0,a.kt)("p",null,"\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. "),(0,a.kt)(o.Z,{mdxType:"Tabs"},(0,a.kt)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"))),(0,a.kt)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"))),(0,a.kt)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n")))),(0,a.kt)("h3",{id:"http-\uc218\uc5c5"},"HTTP \uc218\uc5c5"),(0,a.kt)("p",null,"\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yml"},"server:\n compression:\n enabled: true\n")),(0,a.kt)("p",null,"\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/spring-projects/spring-boot/issues/21369"},"issue"),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. "),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.")),(0,a.kt)("p",null,"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("admonition",{title:"ETag",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","MDN")),(0,a.kt)("h3",{id:"thread-\uc218\uc5c5"},"Thread \uc218\uc5c5"),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"threads.max"),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"max-connections"),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"accept-count"),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. "),(0,a.kt)("mermaid",{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),(0,a.kt)("h3",{id:"\ub9c8\uce58\uba70"},"\ub9c8\uce58\uba70"),(0,a.kt)("p",null,"\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag"},"ETag, mdn"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html"},"Apache Tomcat 8 Configuration Reference"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://bcho.tistory.com/788"},"Apache Tomcat Tuning, Terry Cho"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://dev-ws.tistory.com/96"},"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a710d533.aeb54335.js b/assets/js/a710d533.aeb54335.js new file mode 100644 index 000000000..0885c4c4b --- /dev/null +++ b/assets/js/a710d533.aeb54335.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[1711],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var u=r.createContext({}),c=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=c(e.components);return r.createElement(u.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,u=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=c(n),d=a,g=m["".concat(u,".").concat(d)]||m[d]||p[d]||o;return n?r.createElement(g,i(i({ref:t},s),{},{components:n})):r.createElement(g,i({ref:t},s))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=m;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c{n.d(t,{Z:()=>i});var r=n(67294),a=n(86010);const o="tabItem_Ymn6";function i(e){let{children:t,hidden:n,className:i}=e;return r.createElement("div",{role:"tabpanel",className:(0,a.Z)(o,i),hidden:n},t)}},74866:(e,t,n)=>{n.d(t,{Z:()=>S});var r=n(87462),a=n(67294),o=n(86010),i=n(12466),l=n(16550),u=n(91980),c=n(67392),s=n(50012);function p(e){return function(e){return a.Children.map(e,(e=>{if((0,a.isValidElement)(e)&&"value"in e.props)return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))}(e).map((e=>{let{props:{value:t,label:n,attributes:r,default:a}}=e;return{value:t,label:n,attributes:r,default:a}}))}function m(e){const{values:t,children:n}=e;return(0,a.useMemo)((()=>{const e=t??p(n);return function(e){const t=(0,c.l)(e,((e,t)=>e.value===t.value));if(t.length>0)throw new Error(`Docusaurus error: Duplicate values "${t.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[t,n])}function d(e){let{value:t,tabValues:n}=e;return n.some((e=>e.value===t))}function g(e){let{queryString:t=!1,groupId:n}=e;const r=(0,l.k6)(),o=function(e){let{queryString:t=!1,groupId:n}=e;if("string"==typeof t)return t;if(!1===t)return null;if(!0===t&&!n)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return n??null}({queryString:t,groupId:n});return[(0,u._X)(o),(0,a.useCallback)((e=>{if(!o)return;const t=new URLSearchParams(r.location.search);t.set(o,e),r.replace({...r.location,search:t.toString()})}),[o,r])]}function k(e){const{defaultValue:t,queryString:n=!1,groupId:r}=e,o=m(e),[i,l]=(0,a.useState)((()=>function(e){let{defaultValue:t,tabValues:n}=e;if(0===n.length)throw new Error("Docusaurus error: the component requires at least one children component");if(t){if(!d({value:t,tabValues:n}))throw new Error(`Docusaurus error: The has a defaultValue "${t}" but none of its children has the corresponding value. Available values are: ${n.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return t}const r=n.find((e=>e.default))??n[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:t,tabValues:o}))),[u,c]=g({queryString:n,groupId:r}),[p,k]=function(e){let{groupId:t}=e;const n=function(e){return e?`docusaurus.tab.${e}`:null}(t),[r,o]=(0,s.Nk)(n);return[r,(0,a.useCallback)((e=>{n&&o.set(e)}),[n,o])]}({groupId:r}),f=(()=>{const e=u??p;return d({value:e,tabValues:o})?e:null})();(0,a.useEffect)((()=>{f&&l(f)}),[f]);return{selectedValue:i,selectValue:(0,a.useCallback)((e=>{if(!d({value:e,tabValues:o}))throw new Error(`Can't select invalid tab value=${e}`);l(e),c(e),k(e)}),[c,k,o]),tabValues:o}}var f=n(72389);const b="tabList__CuJ",h="tabItem_LNqP";function N(e){let{className:t,block:n,selectedValue:l,selectValue:u,tabValues:c}=e;const s=[],{blockElementScrollPositionUntilNextRender:p}=(0,i.o5)(),m=e=>{const t=e.currentTarget,n=s.indexOf(t),r=c[n].value;r!==l&&(p(t),u(r))},d=e=>{let t=null;switch(e.key){case"Enter":m(e);break;case"ArrowRight":{const n=s.indexOf(e.currentTarget)+1;t=s[n]??s[0];break}case"ArrowLeft":{const n=s.indexOf(e.currentTarget)-1;t=s[n]??s[s.length-1];break}}t?.focus()};return a.createElement("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.Z)("tabs",{"tabs--block":n},t)},c.map((e=>{let{value:t,label:n,attributes:i}=e;return a.createElement("li",(0,r.Z)({role:"tab",tabIndex:l===t?0:-1,"aria-selected":l===t,key:t,ref:e=>s.push(e),onKeyDown:d,onClick:m},i,{className:(0,o.Z)("tabs__item",h,i?.className,{"tabs__item--active":l===t})}),n??t)})))}function v(e){let{lazy:t,children:n,selectedValue:r}=e;if(t){const e=n.find((e=>e.props.value===r));return e?(0,a.cloneElement)(e,{className:"margin-top--md"}):null}return a.createElement("div",{className:"margin-top--md"},n.map(((e,t)=>(0,a.cloneElement)(e,{key:t,hidden:e.props.value!==r}))))}function C(e){const t=k(e);return a.createElement("div",{className:(0,o.Z)("tabs-container",b)},a.createElement(N,(0,r.Z)({},e,t)),a.createElement(v,(0,r.Z)({},e,t)))}function S(e){const t=(0,f.Z)();return a.createElement(C,(0,r.Z)({key:String(t)},e))}},95220:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>u,default:()=>d,frontMatter:()=>l,metadata:()=>c,toc:()=>p});var r=n(87462),a=(n(67294),n(3905)),o=n(74866),i=n(85162);const l={title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},u=void 0,c={permalink:"/tomcat-retrospective",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",source:"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",description:"\ud1b0\ucea3 \uad6c\ud604",date:"2023-09-11T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 11\uc77c",tags:[{label:"Woowahan Techcourse",permalink:"/tags/woowahan-techcourse"},{label:"Retrospective",permalink:"/tags/retrospective"}],readingTime:12.27,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",slug:"tomcat-retrospective",tags:["Woowahan Techcourse","Retrospective"]},prevItem:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",permalink:"/log-async-exception"},nextItem:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958",permalink:"/performance-test-type"}},s={authorsImageUrls:[]},p=[{value:"\ud1b0\ucea3 \uad6c\ud604",id:"\ud1b0\ucea3-\uad6c\ud604",level:3},{value:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8",level:3},{value:"\ucf54\ub4dc \ub9ac\ubdf0",id:"\ucf54\ub4dc-\ub9ac\ubdf0",level:3},{value:"SessionConfig",id:"sessionconfig",level:3},{value:"HTTP \uc218\uc5c5",id:"http-\uc218\uc5c5",level:3},{value:"Thread \uc218\uc5c5",id:"thread-\uc218\uc5c5",level:3},{value:"\ub9c8\uce58\uba70",id:"\ub9c8\uce58\uba70",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],m={toc:p};function d(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ud1b0\ucea3-\uad6c\ud604"},"\ud1b0\ucea3 \uad6c\ud604"),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. "),(0,a.kt)("p",null,"\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),"\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. "),(0,a.kt)("h3",{id:"\ub2e4\uc774\uc5b4\uadf8\ub7a8"},"\ub2e4\uc774\uc5b4\uadf8\ub7a8"),(0,a.kt)("p",null,"Catalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. "),(0,a.kt)("mermaid",{value:"graph LR\n\tsubgraph coyote\n\t\tHP[Http11Processor] --\x3e A\n\t\tHP --\x3e HttpRequestParser\n\t\tHP --\x3e HttpResponseGenerator\n\t\tA[Adapter]\n end\n\n subgraph catalina\n\t\tRA[RequestAdapter] -.-> A\n\t\tAC[AbstractController] -.-> C[Controller]\n\t\tStaticController -.-> AC\n\t\tSM[SessionManger] -.-> Manager\n\t\tTC[Tomcat] --\x3e RA\n\t\tRA --\x3e C\n\t\tRA --\x3e Manager\n\t\tRA --\x3e RM\n\t\tRM[RequestMapper] --\x3e C\n end\n\n subgraph jwp\n\t\tLC[LoginController] -.-> AC\n\t\tApplication --\x3e TC\n end\n"}),(0,a.kt)("h3",{id:"\ucf54\ub4dc-\ub9ac\ubdf0"},"\ucf54\ub4dc \ub9ac\ubdf0"),(0,a.kt)("p",null,"\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"sessionconfig"},"SessionConfig"),(0,a.kt)("p",null,"\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/apache/tomcat/pull/660"},"\ucee8\ud2b8\ub9ac\ubdf0\ud2b8"),"\ub97c \uc2dc\ub3c4\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. "),(0,a.kt)("p",null,"\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. "),(0,a.kt)("p",null,"\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. "),(0,a.kt)(o.Z,{mdxType:"Tabs"},(0,a.kt)(i.Z,{value:"\uae30\uc874",label:"\uae30\uc874",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_COOKIE_NAME;\n }\n\n return result;\n}\n\npublic static String getSessionUriParamName(Context context) {\n\n String result = getConfiguredSessionCookieName(context);\n\n if (result == null) {\n result = DEFAULT_SESSION_PARAMETER_NAME;\n }\n\n return result;\n}\n\nprivate static String getConfiguredSessionCookieName(Context context) {\n\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc =\n context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n\n return null;\n}\n"))),(0,a.kt)(i.Z,{value:"PR \uc694\uccad",label:"PR \uc694\uccad",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_COOKIE_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n if (context == null) {\n return DEFAULT_SESSION_PARAMETER_NAME;\n }\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n return defaultName;\n}\n"))),(0,a.kt)(i.Z,{value:"\ucd5c\uc885",label:"\ucd5c\uc885",mdxType:"TabItem"},(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},"public static String getSessionCookieName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\n}\n\npublic static String getSessionUriParamName(Context context) {\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\n}\n\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\n // Priority is:\n // 1. Cookie name defined in context\n // 2. Cookie name configured for app\n // 3. Default defined by spec\n if (context != null) {\n String cookieName = context.getSessionCookieName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\n cookieName = scc.getName();\n if (cookieName != null && cookieName.length() > 0) {\n return cookieName;\n }\n }\n return defaultName;\n}\n")))),(0,a.kt)("h3",{id:"http-\uc218\uc5c5"},"HTTP \uc218\uc5c5"),(0,a.kt)("p",null,"\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","HTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yml"},"server:\n compression:\n enabled: true\n")),(0,a.kt)("p",null,"\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/spring-projects/spring-boot/issues/21369"},"issue"),"\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. "),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},"If you're developing a public-facing application then it's probably likely gzip compression would be worthwhile. If, however, you're a microservice application and you're in a dataceter, you may well prefer to reduce CPU load because you know you'll only be talking to other microservices and you have a reliable gigabit network.")),(0,a.kt)("p",null,"Phil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. "),(0,a.kt)("admonition",{title:"ETag",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"ETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","MDN")),(0,a.kt)("h3",{id:"thread-\uc218\uc5c5"},"Thread \uc218\uc5c5"),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. "),(0,a.kt)("p",null,"\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"threads.max"),": Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"max-connections"),": Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"accept-count"),": \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. "),(0,a.kt)("mermaid",{value:'graph LR\n C("Client") -- request --\x3e ACQ("\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \n size = accept-count") --\x3e TCQ("Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\n size = max-connections") --\x3e TP("Thread Pool\n size = threads.max")'}),(0,a.kt)("h3",{id:"\ub9c8\uce58\uba70"},"\ub9c8\uce58\uba70"),(0,a.kt)("p",null,"\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://datatracker.ietf.org/doc/html/rfc2616/"},"RFC 2616"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag"},"ETag, mdn"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://tomcat.apache.org/tomcat-8.5-doc/config/http.html"},"Apache Tomcat 8 Configuration Reference"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://bcho.tistory.com/788"},"Apache Tomcat Tuning, Terry Cho"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://dev-ws.tistory.com/96"},"maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b2b675dd.ef4b1ef8.js b/assets/js/b2b675dd.ef4b1ef8.js new file mode 100644 index 000000000..74ab7354c --- /dev/null +++ b/assets/js/b2b675dd.ef4b1ef8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[533],{28017:n=>{n.exports=JSON.parse('{"blogPosts":[{"id":"log-async-exception","metadata":{"permalink":"/log-async-exception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","description":"\ubb38\uc81c \uc0c1\ud669","date":"2023-09-18T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 18\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"exception","permalink":"/tags/exception"}],"readingTime":3.195,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","slug":"log-async-exception","tags":["async","exception"]},"nextItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"}},"content":"### \ubb38\uc81c \uc0c1\ud669\\n\\n\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 `@Async`\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 `@ControllerAdvice` + `@ExceptionHandler`\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815\\n\\nSpring\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. \\n\\n```java title=AsyncExceptionHandler\\n@Slf4j\\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\\n\\n private static final String LOG_FORMAT = \\"[%s] %s\\";\\n\\n @Override\\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\\n }\\n}\\n```\\n\\nAsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. \\ngetAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n```java title=AsyncConfig\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc774\uc81c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544\uc11c \ucc98\ub9ac\ub97c \ud574\uc900\ub2e4. \\n\\n### MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c\\n\\n\ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc740 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4. \ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc5c8\ub2e4. \\n\\n![./mdc-null.png](./mdc-null.png)\\n\\nSpring 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 [TaskDecorator](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html)\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n```java title=MdcTaskDecorator\\npublic class MdcTaskDecorator implements TaskDecorator {\\n\\n @Override\\n public Runnable decorate(final Runnable runnable) {\\n Map threadContext = MDC.getCopyOfContextMap();\\n return () -> {\\n MDC.setContextMap(threadContext);\\n runnable.run();\\n };\\n }\\n}\\n```\\n\\n\ud574\ub2f9 Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4.\\n\\n```java title=AsyncConfig\\n@RequiredArgsConstructor\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n private final AsyncConfigurationProperties properties;\\n\\n @Bean\\n public ThreadPoolTaskExecutor taskExecutor() {\\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\\n executor.setCorePoolSize(properties.coreSize());\\n executor.setMaxPoolSize(properties.maxSize());\\n executor.setQueueCapacity(properties.queueCapacity());\\n \\n // highlight-next-line\\n executor.setTaskDecorator(new MdcTaskDecorator());\\n executor.setWaitForTasksToCompleteOnShutdown(true);\\n executor.initialize();\\n return executor;\\n }\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4.\\n\\n![./mdc-not-null.png](./mdc-not-null.png)\\n\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[spring async, baeldung](https://www.baeldung.com/spring-async) \\n[@Async will not call by @ControllerAdvice for global exception](https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception) \\n[Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8](https://blog.gangnamunni.com/post/mdc-context-task-decorator/) \\n[TaskDecorator, Spring docs](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html)"},{"id":"tomcat-retrospective","metadata":{"permalink":"/tomcat-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"\ud1b0\ucea3 \uad6c\ud604","date":"2023-09-11T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":12.27,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"tomcat-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45","permalink":"/log-async-exception"},"nextItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"}},"content":"### \ud1b0\ucea3 \uad6c\ud604\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4. \\n\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. \\n\\n\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/)\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. \\n\\n### \ub2e4\uc774\uc5b4\uadf8\ub7a8\\n\\nCatalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4. \\n\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4. \\n\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph coyote\\n\\t\\tHP[Http11Processor] --\x3e A\\n\\t\\tHP --\x3e HttpRequestParser\\n\\t\\tHP --\x3e HttpResponseGenerator\\n\\t\\tA[Adapter]\\n end\\n\\n subgraph catalina\\n\\t\\tRA[RequestAdapter] -.-> A\\n\\t\\tAC[AbstractController] -.-> C[Controller]\\n\\t\\tStaticController -.-> AC\\n\\t\\tSM[SessionManger] -.-> Manager\\n\\t\\tTC[Tomcat] --\x3e RA\\n\\t\\tRA --\x3e C\\n\\t\\tRA --\x3e Manager\\n\\t\\tRA --\x3e RM\\n\\t\\tRM[RequestMapper] --\x3e C\\n end\\n\\n subgraph jwp\\n\\t\\tLC[LoginController] -.-> AC\\n\\t\\tApplication --\x3e TC\\n end\\n\\n```\\n\\n### \ucf54\ub4dc \ub9ac\ubdf0 \\n\\n\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4. \\n\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. \\n\\n\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4. \\n\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### SessionConfig\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 [\ucee8\ud2b8\ub9ac\ubdf0\ud2b8](https://github.com/apache/tomcat/pull/660)\ub97c \uc2dc\ub3c4\ud588\ub2e4. \\n\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4. \\n\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. \\n\\n\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4. \\n\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4. \\n\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_COOKIE_NAME;\\n }\\n\\n return result;\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n\\n return result;\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context) {\\n\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc =\\n context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n\\n return null;\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_COOKIE_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n### HTTP \uc218\uc5c5\\n\\n\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4. \\nHTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```yml\\nserver:\\n compression:\\n enabled: true\\n```\\n\\n\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4. \\n\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 [issue](https://github.com/spring-projects/spring-boot/issues/21369)\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4. \\n\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. \\n\\n> If you\'re developing a public-facing application then it\'s probably likely gzip compression would be worthwhile. If, however, you\'re a microservice application and you\'re in a dataceter, you may well prefer to reduce CPU load because you know you\'ll only be talking to other microservices and you have a reliable gigabit network.\\n\\nPhil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. \\n\\n\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. \\n\\n:::note ETag\\nETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4. \\n\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4. \\nMDN\\n:::\\n\\n### Thread \uc218\uc5c5\\n\\n\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4. \\n\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4. \\n\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n`threads.max`: Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218 \\n`max-connections`: Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218 \\n`accept-count`: \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n C(\\"Client\\") -- request --\x3e ACQ(\\"\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \\n size = accept-count\\") --\x3e TCQ(\\"Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\\n size = max-connections\\") --\x3e TP(\\"Thread Pool\\n size = threads.max\\")\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4. \\n\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/) \\n[ETag, mdn](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag) \\n[Apache Tomcat 8 Configuration Reference](https://tomcat.apache.org/tomcat-8.5-doc/config/http.html) \\n[Apache Tomcat Tuning, Terry Cho](https://bcho.tistory.com/788) \\n[maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30](https://dev-ws.tistory.com/96)"},{"id":"performance-test-type","metadata":{"permalink":"/performance-test-type","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","source":"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","description":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8","date":"2023-09-10T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 10\uc77c","tags":[{"label":"performance test","permalink":"/tags/performance-test"}],"readingTime":5.8,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","slug":"performance-test-type","tags":["performance test"]},"prevItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"},"nextItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"}},"content":"## \uc131\ub2a5 \ud14c\uc2a4\ud2b8\\n\\nAPI\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4. \\n\\n![./test.png](./test.png)\\n\\n### \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)\\n\\n\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\nVU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)\\n\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4. \\n\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4. \\n:::\\n\\n### \uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)\\n\\n\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4. \\n\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)\\n\\n\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ub7a8\ud504 \uc5c5(Ramp-up)\\n\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04\\n:::\\n\\n### \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test) \\n\\n\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4. \\n\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4. \\n\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\\n### \ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test) \\n\\n\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4. \\n\\n### \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)\\n\\n\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Load test types, k6](https://k6.io/docs/test-types/load-test-types/) \\n\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc \\n\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"},{"id":"db-replication","metadata":{"permalink":"/db-replication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","source":"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","description":"\ubcf5\uc81c(Replication)","date":"2023-08-22T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 22\uc77c","tags":[{"label":"mysql","permalink":"/tags/mysql"},{"label":"replication","permalink":"/tags/replication"}],"readingTime":20.58,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","slug":"db-replication","tags":["mysql","replication"]},"prevItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"}},"content":"## \ubcf5\uc81c(Replication)\\n\\n\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4. \\n\\n### \ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720\\n\\n**1. \uc2a4\ucf00\uc77c \uc544\uc6c3**\\n\\n\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4. \\n\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\\n**2. \ub370\uc774\ud130 \ubc31\uc5c5**\\n\\n\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4. \\n\\n**3. \ub370\uc774\ud130 \ubd84\uc11d**\\n\\n\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n**4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0**\\n\\n\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c\\n\\nMySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4. \\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4. \\nMySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph Replica\\n\\t\\tdirection TB\\n\\t\\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\\n\\t\\tSQL[Replication SQL Thread] -- read --\x3e RL\\n\\tend\\n\\n\\tsubgraph Source\\n\\t\\tdirection TB\\n\\t\\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\\n\\tend\\n\\n```\\n\\n:::note \uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560\\n\\nBinary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec \\nReplication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5 \\nReplication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589\\n\\n:::\\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810\\n\\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4. \\n\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4.\\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300] --\x3e B[B Binary-log:300]\\n\\tA[A binary-log:300] --\x3e C[C Binary-log:200]\\n```\\n\\n\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300]\\n\\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]\\n```\\n\\nA \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c\\n\\nGTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4. \\n\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4. \\n\\n:::note GTID\\n\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12 \\n[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4. \\n:::\\n\\n### \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\\n\\n**\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\nreplica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R\\n S[Source] --\x3e R[Replica]\\n```\\n\\n**\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\n\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4. \\n\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n```\\n\\n**\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131**\\n\\nreplica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c 1:M:M \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n S --\x3e R3[Replica3]\\n\\n R3 --\x3e R3-1[Replica 3-1]\\n R3 --\x3e R3-2[Replica 3-2]\\n\\n B[Batch Server] --\x3e R3-2\\n```\\n\\n**\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4. \\n\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]\\n```\\n\\n:::note ACTIVE-ACTIVE, ACTIVE-PASSIVE\\nACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc \\nACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc\\n:::\\n\\n**\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n S1[Source 1] --\x3e R[Replica]\\n S2[Source 2] --\x3e R\\n```\\n\\n## \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30\\n\\nmysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4. \\n[https://github.com/bbiac/db-replication](https://github.com/bbiac/db-replication) \\n\\n### MySQL \ud658\uacbd \uad6c\uc131\\n\\nMySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4. \\n\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4. \\n\\n```yml\\nversion: \'3.8\'\\n\\nservices:\\n source:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-source\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13306:3306\\"\\n volumes:\\n - db-source:/var/lib/mysql\\n - db-source:/var/lib/mysql-files\\n - ./docker/source.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\n replica:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-replica\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13307:3306\\"\\n volumes:\\n - db-replica:/var/lib/mysql\\n - db-replica:/var/lib/mysql-files\\n - ./docker/replica.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\nvolumes:\\n db-source:\\n db-replica:\\n\\nnetworks:\\n mysql_network:\\n driver: bridge\\n```\\n\\n\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4. \\n\\n| \uc124\uc815 | \uc124\uba85 |\\n| --- | --- |\\n| server_id | \uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. |\\n| log_bin | \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4. |\\n| sync_binlog | N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4. |\\n| relay_log | \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815 |\\n| relay_log_purge | \ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158 |\\n| read_only | \uc77d\uae30 \uc804\uc6a9 \uc124\uc815 |\\n| log_replica_updates | Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. |\\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```cnf title=\\"/docker/source.cnf\\"\\n[mysqld]\\nserver_id=1\\nlog_bin=mysql-bin\\nsync_binlog=1\\n```\\n\\n\\n\\n\\n\\n```cnf title=\\"/docker/replica.cnf\\"\\n[mysqld]\\nserver_id=2\\nrelay_log=mysql-relay-bin\\nrelay_log_purge=ON\\nread_only\\nlog_replica_updates\\n```\\n\\n\\n\\n\\n### \ub3c4\ucee4 \uc2e4\ud589\\n\\ndocker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4. \\n-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4. \\n\\n```\\ndocker-compose up -d\\n```\\n\\n### replication slave \uad8c\ud55c \uc124\uc815\\n\\nREPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4. \\nsource \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4. \\n\\nSOURCE \uc811\uc18d\\n\\n```bash\\ndocker exec -it mysql-source mysql -u root -p\\n```\\n\\nuser \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00\\n\\n```mysql\\nGRANT REPLICATION SLAVE ON *.* TO \'user\'@\'%\';\\nFLUSH PRIVILEGES;\\n```\\n\\n### SOURCE DB \uc815\ubcf4 \ud655\uc778\\n\\nreplica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4. \\nPosition \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4. \\n\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```mysql\\nSHOW MASTER STATUS;\\n\\n+------------------+----------+--------------+------------------+-------------------+\\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\\n+------------------+----------+--------------+------------------+-------------------+\\n| mysql-bin.000003 | 1082 | | | |\\n+------------------+----------+--------------+------------------+-------------------+\\n```\\n\\n### SOURCE ip \uc8fc\uc18c \ud655\uc778\\n\\ndocker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4. \\n\\n```bash\\ndocker inspect -f \\"{{with index .NetworkSettings.Networks \\\\\\"db-replication_mysql_network\\\\\\"}}{{.IPAddress}}{{end}}\\" mysql-source\\n```\\n\\nip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4. \\n\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n### replica mysql \uc811\uc18d\\n\\nsource db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4. \\n\\n```bash\\ndocker exec -it mysql-replica mysql -u root -p\\n```\\n\\n### replica \uc124\uc815\\n\\n\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4. \\n\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4. \\nSOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4.\\n\\n```mysql\\nSTOP REPLICA;\\n\\nCHANGE REPLICATION SOURCE TO \\nSOURCE_HOST=\'172.29.0.2\', \\nSOURCE_USER=\'user\', \\nSOURCE_PASSWORD=\'password\', \\nSOURCE_LOG_FILE=\'mysql-bin.000001\', \\nSOURCE_LOG_POS=0, \\nGET_SOURCE_PUBLIC_KEY=1;\\n\\nSTART REPLICA;\\n```\\n\\n### \uc124\uc815 \ud655\uc778\\n\\n```mysql\\nSHOW REPLICA STATUS;\\n\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n```\\n\\nReplica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4. \\n\\n\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4. \\nreplica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nCREATE TABLE member\\n(\\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\\n name VARCHAR(255)\\n);\\n```\\n\\n## \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30\\n\\n\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790. \\n\\n### Environment \uc124\uc815\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4. \\n\\n```yml title=\\"application.yml\\"\\nspring:\\n datasource:\\n source:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13306/db\\n replica:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13307/db\\n```\\n\\n### DataSourceType \uc124\uc815\\n\\n\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4. \\nKey\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```java title=\\"DataSourceType\\"\\npublic enum DataSourceType {\\n SOURCE(SOURCE_NAME),\\n REPLICA(REPLICA_NAME),\\n ;\\n\\n private final String key;\\n\\n DataSourceType(String key) {\\n this.key = key;\\n }\\n\\n public static class Key {\\n public static final String ROUTING_NAME = \\"ROUTING\\";\\n public static final String SOURCE_NAME = \\"SOURCE\\";\\n public static final String REPLICA_NAME = \\"REPLICA\\";\\n }\\n}\\n```\\n\\n### AbstractRoutingDataSource \uc124\uc815\\n\\n\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 Map\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4. \\n\\ndetermineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n- isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n- DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n```java title=\\"RoutingDataSource\\"\\npublic class RoutingDataSource extends AbstractRoutingDataSource {\\n\\n private final Logger log = LoggerFactory.getLogger(getClass());\\n\\n public static RoutingDataSource from(Map dataSources) {\\n RoutingDataSource routingDataSource = new RoutingDataSource();\\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\\n routingDataSource.setTargetDataSources(dataSources);\\n return routingDataSource;\\n }\\n\\n @Override\\n protected Object determineCurrentLookupKey() {\\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\\n\\n if (readOnly) {\\n log.info(\\"readOnly = true, request to replica\\");\\n return DataSourceType.REPLICA;\\n }\\n log.info(\\"readOnly = false, request to source\\");\\n return DataSourceType.SOURCE;\\n }\\n}\\n```\\n\\n### DataSource \uc124\uc815\\n\\n\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4. \\n\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4. \\n\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 setDefaultTargetDataSource\ub85c \uc124\uc815\ud55c source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4. \\nLazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\n```java title=\\"DataSourceConfiguration\\"\\n@Configuration\\npublic class DataSourceConfiguration {\\n\\n @Bean\\n @Qualifier(SOURCE_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.source\\")\\n public DataSource sourceDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(REPLICA_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.replica\\")\\n public DataSource replicaDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(ROUTING_NAME)\\n public DataSource routingDataSource(\\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\\n ) {\\n return RoutingDataSource.from(Map.of(\\n DataSourceType.SOURCE, sourceDataSource,\\n DataSourceType.REPLICA, replicaDataSource\\n ));\\n }\\n\\n @Bean\\n @Primary\\n public DataSource dataSource(\\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\\n ) {\\n return new LazyConnectionDataSourceProxy(routingDataSource);\\n }\\n}\\n```\\n\\n\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\\n\\tRDS --\x3e S[SourceDataSource]\\n\\tRDS --\x3e R[ReplicaDataSource]\\n```\\n\\n### \ub3d9\uc791 \ud655\uc778\\n\\n\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4. \\nsave \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional`, findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional(readOnly = true)`\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4. \\n\\n```java title=\\"MemberServiceTest\\"\\n@SpringBootTest\\nclass MemberServiceTest {\\n\\n @Autowired\\n private MemberService memberService;\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = false\\n memberService.save(\\"bbiac\\");\\n }\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = true\\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\\n .isInstanceOf(NoSuchElementException.class);\\n }\\n}\\n```\\n\\nDB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4. \\n\\n```sql\\nSET GLOBAL log_output = \'table\';\\nSET GLOBAL general_log = 1;\\n```\\n\\ngeneral log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4. \\nserver_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nSELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like \'%select%\';\\n\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user_host | thread_id | server_id | convert(argument using utf8) |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n```\\n\\n\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n```sql\\nSET GLOBAL general_log = 0;\\nSHOW VARIABLES LIKE \'%general%\';\\n\\n+------------------+---------------------------------+\\n| Variable_name | Value |\\n+------------------+---------------------------------+\\n| general_log | OFF |\\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\\n+------------------+---------------------------------+\\n```\\n\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Replication, MySQL Docs](https://dev.mysql.com/doc/refman/8.1/en/replication.html) \\n[MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30](https://huisam.tistory.com/entry/mysql-replication) \\n[Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd](https://cheese10yun.github.io/spring-transaction/) \\n[replication-datasource](https://github.com/kwon37xi/replication-datasource) \\n[Simplified Guide to MySQL Replication with Docker Compose](https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/) \\n[Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4](https://www.daleseo.com/dockerfile/) \\n[CHANGE REPLICATION SOURCE TO Statement](https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html) \\n[LazyConnectionDataSourceProxy](https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy) \\n[\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)](https://hudi.blog/database-replication-with-springboot-and-mysql/) \\n[\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30](https://chagokx2.tistory.com/100) \\n[Use Docker Compose, Docker](https://docs.docker.com/get-started/08_using_compose/)"},{"id":"woowacourse-level3-retrospective","metadata":{"permalink":"/woowacourse-level3-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","description":"\ud68c\uace0","date":"2023-08-19T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 19\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.945,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","slug":"woowacourse-level3-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"},"nextItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"}},"content":"import logo from \'./logo.png\';\\n\\n### \ud68c\uace0\\n\\n\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4. \\n\\n### \uc544\uc26c\uc6b4 \uc810\\n\\n**\ubb38\uc11c\ud654**\\n\\n\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n**\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790**\\n\\n\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790. \\n\\n**\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30**\\n\\n\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4. \\n\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4. \\n\\n### \uc88b\uc558\ub358 \uc810\\n\\n**\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654**\\n\\n[\ud300 \ube14\ub85c\uadf8](https://tripdraw.blog)\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\\n**\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0**\\n\\n\\n\\n\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4. \\n\\n**\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720**\\n\\n\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4. \\n100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n### \ub9c8\uce58\uba70\\n\\n\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4. \\n\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."},{"id":"cloudwatch","metadata":{"permalink":"/cloudwatch","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","source":"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","description":"CloudWatch","date":"2023-08-17T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 17\uc77c","tags":[{"label":"cloudwatch","permalink":"/tags/cloudwatch"},{"label":"log","permalink":"/tags/log"},{"label":"monitoring","permalink":"/tags/monitoring"}],"readingTime":5.35,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","slug":"cloudwatch","tags":["cloudwatch","log","monitoring"]},"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"}},"content":"## CloudWatch\\n\\nAWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4. \\n\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4. \\n\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4. \\n\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 [\ub2e4\uc74c \ub9c1\ud06c](https://aws.amazon.com/ko/cloudwatch/pricing/)\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n## CloudWatch Metrics\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4. \\n\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4. \\n\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch1.png](./cloudwatch1.png)\\n\\nCPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4.\\n\\n## CloudWatch Agent \uc124\uce58\\n\\nCloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4. \\n\\n### IAM \uc5ed\ud560 \uc124\uc815\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\nIAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4.\\n\\n![./cloudwatch2.png](./cloudwatch2.png)\\n\\nCloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\\n![./cloudwatch3.png](./cloudwatch3.png)\\n\\nEC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4. \\n\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4.\\n\\n![./cloudwatch4.png](./cloudwatch4.png)\\n\\n### \uc124\uce58\\n\\n\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\nOS: ubuntu 22.04 \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64) \\n\\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4.\\n\\n```bash\\nwget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\\n```\\n\\n[\uc0ac\uc6a9 \uc124\uba85\uc11c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html)\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4.\\n\\n### Wizard\\n\\nCloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\\n```\\n\\n\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4. \\n\\n![./cloudwatch5.png](./cloudwatch5.png)\\n\\n\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4. \\n\\n```bash\\nDo you want to store the config in the SSM parameter store?\\n1. yes\\n2. no\\n```\\n\\n\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4. \\nParameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 [\ubb38\uc11c](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4. \\n\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 `/opt/aws/amazon-cloudwatch-agent/bin/config.json` \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc801\uc6a9\\n\\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nfile \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\\n```\\n\\n### types.db: no such file or directory \uc5d0\ub7ec\\n\\n\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.\\n\\n```bash\\nError running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\\n```\\n\\ntypes.db \ud30c\uc77c \uc0dd\uc131\\n\\n```bash\\nsudo mkdir /usr/share/collectd\\nsudo touch /usr/share/collectd/types.db\\n```\\n\\n### \uc9c0\ud45c \ud655\uc778\\n\\nCloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n![./cloudwatch6.png](./cloudwatch6.png)\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\\n```json\\n{\\n \\"metrics\\": {\\n \\"namespace\\": \\"2023-hello-world\\",\\n ......\\n },\\n} \\n```\\n\\n### \ub85c\uadf8\\n\\nCloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch7.png](./cloudwatch7.png)\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) \\n[Amazon CloudWatch \uc694\uae08](https://aws.amazon.com/ko/cloudwatch/pricing/) \\n[Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) \\n[\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html) \\n[CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/) \\n[CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html)"},{"id":"route-image-async-with-event","metadata":{"permalink":"/route-image-async-with-event","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","description":"\uc774\uc804 \uae00","date":"2023-08-13T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 13\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"event","permalink":"/tags/event"}],"readingTime":11.2,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","slug":"route-image-async-with-event","tags":["async","event"]},"prevItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"}},"content":"## \uc774\uc804 \uae00\\n\\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd](./route-image-intro) \\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604](./route-image-implementation)\\n\\n## \uac1c\uc694\\n\\n\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120\\n\\n\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4. \\n\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4. \\n\\n### \ud655\uc7a5\uc131 \ub300\ube44\\n\\n\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4. \\n\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4. \\n\\n## \ube44\ub3d9\uae30 \ucc98\ub9ac\\n\\n@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc124\uc815\\n\\n\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4. \\n\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4. \\n\\n```java title=\\"AsyncConfig\\"\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig {\\n}\\n```\\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4. \\n\\n> In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\\n> 7.7. Task Execution and Scheduling, Spring Boot Docs\\n\\n### @Async \uc801\uc6a9\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java title=\\"RouteImageGenerator\\"\\n@Async\\npublic void generate(\\n List latitudes,\\n List longitudes,\\n List pointedLatitudes,\\n List pointedLongitudes,\\n Long tripId\\n) {\\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\\n\\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\\n\\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\\n routeImageDrawer.dispose();\\n\\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\\n Trip trip = tripRepository.findById(tripId)\\n .orElseThrow();\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n}\\n```\\n\\n### \ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810\\n\\n\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4. \\n\\n```mermaid\\ngraph LR\\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\\n draw --\x3e trip\\n```\\n\\n\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph draw\\n\\t\\tdirection LR\\n\\t\\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\\n\\tend\\n subgraph trip\\n\\t\\tdirection LR\\n\\t\\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\\n\\t\\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\\n\\tend\\n\\n\\ttrip --\x3e draw\\n```\\n\\n\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n## \uc774\ubca4\ud2b8 \uc0ac\uc6a9\\n\\n\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4.\\n\\n### \uc774\ubca4\ud2b8 \ubc1c\ud589\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4. \\n\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4. \\n\\n```java title=\\"TripService & TripUpdateEvent\\"\\npublic void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\\n ...\\n\\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\\n}\\n\\npublic record TripUpdateEvent(Long tripId) {\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4. \\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4. \\n\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4. \\n\\n### \uc774\ubca4\ud2b8 \uad6c\ub3c5\\n\\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec `@Async` \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4. \\n\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 `@TransactionalEventListener`\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n:::note TransactionPhase \uc124\uc815\\nTransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\nAFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nBEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\n:::\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```java title=\\"TripUpdateEventHandler\\"\\n@Component\\npublic class TripUpdateEventHandler {\\n\\n private final RouteImageGenerator routeImageGenerator;\\n private final TripRepository tripRepository;\\n\\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\\n this.routeImageGenerator = routeImageGenerator;\\n this.tripRepository = tripRepository;\\n }\\n\\n @Async\\n @TransactionalEventListener(phase = AFTER_COMMIT)\\n public void handle(TripUpdateEvent tripUpdateEvent) {\\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\\n\\n String imageUrl = routeImageGenerator.generate(\\n trip.getLatitudes(),\\n trip.getLongitudes(),\\n trip.getPointedLatitudes(),\\n trip.getPointedLongitudes()\\n );\\n\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n }\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4. \\n\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4.\\n\\n```mermaid\\ngraph LR\\n subgraph trip\\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\\n TripRepository\\n end\\n\\n subgraph draw\\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\\n end\\n```\\n\\n### \ud14c\uc2a4\ud2b8\\n\\n\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(Mockito.timeout(5000).times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\n@ContextConfiguration(classes = TestSyncConfig.class)\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4. \\n\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 `\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0` \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c `Mockito.timeout` \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4. \\n\\n## \uacb0\uacfc\\n\\n![./time.png](./time.png)\\n\\n\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4. \\n\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[7.7. Task Execution and Scheduling, Spring Boot Docs](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling) \\n[Spring Events, Baeldung](https://www.baeldung.com/spring-events) \\n[\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30](https://techblog.woowahan.com/7835/)"},{"id":"route-image-implementation","metadata":{"permalink":"/route-image-implementation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","source":"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","description":"\uac1c\uc694","date":"2023-08-02T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 2\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":11.665,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","slug":"route-image-implementation","tags":["image","awt"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"}},"content":"## \uac1c\uc694\\n\\n\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 [\ub9c1\ud06c](./route-image-intro)\uc5d0 \uc788\ub2e4.\\n\\n### \uad6c\ud604 \uacb0\uacfc\\n\\n![./result.png](./result.png)\\n\\n\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n**\uc11c\uc6b8\uc5ed(\uc810)** \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 **\uad6c\ub85c\uc5ed(\uc810)** \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed\\n\\n```java title=\\"\uc608\uc2dc \ub370\uc774\ud130\\"\\nList x = List.of(\\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\\n);\\nList y = List.of(\\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\\n);\\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\\n```\\n\\n### IMAGE_SIZE & ROUTE_SIZE\\n\\n```java title=\\"RouteImageGenerator.java\\"\\nprivate static final int IMAGE_SIZE = 800;\\nprivate static final int ROUTE_SIZE = 600;\\n```\\n\\n\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4. \\nIMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4. \\nROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4. \\n\\n![./600.png](./600.png)\\n\\n**\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720**\\n\\n255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4.\\n\\n## \uc8fc\uc694 \ud074\ub798\uc2a4\\n\\n### \uc694\uc57d\\n\\n| \ud074\ub798\uc2a4\uba85 | \uc124\uba85 | \ud2b9\uc774\uc0ac\ud56d |\\n| --- | --- | --- |\\n| Coordinate | \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12 | \uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9 |\\n| Coordinates | Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| Position | \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12 | Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9 |\\n| Positions | Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| RouteImageDrawer | \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c | \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c |\\n| RouteImageUploader | BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4 | \ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131 |\\n| RouteImageGenerator | \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4 | \uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad |\\n| BufferedImage(AWT) | \uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9 | \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0) |\\n| Graphics2D(AWT) | \uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc | JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131 |\\n\\n### \uc758\uc874\uad00\uacc4\\n\\n```mermaid\\ngraph TD\\n C1[Coordinates] --\x3e C[Coordinate]\\n P1[Positions] --\x3e P[Position]\\n\\n\\tRID[RouteImageDrawer] -- \\"\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131\\" --\x3e P1\\n\\tRID --\x3e B[BufferedImage]\\n\\tRID --\x3e G[Graphics2D]\\n\\n\\tC1 -- \\"calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0\\" --\x3e P1\\n\\n\\tRIU[RouteImageUploader] --\x3e B\\n\\tRIG[RouteImageGenerator] --\x3e RID\\n\\tRIG --\x3e RIU\\n\\tRIG --\x3e C1\\n\\tRIG --\x3e P1\\n```\\n\\n### Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)\\n\\n`List` 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4. \\nCoordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658\\n- indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294 \\n\\nPositions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n```java title=\\"Coordinates.java\\"\\n// \ud638\ucd9c\\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\\n\\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\\n Double minValue = Collections.min(values);\\n return values.stream()\\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\\n .map(value -> mapToPosition(value, routeImageSize))\\n .toList();\\n}\\n\\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\\n return (coordinate - minValue) / maxDifference;\\n}\\n\\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\\n return (int) (coordinate * routeImageSize);\\n}\\n```\\n\\n\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4.\\n\\n1. Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4.\\n2. normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 **\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774**\ub85c \ub098\ub208\ub2e4.\\n3. mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n### Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)\\n\\nPositions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4.\\n- getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4.\\n- xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```java title=\\"Positions.java\\"\\npublic Positions align(int imageSize, int routeSize) {\\n int xOffset = calculateOffset(Position::x, imageSize);\\n int yOffset = calculateOffset(Position::y, imageSize);\\n\\n return items.stream()\\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\\n .collect(collectingAndThen(toList(), Positions::new));\\n}\\n\\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\\n List positions = items.stream()\\n .mapToInt(positionToInteger)\\n .boxed()\\n .toList();\\n\\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\\n return imageSize / 2 - midValue;\\n}\\n```\\n\\n\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4. \\nBufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4. \\n\\n![./800.png](./800.png)\\n\\n\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4.\\n\\nx \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4. \\ny \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4. \\n\\n### RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)\\n\\nBufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4. \\n\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.\\n\\n```java title=\\"RouteImageDrawer.java\\"\\n// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\\n// \ubc30\uacbd \ud22c\uba85\uc0c9\\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\\nprivate static final int LINE_STROKE_WIDTH = 7;\\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\\nprivate static final int POINT_STROKE_WIDTH = 20;\\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\\nprivate static final Map renderingHints = Map.of(\\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\\n);\\n```\\n\\nRouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4.\\n- drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4.\\n- dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4. \\n\\ndispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4.\\n\\n## \uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow\\n\\n### 1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n\\n```\\n\\n### 2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 4. \uc5c5\ub85c\ub4dc \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n \\tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n \\tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n \\tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n```\\n\\n### \uc804\uccb4 Flow\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n\\t\\n```"},{"id":"route-image-python","metadata":{"permalink":"/route-image-python","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","source":"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","description":"\uac1c\uc694","date":"2023-07-31T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 31\uc77c","tags":[{"label":"Image","permalink":"/tags/image"},{"label":"Python","permalink":"/tags/python"}],"readingTime":6.185,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","slug":"route-image-python","tags":["Image","Python"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"},"nextItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"}},"content":"### \uac1c\uc694\\n\\n\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4. \\n\\n### \uc0ac\uc6a9 \uae30\uc220\\n\\n\uc5b8\uc5b4: Python 3.10 \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib \\n\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront \\n\\n\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```mermaid\\ngraph LR\\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\\n Client --\x3e CloudFront --\x3e S3\\n```\\n\\n### \uc694\uad6c\uc0ac\ud56d\\n\\n![./route.png](./route.png)\\n\\n\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4. \\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n- \uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\\n\\n1. \uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n2. \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n\\n\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4. \\n\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604\\n\\n```python\\nimport time\\n\\nimport matplotlib.pyplot as plt\\n\\n\\ndef draw(point):\\n start = time.time()\\n x, y = zip(*point)\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n draw_lines(pixel_x, pixel_y)\\n end = time.time()\\n print(end - start)\\n \\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n return scaled_coordinates\\n\\n\\ndef draw_lines(x, y):\\n figure = plt.gcf()\\n figure.set_size_inches(5, 5)\\n plt.plot(x, y, c = \'w\',linewidth=5)\\n plt.scatter(x[3],y[3], c = \'w\', s = 125)\\n plt.axis(\'off\')\\n plt.savefig(\'name.png\', transparent=True, format=\'png\')\\n\\npoint = [\\n [126.96352960597338, 37.590841000217125],\\n [126.96987292787792, 37.58435564234159],\\n [126.98128481452298, 37.58594375113966],\\n [126.99360339342958, 37.58248524741927],\\n [126.99867565340067, 37.56778118088622],\\n [127.001935378366117, 37.55985240444085],\\n [126.9831048919687, 37.548030119488665],\\n [126.97189273528845, 37.5119879225856],\\n [127.02689859997221, 37.48488593333883]\\n]\\n\\ndraw(point)\\n```\\n\\n\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)\\n\\n![./routeImage.png](./routeImage.png)\\n\\n### AWS Lambda\\n\\n\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4. \\n\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131\\n\\nAmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc\\n\\n\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```python\\n\\nimport io\\nimport uuid\\n\\nimport boto3\\nimport matplotlib.pyplot as plt\\n\\nPIXEL = 255\\nBUCKET_NAME = \'image-plot\'\\nS3 = \'s3\'\\n\\ndef lambda_handler(event, context):\\n x = event[\'x\']\\n y = event[\'y\']\\n image_name = str(uuid.uuid4())\\n\\n img_data = draw(x, y)\\n s3 = boto3.client(S3)\\n s3.put_object(Body=img_data.getvalue(), ContentType=\'image/png\', Bucket=BUCKET_NAME, Key=image_name)\\n url = f\'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}\'\\n\\n return {\\n \'statusCode\': 200,\\n \'body\': url\\n }\\n\\ndef draw(x, y):\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n img_data = draw_lines(pixel_x, pixel_y)\\n plt.close()\\n return img_data\\n\\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\\n return pixel_values\\n\\ndef draw_lines(x, y):\\n plt.plot(x, y, \'k-\', linewidth=10)\\n plt.axis(\'off\')\\n img_data = io.BytesIO()\\n plt.savefig(img_data, transparent=True, format=\'png\')\\n img_data.seek(0)\\n return img_data\\n\\n```\\n\\n### Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131\\n\\nmatplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4. \\nzip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4. \\n\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4. \\n\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```\\npillow.zip\\n\u2502 python/PIL\\n\u2514 python/Pillow-5.3.0.dist-info\\n```\\n\\nUbuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\\n```\\nsudo apt update\\nsudo apt install zip\\nsudo apt install python3-pip\\n\\nmkdir python\\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\\n```\\n\\n### `No module named \'numpy.core._multiarray_umath\'` \uc5d0\ub7ec\\n\\nLayer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4. \\n\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4. \\n\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### \uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01\\n\\n\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4. \\nAWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4. \\n\\n**\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.**\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[AWS Lambda](https://aws.amazon.com/ko/lambda/) \\n[Lambda Layer](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html) \\n[Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html) \\n[No module named \'numpy.core._multiarray_umath\'](https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b) \\n[\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc](https://techblog.woowahan.com/6217/)"},{"id":"mock-static-method","metadata":{"permalink":"/mock-static-method","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","source":"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","description":"\uac1c\uc694","date":"2023-07-30T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 30\uc77c","tags":[{"label":"Mockito","permalink":"/tags/mockito"},{"label":"static","permalink":"/tags/static"}],"readingTime":2.635,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","slug":"mock-static-method","tags":["Mockito","static"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"}},"content":"### \uac1c\uc694\\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4. \\n\\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4. \\n\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4. \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4. \\n\\n```java\\npublic void upload(BufferedImage bufferedImage) {\\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\\n try {\\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\\n } catch (IOException e) {\\n throw new DrawException(IMAGE_SAVE_FAIL);\\n }\\n}\\n```\\n\\n### Mocking static methods\\n\\nMockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\nmockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 `MockedStatic`\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4. \\n\\nJUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc `MockedStatic`\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4. \\n\\n```java\\n// given\\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\\nRouteImageUploader routeImageUploader = new RouteImageUploader();\\n\\n// expect\\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\\n routeImageUploader.upload(bufferedImage);\\n imageIO.verify(\\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\\n times(1)\\n );\\n}\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790. \\n\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4. \\n\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Mocking static methods](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks) \\n[Mockito mock static methods](https://www.baeldung.com/mockito-mock-static-methods) \\n[Enable mocking static methods in Mockito](https://github.com/mockito/mockito/issues/1013)"},{"id":"route-image-intro","metadata":{"permalink":"/route-image-intro","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","source":"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","description":"./route.png","date":"2023-07-27T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 27\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":5.865,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","slug":"route-image-intro","tags":["image","awt"]},"prevItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"},"nextItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"}},"content":"![./route.png](./route.png)\\n\\n### \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784\\n\\n\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c `\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac`\uc640 `\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0`\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4.\\n\\n\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4.\\n\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n\\n\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4.\\n\\n### \uace0\ub824\ud55c \uae30\uc220\\n\\n\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4. \\n\\n- Python\uc758 Matplotlib\\n- **AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]**\\n- \uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)\\n- Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)\\n\\n## Python & Matplotlib\\n\\n\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08 \\n\\n- \ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4. \\n- AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.\\n- Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4.\\n\\n### Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\\n\\nPython\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4.\\n\\n\ub77c\uc774\ube0c\ub7ec\ub9ac | \uc124\uba85 | \uc81c\uc678 \uc774\uc720\\n-- | -- | --\\nSwing | AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\nJavaFX | Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\n[simple-java-plot](https://github.com/yuriy-g/simple-java-plot) | AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac | AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c\\n[matplotlib4j](https://github.com/sh0nk/matplotlib4j) | Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac | \ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c\\n\\n### Java & AWT(Abstract Window Toolkit)\\n\\n\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08 \\n\\n- \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4.\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.\\n- \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n\\n### \uae30\uc220 \uc120\ud0dd\\n\\nAWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.\\n\\n### \uc720\uc9c0 \ubcf4\uc218\\n\\nAWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n1. \ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4. \\n2. AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4.\\n\\n### \ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00\\n\\n\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4. \\nAWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."},{"id":"java-spring-springboot","metadata":{"permalink":"/java-spring-springboot","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","source":"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","description":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","date":"2023-07-24T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 24\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Spring Boot","permalink":"/tags/spring-boot"},{"label":"Spring","permalink":"/tags/spring"}],"readingTime":4.725,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","slug":"java-spring-springboot","tags":["Java","Spring Boot","Spring"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"},"nextItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"}},"content":"## \uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\\n\\n\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4. \\n2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4.\\n\\n## \uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### Switch Expressions(Java 14)\\n\\nJava 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n```java\\nenum RESULT {\\n WIN, LOSE, DRAW\\n}\\n\\nRESULT result = RESULT.WIN;\\n\\nint prize = switch (result) {\\n case WIN -> 10_000_000;\\n case LOSE, DRAW -> 5_000_000;\\n\\tdefault -> 0;\\n};\\n```\\n\\n\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- `->` \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4.\\n- case\ub97c \ucf64\ub9c8(`,`)\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n- break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4.\\n- default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\n### Text Block(Java 15)\\n\\nJava 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@Repository\\npublic interface PostRepository extends JpaRepository {\\n @Query(\\"\\"\\"\\n SELECT p FROM Post p\\n WHERE p.title LIKE %:keyword%\\n OR p.content LIKE %:keyword%\\n \\"\\"\\")\\n List findPostsByTitleOrContentContainingKeyword(String keyword);\\n}\\n```\\n\\n### NPE \uba54\uc2dc\uc9c0(Java 15)\\n\\n```java\\nString name = null;\\nname.chars();\\n\\n/** \\n# before\\njava.lang.NullPointerException\\n\\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\\n\\n# after\\nCannot invoke \\"String.chars()\\" because \\"name\\" is null\\njava.lang.NullPointerException: Cannot invoke \\"String.chars()\\" because \\"name\\" is null\\n*/\\n```\\n\\n### Record(Java 16)\\n\\nLombok\uc758 `@Data`, kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nRecord\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4. \\n\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4. \\n\\n```java\\npublic record PostDto(String title, String content) {\\n}\\n```\\n\\n### \ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d\\n\\n\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n## \uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4. \\n\\n### \uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d\\n\\nJava 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n### \ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd\\n\\nJakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4. \\n\\n### PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c\\n\\n6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c `@GetMapping(\\"/hello\\")`\uc640 `@GetMapping(\\"/hello/\\")`\uac00 \ub3d9\uc77c\ud588\ub2e4. \\n6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, `/hello`\uc640 `/hello/`\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4. \\n\\n> PathPatternParser used by default (with the ability to opt into PathMatcher). \\n\\n### HTTP interface client\\n\\n\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [\ud1a0\ube44\ub2d8\uc758 \uac15\uc758](https://www.youtube.com/watch?v=Kb37Q5GCyZs)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d\\n\\nGradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6 \\n\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30](https://www.youtube.com/watch?v=1WT6oxchM9M) \\n[\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30](https://www.youtube.com/watch?v=7SlDdzVk6GE) \\n[Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658](https://www.samsungsds.com/kr/insights/java_jakarta.html) \\n[Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529](https://www.youtube.com/watch?v=Kb37Q5GCyZs) \\n[What\'s New in Spring Framework 6.x](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x) \\n[Spring Boot 3.0 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes) \\n[Spring Boot 3.1 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes)"},{"id":"websocket","metadata":{"permalink":"/websocket","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx","source":"@site/blog/2023-2/2023-06-26-WebSocket.mdx","title":"\uc6f9\uc18c\ucf13","description":"\uc6f9\uc18c\ucf13","date":"2023-06-26T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 26\uc77c","tags":[{"label":"WebSocket","permalink":"/tags/web-socket"}],"readingTime":4.165,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9\uc18c\ucf13","slug":"websocket","tags":["WebSocket"]},"prevItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"},"nextItem":{"title":"Docusaurus","permalink":"/docusaurus"}},"content":"### \uc6f9\uc18c\ucf13\\n\\n\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c \\n\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\\n\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4. \\n\\n### \uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd\\n\\n\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4. \\n\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n:::note polling, long polling, streaming\\n\\nPolling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95\\n- \uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4. \\n- \uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4. \\n\\nLong Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95\\n- \ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4.\\n\\nStreaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n- \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4. \\n:::\\n\\n### \uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791\\n\\n```mermaid\\nsequenceDiagram\\n participant Client\\n participant Server\\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\\n\\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\\n Server->>Client: \\n\\n Client->>Server: \uc885\ub8cc\\n Server->>Client: \\n```\\n\\n### 1. Upgrade \uc694\uccad\\n\\nWebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4. \\n\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4. \\nSec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4. \\nSec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4. \\n\\n```\\nGET /chats HTTP/1.1\\nHost: localhost:8080\\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\\nSec-WebSocket-Version: 13\\nOrigin: http://localhost:8080\\n```\\n\\n### 2. Switching Protocols\\n\\n\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4. \\nSec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\\n```\\nHTTP/1.1 101 Switching Protocols \\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\\nSec-WebSocket-Protocol: v10.stomp\\n```\\n\\n### 3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc\\n\\n\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4. \\n\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\nhttps://datatracker.ietf.org/doc/html/rfc6455 \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers \\nhttps://docs.spring.io/spring-framework/reference/web/websocket.html"},{"id":"docusaurus","metadata":{"permalink":"/docusaurus","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","source":"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","title":"Docusaurus","description":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.","date":"2023-06-18T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 18\uc77c","tags":[{"label":"Documentation","permalink":"/tags/documentation"}],"readingTime":10.095,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Docusaurus","slug":"docusaurus","tags":["Documentation"]},"prevItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"}},"content":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n## \uc124\uce58\\n\\n[\uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://docusaurus.io/docs/installation)\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4. \\n\\n```bash\\nyarn create docusaurus\\n````\\n\\n## \ubc30\ud3ec\\n\\n[\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c](https://docusaurus.io/docs/next/deployment#deploying-to-github-pages) \\nnetlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4.\\n\\n### \ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131\\n\\ngithub pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 [\uc608\uc2dc](https://github.com/greeng00se/greeng00se.github.io)\uc640 \uac19\uc774 `username.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\n\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 `organization.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc218\uc815\\n\\n```js title=\\"docusaurus.config\\"\\nmodule.exports = {\\n // ...\\n url: \'https://greeng00se.github.io\',\\n baseUrl: \'/\',\\n projectName: \'greeng00se.github.io\',\\n organizationName: \'greeng00se\',\\n trailingSlash: false,\\n // ...\\n};\\n```\\n\\n### \ud1a0\ud070 \uc124\uc815\\n\\ngithub action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4. \\n\\n![github](./github.png)\\n\\n### \ube0c\ub79c\uce58 \uc0dd\uc131\\n\\ngithub\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4. \\nrepository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4. \\n\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\\n### \uc6cc\ud06c\ud50c\ub85c \uc791\uc131\\n\\nDocusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4. \\n\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4. \\n\\n```yml title=\\".github/workflows/deploy.yml\\"\\nname: blog\\n\\non:\\n push:\\n branches: [main]\\n\\njobs:\\n deploy:\\n name: Deploy to GitHub Pages\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/checkout@v2\\n - uses: actions/setup-node@v3\\n with:\\n node-version: 18\\n cache: yarn\\n\\n - name: Install dependencies\\n run: yarn install --frozen-lockfile\\n - name: Build website\\n run: yarn build\\n\\n - name: Deploy to GitHub Pages\\n uses: peaceiris/actions-gh-pages@v3\\n with:\\n github_token: ${{ secrets.DEPLOY_TOKEN }}\\n publish_dir: ./build\\n user_name: github-actions[bot]\\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\\n```\\n\\n## \ub313\uae00 \uae30\ub2a5\\n\\ngiscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4. \\n\\n### giscus \uc124\uc815\\n\\n1. \uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4.\\n2. giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n3. Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n\\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [giscus](https://giscus.app/ko)\ub97c \ud655\uc778\ud558\uc790.\\n\\n### docusaurus \uc124\uc815\\n\\n[swizzling](https://docusaurus.io/ko/docs/next/swizzling)\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4. \\n\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nyarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\\n```\\n\\n\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 `/src/theme/BlogPostItem/index.js` \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4. \\n\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4. \\n\\n```js title=\\"/src/theme/BlogPostItem/index.js\\"\\nimport OriginalBlogPostItem from \\"@theme-original/BlogPostItem\\";\\nimport React, { useEffect, useRef } from \\"react\\";\\n// @ts-expect-error internal code\\nimport { useColorMode } from \\"@docusaurus/theme-common\\";\\nimport { useBlogPost } from \\"@docusaurus/theme-common/internal\\";\\n\\nconst giscusSelector = \\"iframe.giscus-frame\\";\\n\\nfunction BlogPostItem(props) {\\n const { colorMode } = useColorMode();\\n const { isBlogPostPage } = useBlogPost();\\n const giscusTheme = colorMode === \\"dark\\" ? \\"dark\\" : \\"light\\";\\n const containerRef = useRef(null);\\n\\n useEffect(() => {\\n if (!isBlogPostPage) return;\\n\\n const giscusEl = containerRef.current.querySelector(giscusSelector);\\n\\n const createGiscusEl = () => {\\n const script = document.createElement(\\"script\\");\\n\\n script.src = \\"https://giscus.app/client.js\\";\\n script.setAttribute(\\"data-repo\\", \\"teco-chat/teco-chat.github.io\\");\\n script.setAttribute(\\"data-repo-id\\", \\"R_kgDOJZ5j0Q\\");\\n script.setAttribute(\\"data-category\\", \\"Announcements\\");\\n script.setAttribute(\\"data-category-id\\", \\"DIC_kwDOJZ5j0c4CXS_Q\\");\\n script.setAttribute(\\"data-mapping\\", \\"pathname\\");\\n script.setAttribute(\\"data-strict\\", \\"0\\");\\n script.setAttribute(\\"data-reactions-enabled\\", \\"1\\");\\n script.setAttribute(\\"data-emit-metadata\\", \\"0\\");\\n script.setAttribute(\\"data-input-position\\", \\"bottom\\");\\n script.setAttribute(\\"data-theme\\", giscusTheme);\\n script.setAttribute(\\"data-lang\\", \\"ko\\");\\n script.crossOrigin = \\"anonymous\\";\\n script.async = true;\\n \\n containerRef.current.appendChild(script);\\n };\\n\\n const postThemeMessage = () => {\\n const message = {\\n setConfig: {\\n theme: giscusTheme,\\n }\\n };\\n\\n giscusEl.contentWindow.postMessage({ giscus: message }, \\"https://giscus.app\\");\\n };\\n\\n giscusEl ? postThemeMessage() : createGiscusEl();\\n }, [giscusTheme]);\\n\\n return (\\n <>\\n \\n {isBlogPostPage &&
}\\n \\n );\\n}\\n\\nexport default BlogPostItem;\\n```\\n\\n## \uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30\\n\\n\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4. \\n\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, [docsearch](https://docsearch.algolia.com/)\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\ndocsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n- [\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1](https://docsearch.algolia.com/docs/legacy/run-your-own/) \\n- [\uc124\uc815 \ud30c\uc77c](https://docsearch.algolia.com/docs/legacy/config-file)\\n\\n### \uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778\\n\\n\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4. \\n\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n![algolia](./algolia.png)\\n\\n### \ud0a4 \uc0dd\uc131\\n\\n\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4. \\naddObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4. \\n\\n![key](./key.png)\\n\\n### .env \ud30c\uc77c \uc0dd\uc131\\n\\n\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\\n```bash title=\\".env\\"\\nAPPLICATION_ID=MVIU5UEMOM\\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\\n```\\n\\n### config \ud30c\uc77c \uc0dd\uc131\\n\\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 [\ub9c1\ud06c](https://docsearch.algolia.com/docs/legacy/config-file)\ub97c \ucc38\uace0\ud55c\ub2e4. \\n\ub610\ub294 Docusaurus\uc758 [\uc124\uc815 \ud30c\uc77c](https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json)\uc744 \ucc38\uace0\ud55c\ub2e4.\\n\\n```json title=\\"config.json\\"\\n{\\n \\"index_name\\": \\"teco\\",\\n \\"start_urls\\": [\\n \\"https://teco-chat.github.io/\\"\\n ],\\n \\"sitemap_urls\\": [\\n \\"https://teco-chat.github.io/sitemap.xml\\"\\n ],\\n \\"sitemap_alternate_links\\": true,\\n \\"stop_urls\\": [\\n \\"/tests\\"\\n ],\\n \\"selectors\\": {\\n \\"lvl0\\": {\\n \\"selector\\": \\"(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]\\",\\n \\"type\\": \\"xpath\\",\\n \\"global\\": true,\\n \\"default_value\\": \\"Documentation\\"\\n },\\n \\"lvl1\\": \\"header h1\\",\\n \\"lvl2\\": \\"article h2\\",\\n \\"lvl3\\": \\"article h3\\",\\n \\"lvl4\\": \\"article h4\\",\\n \\"lvl5\\": \\"article h5, article td:first-child\\",\\n \\"lvl6\\": \\"article h6\\",\\n \\"text\\": \\"article p, article li, article td:last-child\\"\\n },\\n \\"strip_chars\\": \\" .,;:#\\",\\n \\"custom_settings\\": {\\n \\"separatorsToIndex\\": \\"_\\",\\n \\"attributesForFaceting\\": [\\n \\"language\\",\\n \\"version\\",\\n \\"type\\",\\n \\"docusaurus_tag\\"\\n ],\\n \\"attributesToRetrieve\\": [\\n \\"hierarchy\\",\\n \\"content\\",\\n \\"anchor\\",\\n \\"url\\",\\n \\"url_without_anchor\\",\\n \\"type\\"\\n ]\\n },\\n \\"conversation_id\\": [\\n \\"833762294\\"\\n ],\\n \\"nb_hits\\": 46250\\n}\\n```\\n\\n### docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\\n\\ndocker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4. \\njq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nbrew install jq\\n```\\n\\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4. \\n\\n```bash\\ndocker run -it --env-file=.env -e \\"CONFIG=$(cat ./config.json | jq -r tostring)\\" algolia/docsearch-scraper\\n```\\n\\n### docusaurus \uc124\uc815\\n\\n\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n algolia: {\\n appId: \'MVIU5UEMOM\', // Application ID\\n apiKey: \'b68f378013817d9a190df88cdde226a0\', // Search-Only API Key\\n indexName: \'teco\', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\\n contextualSearch: true,\\n },\\n })\\n```\\n\\n## \ubd80\uac00 \uc124\uc815\\n\\n### \ud654\uba74 \uc0c1\ub2e8 Github Icon\\n\\n\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```css title=\\"/src/css/custom.css\\"\\n.header-github-link:hover {\\n opacity: 0.6;\\n}\\n\\n.header-github-link:before {\\n content: \'\';\\n width: 24px;\\n height: 24px;\\n display: flex;\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n\\nhtml[data-theme=\'dark\'] .header-github-link:before {\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath fill=\'white\' d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n```\\n\\nthemeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nnavbar: {\\n title: \'HELLO\',\\n items: [\\n {\\n href: \'https://github.com/greeng00se\',\\n position: \'right\',\\n className: \'header-github-link\',\\n \'aria-label\': \'GitHub repository\',\\n },\\n ],\\n},\\n```\\n\\n### \ucf54\ub4dc\ube14\ub7ed\\n\\njava\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4. \\nprism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nprism: {\\n theme: lightCodeTheme,\\n darkTheme: darkCodeTheme,\\n additionalLanguages: [\'java\', \'kotlin\'],\\n}\\n```\\n\\n### mermaid\\n\\nmermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 `@docusaurus/theme-mermaid` \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4.\\n\\n```bash\\nyarn add @docusaurus/theme-mermaid\\n```\\n\\n\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```js title=\\"docusaurus.config\\"\\nconst config = {\\n ...\\n markdown: {\\n mermaid: true,\\n },\\n themes: [\\n \'@docusaurus/theme-mermaid\'\\n ],\\n};\\n```\\n\\nthemeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n mermaid: {\\n theme: {\\n light: \'neutral\', \\n dark: \'dark\'\\n },\\n },\\n }),\\n```\\n\\n### \uad6d\uc81c\ud654 \uc124\uc815\\n\\n\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 `Older Entries` \ud615\ud0dc\uc758 \uc124\uba85\uc774 `\ub2e4\uc74c \ud398\uc774\uc9c0` \ub85c \ubcc0\uacbd\ub41c\ub2e4. \\n\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\ni18n: {\\n defaultLocale: \\"ko\\",\\n locales: [\\"ko\\"],\\n},\\n```\\n\\n### \ube14\ub85c\uadf8 \uae00 author\\n\\n\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4. \\n\\n![author](./author.png)\\n\\n`authors.yml` \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```yml title=\\"/blog/authors.yml\\"\\nherb:\\n name: \ud5c8\ube0c\\n title: Backend\\n url: https://github.com/greeng00se\\n image_url: https://github.com/greeng00se.png\\n\\nmallang:\\n name: \ub9d0\ub791\\n title: Backend\\n url: https://github.com/shin-mallang\\n image_url: https://github.com/shin-mallang.png\\n```\\n\\n\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4. \\n\\n```mdx\\n---\\nslug: 1\\ntitle: Hello World\\nauthors: [herb, mallang]\\ntags: [hello, docusaurus]\\n---\\n\\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\\n```"},{"id":"woowacourse-level2-retrospective","metadata":{"permalink":"/woowacourse-level2-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","description":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.","date":"2023-06-11T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":2.545,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","slug":"woowacourse-level2-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"Docusaurus","permalink":"/docusaurus"},"nextItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"}},"content":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4. \\n\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4. \\n\\n### \ud559\uc2b5\\n\\n\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4. \\n\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4. \\n\\n\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4. \\n\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4. \\n\\n\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4. \\n\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc218\uba74\\n\\n\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### \ud611\uc5c5\\n\\n\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4. \\n\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4. \\n\\n\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4. \\n\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70\\n\\n\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."},{"id":"level2-interview-retrospective","metadata":{"permalink":"/level2-interview-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","description":"\ub808\ubca8 \uc778\ud130\ubdf0","date":"2023-06-08T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 8\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.435,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","slug":"level2-interview-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"},"nextItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"}},"content":"### \ub808\ubca8 \uc778\ud130\ubdf0\\n\\n\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4. \\n\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd\\n\\n\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4.\\n\\n\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4.\\n\\n> \ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c. \\n> \uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d\\n>\\n\\n### PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158\\n\\nPUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4. \\n\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4. \\n\\n\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4. \\n\\n### \uadf8 \uc678 \uac1c\uc120\ud560 \uc810\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30 \\n\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c \\"\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?\\"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30 \\n\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30 \\n\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"},{"id":"order-retrospective","metadata":{"permalink":"/order-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","description":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158","date":"2023-06-04T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 4\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.595,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","slug":"order-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"}},"content":"### \uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158\\n\\n\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4. \\n\\n### \ubc30\ud3ec\\n\\n\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4. \\n\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4.\\n\\n```bash\\necho \\"Start Deploy Script\\"\\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\\nPROJECT_NAME=jwp-shopping-order\\n\\necho \\"Change Directory\\"\\ncd $REPOSITORY_NAME\\n\\necho \\"Git Pull\\"\\ngit pull origin step2\\n\\necho \\"Build\\"\\n./gradlew bootJar\\n\\necho \\"Copy, Start Server\\"\\nmv ./build/libs/$PROJECT_NAME.jar .\\n\\nPID=$(pgrep -f $PROJECT_NAME)\\n\\nif [ -n $PID ]; then\\n kill -9 $PID\\n\\tsleep 5\\nfi\\n\\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\\n```\\n\\n### \ud611\uc5c5\\n\\n\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4. \\n\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30**\\n\\n\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c? \\n\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84\\n\\n**expose headers**\\n\\n\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c [\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header)\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nnginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4. \\n\\n```bash\\nadd_header \'Access-Control-Expose-Headers\' \'Location\'\\n```\\n\\n**\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158** \\n\\n\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4. \\nTransactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4.\\n\\nsetReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4.\\n- h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4. \\n- MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4.\\n\\nORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4. \\n\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4. \\n\\n**DAO\uc5d0 `@Transactional` \uc801\uc6a9** \\n\\nDAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nService \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\nDAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) `@Transactional`\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."},{"id":"tecochat-retrospective-3","metadata":{"permalink":"/tecochat-retrospective-3","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","source":"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","description":"\uac1c\uc694","date":"2023-06-01T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.005,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","slug":"tecochat-retrospective-3","tags":["TecoChat","Retrospective"]},"prevItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"},"nextItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"}},"content":"### \uac1c\uc694\\n\\n\uc6d0\ub798 \ubaa9\uc801\uc778 `\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0`\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### \ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\nGPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4. \\n\\n![chat1](./chat1.png)\\n\\n### \uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5\\n\\n\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4. \\n\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.\\n\\n### \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\\n\\n\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4. \\n\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\nCSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4. \\n\\n![chat2](./chat2.png)\\n\\n### \ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\n\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4. \\n\\n### \uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30\\n\\n![chat3](./chat3.png)\\n\\n\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4. \\n\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4. \\n\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ud5a5\ud6c4 \uacc4\ud68d\\n\\n\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4. \\n\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4. \\n\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."},{"id":"composite","metadata":{"permalink":"/composite","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","source":"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","description":"\uc694\uad6c\uc0ac\ud56d","date":"2023-05-26T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 26\uc77c","tags":[{"label":"Pattern","permalink":"/tags/pattern"},{"label":"Composite","permalink":"/tags/composite"}],"readingTime":4.74,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","slug":"composite","tags":["Pattern","Composite"]},"prevItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"},"nextItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"}},"content":"### \uc694\uad6c\uc0ac\ud56d\\n\\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.\\n\\n- \uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4. \\n\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4.\\n\\n```java\\npublic interface FarePolicy {\\n int calculate(Path path, Passenger passenger, int fare);\\n}\\n\\npublic class BaseFarePolicy implements FarePolicy { ... }\\npublic class DistanceFarePolicy implements FarePolicy { ... }\\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\\n```\\n\\n![composite1](./composite1.png)\\n\\n### \ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30\\n\\n\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n```java\\npublic class SubwayFarePolicy implements FarePolicy {\\n\\n private final List farePolicies;\\n\\n public SubwayFarePolicy(final List farePolicies) {\\n this.farePolicies = farePolicies;\\n }\\n\\n @Override\\n public int calculate(final Path path, final Passenger passenger, final int fare) {\\n int calculatedFare = fare;\\n for (FarePolicy farePolicy : farePolicies) {\\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\\n }\\n return calculatedFare;\\n }\\n}\\n```\\n\\n\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4.\\n\\n![composite2](./composite2.png)\\n\\n### \uc815\ucc45\uc758 \uc21c\uc11c\\n\\n\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4. \\n\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4. \\nConfiguration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4. \\n\\n```java\\n@Configuration\\npublic class FareConfiguration {\\n\\n @Bean\\n public FarePolicy farePolicy() {\\n return new SubwayFarePolicy(List.of(\\n new BaseFarePolicy(),\\n new DistanceFarePolicy(),\\n new AgeDiscountFarePolicy()\\n ));\\n }\\n}\\n```\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?\\n\\n![composite3](./composite3.png)\\n\\nGOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n> \ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4. \\n\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4.\\n> \\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c\\n\\nComponent\\n\\n- \uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4 \\n- ex) \uc694\uae08 \uc815\ucc45(FarePolicy) \\n\\nLeaf\\n\\n- \uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9 \\n- ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy) \\n\\nComposite\\n\\n- \uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4 \\n- ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy) \\n\\nClient\\n\\n- \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c\\n\\n\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c \\nClient \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c\\n\\n### \ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84\\n\\n\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4. \\n\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4. \\n\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134 \\n\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"},{"id":"subway-retrospective","metadata":{"permalink":"/subway-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","description":"\uc9c0\ud558\ucca0 \ubbf8\uc158","date":"2023-05-25T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 25\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.91,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","slug":"subway-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"},"nextItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"}},"content":"### \uc9c0\ud558\ucca0 \ubbf8\uc158\\n\\n\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4. \\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nAPI\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4.\\n\\n**\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c**\\n\\n\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4.\\n\\n1. \uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95\\n2. \ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654**\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4.\\n\\n**\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac**\\n\\n\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4. \\n\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4. \\n\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n:::note \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n:::\\n\\n**\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131**\\n\\n\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4. \\n\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4. \\n\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4.\\n\\n\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4.\\n\\n```java\\n@Nested\\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\\n\\n @Test\\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\\n // given\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", 5);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \uc624\ub978\ucabd, 5);\\n\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", 3);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\", \uc624\ub978\ucabd, 7);\\n\\n // when\\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\\n\\n // then\\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\\n \uc870\ud68c_\uacb0\uacfc,\\n \ub178\uc120_\uc815\ubcf4(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0, \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\"),\\n \ub178\uc120_\uc815\ubcf4(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0, \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\")\\n );\\n }\\n}\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc758\uacac \uc870\uc728\ud558\uae30**\\n\\n\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4. \\n\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30**\\n\\n\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4. \\n\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4! \\n\\n**\ud3b8\ud55c \ubd84\uc704\uae30**\\n\\n\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"},{"id":"accidental-duplication","metadata":{"permalink":"/accidental-duplication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","source":"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","description":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.","date":"2023-05-24T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 24\uc77c","tags":[{"label":"DTO","permalink":"/tags/dto"}],"readingTime":7.525,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","slug":"accidental-duplication","tags":["DTO"]},"prevItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"},"nextItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"}},"content":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4.\\n\\n### \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815\\n\\n![\uc911\ubcf51](./\uc911\ubcf51.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?\\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4.\\n\\n> `ProductSaveRequest`\uc640 `ProductUpdateRequest`\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e\\n> \\n\\n\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4.\\n\\n> \uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!\\n> \\n\\n### \uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5\\n\\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n### \ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\\n\\n\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c? \\n\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c? \\n\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790! \\n\\n### \uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc\\n\\n\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4. \\nController\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\\n\u251c\u2500\u2500 dto\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n![\uc911\ubcf52](./\uc911\ubcf52.png)\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf53](./\uc911\ubcf53.png)\\n\\n\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic interface ProductSaveRequest {\\n\\n String getName();\\n\\n String getImage();\\n\\n Long getPrice();\\n}\\n\\n// ProductService\\npublic Long save(final ProductSaveRequest request) {\\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\\n return productDao.saveAndGetId(product);\\n}\\n```\\n\\n### \uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf54](./\uc911\ubcf54.png)\\n\\n\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4. \\n\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\\n\\n @NotBlank(message = \\"\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n @Size(min = 1, max = 100, message = \\"\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final String name;\\n\\n @NotBlank(message = \\"\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n private final String image;\\n\\n @Range(message = \\"\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final long price;\\n\\n public ProductRequest(final String name, final String image, final long price) {\\n this.name = name;\\n this.image = image;\\n this.price = price;\\n }\\n\\n @Override\\n public String getName() {\\n return name;\\n }\\n\\n @Override\\n public String getImage() {\\n return image;\\n }\\n\\n @Override\\n public long getPrice() {\\n return price;\\n }\\n}\\n\\n// ProductController\\n@PostMapping(\\"/products\\")\\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\\n final Long id = productService.save(request);\\n return ResponseEntity.created(URI.create(\\"/products/\\" + id)).build();\\n}\\n```\\n\\n### \uc815\ub9ac\\n\\n\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\\n1. Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n2. \uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4.\\n3. \uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n[https://techblog.woowahan.com/2647/](https://techblog.woowahan.com/2647/) \\n[https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/](https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/)"},{"id":"shopping-cart-retrospective","metadata":{"permalink":"/shopping-cart-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","description":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158","date":"2023-05-12T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 12\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.78,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","slug":"shopping-cart-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"},"nextItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"}},"content":"### \uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\nInterceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4. \\n\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5**\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\\n![dto1](./dto1.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4. \\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4. \\n\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4. \\n\\n![dto2](./dto2.png)\\n\\n**Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9**\\n\\n\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4. \\n\\n\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4. \\n\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4. \\n\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uae30\ub85d**\\n\\n\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4. \\n\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4. \\n\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!\\n\\n**\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30**\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"},{"id":"web-racing-car-retrospective","metadata":{"permalink":"/web-racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","description":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158","date":"2023-05-02T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 2\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.535,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","slug":"web-racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"}},"content":"### \uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\\n\\n\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4. \\n\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4. \\n\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4! \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4. \\n\\n\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4. \\n\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4. \\n\\n\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 `\ub09c\uc774\ub3c4 \ub192\uc774\uae30`\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30**\\n\\n```java\\n@SuppressWarnings(\\"NonAsciiCharacters\\")\\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\\n@Transactional\\n@AutoConfigureMockMvc\\n@SpringBootTest\\npublic class RacingGameIntegrationTest {\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ube44\ubc84\uc758 \uc131\uaca9** \\n\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84** \\n\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4. \\n\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00? \\n\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n**\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815** \\n\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."},{"id":"tecochat-retrospective-2","metadata":{"permalink":"/tecochat-retrospective-2","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","source":"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","description":"\ud504\ub860\ud2b8\uc5d4\ud2b8","date":"2023-05-01T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.67,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","slug":"tecochat-retrospective-2","tags":["TecoChat","Retrospective"]},"prevItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"},"nextItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"}},"content":"### \ud504\ub860\ud2b8\uc5d4\ud2b8\\n\\n\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4. \\n\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4. \\n\\n### \ubc31\uc5d4\ub4dc\\n\\n\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4. \\n\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Http Request Header\\n\\n\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n```ts\\nconst encodedName = () => {\\n const uriComponent = unescape(encodeURIComponent(name.value));\\n return btoa(uriComponent);\\n};\\n```\\n\\n### Elastic Beanstalk\\n\\n\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\nElastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\n\\n### Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac\\n\\n\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4. \\nRDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4. \\n\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4. \\n\\n### Elastic Beanstalk nginx \uc124\uc815\\n\\n\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 `.platform/nginx/conf.d/` \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### Jenkins\\n\\n\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nt4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4. \\n\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4. \\n\\n```groovy\\ntest {\\n maxHeapSize = \\"1024m\\"\\n}\\n```\\n\\n### Jenkins Blue Ocean\\n\\nBlue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4. \\n\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4. \\n\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 \\"Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?\\" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Elastic Beanstalk, AWS](https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html) \\n[EC2 AWS Graviton, AWS](https://aws.amazon.com/ko/ec2/graviton/) \\n[Default Memory Settings, AWS](https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings)"},{"id":"jenkins","metadata":{"permalink":"/jenkins","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","source":"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","title":"Jenkins\ub85c CI/CD \uc124\uc815","description":"\uc124\uc815 \ud658\uacbd","date":"2023-04-30T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 30\uc77c","tags":[{"label":"Jenkins","permalink":"/tags/jenkins"},{"label":"Elastic Beanstalk","permalink":"/tags/elastic-beanstalk"}],"readingTime":7.495,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","slug":"jenkins","tags":["Jenkins","Elastic Beanstalk"]},"prevItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"}},"content":"### \uc124\uc815 \ud658\uacbd\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI \\n\uc544\ud0a4\ud14d\uccd0: ARM \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small \\n\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk \\n\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository\\n\\n### \\\\[EC2 CLI\\\\] Swap \uba54\ubaa8\ub9ac \uc124\uc815\\n\\nt4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n``` bash\\n# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\\nsudo fallocate -l 2G /swapfile\\n\\n# \uad8c\ud55c \uc124\uc815\\nsudo chmod 600 /swapfile\\n\\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\\nsudo mkswap /swapfile\\nsudo swapon /swapfile\\n\\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\\nsudo vim /etc/fstab\\n```\\n\\n\\n### \\\\[EC2 CLI\\\\] jenkins \uc124\uce58\\n\\n```bash\\nsudo wget -O /etc/yum.repos.d/jenkins.repo \\\\\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\\nsudo yum upgrade\\nsudo yum install java-17-amazon-corretto-devel\\nsudo yum install jenkins\\nsudo systemctl daemon-reload\\n```\\n\\n[Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] Jenkins \uc2dc\uc791\\n\\n```bash\\nsudo systemctl enable jenkins\\nsudo systemctl start jenkins\\n```\\n\\nenable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx & git \uc124\uce58\\n\\n```bash\\nsudo yum install nginx\\nsudo systemctl enable nginx\\nsudo systemctl start nginx\\n\\nsudo yum install git\\n```\\n\\nnginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815\\n\\n\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4.\\n\\n```bash\\nupstream jenkins {\\n keepalive 32; # keepalive connections\\n server 127.0.0.1:8080; # jenkins ip and port\\n}\\n\\n# Required for Jenkins websocket agents\\nmap $http_upgrade $connection_upgrade {\\n default upgrade;\\n \'\' close;\\n}\\n\\nserver {\\n listen 80; # Listen on port 80 for IPv4 requests\\n\\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\\n\\n # this is the jenkins web root directory\\n # (mentioned in the output of \\"systemctl cat jenkins\\")\\n root /var/run/jenkins/war/;\\n\\n access_log /var/log/nginx/jenkins.access.log;\\n error_log /var/log/nginx/jenkins.error.log;\\n\\n # pass through headers from Jenkins that Nginx considers invalid\\n ignore_invalid_headers off;\\n\\n location ~ \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)$\\" {\\n # rewrite all static files into requests to the root\\n # E.g /static/12345678/css/something.css will become /css/something.css\\n rewrite \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)\\" /$1 last;\\n }\\n\\n location /userContent {\\n # have nginx handle all the static requests to userContent folder\\n # note : This is the $JENKINS_HOME dir\\n root /var/lib/jenkins/;\\n if (!-f $request_filename){\\n # this file does not exist, might be a directory or a /**view** url\\n rewrite (.*) /$1 last;\\n break;\\n }\\n sendfile on;\\n }\\n\\n location / {\\n sendfile off;\\n proxy_pass http://jenkins;\\n proxy_redirect default;\\n proxy_http_version 1.1;\\n\\n # Required for Jenkins websocket agents\\n proxy_set_header Connection $connection_upgrade;\\n proxy_set_header Upgrade $http_upgrade;\\n\\n proxy_set_header Host $host;\\n proxy_set_header X-Real-IP $remote_addr;\\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\\n proxy_set_header X-Forwarded-Proto $scheme;\\n proxy_max_temp_file_size 0;\\n\\n #this is the maximum upload size\\n client_max_body_size 10m;\\n client_body_buffer_size 128k;\\n\\n proxy_connect_timeout 90;\\n proxy_send_timeout 90;\\n proxy_read_timeout 90;\\n proxy_buffering off;\\n proxy_request_buffering off; # Required for HTTP CLI commands\\n proxy_set_header Connection \\"\\"; # Clear for keepalive\\n }\\n\\n}\\n```\\n\\nJenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4. \\n`/etc/nginx/conf.d`\xa0\uc544\ub798\xa0`default.conf`\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4. \\nnginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0`include /etc/nginx/conf.d/*.conf;`\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0`.conf`\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4. \\n\uc124\uc815 \ud6c4\xa0`sudo nginx -t`\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0`sudo systemctl restart nginx`\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins \uc811\uc18d\\n\\nJenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\nEC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4.\\n\\n![jenkins-start](./jenkins-start.png)\\n\\n\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 `sudo cat /var/lib/jenkins/secrets/initialAdminPasswor` \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 `install suggested plugins`\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4. \\n\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins Blue Ocean \uc124\uce58\\n\\nJenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[AWS IAM & EC2\\\\] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30\\n\\nS3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\nIAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4.\\n\\n1. \uc5d4\ud130\ud2f0 \uc120\ud0dd\\n\\n![aws-iam1](./aws-iam1.png)\\n\\n2. \uad8c\ud55c \ucd94\uac00\\n\\n![aws-iam2](./aws-iam2.png)\\n\\n3. \uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131\\n\\n![aws-iam3](./aws-iam3.png)\\n\\n4. \uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815\\n\\n![aws-iam4](./aws-iam4.png)\\n\\n### \\\\[AWS S3\\\\] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131\\n\\n\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4.\\n\\n- `\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8`\\n\\n![aws-s3](./aws-s3.png)\\n\\n### \\\\[Github\\\\] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131\\n\\nrepo, user:email \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4. \\n\\n### \\\\[Jenkins\\\\] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\\n\\n![jenkins-blue-ocean1](./jenkins-blue-ocean1.png)\\n\\n\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4. \\nJenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4. \\n\\n![jenkins-blue-ocean2](./jenkins-blue-ocean2.png)\\n\\n\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4.\\n\\n![jenkins-blue-ocean3](./jenkins-blue-ocean3.png)\\n\\n### \\\\[Github Repsoitory\\\\] Jenkinsfile \uc124\uc815\\n\\n\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n```bash\\npipeline {\\n agent any\\n stages {\\n stage(\'build and test\') {\\n steps {\\n sh \'/gradlew clean build\'\\n }\\n }\\n stage(\'zip\') {\\n steps {\\n sh \'mv ./build/libs/woowachat.jar .\'\\n sh \'zip -r woowachat.zip .platform delivery.jar Procfile\'\\n }\\n }\\n stage(\'upload\') {\\n steps {\\n sh \'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2\'\\n }\\n }\\n stage(\'deploy\') {\\n steps {\\n sh \'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\\"woowa-chat\\",S3Key=\\"woowachat.zip\\"\'\\n sh \'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}\'\\n }\\n }\\n }\\n}\\n```\\n\\n### \\\\[Github\\\\] Webhooks \uc124\uc815\\n\\n![github-hook](./github-hook.png)\\n\\npush \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c `http://Jenkins\uc8fc\uc18c/github-webhook/` \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Install Jenkins - CentOS, Jenkins](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \\n[Nginx Reverse Proxy Configuration, Jenkins](https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/) \\n[Amazon Corretto 17 JDK Install, AWS](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html) \\n[Amazon Linux 2023 packages, AWS](https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html)"},{"id":"tecochat-retrospective-1","metadata":{"permalink":"/tecochat-retrospective-1","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","description":"4\uc6d4 21\uc77c \uae08\uc694\uc77c","date":"2023-04-22T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 22\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.68,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","slug":"tecochat-retrospective-1","tags":["TecoChat","Retrospective"]},"prevItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"},"nextItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"}},"content":"### 4\uc6d4 21\uc77c \uae08\uc694\uc77c\\n\\n\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4. \\n\\n\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4. \\n`Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?` \\n\\n\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4. \\n\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4. \\n\\n\uc774\uac74 \ubabb\ucc38\uc9c0\\n\\n### \ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?\\n\\n\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4. \\n\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4. \\ndev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4.\\n\\n### \ub9d0\ub791\uc758 DM\\n\\n\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4. \\n\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\\n\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4. \\n\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!\\n\\n### \ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec\\n\\n\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4. \\n\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4. \\n\\n### GPT\\n\\n\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4. \\n\\n### Sonarcloud\\n\\n\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4. \\nSonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4. \\n\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4. \\nSonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4. \\n\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124\\n\\n### Tiptap\\n\\n\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\nTiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4. \\n\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4. \\napi \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c `
`\ub85c \ubcc0\ud658\ud588\ub2e4.  \\n\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c `\\\\n`\ub97c `
`\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4. \\n\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4. \\n\\n```ts\\nconst replaceCodeFences = (input: String) => {\\n const codeFencesRegex = /```([\\\\w-]*)\\\\n([\\\\s\\\\S]*?)\\\\n```/g;\\n return input\\n .replace(codeFencesRegex, (match, p1, p2) => {\\n const languageClass = p1 ? ` class=\\"language-${p1}\\"` : \\"\\";\\n return `
${p2}
`;\\n })\\n .replace(/\\\\n/g, \\"
\\");\\n};\\n```\\n\\nTiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\\n![tecochat](./teco-chat.png)\\n\\n### \ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9\\n\\n\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."},{"id":"book-leadership-and-self-deception","metadata":{"permalink":"/book-leadership-and-self-deception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","source":"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","description":"\ucc45 \uc815\ubcf4","date":"2023-04-08T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 8\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.16,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","slug":"book-leadership-and-self-deception","tags":["Book"]},"prevItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"},"nextItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c \\n> \uc544\ube48\uc800\uc5f0\uad6c\uc18c\\n> \\n\\n### \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\\n\\n\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4. \\n- \uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \\n- \uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704\\n\\n\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4. \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4. \\n\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4. \\n\\n\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098 \\n\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4. \\n\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\\n\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790. \\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4. \\nR. D. \ub7ad \\np.19\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4. \\np.66\\n>\\n\\n> \ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4. \\n\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4. \\n\uc54c\ub7ad, \ud0c1\ub2db\ud55c \\np.103\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4. \\n\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4. \\n\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\np.175\\n> \\n\\n> \uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0. \\np.188\\n> \\n\\n> \ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4. \\np.214\\n> \\n\\n> \ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4. \\n\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4. \\np.224\\n>\\n\\n> \uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4. \\np.280\\n>"},{"id":"innodb-lock","metadata":{"permalink":"/innodb-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-07T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 7\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"InnoDB","permalink":"/tags/inno-db"}],"readingTime":5.805,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"innodb-lock","tags":["DataBase","Lock","InnoDB"]},"prevItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"},"nextItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"}},"content":"## InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4. \\nInnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n:::note \ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd \\n\\n:::\\n\\n:::note \ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd \\n\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4.\\n\\n:::\\n\\n### Shared & Exclusive Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n**\uacf5\uc720 \uc7a0\uae08(S, shared lock)**\\n\\n\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;`\\n\\n**\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)** \\n\\n\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 FOR UPDATE;`\\n\\n### Intention Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4. \\n\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n**\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)**\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n**\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)** \\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **\\n\\n| | X | IX | S | IS |\\n| --- | --- | --- | --- | --- |\\n| X | Conflict | Conflict | Conflict | Conflict |\\n| IX | Conflict | Compatible | Conflict | Compatible |\\n| S | Conflict | Conflict | Compatible | Compatible |\\n| IS | Conflict | Compatible | Compatible | Compatible |\\n\\n### Record Locks\\n\\n\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4. \\n\\n### Gap Locks\\n\\n\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### Next-Key Locks\\n\\n\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4. \\n`REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4. \\n\\n### AUTO-INC Locks\\n\\n`AUTO_INCREMENT` \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 `INSERT`\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. \\nInnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 `INSERT`\ub098 `REPLACE` \ubb38\uc7a5\uc5d0\uc11c `AUTO_INCREMENT` \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4.\\n\\n### \uc7a0\uae08 \uc608\uc2dc\\n\\n```sql\\n-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id = 10 for update;\\n\\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id > 100 for update;\\n\\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Optimistic and Pessimistic record locking, IBM](https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking) \\n[MySQL Innodb Locks, cecil1018](https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/) \\n[MySQL 8.0 InnoDB Locks, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html) \\n[Locks Set by Different SQL Statements in InnoDB, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html)"},{"id":"mysql-lock","metadata":{"permalink":"/mysql-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-06T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 6\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"MySQL","permalink":"/tags/my-sql"}],"readingTime":4.405,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"mysql-lock","tags":["DataBase","Lock","MySQL"]},"prevItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"},"nextItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"}},"content":"## MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4. \\nMySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ub77d(Global lock)\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4. \\n - \uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4.\\n - \uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4.\\n\\n\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- GLOBAL LOCK\\nFLUSH TABLES WITH READ LOCK;\\n-- UNLOCK\\nUNLOCK TABLES;\\n\\n-- BACKUP LOCK\\nLOCK INSTANCE FOR BACKUP;\\n-- UNLOCK\\nUNLOCK INSTANCE;\\n```\\n\\n:::note MyISAM\\n\\nMySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4.\\n\\n:::\\n\\n### \ud14c\uc774\ube14 \ub77d(Table lock)\\n\\n\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4. \\n\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4. \\nInnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4.\\n\\n```sql\\n-- TABLE LOCK\\nLOCK TABLES table_name [ READ | WRITE ]\\n\\n-- UNLOCK\\nUNLOCK TABLES;\\n```\\n\\n### \ub124\uc784\ub4dc \ub77d(Named lock)\\n\\n\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\\nSELECT GET_LOCK(\'aGVyYg==\', 1);\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\\nSELECT IS_FREE_LOCK(\'aGVyYg==\');\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\\nSELECT RELEASE_LOCK(\'aGVyYg==\');\\n\\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\\nSELECT RELEASE_ALL_LOCKS();\\n```\\n\\n### \uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4.\\n\\n```sql\\n-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi](https://gywn.net/2013/12/mysql-user-level-lock/) \\n[Locking Functions, MySQL 5.7 Reference](https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks) \\n[Locking Functions, MySQL 8.0 Reference](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks)"},{"id":"transaction-and-isolation","metadata":{"permalink":"/transaction-and-isolation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","source":"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","description":"\ud2b8\ub79c\uc7ad\uc158(Transaction)","date":"2023-04-05T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 5\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Transaction","permalink":"/tags/transaction"},{"label":"Isolation","permalink":"/tags/isolation"}],"readingTime":9.68,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","slug":"transaction-and-isolation","tags":["DataBase","Transaction","Isolation"]},"prevItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"},"nextItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"}},"content":"## \ud2b8\ub79c\uc7ad\uc158(Transaction)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4. \\n\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)\\n\\n\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4. \\n\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4. \\n\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c) \\n\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\\n:::info \uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14\\n\\n\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n- \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)\\n- \ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)\\n\\n:::\\n\\n## \uaca9\ub9ac \uc218\uc900(Isolation level)\\n\\n\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4. \\n\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, `SERIALIZABLE`\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### READ UNCOMMITTED\\n\\n\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 `COMMIT`\uc774\ub098 `ROLLBACK` \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4. \\n\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c `READ COMMITTED` \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ UNCOMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: INSERT(Alice)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: COMMIT(Alice)\\n```\\n\\n### READ COMMITTED\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\n\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uba70, \uc628\ub77c\uc778 \uc11c\ube44\uc2a4\uc5d0\uc11c \uac00\uc7a5 \ub9ce\uc774 \uc120\ud0dd\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\n`REPEATABLE READ`\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 `NON-REPEATABLE READ` \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ COMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n Alice->>Database: COMMIT\\n```\\n\\n### REPEATABLE READ\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\nMySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4. \\n\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n - \ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4.\\n - Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4.\\n - Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4.\\n - `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\nInnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n```\\n\\n:::note \uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)\\n\\n\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.\\n\\n:::\\n\\n:::note MVCC(Multi Version Concurrency Control)\\n\\n\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4.\\n - PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4.\\n - Oracle, InnoDB\ub294 `Undo log`\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)\\n\\n\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4.\\n\\n:::\\n\\n### SERIALIZABLE\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4. \\nInnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4. \\n\\n## \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c\\n\\n\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n| \uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c | \ub354\ud2f0 \ub9ac\ub4dc | \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c | \ud32c\ud140 \ub9ac\ub4dc |\\n| --- | --- | --- | --- |\\n| READ UNCOMMITTED | O | O | O |\\n| READ COMMITTED | X | O | O |\\n| REPEATABLE READ | X | X | O(InnoDB\ub294 X) |\\n| SERIALIZABLE | X | X | X |\\n\\n### \ub354\ud2f0 \ub9ac\ub4dc(Dirty read)\\n\\n\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1 \\n\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4. \\n\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0\\n\\n### \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: NON REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Bob\\n```\\n\\n### \ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: PHANTOM READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 1\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: INSERT(Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 2\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Isolation Level, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)"},{"id":"test-double","metadata":{"permalink":"/test-double","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","source":"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","description":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?","date":"2023-04-04T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 4\uc77c","tags":[{"label":"Test","permalink":"/tags/test"},{"label":"Mock","permalink":"/tags/mock"}],"readingTime":4.52,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","slug":"test-double","tags":["Test","Mock"]},"prevItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"},"nextItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"}},"content":"### \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?\\n\\n\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4. \\nGerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4.\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4. \\n\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870**\\n\\n```mermaid\\nflowchart LR\\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\\n Fake --\x3e TestDouble\\n```\\n\\n### \ub354\ubbf8(Dummy)\\n\\n\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n### \uc2a4\ud141(Stub)\\n\\n\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \uc2a4\ud30c\uc774(Spy)\\n\\n\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4. \\n\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4. \\n\\n### \ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)\\n\\n\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4. \\n\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### \uac00\uc9dc(Fake)\\n\\nDOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4. \\n\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note DOC(depended-on component)\\n\\n\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4. \\n\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4. \\n\\n:::\\n\\n### \uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84\\n\\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4. \\n\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4. \\n\\n| TestDouble | Mock | Stub |\\n| --- | --- | --- |\\n| \ud3ec\ud568 \uc720\ud615 | \ubaa9, \uc2a4\ud30c\uc774 | \uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c |\\n| \uc6a9\ub3c4 | \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9 | \ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9 |\\n| \uc124\uba85 | SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9 | SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9\\n| \uc608\uc2dc | \uc774\uba54\uc77c \ubc1c\uc1a1 | \ub370\uc774\ud130 \uac80\uc0c9 |\\n\\n:::note SUT(system under test)\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c \\n\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1\\n\\n:::\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504 \\n\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0 \\n[\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler](https://www.martinfowler.com/bliki/TestDouble.html) \\n[\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib](https://johngrib.github.io/wiki/test-terms/) \\n[Test Double, Gerard Meszaros](http://xunitpatterns.com/Test%20Double.html)"},{"id":"java-class-file","metadata":{"permalink":"/java-class-file","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","source":"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","description":"\ud074\ub798\uc2a4 \ud30c\uc77c","date":"2023-04-03T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 3\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Class","permalink":"/tags/class"}],"readingTime":5.63,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","slug":"java-class-file","tags":["Java","Class"]},"prevItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"},"nextItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"}},"content":"### \ud074\ub798\uc2a4 \ud30c\uc77c\\n\\n\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?\\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd\\n\\n8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4. \\n16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4. \\n\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4. \\n\\nu1 \u2192 unsigned 1byte \\nu2 \u2192 unsigned 2byte \\nu4 \u2192 unsigned 4byte \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870\\n\\n```\\nClassFile {\\n u4 magic;\\n u2 minor_version;\\n u2 major_version;\\n u2 constant_pool_count;\\n cp_info constant_pool[constant_pool_count-1];\\n u2 access_flags;\\n u2 this_class;\\n u2 super_class;\\n u2 interfaces_count;\\n u2 interfaces[interfaces_count];\\n u2 fields_count;\\n field_info fields[fields_count];\\n u2 methods_count;\\n method_info methods[methods_count];\\n u2 attributes_count;\\n attribute_info attributes[attributes_count];\\n}\\n```\\n\\n### \ub9e4\uc9c1\ub118\ubc84\\n\\n\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804\\n\\n\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4. \\n- Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D\\n\\n\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 `UnsupportedClassVersionError` \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n**class\xa0file format major versions**\\n\\n| Java SE | Released | Major | Supported majors |\\n| --- | --- | --- | --- |\\n| 8 | March 2014 | 52 | 45 .. 52 |\\n| 9 | September 2017 | 53 | 45 .. 53 |\\n| 10 | March 2018 | 54 | 45 .. 54 |\\n| 11 | September 2018 | 55 | 45 .. 55 |\\n| 12 | March 2019 | 56 | 45 .. 56 |\\n| 13 | September 2019 | 57 | 45 .. 57 |\\n| 14 | March 2020 | 58 | 45 .. 58 |\\n| 15 | September 2020 | 59 | 45 .. 59 |\\n| 16 | March 2021 | 60 | 45 .. 60 |\\n| 17 | September 2021 | 61 | 45 .. 61 |\\n\\n### \uc0c1\uc218 \ud480\\n\\n2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4. \\n\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4. \\nJVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4.\\n\\n### \uc561\uc138\uc2a4 \ud50c\ub798\uadf8\\n\\n\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4. \\n- \uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. `ACC_PUBLIC` xor `ACC_INTERFACE` xor `ACC_ABSTRACT`\\n\\n\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4.\\n\\n**Class access and property modifiers**\\n\\n| Flag Name | Value | Interpretation |\\n| --- | --- | --- |\\n| ACC_PUBLIC | 0x0001 | Declared\xa0public; may be accessed from outside its package. |\\n| ACC_FINAL | 0x0010 | Declared\xa0final; no subclasses allowed. |\\n| ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction. |\\n| ACC_INTERFACE | 0x0200 | Is an interface, not a class. |\\n| ACC_ABSTRACT | 0x0400 | Declared\xa0abstract; must not be instantiated. |\\n| ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |\\n| ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |\\n| ACC_ENUM | 0x4000 | Declared as an\xa0enum\xa0type. |\\n| ACC_MODULE | 0x8000 | Is a module, not a class or interface. |\\n\\n### this_class\\n\\n\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 `CONSTANT_Class_infoclass` \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### super_class\\n\\n\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 `java.lang.Object`\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.\\n\\n### interface, field, method\\n\\n\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4. \\ninterface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4.\\n\\n### attributes\\n\\n\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85 \\n\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234\\n\\nIntelliJ plugin - BinEd \\nIntelliJ plugin - jclasslib Bytecode Viewer\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654 \\n[Class file in Java, File Format](https://docs.fileformat.com/ko/programming/class/) \\n[java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html) \\n[java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html)"},{"id":"custom-jdbc-template","metadata":{"permalink":"/custom-jdbc-template","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","description":"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.","date":"2023-04-02T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 2\uc77c","tags":[{"label":"JDBC","permalink":"/tags/jdbc"},{"label":"Java","permalink":"/tags/java"}],"readingTime":9.025,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","slug":"custom-jdbc-template","tags":["JDBC","Java"]},"prevItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4. \\n\\n### \uae30\uc874 \ucf54\ub4dc\\n\\n\\n\\n\\n```java\\npublic class User {\\n private final int id;\\n private final String name;\\n\\n public User(final int id, final String name) {\\n this.id = id;\\n this.name = name;\\n }\\n\\n public int getId() {\\n return id;\\n }\\n\\n public String getName() {\\n return name;\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final ConnectionPool connectionPool;\\n\\n public UserDao(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void insert(final String name) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setString(1, name);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public void delete(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"DELETE FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public User findById(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n if (resultSet.next()) {\\n return new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n );\\n }\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n return null;\\n }\\n\\n public List findAll() {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n ));\\n }\\n return result;\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class ConnectionPool {\\n private static final String SERVER = \\"localhost:13306\\";\\n private static final String DATABASE = \\"chess\\";\\n private static final String OPTION = \\"?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true\\";\\n private static final String URL = \\"jdbc:mysql://\\" + SERVER + \\"/\\" + DATABASE + OPTION;\\n private static final String USERNAME = \\"root\\";\\n private static final String PASSWORD = \\"root\\";\\n\\n private final AtomicInteger index = new AtomicInteger();\\n private final List connections;\\n\\n public ConnectionPool(final int connectionCount) {\\n connections = generateConnections(connectionCount);\\n }\\n\\n private List generateConnections(final int connectionCount) {\\n return Stream.generate(this::generateConnection)\\n .limit(connectionCount)\\n .collect(toList());\\n }\\n\\n private Connection generateConnection() {\\n try {\\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\\n } catch (SQLException e) {\\n throw new IllegalStateException(\\"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\");\\n }\\n }\\n\\n public Connection getConnection() {\\n int currentIndex = index.getAndIncrement();\\n return connections.get(currentIndex % connections.size());\\n }\\n}\\n```\\n\\n\\n\\n\\n### SELECT, DELETE \uc911\ubcf5 \uc81c\uac70\\n\\n\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1 \\n\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218 \\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n```java\\npublic void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n executeUpdate(query, name);\\n}\\n\\npublic void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n executeUpdate(query, userId);\\n}\\n\\nprivate void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758\\n\\n\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. \\n\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ucf5c\ubc31(Callback)\\n\\n\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4. \\n\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n```mermaid\\nflowchart LR\\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31\\n```\\n\\n:::\\n\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\nexecuteQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4. \\n\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n User mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c\\n\\n\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c? \\n\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java\\npublic User findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return queryForSingleResult(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n }, userId);\\n}\\n\\nprivate User queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return rowMapper.mapRow(resultSet);\\n }\\n return null;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c\\n\\n\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4.\\n\\n```java\\npublic List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return query(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n });\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30\\n\\n\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n T mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\n```\\n\\n### \uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30\\n\\n\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4. \\n\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final RowMapper rowMapper = resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n };\\n private final JdbcTemplate jdbcTemplate;\\n\\n public UserDao(final JdbcTemplate jdbcTemplate) {\\n this.jdbcTemplate = jdbcTemplate;\\n }\\n\\n public void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n jdbcTemplate.executeUpdate(query, name);\\n }\\n\\n public void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n jdbcTemplate.executeUpdate(query, userId);\\n }\\n\\n public Optional findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\\n }\\n\\n public List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return jdbcTemplate.query(query, rowMapper);\\n }\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic class JdbcTemplate {\\n private final ConnectionPool connectionPool;\\n\\n public JdbcTemplate(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public Optional queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return Optional.of(rowMapper.mapRow(resultSet));\\n }\\n return Optional.empty();\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n private ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters\\n ) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n }\\n\\n public List query(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n"},{"id":"woowacourse-level1-retrospective","metadata":{"permalink":"/woowacourse-level1-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","description":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.","date":"2023-04-01T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 1\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.48,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","slug":"woowacourse-level1-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"},"nextItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"}},"content":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4. \\n\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4. \\n\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4. \\n\\n### Keep\\n\\n**\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30** \\n\\n\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0 \\n\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0 \\n\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4. \\n\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22 \\n\\n\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4. \\n\\n**\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30** \\n\\n10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :) \\n\\n**\uae00\uc4f0\uae30** \\n\\n\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4. \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4. \\n\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4. \\n\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4. \\n\\n**\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514** \\n\\n\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4. \\n\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4. \\n\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098? \\n\\n**\ub808\ubca8 \uc778\ud130\ubdf0**\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370 \\n\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4. \\n\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n- \ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30 \\n- \ub450\uad04\uc2dd \ud45c\ud604\\n- \uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30 \\n- \uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30\\n- \uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30\\n- \ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)\\n- \uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30\\n- \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30\\n\\n### Problem\\n\\n**\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4. \\n\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4. \\n\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4. \\n\\n**\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871** \\n\\n\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Try\\n\\n**\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?** \\n\\n\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 `\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)` \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4. \\n\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694? \\n\\n**\uae30\uc220\uc801\uc778 \ubd80\ubd84** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4. \\n\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70 \\n\\n\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4. \\n\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."},{"id":"chess-retrospective","metadata":{"permalink":"/chess-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","description":"\uccb4\uc2a4","date":"2023-03-31T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 31\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.63,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","slug":"chess-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"},"nextItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"}},"content":"### \uccb4\uc2a4\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4! \\n\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4. \\n \\n\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n**\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80** \\nRank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4. \\n\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2) \\n\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n**\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80** \\n\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4. \\n\\n**\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80** \\n\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4. \\n\\n**\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9** \\n\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4. \\n\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n- \uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95 \\n- \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95 \\n\\n\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4. \\n\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n- \ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4. \\n- \uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4. \\n- \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4. \\n\\n\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4. \\n\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac) \\n\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)\\n\\n\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d \\n\\n**\ubd80\uac00\uc801\uc778 \ubd80\ubd84**\\n\\n\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4. \\n- \ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604 \\n- ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac \\n- \uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.) \\n\\n\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84** \\nDB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n**\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10** \\n\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DAO \uc911\ubcf5 \uc81c\uac70**\\n\\n\ud504\ub864\ub85c\uadf8\uc5d0 [\uae00](https://prolog.techcourse.co.kr/studylogs/2947)\uc744 \uc791\uc131\ud588\ub2e4. \\nDAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc0dd\uac01\ud558\uae30** \\n\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4! \\n\\n**\ubbf8\uc158 \ubab0\uc785\ud558\uae30** \\n\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4. \\n\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04 \\n\\n**\uc194\uc9c1\ud568** \\n\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4. \\n\\n\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"},{"id":"grasp","metadata":{"permalink":"/grasp","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx","source":"@site/blog/2023-1/2023-03-30-GRASP.mdx","title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","description":"GRASP(General Responsibility Assignment Software Pattern)","date":"2023-03-30T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 30\uc77c","tags":[{"label":"GRASP","permalink":"/tags/grasp"},{"label":"OOP","permalink":"/tags/oop"}],"readingTime":8.085,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","slug":"grasp","tags":["GRASP","OOP"]},"prevItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"},"nextItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"}},"content":"### GRASP(General Responsibility Assignment Software Pattern)\\n\\n\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134\\n\\n\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4.\\n\\n### \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)\\n\\nQ: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?\\n\\nA: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4.\\n\\n### \ucc3d\uc870\uc790 \ud328\ud134(Creator)\\n\\nQ: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?\\n\\nA: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)\\n\\nQ: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?\\n\\nA: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uacb0\ud569\ub3c4(Coupling)\\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.17\\n> \\n\\n\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4.\\n- \uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4.\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)\\n\\n### \ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)\\n\\nQ. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uc751\uc9d1\ub3c4(Cohesion)\\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.26\\n> \\n\\n\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)\\n- \uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4.\\n- \ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4.\\n- \uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4.\\n\\n### \ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)\\n\\nQ. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?\\n\\nA. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n\\n\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c\\n\\n- \uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4.\\n- \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4.\\n- \ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4.\\n\\n### \ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)\\n\\nQ. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?\\n\\nA. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)\\n\\n\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.\\n\\n\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\\n\\nQ. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?\\n\\nA. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n### \uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)\\n\\nQ. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4.\\n\\n### \uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)\\n\\nQ. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4.\\n\\n\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815\\n\\n- \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4.\\n- \ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, [\uc870\uc601\ud638](http://aeternum.egloos.com/)\\n\\nApplying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman\\n\\n[GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c](https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397)"},{"id":"blackjack-retrospective","metadata":{"permalink":"/blackjack-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","description":"\ube14\ub799\uc7ad","date":"2023-03-14T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.105,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","slug":"blackjack-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"},"nextItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"}},"content":"### \ube14\ub799\uc7ad\\n\\n\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4. \\n\\n\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc \\n\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4. \\n\\"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?\\" \\n\\n\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c? \\n\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4. \\n\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4. \\n\\n\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30** \\n\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4. \\n\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?\\n\\n**\uccb4\ub825 \uad00\ub9ac** \\n\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4.\\n\\n**\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30** \\n\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc0c1\ud0dc \ud328\ud134** \\n\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4. \\n\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4. \\n\\n**\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654** \\n\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4! \\n\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4. \\n\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc \\n\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4. \\n\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc) \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc0dd\uac01 \uc815\ub9ac** \\n\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4. \\n\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84** \\n\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4. \\n\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84** \\n\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4. \\n\\n\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"},{"id":"ladder-retrospective","metadata":{"permalink":"/ladder-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","description":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30","date":"2023-02-26T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 26\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":10.22,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","slug":"ladder-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"},"nextItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"}},"content":"### \uc0ac\ub2e4\ub9ac \ud0c0\uae30\\n\\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4.\\n\\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4.\\n\\n1. LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n2. Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n\\n### Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\n\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4. \\n\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4. \\n\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n\\n LadderGame --\x3e Position\\n Ladder --\x3e Position\\n Items --\x3e Position\\n Line --\x3e Position\\n Players --\x3e Position\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item\\n Players --\x3e Player\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n final Map result = new LinkedHashMap<>();\\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\\n for (Position position : Position.range(players.count())) {\\n final Position resultPosition = ladder.play(position);\\n result.put(players.get(position), items.get(resultPosition));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\nPosition\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\n\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n Line --\x3e Position\\n\\n Players --\x3e Ladder\\n Player --\x3e Ladder\\n\\n Item --\x3e Position\\n Player --\x3e Position\\n\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item --\x3e ItemName\\n Players --\x3e Player --\x3e PlayerName\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n OutputView --\x3e LadderMessageGenerator\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\\n final Map playResult = players.play(ladder);\\n\\n final Map result = new LinkedHashMap<>();\\n for (Player player : playResult.keySet()) {\\n result.put(player, toItem(playResult.get(player)));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30** \\n\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4. \\n\\n**\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30** \\n\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72\\n\\n**README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c** \\n\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4.\\n\\n**\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30** \\n\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4. \\n\\n**PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30** \\n\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4. \\nPR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4. \\ngithub pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30** \\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784** \\nPlayers\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\\n\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4. \\n\\n\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4.\\n\\n**\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900** \\n\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4. \\n\\n**\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30** \\nPosition\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0~19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0~19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4. \\n\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4. \\n\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4! \\n\\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4. \\n\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!\\n\\n\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"},{"id":"racing-car-retrospective","metadata":{"permalink":"/racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","description":"\uc790\ub3d9\ucc28 \uacbd\uc8fc","date":"2023-02-14T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.56,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","slug":"racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"},"nextItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"}},"content":"### \uc790\ub3d9\ucc28 \uacbd\uc8fc\\n\\n\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4. \\n\\n\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4. \\n\\n\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4. \\nmermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n- \ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4. \\n- github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```mermaid\\n---\\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\\n---\\ngraph TD\\n Cars --\x3e Car\\n Car --\x3e Name\\n Car --\x3e Position\\n RacingGame --\x3e Count\\n RacingGame --\x3e NumberGenerator\\n RacingGame --\x3e Cars\\n RacingCarController --\x3e RacingGame\\n RandomNumberGenerator -.-> NumberGenerator\\n RacingCarController --\x3e InputView\\n InputView --\x3e InputValidator\\n RacingCarController --\x3e OutputView\\n```\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4.\\n\\n\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4. \\n\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4. \\n\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc \\n\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4.\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**Assertions extracting**\\n\\n\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4. \\n\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4.\\n\\n```java\\n@Test\\nvoid extracting() {\\n final Cars cars = new Cars(List.of(\\"car1\\", \\"car2\\"));\\n\\n assertThat(cars.getCars())\\n .extracting(Car::getName)\\n .containsExactly(\\"car1\\", \\"car2\\");\\n}\\n```\\n\\n---\\n\\n\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4.\\n\\n**\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4. \\n\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n**\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4. \\n\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc \\n\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9**\\n\\n\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4. \\n\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4. \\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4. \\n\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4. \\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4. \\n\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?) \\n\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4.\\n\\n\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4. \\n\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4. \\n\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4. \\n\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00? \\n\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\\n\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc. \\n\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."},{"id":"parameterized-tests","metadata":{"permalink":"/parameterized-tests","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx","source":"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx","title":"Parameterized Tests","description":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.","date":"2023-02-12T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 12\uc77c","tags":[{"label":"Java","permalink":"/tags/java"}],"readingTime":3.17,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Parameterized Tests","slug":"parameterized-tests","tags":["Java"]},"prevItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"},"nextItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"}},"content":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4. \\n\uc774 \ub54c `@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4.\\n\\n## Argument Sources\\n\\n`@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4. \\nJUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### Value Source\\n\\n\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4. \\n- short, int, long, float, double\\n- byte, char, boolean, String, Class \\n\\n```java\\n@ParameterizedTest\\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\\nvoid valueTest(final int value) {\\n Assertions.assertThat(value).isPositive();\\n}\\n```\\n\\n### Null & Empty Source\\n\\nnull \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nEmpty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n- String\\n- java.util.List, java.util.Set, java.util.Map\\n- primitive arrays \u2014 ex) int[]\\n- object arrays \u2014 ex) String[]\\n\\n```java\\n@ParameterizedTest\\n@NullAndEmptySource\\nvoid nullAndEmptyTest(final String value) {\\n Assertions.assertThat(value).isNullOrEmpty();\\n}\\n```\\n\\n### Enum Source\\n\\nEnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\nenum Day {\\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\\n}\\n\\n@ParameterizedTest\\n@EnumSource(Day.class)\\nvoid enumTest(final Day day) {\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)\\n\\n```java\\n@ParameterizedTest\\n@EnumSource(value = Day.class, names = {\\"SATURDAY\\", \\"SUNDAY\\"}, mode = Mode.EXCLUDE)\\nvoid enumTest(final Day day) {\\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n### CSV Source\\n\\ncsv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@CsvSource({\\"1,1\\", \\"2,4\\", \\"3,9\\", \\"4,16\\"})\\nvoid csvTest(final int number, final int result) {\\n assertThat(number * number).isEqualTo(result);\\n}\\n```\\n\\n### Method Source\\n\\n\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@MethodSource\\nvoid methodTest(final List numbers, final int count) {\\n assertThat(numbers).hasSize(count);\\n}\\n\\nprivate static Stream methodTest() {\\n return Stream.of(\\n Arguments.of(List.of(1), 1),\\n Arguments.of(List.of(1, 2), 2),\\n Arguments.of(List.of(1, 2, 3), 3)\\n );\\n}\\n```\\n\\n### ETC.\\n\\n\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n- CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource\\n- ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)"},{"id":"intellij-settings","metadata":{"permalink":"/intellij-settings","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","source":"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","title":"IntelliJ \uc124\uc815","description":"Import \uc790\ub3d9 \uc801\uc6a9","date":"2023-01-30T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 30\uc77c","tags":[{"label":"IntelliJ","permalink":"/tags/intelli-j"}],"readingTime":0.465,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"IntelliJ \uc124\uc815","slug":"intellij-settings","tags":["IntelliJ"]},"prevItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"},"nextItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"}},"content":"### Import \uc790\ub3d9 \uc801\uc6a9\\n\\nPrefrences > Editor > General > Auto Import > Add unambiguous imports on the fly\\n\\n![auto-import](./auto-import.png)\\n\\n### \uc800\uc7a5\uc2dc \ub3d9\uc791\\n\\nPrefrences > Tools > Actions on Save\\n\\n![actions-on-save](./actions-on-save.png)\\n\\nReformat Code: Code Reformmating\\n\\nOptimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70\\n\\nRearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c\\n\\n### \uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9\\n\\nPrefrences > Editor > Code Style > Java > Code Generation > Final Modifier\\n\\n![final-modifier](./final-modifier.png)"},{"id":"kotlin-null","metadata":{"permalink":"/kotlin-null","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","source":"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","description":"nullable \ud0c0\uc785","date":"2023-01-16T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 16\uc77c","tags":[{"label":"Kotlin","permalink":"/tags/kotlin"}],"readingTime":4.225,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","slug":"kotlin-null","tags":["Kotlin"]},"prevItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"},"nextItem":{"title":"JSR-310","permalink":"/jsr-310"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n### nullable \ud0c0\uc785\\n\\n\ucf54\ud2c0\ub9b0\uc740 `NullPointerException` \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4. \\n\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4.\\n\\n```kotlin\\nval number: Int?\\n```\\n\\n\ud0c0\uc785 \ub4a4\uc5d0 `?`\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\ub9cc\uc57d `?`\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4.\\n\\n### `?.` Safe Calls \uc5f0\uc0b0\uc790\\n\\n\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 `?.` \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n\\n\\n\\n```java\\npublic String repeat(String word) {\\n if (word == null) {\\n return null;\\n }\\n return word.repeat(2);\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun repeat(word: String?): String? {\\n return word?.repeat(2)\\n}\\n```\\n\\n\\n\\n\\n### `?:` \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\\n\\n\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c? \\n\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic String stringSafe(String word) {\\n if (word == null) {\\n return \\"\\";\\n }\\n return word;\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun stringSafe(word: String?): String {\\n return word ?: \\"\\"\\n}\\n```\\n\\n\\n\\n\\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```kotlin\\nuserRepository.findByName(name) ?: throw IllegalArgumentException()\\n```\\n\\n### `!!` \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790\\n\\n!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4. \\n\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4. \\n\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n```kotlin\\nval length: Int = word!!.length\\n```\\n\\n### `as?` \uc548\uc804\ud55c \uce90\uc2a4\ud305\\n\\n\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 `ClassCastException`\uc774 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4. \\n\\n\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n```kotlin\\nval value: Int? = something as? Int\\n```\\n\\n### List\uc5d0\uc11c\uc758 null \ucc98\ub9ac\\n\\nList\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 `filterNotNull` \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4.\\n\\n```kotlin\\nval foodsWithNull: List = listOf(\\"Pizza\\", \\"Cheese\\", null, \\"Potato\\")\\nval foods = foodsWithNull.filterNotNull()\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [Kotlin in Action](https://product.kyobobook.co.kr/detail/S000001804588)\\n- [Effective Kotlin Item 8](https://product.kyobobook.co.kr/detail/S000001033129)\\n- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin/null-safety)\\n- [Kotlin NullSafety](https://kotlinlang.org/docs/null-safety.html)"},{"id":"jsr-310","metadata":{"permalink":"/jsr-310","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx","source":"@site/blog/2023-1/2023-01-08-JSR-310.mdx","title":"JSR-310","description":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API","date":"2023-01-08T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 8\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Time","permalink":"/tags/time"}],"readingTime":1.685,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"JSR-310","slug":"jsr-310","tags":["Java","Time"]},"prevItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"},"nextItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"}},"content":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API \\nISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131 \\n\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131\\n\\n:::note ISO-8601\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900\\n\\n:::\\n\\n### LocalDate, LocalTime, LocalDateTime\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### Instant\\n\\n\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4 \\n\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604\\n\\n### Duration, Period\\n\\n\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### TemporalAdjusters\\n\\n\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9 \\n\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5\\n\\n```java\\n@FunctionalInterface\\npublic interface TemporalAdjuster {\\n Temporal adjustInto(Temporal temporal);\\n}\\n```\\n\\n### DateTimeFormatter\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4 \\n\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5\\n\\n### ZoneId, ZoneOffset\\n\\nZoneId\ub294 \uc9c0\uc5ed ID\ub294 `\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019` \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9 \\nZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9\\n\\n```java\\nInstant instant = Instant.now();\\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158](https://product.kyobobook.co.kr/detail/S000001810171)\\n- [Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API](https://d2.naver.com/helloworld/645609)\\n- [ISO-8601](https://www.w3.org/TR/NOTE-datetime)\\n- [JSR-310 Spec](https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4)\\n- [Temporal Adjuster](https://www.baeldung.com/java-temporal-adjuster)\\n- [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)"},{"id":"the-essence-of-object-orientation","metadata":{"permalink":"/the-essence-of-object-orientation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","source":"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","description":"\ucc45 \uc815\ubcf4","date":"2023-01-07T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 7\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.415,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","slug":"the-essence-of-object-orientation","tags":["Book"]},"prevItem":{"title":"JSR-310","permalink":"/jsr-310"},"nextItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574 \\n> \uc870\uc601\ud638\\n> \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4. \\n\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4. \\n\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4. \\n\\n\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0 \\n\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4.\\n\\n### \ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173\\n\\n\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4.\\n\\n- \uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558\\n- \ucc45\uc784\uc758 \ucd94\uc0c1\ud654\\n\\n\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4.\\n\\n- \uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac\\n\\n\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4.\\n\\n- \ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558\\n\\n\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4.\\n\\n- \uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00\\n\\n\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4.\\n\\n- \uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\np.21\\n> \\n\\n> \uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\\np.33\\n> \\n\\n> **\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8**\\n> \\n> \\n> \uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95\\n> \\n> \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\\n> p.35\\n> \\n\\n> \ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\np.38\\n> \\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\\np.105\\n> \\n\\n> \ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\\np.158\\n>"},{"id":"2022-retrospective","metadata":{"permalink":"/2022-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","title":"2022\ub144 \ud68c\uace0","description":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70","date":"2023-01-02T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 2\uc77c","tags":[{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.705,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"2022\ub144 \ud68c\uace0","slug":"2022-retrospective","tags":["Retrospective"]},"prevItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"},"nextItem":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","permalink":"/book-writer"}},"content":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70 \\n\\n### \uc804\uc5ed\\n\\n\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4. \\n\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0. \\n\\n\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4. \\n\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4. \\n\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4. \\n\\n### \uc790\ubc14\\n\\n\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 [\uc790\ubc14 \uacf5\ud654\uad6d](https://jojoldu.tistory.com/609) \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4.\\n\\n23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4. \\n\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud130\ub514\\n\\n\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0 \\n\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4. \\n\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\\n\\n\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4. \\n\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4. \\n\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4. \\n\\n\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### 2023\ub144\uc5d0\ub294\\n\\n\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."},{"id":"book-writer","metadata":{"permalink":"/book-writer","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","source":"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","description":"\ucc45 \uc815\ubcf4","date":"2023-01-01T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 1\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":4.425,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","slug":"book-writer","tags":["Book"]},"prevItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \\n> \ubc15\uc194\ubbf8 \\n>\\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4. \\n\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4. \\n\\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4. \\n\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4. \\n\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694.\\n> \\n\\n> \ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec.\\n> \\n\\n> \uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30.\\n> \\n\\n> \uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694.\\n> \\n\\n> \uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c\\n> \\n\\n> \uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694.\\n> \\n\\n> \uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4.\\n> \\n\\n> \ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4.\\n> \\n\\n> \uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4.\\n>"}]}')}}]); \ No newline at end of file diff --git a/assets/js/b2b675dd.f512bfe6.js b/assets/js/b2b675dd.f512bfe6.js deleted file mode 100644 index f16465215..000000000 --- a/assets/js/b2b675dd.f512bfe6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[533],{28017:n=>{n.exports=JSON.parse('{"blogPosts":[{"id":"async-exception","metadata":{"permalink":"/async-exception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx","title":"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac","description":"\uac1c\uc694","date":"2023-09-18T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 18\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"exception","permalink":"/tags/exception"}],"readingTime":3.15,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac","slug":"async-exception","tags":["async","exception"]},"nextItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"}},"content":"### \uac1c\uc694\\n\\n\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 `@Async`\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 `@ControllerAdvice` + `@ExceptionHandler`\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\ub2e4. \ub530\ub77c\uc11c Spring\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 `AsyncUncaughtExceptionHandler` \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc608\uc678\ucc98\ub9ac\\n\\n```java title=AsyncExceptionHandler\\n@Slf4j\\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\\n\\n private static final String LOG_FORMAT = \\"[%s] %s\\";\\n\\n @Override\\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\\n }\\n}\\n```\\n\\n\ud574\ub2f9 `AsyncExceptionHandler`\uc758 \uacbd\uc6b0 `AsyncConfigurer`\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. `getAsyncUncaughtExceptionHandler` \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \uc774\uc804\uc5d0 \uc0dd\uc131\ud574 \uc900 `AsyncExceptionHandler`\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4. \\n\uc774\ub807\uac8c \uc124\uc815\ud55c\ub2e4\uba74 \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 `AsyncUncaughtExceptionHandler`\uc758 \uad6c\ud604\uccb4\uc778 `AsyncExceptionHandler`\uac00 \uc608\uc678\ub97c \uc7a1\uc544\uc11c \ucc98\ub9ac\ub97c \ud574\uc900\ub2e4. \\n\\n```java title=AsyncConfig\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n### MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c\\n\\n![./mdc-null.png](./mdc-null.png)\\n\\n\uae30\uc874 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \\n\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc5c8\ub2e4. \\n\\n\uc774\ub97c \uc801\uc808\ud558\uac8c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815\ud558\uc5ec MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud574\uc11c \ub118\uaca8\uc904 \uc218 \uc788\ub2e4. \\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4. \\n\\n```java title=MdcTaskDecorator\\npublic class MdcTaskDecorator implements TaskDecorator {\\n\\n @Override\\n public Runnable decorate(final Runnable runnable) {\\n Map threadContext = MDC.getCopyOfContextMap();\\n return () -> {\\n MDC.setContextMap(threadContext);\\n runnable.run();\\n };\\n }\\n}\\n```\\n\\n\ud574\ub2f9 Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4.\\n\\n```java title=AsyncConfig\\n@RequiredArgsConstructor\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig implements AsyncConfigurer {\\n\\n private final AsyncConfigurationProperties properties;\\n\\n @Bean\\n public ThreadPoolTaskExecutor taskExecutor() {\\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\\n executor.setCorePoolSize(properties.coreSize());\\n executor.setMaxPoolSize(properties.maxSize());\\n executor.setQueueCapacity(properties.queueCapacity());\\n \\n // highlight-next-line\\n executor.setTaskDecorator(new MdcTaskDecorator());\\n executor.setWaitForTasksToCompleteOnShutdown(true);\\n executor.initialize();\\n return executor;\\n }\\n\\n @Override\\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\\n return new AsyncExceptionHandler();\\n }\\n}\\n```\\n\\n\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4.\\n\\n![./mdc-not-null.png](./mdc-not-null.png)\\n\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[spring async, baeldung](https://www.baeldung.com/spring-async) \\n[@Async will not call by @ControllerAdvice for global exception](https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception) \\n[Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8](https://blog.gangnamunni.com/post/mdc-context-task-decorator/)"},{"id":"tomcat-retrospective","metadata":{"permalink":"/tomcat-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","description":"\ud1b0\ucea3 \uad6c\ud604","date":"2023-09-11T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":12.27,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","slug":"tomcat-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac","permalink":"/async-exception"},"nextItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"}},"content":"### \ud1b0\ucea3 \uad6c\ud604\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c0\uc6d0\ud560 \ub54c \uac1d\uccb4\uc9c0\ud5a5\uacfc \uad00\ub828\ub41c \ubbf8\uc158\ub3c4 \uae30\ub300\ub97c \ub9ce\uc774 \ud588\uc9c0\ub9cc \ub808\ubca8 4\uc5d0 \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc774 \uc815\ub9d0 \ud558\uace0 \uc2f6\uc5c8\ub2e4. \\n\uadf8\ub798\uc11c \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc744\uae4c\ub77c\ub294 \uac71\uc815 \ubc18, \ubbf8\uc158\uc5d0 \ub300\ud55c \uae30\ub300 \ubc18\uc73c\ub85c \ubd80\ud47c \ub9c8\uc74c\uc744 \uac00\uc9c0\uace0 \ubbf8\uc158\uc744 \uc2dc\uc791\ud588\ub358 \uac83 \uac19\ub2e4. \\n\\n\uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc801\uc808\ud558\uac8c \ucd94\uc0c1\ud654\ud558\uace0, \ubbf8\uc158\uc758 \ubcf8\uc9c8\uc744 \uc774\ud574\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158\uc740 [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/)\uc5d0 \uba85\uc2dc\ub41c \uc2a4\ud399(\uc644\ubcbd\ud558\uc9c0 \uc54a\uc9c0\ub9cc \ubbf8\uc158\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 \uc694\uad6c\uc0ac\ud56d\ub9cc \ub9cc\uc871\ud558\ub3c4\ub85d)\uc73c\ub85c \uc694\uccad\uc744 \ubc1b\uc544 \ucc98\ub9ac \ud6c4 \ubc18\ud658\ud558\ub294\ub370 \uc9d1\uc911\ud588\ub2e4. \\n\\n### \ub2e4\uc774\uc5b4\uadf8\ub7a8\\n\\nCatalina\ub294 Tomcat\uc758 \uc11c\ube14\ub9bf \ucee8\ud14c\uc774\ub108, Coyote\ub294 HTTP 1.1 \uc6f9 \uc11c\ubc84\ub97c \uc9c0\uc6d0\ud558\ub294 \uad6c\uc131 \uc694\uc18c\ub77c\uace0 \uc0dd\uac01\ud558\uace0 \uc544\ub798\uc640 \uac19\uc774 \uad6c\uc131\ud588\ub2e4. \\n\uc0ac\uc2e4 \ub0b4\ubd80 \uad6c\uc870\ub97c \uae4a\uac8c \uacf5\ubd80\ud560 \uc2dc\uac04\uc744 \uac00\uc9c0\uc9c0 \ubabb\ud574\uc11c \uac01 \uad6c\uc131 \uc694\uc18c\uac00 \uc65c \ud574\ub2f9 \uc704\uce58\uc5d0 \uc788\ub294\uc9c0 \uc644\ubcbd\ud558\uac8c \uc124\uba85\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc774\uac74 \uc5ec\uae30\uc5d0 \uc788\uc73c\uba74 \uc88b\uc744 \uac83 \uac19\uc740\ub370? \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e4\uba74 \uc801\uc808\ud55c \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\uc2dc\ud0a4\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\ub2e4. \\n\ub610\ud55c \uc801\uc808\ud558\uac8c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc744 \ub2e8\ubc29\ud5a5\uc73c\ub85c \ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph coyote\\n\\t\\tHP[Http11Processor] --\x3e A\\n\\t\\tHP --\x3e HttpRequestParser\\n\\t\\tHP --\x3e HttpResponseGenerator\\n\\t\\tA[Adapter]\\n end\\n\\n subgraph catalina\\n\\t\\tRA[RequestAdapter] -.-> A\\n\\t\\tAC[AbstractController] -.-> C[Controller]\\n\\t\\tStaticController -.-> AC\\n\\t\\tSM[SessionManger] -.-> Manager\\n\\t\\tTC[Tomcat] --\x3e RA\\n\\t\\tRA --\x3e C\\n\\t\\tRA --\x3e Manager\\n\\t\\tRA --\x3e RM\\n\\t\\tRM[RequestMapper] --\x3e C\\n end\\n\\n subgraph jwp\\n\\t\\tLC[LoginController] -.-> AC\\n\\t\\tApplication --\x3e TC\\n end\\n\\n```\\n\\n### \ucf54\ub4dc \ub9ac\ubdf0 \\n\\n\ud06c\ub8e8 \uc911 \ud55c \uba85\uc774 \ub098\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\uace0, \ub0b4\uac00 \ub2e4\ub978 \ud06c\ub8e8\uc758 \ub9ac\ubdf0\uc5b4\uac00 \ub418\ub294 \ud615\ud0dc\ub85c \uc9c4\ud589\uc774 \ub418\uc5c8\ub2e4. \\n\ub098\uc758 \ub9ac\ubdf0\uc5b4\ub294 \ub514\ub178, \ub9ac\ubdf0\uc774\ub294 \ud544\ub9bd\uc774\uc5c8\ub2e4. \\n\\n\ub514\ub178(\ub9e4\uc758 \ub208\uc774 \uc544\ub2cc \uacf5\ub8e1\uc758 \ub208?)\uac00 \ub9e4\uc6b0 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud574\uc8fc\uc5b4\uc11c \uc870\uae08 \ub354 \ub098\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \uc218 \uc788\uc5c8\uace0, \ud544\ub9bd\uc758 \ucf54\ub4dc\uc5d0\uc11c\ub294 \uaf3c\uaf3c\ud558\uac8c \uc608\uc678\ucc98\ub9ac \ud558\ub294 \ubd80\ubd84\uc744 \ubc30\uc6b8 \uc218 \uc788\uc5c8\ub2e4. \\n\ud55c \uac00\uc9c0 \uc544\uc26c\uc6b4 \uc810\uc740 \ud544\ub9bd\uc5d0\uac8c \uc791\uc131\ud55c \ub098\uc758 \ucf54\uba58\ud2b8\ub4e4\uc774 \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uacbd\ud5d8 \uae30\ubc18\uc73c\ub85c \uc791\uc131\ud55c \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uadfc\uac70\uac00 \uc870\uae08 \ubd80\uc871\ud588\uace0, \uc815\ub9ac\ub418\uc9c0 \uc54a\uc740 \ubd80\ubd84\uc774 \ub9ce\uc558\ub358 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130 \ub9ac\ubdf0\ud560 \ub54c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ub354 \uc88b\uc740 \ub0b4\uc6a9\uc744 \ud06c\ub8e8\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### SessionConfig\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589 \uc911 catalina \ud328\ud0a4\uc9c0\uc758 Session \uad00\ub828 \ubd80\ubd84\uc744 \ubcf4\uba74\uc11c \uc911\ubcf5 \ub85c\uc9c1\uc744 \uac1c\uc120\ud574 \ubcfc \uc218 \uc788\uc744 \uac83 \uac19\uc544 [\ucee8\ud2b8\ub9ac\ubdf0\ud2b8](https://github.com/apache/tomcat/pull/660)\ub97c \uc2dc\ub3c4\ud588\ub2e4. \\n\uc138\uc158 \ucfe0\ud0a4\uc758 \uc774\ub984\uc744 \uac00\uc838\uc624\ub294 Util \ud074\ub798\uc2a4\uc758 \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub294\ub370 \uae30\ubcf8 \uac12\uc740 JSESSIONID \uc9c0\ub9cc \uc124\uc815\uc5d0 \ub530\ub77c\uc11c \uc138\uc158 \ucfe0\ud0a4\uba85\uc744 \ub2e4\ub974\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ub85c\uc9c1\uc774 \uc788\ub294 \uac83\uc73c\ub85c \uc0dd\uac01\ud588\ub2e4. \\n\uae30\uc874\uc758 \ucf54\ub4dc\ub294 \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \ucf54\ub4dc\uc758 \ud750\ub984\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc544\uc11c \uc57d\uac04 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6e0\ub2e4. \\n\\n\ucd08\uae30\uc5d0 \uc694\uccad\ud588\ub358 PR\uc740 \uae30\uc874\uc758 \ucf54\ub4dc\ubcf4\ub2e4 \uc804\uccb4\uc801\uc73c\ub85c \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, context\uac00 null\uc778 \uacbd\uc6b0 \ubc14\ub85c \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud568\uc73c\ub85c\uc368 \uc131\ub2a5 \uac1c\uc120\uc758 \ud6a8\uacfc\uac00 \uc788\uc744 \uac70\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uba54\uc778\ud14c\uc774\ub108\uc778 Mark Thomas \ud615\uc774 \ud574\ub2f9 \ub85c\uc9c1\uc758 \uacbd\uc6b0 \ucef4\ud30c\uc77c\ub7ec\uac00 \ud574\ub2f9 \ubd80\ubd84\uc744 \ucd5c\uc801\ud654 \ud560 \uc218 \uc788\uc744 \uac70\ub77c\uace0 \uae30\ub300\ud55c\ub2e4\uace0 \ud588\uace0, \uac00\ub3c5\uc131\uc744 \uac1c\uc120\uc2dc\ucf1c\ubcf4\ub77c\uace0 \uc870\uc5b8\ud574\uc8fc\uc168\ub2e4. \\n\ucef4\ud30c\uc77c\ub7ec \ucd5c\uc801\ud654\ub294 \uace0\ub824\ud574\ubcf4\uc9c0 \ubabb\ud55c \ubd80\ubd84\uc778\ub370, \uc55e\uc73c\ub85c \ud559\uc2b5\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc0b0\ub354\ubbf8\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ub0a8\uaca8\uc900 \ucf54\uba58\ud2b8\uc5d0 \ub530\ub77c \ucd5c\uc885\uc801\uc73c\ub85c\ub294 \uc911\ubcf5\ub41c \ucf54\ub4dc\ub97c \uc904\uc774\ub294 \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc218\uc815\ud588\ub2e4. \\n\uacb0\uacfc\uc801\uc73c\ub85c \uae30\uc874 \ub85c\uc9c1 \ub300\ube44 \ube44\uad50 \uc5f0\uc0b0\uc744 \ud55c \ubc88 \uc904\uc77c \uc218 \uc788\uc5c8\uace0, \uba85\uc2dc\ub41c \uc8fc\uc11d\uc758 \ub0b4\uc6a9\uacfc \uc720\uc0ac\ud55c \ud750\ub984\uc758 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc5ec \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1\uc744 \ud588\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_COOKIE_NAME;\\n }\\n\\n return result;\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n\\n String result = getConfiguredSessionCookieName(context);\\n\\n if (result == null) {\\n result = DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n\\n return result;\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context) {\\n\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc =\\n context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n\\n return null;\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_COOKIE_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n if (context == null) {\\n return DEFAULT_SESSION_PARAMETER_NAME;\\n }\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic static String getSessionCookieName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_COOKIE_NAME);\\n}\\n\\npublic static String getSessionUriParamName(Context context) {\\n return getConfiguredSessionCookieName(context, DEFAULT_SESSION_PARAMETER_NAME);\\n}\\n\\nprivate static String getConfiguredSessionCookieName(Context context, String defaultName) {\\n // Priority is:\\n // 1. Cookie name defined in context\\n // 2. Cookie name configured for app\\n // 3. Default defined by spec\\n if (context != null) {\\n String cookieName = context.getSessionCookieName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n\\n SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();\\n cookieName = scc.getName();\\n if (cookieName != null && cookieName.length() > 0) {\\n return cookieName;\\n }\\n }\\n return defaultName;\\n}\\n```\\n\\n\\n\\n\\n### HTTP \uc218\uc5c5\\n\\n\ubbf8\uc158 \uc911\uac04\uc5d0 \uc9c4\ud589\ub418\uc5c8\ub358 HTTP \uc218\uc5c5\uc5d0\ub294 HTTP\ub97c \uc801\uc808\ud558\uac8c \ud65c\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\ud56d\uc0c1 \uc131\ub2a5 \uac1c\uc120\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub2e8\uc5d0\uc11c \ucd5c\uc801\ud654\ud574\ubcf4\ub824\uace0 \ub178\ub825\uc744 \ud588\uc9c0\ub9cc, \ub354 \uc801\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574\uc11c \ud6a8\uc728\uc801\uc73c\ub85c \uc131\ub2a5\uc744 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574 \uc54c \uc218 \uc788\uc5c8\ub358 \uc218\uc5c5\uc774\uc5c8\ub2e4. \\nHTTP \uc555\ucd95, HTTP \uce90\uc2f1, \ub9ac\uc18c\uc2a4 \ucd5c\uc801\ud654 \uae30\ubc95\uc5d0 \ub300\ud574 \ud559\uc2b5\ud588\ub2e4. \\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \ub2e4\uc74c \uc635\uc158\uc744 \uc124\uc815\ud558\uc5ec http\uc758 \uc1a1\uc218\uc2e0\uc758 \uc555\ucd95\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```yml\\nserver:\\n compression:\\n enabled: true\\n```\\n\\n\uc218\uc5c5 \uc911 \ud574\ub2f9 \uc555\ucd95 \uc131\ub2a5\uc774 \uc88b\ub2e4\uba74 \uc65c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\uc11c\ub294 \uae30\ubcf8 \uac12\uc73c\ub85c \uc124\uc815\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\uc9c0 \uad81\uae08\ud574\uc84c\ub2e4. \\n\uad81\uae08\uc99d\uc744 \ud574\uc18c\ud558\uc9c0 \ubabb\ud588\ub294\ub370 \ub9d0\ub791\uc774 \uc7a1\ub2f4 \ucc44\ub110\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc740 [issue](https://github.com/spring-projects/spring-boot/issues/21369)\ub97c \ucc3e\uc544\uc8fc\uc5c8\ub2e4. \\n\ub0b4\uc6a9\uc744 \uc694\uc57d\ud574 \ubcf4\uc790\uba74 WAS \ubcc4\ub85c \uc555\ucd95\uc744 \ud558\uae30 \uc704\ud574 \uc124\uc815\ud574\uc57c \ud558\ub294 \uac83\uc774 \ub2e4\ub974\uace0, \ubb34\uc870\uac74 \uc555\ucd95\uc744 \ud558\ub294 \uac83\uc774 \ucd5c\uc801\uc758 \uacbd\uc6b0\uac00 \uc544\ub2d0 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uae30\ubcf8\uac12\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \uac19\ub2e4. \\n\\n> If you\'re developing a public-facing application then it\'s probably likely gzip compression would be worthwhile. If, however, you\'re a microservice application and you\'re in a dataceter, you may well prefer to reduce CPU load because you know you\'ll only be talking to other microservices and you have a reliable gigabit network.\\n\\nPhil Webb \ud615\ub2d8\uc758 \ub9d0\uc5d0 \ub530\ub974\uba74 \uc77c\ubc18\uc801\uc778 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uac1c\ubc1c\ud558\ub294 \uacbd\uc6b0 gzip \uc555\ucd95\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc9c0\ub9cc, MSA \ud658\uacbd + \ub370\uc774\ud130 \uc13c\ud130\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \uc624\uc9c1 \ub2e4\ub978 MSA \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uacfc \ud1b5\uc2e0\ud558\uace0, \uace0\uc131\ub2a5 \ub124\ud2b8\uc6cc\ud06c\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0 CPU \ubd80\ud558\ub97c \uc904\uc774\ub294 \uac83\uc774 \uc6b0\uc120\uc2dc \ub420 \uc218\ub3c4 \uc788\ub2e4\ub294 \uac83\uc774\uc5c8\ub2e4. \\n\\n\uc774\uc678\uc5d0\ub3c4 \uc758\ub3c4\ud558\uc9c0 \uc54a\uc740 \uce90\uc2f1\uc744 \ub9c9\uae30 \uc704\ud574 \ud734\ub9ac\uc2a4\ud2f1 \uce90\uc2f1\uc744 \uc81c\uac70\ud558\uac70\ub098, \uac1c\uc778 \uc815\ubcf4 \uc720\ucd9c\uc744 \ub9c9\uae30 \uc704\ud574 \uc751\ub2f5 \ud5e4\ub354\uc5d0 private\uc744 \uc124\uc815, ETag\ub3c4 \ud559\uc2b5\ud588\ub2e4. \\n\\n:::note ETag\\nETag HTTP \uc751\ub2f5 \ud5e4\ub354\ub294 \ud2b9\uc815 \ubc84\uc804\uc758 \ub9ac\uc18c\uc2a4\ub97c \uc2dd\ubcc4\ud558\ub294 \uc2dd\ubcc4\uc790\ub2e4. \\n\uc6f9 \uc11c\ubc84\uac00 \ub0b4\uc6a9\uc744 \ud655\uc778\ud558\uace0 \ubcc0\ud558\uc9c0 \uc54a\uc558\uc73c\uba74, \uc6f9 \uc11c\ubc84\ub85c full \uc694\uccad\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0, \uce90\uc2dc\uac00 \ub354 \ud6a8\uc728\uc801\uc774\uac8c \ub41c\ub2e4. \\nMDN\\n:::\\n\\n### Thread \uc218\uc5c5\\n\\n\uc2a4\ub808\ub4dc\uc5d0 \ub300\ud55c \uc218\uc5c5\uc744 \ub4e4\uc5c8\uc9c0\ub9cc, \ubcf5\uc7a1\ud55c \ub0b4\uc6a9\ub3c4 \uc6cc\ub099 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0 \uc124\uba85\ud558\ub77c\uace0 \ud558\uba74 \uc798 \ubabb\ud560 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e0\ub2e4. \\n\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8, \ubbf8\uc158, \ud14c\ucf54\ud1a1 \uc900\ube44\ub97c \ubcd1\ud589\ud574\uc57c \ud574\uc11c \uc138\ubd80\uc801\uc778 \ub0b4\uc6a9\uc740 \uc2dc\uac04 \ub0a0 \ub54c \ubcf5\uc2b5\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n\uc2a4\ub808\ub4dc\ub97c \uc774\ud574\ud558\uace0, WAS\uc5d0 \uc2a4\ub808\ub4dc \uc124\uc815 \uad00\ub828\ud55c \uc2e4\uc2b5\uc774 \uc788\uc5c8\ub294\ub370 \ud14c\uc624\uc640 \uac19\uc774 1\uc2dc\uac04 \uc815\ub3c4 \ud398\uc5b4\ub85c Thread \uc2e4\uc2b5\uc744 \uc9c4\ud589\ud574 \ubcf4\uc558\ub2e4. \\n\ud559\uc2b5\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n`threads.max`: Tomcat\uc758 \ucd5c\ub300 \uc2a4\ub808\ub4dc \uac1c\uc218 \\n`max-connections`: Tomcat\uc774 \uc720\uc9c0\ud560 \uc218 \uc788\ub294 \ucd5c\ub300 \ucee4\ub125\uc158 \uac1c\uc218 \\n`accept-count`: \ucd5c\ub300 \uc5f0\uacb0 \uc218\uc5d0 \ub3c4\ub2ec\ud588\uc744 \ub54c \uc5f0\uacb0 \uc694\uccad\uc5d0 \ub300\ud574 \uc6b4\uc601 \uccb4\uc81c\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub300\uae30\uc5f4\uc758 \ucd5c\ub300 \uae38\uc774. \ud574\ub2f9 Queue\uc5d0 \uc694\uccad\uc774 \uc313\uc774\ub294 \uac83\uc740 Tomcat\uc774 \ub354 \uc774\uc0c1 \uc694\uccad\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub2e4\ub294 \ub73b\uc774\ub2e4. accpet-count queue\uc5d0\ub3c4 \uc694\uccad\uc774 \uac00\ub4dd\ucc28\uba74 \uadf8 \uc774\ud6c4\uc5d0 \uc624\ub294 \uc694\uccad\uc740 \uac70\ubd80\ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n C(\\"Client\\") -- request --\x3e ACQ(\\"\uc6b4\uc601\uccb4\uc81c\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue \\n size = accept-count\\") --\x3e TCQ(\\"Tomcat Connector\uc5d0 \uc758\ud574 \uad00\ub9ac\ub418\ub294 Queue\\n size = max-connections\\") --\x3e TP(\\"Thread Pool\\n size = threads.max\\")\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc2dc\uac04\uc740 \ub108\ubb34 \ube60\ub974\uac8c \uac00\uace0 \ud560 \uc77c\uc740 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\uc6b0\uc120\uc21c\uc704\ub97c \uc798 \uc815\ud558\uace0 \ud559\uc2b5\uc744 \uc9c4\ud589\ud574\uc57c\uaca0\ub2e4. \\n\ud604\uc7ac \ub370\uc774\ud130 \ub2e4\ub8e8\ub294 \ubd80\ubd84(DB)\uc5d0 \ub300\ud55c \ud559\uc2b5\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\ub2e4. \ud574\ub2f9 \ubd80\ubd84\uc740 \ud14c\ucf54\ud1a1\uc774 \ub05d\ub098\ub294\ub300\ub85c \ucc44\uc6cc\uc57c\uaca0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616/) \\n[ETag, mdn](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag) \\n[Apache Tomcat 8 Configuration Reference](https://tomcat.apache.org/tomcat-8.5-doc/config/http.html) \\n[Apache Tomcat Tuning, Terry Cho](https://bcho.tistory.com/788) \\n[maxThreads, maxConnections, acceptCount\ub85c Tomcat \ud29c\ub2dd\ud558\uae30](https://dev-ws.tistory.com/96)"},{"id":"performance-test-type","metadata":{"permalink":"/performance-test-type","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","source":"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx","title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","description":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8","date":"2023-09-10T00:00:00.000Z","formattedDate":"2023\ub144 9\uc6d4 10\uc77c","tags":[{"label":"performance test","permalink":"/tags/performance-test"}],"readingTime":5.8,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","slug":"performance-test-type","tags":["performance test"]},"prevItem":{"title":"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0","permalink":"/tomcat-retrospective"},"nextItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"}},"content":"## \uc131\ub2a5 \ud14c\uc2a4\ud2b8\\n\\nAPI\uc758 \uc694\uccad\uc774 \ub9ce\uc740 \uc0c1\ud669\uc5d0\uc11c \uc11c\ubc84\uac00 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\uc2dc\uc2a4\ud15c\uc5d0 \ubd80\ud558\uac00 \uac78\ub9ac\uba74 \ubb38\uc81c \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc591\ud55c \uc0c1\ud669\uc5d0 \ub300\ube44\ud574\uc11c \uc131\ub2a5 \ud14c\uc2a4\ud2b8\ub97c \ud574\uc57c\ud55c\ub2e4. \\n\\n![./test.png](./test.png)\\n\\n### \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8(Smoke Test)\\n\\n\ucd5c\uc18c\ud55c\uc758 \ubd80\ud558\ub97c \uc8fc\uc5b4 \uc2dc\uc2a4\ud15c\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\nVU\ub97c \ucd5c\uc18c\ud55c\uc73c\ub85c \ub450\uace0, \uc9e7\uc740 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \ud14c\uc2a4\ud2b8\ud55c\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \uc2dc\uc791\ud558\uae30 \uc804\uc5d0 \uc2a4\ubaa8\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud568\uc73c\ub85c\uc368 \ud14c\uc2a4\ud2b8 \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc624\ub958\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\uace0, \uc131\ub2a5 \uc9c0\ud45c\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc9d1, \ubaa8\ub2c8\ud130\ub9c1 \ub418\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \uac00\uc0c1 \uc0ac\uc6a9\uc790(VU)\\n\uac00\uc0c1 \uc0ac\uc6a9\uc790\ub294 \uc11c\ubc84 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0 \ub300\ud574 \ud2b9\uc815 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c\ub2e4. \\n\uc774\ub294 \ub2e4\ub978 \uac00\uc0c1 \uc0ac\uc6a9\uc790\uc640 \ub3c5\ub9bd\uc801\uc73c\ub85c \uc2e4\ud589\ub418\uba70, \uc5ec\ub7ec \uac00\uc0c1 \uc0ac\uc6a9\uc790\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub3d9\uc2dc \uc5f0\uacb0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\uc2a4\ub808\ub4dc\ub77c\uace0 \uc0dd\uac01\ud558\uba74 \ub41c\ub2e4. \\n:::\\n\\n### \uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8(Spike Test)\\n\\n\uc0ac\uc6a9\ub7c9\uc774 \uae09\uc99d\ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uacac\ub514\uace0 \uc131\ub2a5\uc5d0 \ubb38\uc81c\uac00 \uc5c6\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud2f0\ucf13 \ubc1c\uae09, \ud560\uc778 \ucfe0\ud3f0 \ubc1c\uae09\uacfc \uac19\uc740 \uc774\ubca4\ud2b8\ub97c \ud558\ub294 \uacbd\uc6b0 \ub300\uaddc\ubaa8 \ud2b8\ub798\ud53d\uc774 \ub4e4\uc5b4\uc628\ub2e4. \\n\uc2a4\ud30c\uc774\ud06c \ud14c\uc2a4\ud2b8\ub97c \ud1b5\ud574 \uae09\uc99d\ud558\ub294 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\uace0, \ubd80\ud558\ub97c \uc798 \ubc84\ud2f0\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ubd80\ud558 \ud14c\uc2a4\ud2b8(Load Test)\\n\\n\ubaa9\ud46f\uac12\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \uacac\ub51c \uc218 \uc788\uc744\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uc77c\ubc18\uc801\uc778 \ubd80\ud558 \uc0c1\ud669\uc5d0\uc11c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ub7a8\ud504\uc5c5 \ub610\ub294 \ubb19\ud46f\uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ubd80\ud558 \uae30\uac04\ub3d9\uc548 \uc131\ub2a5\uc774 \ubb38\uc81c\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\uace0, \uc2dc\uc2a4\ud15c \ubcc0\uacbd \ud6c4\uc5d0\ub3c4 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \ub3cc\ub824 \ub3d9\uc77c\ud558\uac8c \ubaa9\ud46f\uac12\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ub7a8\ud504 \uc5c5(Ramp-up)\\n\ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574 \uc124\uc815\ud55c \uac00\uc0c1 \uc0ac\uc6a9\uc790 \uc218\uc5d0 \ub3c4\ub2ec\ud558\ub294 \ub370 \uac78\ub9ac\ub294 \uc2dc\uac04\\n:::\\n\\n### \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8(Stress Test) \\n\\n\uc2dc\uc2a4\ud15c\uc758 \ucd5c\ub300\uce58\uc5d0 \ud574\ub2f9\ub418\ub294 \ubd80\ud558\ub97c \ubc1b\uc558\uc744 \ub54c \uc2dc\uc2a4\ud15c\uc774 \uc5b4\ub5bb\uac8c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\uadf8\ub798\ud504\ub97c \ubd24\uc744 \ub54c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc640 \uc720\uc0ac\ud55c \ud615\ud0dc\ub85c \ubcf4\uc774\uc9c0\ub9cc, \ubd80\ud558\ub7c9\uc774 \ub2e4\ub974\ub2e4. \\n\uc77c\ubc18\uc801\uc73c\ub85c \ud3c9\uade0\uc801\uc778 \ubaa9\ud46f\uac12 \ub300\ube44 \uc791\uac8c\ub294 50% \uc774\uc0c1, \ud544\uc694\uc758 \uacbd\uc6b0 \uadf8 \uc774\uc0c1\uc73c\ub85c \ubd80\ud558\ub97c \uc900\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub294 \ubd80\ud558 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud55c \ud6c4\uc5d0\ub9cc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4. \ubd80\ud558 \ud14c\uc2a4\ud2b8\uac00 \uc774\ub8e8\uc5b4\uc9c0\uc9c0 \uc54a\uc740 \uc0c1\ud669\uc5d0\uc11c \uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc2e4\ud589\ud558\ub294 \uacbd\uc6b0\uc5d0\ub294 \ubcd1\ubaa9 \uc9c0\uc810\uc774\ub098 \ubb38\uc81c \uc0c1\ud669\uc744 \ucc3e\uae30 \uc5b4\ub824\uc6cc\uc9c4\ub2e4. \\n\ub610\ud55c \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud55c \uc2a4\ud06c\ub9bd\ud2b8\ub97c VU\uac12(\uc2a4\ub808\ub4dc \uc218)\ub9cc \uc218\uc815\ud558\uc5ec \uc7ac\uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\\n### \ub0b4\uad6c \ud14c\uc2a4\ud2b8(Endurance Test) \\n\\n\ud3c9\uade0 \uc0ac\uc6a9\ub960\ub85c \uc77c\uc815 \ubd80\ud558\ub97c \uc9c0\uc18d\uc801\uc73c\ub85c \uc8fc\uba70 \uc2dc\uc2a4\ud15c\uc774 \ubb38\uc81c\ub418\ub294 \uc9c0\uc810\uc744 \ud655\uc778\ud558\ub294 \ud14c\uc2a4\ud2b8 \\n\\n\ud761\uc218 \ud14c\uc2a4\ud2b8(Soak Test)\ub77c\uace0\ub3c4 \ud558\uba70, \uae30\ubcf8\uc801\uc778 \ubd80\ud558 \ud14c\uc2a4\ud2b8\uc758 \ubcc0\ud615\uc774\ub77c\uace0 \ubcfc \uc218 \uc788\ub2e4. \\n\ub2e4\ub978 \ud14c\uc2a4\ud2b8\uc640 \ub2ec\ub9ac \uae34 \uc2dc\uac04\ub3d9\uc548 \ud14c\uc2a4\ud2b8\ub97c \ud558\ub294 \uac83\uc774 \ud2b9\uc9d5\uc774\uba70, \uba54\ubaa8\ub9ac \ub204\uc218 \ubb38\uc81c\uc640 \uac19\uc774 \uc7a5\uc2dc\uac04 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc2e4\ud589\ud560 \ub54c \uc2dc\uc2a4\ud15c\uc758 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \ubd80\ubd84\uc744 \ud655\uc778\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4. \\n\\n### \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8(Breakpoint Test)\\n\\n\uc784\uacc4 \uc9c0\uc810\uc744 \ucc3e\uae30 \uc704\ud574 \ubd80\ud558\ub97c \uc810\uc9c4\uc801\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a4\uba70 \uc9c4\ud589\ud558\ub294 \ud14c\uc2a4\ud2b8\\n\\n\ubb38\uc81c\ub418\ub294 \ubd80\ubd84\uc744 \ub354 \ube68\ub9ac \ucc3e\uae30 \uc704\ud574 \ub2e4\ub978 \ud14c\uc2a4\ud2b8\ub97c \ud1b5\uacfc\ud55c \ub2e4\uc74c\uc5d0 \uc911\ub2e8\uc810 \ud14c\uc2a4\ud2b8\ub97c \uc9c4\ud589\ud558\uace0, \uc774 \ub54c \uc810\uc9c4\uc801\uc73c\ub85c \ubd80\ud558\ub97c \ub298\ub824\ub098\uac00\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc2a4\ud2b8\ub808\uc2a4 \ud14c\uc2a4\ud2b8\ub97c \uc131\ub2a5 \ud29c\ub2dd\uacfc \ubc18\ubcf5\ud574\uc11c \uc9c4\ud589\ud55c\ub2e4\uba74, \uc2dc\uc2a4\ud15c\uc744 \ub354\uc6b1 \ubc1c\uc804\uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\ub2e4\ub9cc Auto Scaling\uc774 \uc801\uc6a9\ub41c \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c\ub294 \uc9c4\ud589\ud558\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Load test types, k6](https://k6.io/docs/test-types/load-test-types/) \\n\uc790\ubc14 \ucd5c\uc801\ud654 - \ubca4\uc800\ubbfc J. \uc5d0\ubc88\uc2a4, \uc81c\uc784\uc2a4 \uace0\ud504, \ud06c\ub9ac\uc2a4 \ub274\ub79c\ub4dc \\n\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"},{"id":"db-replication","metadata":{"permalink":"/db-replication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","source":"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx","title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","description":"\ubcf5\uc81c(Replication)","date":"2023-08-22T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 22\uc77c","tags":[{"label":"mysql","permalink":"/tags/mysql"},{"label":"replication","permalink":"/tags/replication"}],"readingTime":20.58,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","slug":"db-replication","tags":["mysql","replication"]},"prevItem":{"title":"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc885\ub958","permalink":"/performance-test-type"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"}},"content":"## \ubcf5\uc81c(Replication)\\n\\n\ud55c \uc11c\ubc84\uc5d0\uc11c \ub2e4\ub978 \uc11c\ubc84\ub85c \ub370\uc774\ud130\ub97c \ub3d9\uae30\ud654\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\uc6d0\ubcf8 \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Primary \ub610\ub294 Source \ub77c\uace0 \ubd80\ub974\uace0, \ubcf5\uc81c\ub41c \ub370\uc774\ud130\ub97c \uac00\uc9c0\ub294 \uc11c\ubc84\ub97c Secondary \ub610\ub294 Replica \ub77c\uace0 \ubd80\ub978\ub2e4. \\n\\n### \ubcf5\uc81c\ub97c \ud558\ub294 \uc774\uc720\\n\\n**1. \uc2a4\ucf00\uc77c \uc544\uc6c3**\\n\\n\uc0ac\uc6a9\uc790\uc758 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0, \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uac00\ud574\uc9c0\ub294 \ubd80\ud558\ub3c4 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc99d\uac00\ud55c\ub2e4. \\n\uc774\ub97c \ucc98\ub9ac\ud558\uae30 \uc704\ud574 \ubcf5\uc81c\ub97c \ud1b5\ud55c \uc2a4\ucf00\uc77c \uc544\uc6c3\uc744 \uc801\uc6a9\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucffc\ub9ac\ub4e4\uc744 \uac01\uac01\uc758 \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub85c \ubd84\uc0b0 \uc2dc\ud0ac \uc218 \uc788\ub2e4. \\n\\n**2. \ub370\uc774\ud130 \ubc31\uc5c5**\\n\\n\uc2e4\uc81c \uc6b4\uc601\ub418\ub294 \uc11c\ube44\uc2a4\uac00 \uc0ac\uc6a9\ud558\uace0 \uc788\ub294 DB\uc5d0\uc11c \ubc31\uc5c5\uc744 \uc9c4\ud589\ud558\ub294 \uacbd\uc6b0, \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc774 \uac00\uc9c0 \uc54a\ub3c4\ub85d \ubcf5\uc81c\ub97c \ud1b5\ud574 Replica \uc11c\ubc84\ub97c \uad6c\ucd95\ud558\uc5ec, Replica \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ub97c \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\uc73c\ub85c \uc601\ud5a5\uc744 \ucd5c\uc18c\ud654 \ud560 \uc218 \uc788\ub2e4. \\n\\n**3. \ub370\uc774\ud130 \ubd84\uc11d**\\n\\n\ubc31\uc5c5\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc7a1\ud558\uace0 \ubb34\uac70\uc6b4 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\uc758 \uc11c\ube44\uc2a4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce60 \uc218 \uc788\ub2e4. \\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ubcf5\uc81c\ub97c \uc0ac\uc6a9\ud574 \ubd84\uc11d\uc6a9 \ucffc\ub9ac\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc744 \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n**4. \ub370\uc774\ud130\uc758 \uc9c0\ub9ac\uc801 \ubd84\uc0b0**\\n\\n\ube60\ub978 \uc751\ub2f5\uc744 \uc704\ud574 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc11c\ubc84\uc5d0 \uac00\uae5d\uac8c \uc11c\ubc84\ub97c \uad6c\uc131\ud558\uac70\ub098, \uace0\uac00\uc6a9\uc131(High Availability)\uc744 \uc704\ud574\uc11c\ub3c4 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uc704\uce58 \uae30\ubc18 \ubcf5\uc81c\\n\\nMySQL \uc11c\ubc84\uc5d0\uc11c \ubc1c\uc0dd\ud558\ub294 \ubcc0\uacbd\uc0ac\ud56d\uc5d0 \ub300\ud55c \ub85c\uadf8 \ud30c\uc77c\uc744 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub77c\uace0 \ud55c\ub2e4. \\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ud1b5\ud574 \ub370\uc774\ud130 \ubcc0\uacbd, \ud14c\uc774\ube14 \uad6c\uc870 \ubcc0\uacbd, \uacc4\uc815\uc774\ub098 \uad8c\ud55c \ubcc0\uacbd\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc800\uc7a5\ub41c\ub2e4. \\nMySQL\uc758 \ubcf5\uc81c\ub294 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 \uc788\ub2e4. \uc774\ub97c Replica \uc11c\ubc84\ub85c \uc804\ub2ec\ud558\uace0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \uae30\ubc18\uc73c\ub85c \ub370\uc774\ud130\ub97c \ubcc0\uacbd \uc0ac\ud56d\uc744 \ubc18\uc601\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph Replica\\n\\t\\tdirection TB\\n\\t\\tIO[Replication I/O thread] -- save --\x3e RL[Relay Log]\\n\\t\\tSQL[Replication SQL Thread] -- read --\x3e RL\\n\\tend\\n\\n\\tsubgraph Source\\n\\t\\tdirection TB\\n\\t\\tBLD[Binary Log Dump Thread] -- Send Binary Log Dump--\x3e IO\\n\\tend\\n\\n```\\n\\n:::note \uc2a4\ub808\ub4dc\ubcc4 \uc5ed\ud560\\n\\nBinary Log Dump Thread: \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc758 \ub0b4\uc6a9\uc744 Replica \uc11c\ubc84\ub85c \uc804\ub2ec \\nReplication I/O Thread: Binary \ub85c\uadf8 \uc774\ubca4\ud2b8\ub97c \uac00\uc838\uc640 \ub85c\uceec \uc11c\ubc84\uc758 \ud30c\uc77c(Relay Log)\ub85c \uc800\uc7a5 \\nReplication SQL Thread: \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc774\ubca4\ud2b8\ub97c \uc77d\uace0 \uc2e4\ud589\\n\\n:::\\n\\n### \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc758 \ubb38\uc81c\uc810\\n\\n\ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd\uc740 \uc11c\ubc84\uc5d0 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0 \ubcc0\uacbd\uc774 \uae4c\ub2e4\ub86d\ub2e4. \\n\ud1a0\ud3f4\ub85c\uc9c0\ub780 \ub124\ud2b8\uc6cc\ud06c\uc758 \uc694\uc18c\ub4e4\uc744 \ubb3c\ub9ac\uc801\uc73c\ub85c \uc5f0\uacb0\ud574 \ub193\uc740 \uac83, \ub610\ub294 \uadf8 \uc5f0\uacb0 \ubc29\uc2dd\uc744 \ub9d0\ud55c\ub2e4.\\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300] --\x3e B[B Binary-log:300]\\n\\tA[A binary-log:300] --\x3e C[C Binary-log:200]\\n```\\n\\n\uc704\uc640 \uac19\uc774 Source \uc11c\ubc84, Replica 2\ub300\uac00 \uc874\uc7ac\ud558\uace0, C \uc11c\ubc84\uc5d0 \ubcf5\uc81c \uc9c0\uc5f0\uc774 \ub418\uc5c8\uc744 \ub54c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\tA[A binary-log:300]\\n\\tB[B Binary-log:300] --\x3e C[C Binary-log:200 \ubb38\uc81c \ubc1c\uc0dd]\\n```\\n\\nA \uc11c\ubc84\uc5d0\uc11c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 B \uc11c\ubc84\ub97c Source \uc11c\ubc84\ub85c \uc2b9\uaca9\ud558\uace0, C\uc5d0\uac8c \uc870\ud68c \ucffc\ub9ac\ub97c \ubd84\uc0b0\uc2dc\ud0a8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc5ec\uae30\uc11c C \uc11c\ubc84\uc5d0\ub294 A \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\uac00 \uc548\ub418\uc5c8\uc73c\ub2c8 \uc870\ud68c \uc2dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ub4a4\ub2a6\uac8c B \uc11c\ubc84\uc640 \ub3d9\uae30\ud654\ub97c \ud558\ub824\uace0 \ud574\ub3c4, \uc5b4\ub5a4 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8, \uc5b4\ub5a4 \uc704\uce58\uc640 \ub3d9\uae30\ud654\ud574\uc57c\ud558\ub294\uc9c0 \uc54c\uae30 \uc5b4\ub835\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ud2b8\ub79c\uc7ad\uc158 \uc544\uc774\ub514(GTID) \uae30\ubc18 \ubcf5\uc81c\\n\\nGTID \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \ubc1c\uc0dd\ud55c \uc774\ubca4\ud2b8\uc5d0 \uace0\uc720\ud55c \uc2dd\ubcc4\uac12\uc744 \ubd80\uc5ec\ud55c\ub2e4\uba74, \ub3d9\uae30\ud654\uc5d0 \ub300\ud55c \ubb38\uc81c\ub97c \uac04\ub2e8\ud558\uac8c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4. \\n\uc704\uc758 \uc608\uc2dc\uc640 \uac19\uc774 \ubcf5\uc81c \uc9c0\uc5f0\uacfc \ud568\uaed8 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c\ub2e4\ud574\ub3c4 \ud2b9\uc815 GTID \ubd80\ud130 \ubcf5\uc81c\ub97c \uc7ac\uac1c\ud558\uba74 \ub41c\ub2e4. \\n\\n:::note GTID\\n\ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\uc5d0 \ucc38\uc5ec\ud55c \ubaa8\ub4e0 \uc11c\ubc84\uc5d0\uc11c \uace0\uc720\ud558\ub3c4\ub85d \uac01 \uc774\ubca4\ud2b8\uc5d0 \ubd80\uc5ec\ub41c \uc2dd\ubcc4\uac12 \\n[source_id]:[transaction_id]\ub85c \uad6c\uc131\ub418\uba70, source_id\ub294 \uc11c\ubc84\ub97c \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc774\uace0 transaction_id\ub294 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dd\ubcc4\ud558\uae30 \uc704\ud55c \uac12\uc73c\ub85c 1\uc529 \uc99d\uac00\ud558\ub294 \ud615\ud0dc\ub85c \ubc1c\uae09\ub41c\ub2e4. \\n:::\\n\\n### \ubcf5\uc81c \ud1a0\ud3f4\ub85c\uc9c0\\n\\n**\uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uac00\uc7a5 \uac04\ub2e8\ud55c \uad6c\uc131\uc73c\ub85c \uc81c\uc77c \ub9ce\uc774 \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\nreplica \uc11c\ubc84\ub97c \uc77d\uae30 \uc804\uc6a9, \uc608\ube44 \uc11c\ubc84, \ubc31\uc5c5 \uc6a9\ub3c4\ub85c \ub9ce\uc774 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R\\n S[Source] --\x3e R[Replica]\\n```\\n\\n**\uba40\ud2f0 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \ud615\ud0dc\ub2e4. \\n\ud558\ub098\uc758 replica\ub294 \uc608\ube44 \uc6a9\ub3c4\ub85c \ub0a8\uaca8\ub450\ub294 \ud615\ud0dc\ub2e4. \\n\ucd94\ud6c4\uc5d0 \ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 \uc608\ube44 \uc6a9\ub3c4\uc758 replica\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c \uc77d\uae30 \uc694\uccad\uc758 \ubd80\ud558 \ubd84\uc0b0\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n```\\n\\n**\uccb4\uc778 \ubcf5\uc81c \uad6c\uc131**\\n\\nreplica \uc11c\ubc84\uac00 \ub9ce\uc740 \uacbd\uc6b0 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \uc804\ub2ec\ud558\ub294 \uc791\uc5c5 \uc790\uccb4\uac00 \ubd80\ud558\uac00 \ub420 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c 1:M:M \uad6c\uc870\ub85c \uccb4\uc778 \ubcf5\uc81c \uad6c\uc131\uc744 \uace0\ub824\ud560 \uc218 \uc788\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e S\\n W -- \uc77d\uae30 --\x3e R1\\n S[Source] --\x3e R1[Replica1]\\n S --\x3e R2[Replica2]\\n S --\x3e R3[Replica3]\\n\\n R3 --\x3e R3-1[Replica 3-1]\\n R3 --\x3e R3-2[Replica 3-2]\\n\\n B[Batch Server] --\x3e R3-2\\n```\\n\\n**\ub4c0\uc5bc \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n2\uac1c\uc758 MySQL \uc11c\ubc84 \ubaa8\ub450 \uc77d\uae30\uc640 \uc4f0\uae30\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d \ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uac01 \uc11c\ubc84\uc5d0\uc11c \ubcc0\uacbd\ub41c \ub370\uc774\ud130\ub294 \ub2e4\ub978 \uc11c\ubc84\uc5d0 \ubc18\uc601\ub41c\ub2e4. \\n\ubaa9\uc801\uc5d0 \ub530\ub77c ACTIVE-ACTIVE \ud615\ud0dc \ub610\ub294 ACTIVE-PASSIVE \ud615\ud0dc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nACTIVE-PASSIVE \ud615\ud0dc\uc778 \uacbd\uc6b0 \uc2f1\uae00 \ub808\ud50c\ub9ac\uce74 \ubcf5\uc81c \uad6c\uc131\uacfc \ub3d9\uc77c\ud574\ubcf4\uc774\uc9c0\ub9cc, ACTIVE \uc11c\ubc84\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uba74 \uc124\uc815\uc758 \ubcc0\uacbd\uc5c6\uc774 PASSIVE \uc11c\ubc84\ub85c \uc4f0\uae30 \uc791\uc5c5\uc744 \uc804\ud658\ud560 \uc218 \uc788\ub2e4\ub294 \uac83\uc774 \uc7a5\uc810\uc774\ub2e4. \\n\\n```mermaid\\ngraph LR\\n W[Web Server] -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR1\\n W -- \uc77d\uae30 + \uc4f0\uae30 --\x3e SR2\\n SR1[Source/Replica 1] --\x3e SR2[Source/Replica 2]\\n```\\n\\n:::note ACTIVE-ACTIVE, ACTIVE-PASSIVE\\nACTIVE-ACTIVE: 2\uac1c\uc758 \uc11c\ubc84 \ubaa8\ub450 \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc \\nACTIVE-PASSIVE: \ud558\ub098\uc758 \uc11c\ubc84\uc5d0\uc11c\ub9cc \uc4f0\uae30 \uc791\uc5c5\uc744 \uc218\ud589\ud558\ub294 \ud615\ud0dc\\n:::\\n\\n**\uba40\ud2f0 \uc18c\uc2a4 \ubcf5\uc81c \uad6c\uc131**\\n\\n\uc5ec\ub7ec\uac1c\uc758 source \uc11c\ubc84\uc640 \ud558\ub098\uc758 replica \uc11c\ubc84\ub97c \uc0ac\uc6a9\ud558\ub294 \uad6c\uc131\uc774\ub2e4. \\n\uc774\ub294 source \uc11c\ubc84\uc758 \ub370\uc774\ud130\ub97c \ud55c \uacf3\uc5d0 \ubc31\uc5c5\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9, \uc5ec\ub7ec \uc11c\ubc84\uc5d0 \uc874\uc7ac\ud558\ub294 \ub370\uc774\ud130\ub97c \ud1b5\ud569, \uc0e4\ub529\ub418\uc5b4\uc788\ub294 \ud14c\uc774\ube14 \ub370\uc774\ud130\ub97c \ud1b5\ud569\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n S1[Source 1] --\x3e R[Replica]\\n S2[Source 2] --\x3e R\\n```\\n\\n## \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ubc29\uc2dd Replication \uad6c\uc131\ud558\uae30\\n\\nmysql 2\ub300\ub97c \uc774\uc6a9\ud558\uc5ec replication\uc744 \uad6c\uc131\ud558\uace0, spring boot application\uc73c\ub85c source, replica \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\ubcf4\ub294 \uc608\uc81c\uc774\ub2e4. \\n[https://github.com/bbiac/db-replication](https://github.com/bbiac/db-replication) \\n\\n### MySQL \ud658\uacbd \uad6c\uc131\\n\\nMySQL \ubc84\uc804\uc740 8.1\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n13306, 13307 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud574\uc11c MySQL \uc11c\ubc84 2\ub300\ub97c \ub744\uc6e0\ub2e4. \\n\ub610\ud55c \uc0ac\uc2e4 IP \ub300\uc5ed\uc73c\ub85c \ud1b5\uc2e0\ud560 \uc218 \uc788\ub3c4\ub85d \ucee4\uc2a4\ud140 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud588\ub2e4. \\n\\n```yml\\nversion: \'3.8\'\\n\\nservices:\\n source:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-source\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13306:3306\\"\\n volumes:\\n - db-source:/var/lib/mysql\\n - db-source:/var/lib/mysql-files\\n - ./docker/source.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\n replica:\\n platform: linux/x86_64\\n image: mysql:latest\\n restart: always\\n container_name: mysql-replica\\n environment:\\n TZ: \'Asia/Seoul\'\\n MYSQL_DATABASE: \'db\'\\n MYSQL_USER: \'user\'\\n MYSQL_PASSWORD: \'password\'\\n MYSQL_ROOT_PASSWORD: \'password\'\\n ports:\\n - \\"13307:3306\\"\\n volumes:\\n - db-replica:/var/lib/mysql\\n - db-replica:/var/lib/mysql-files\\n - ./docker/replica.cnf:/etc/mysql/my.cnf\\n networks:\\n - mysql_network\\n\\nvolumes:\\n db-source:\\n db-replica:\\n\\nnetworks:\\n mysql_network:\\n driver: bridge\\n```\\n\\n\ub610\ud55c source, replica \uac01\uac01 \ub2e4\uc74c\uacfc \uac19\uc774 db \uc124\uc815\uc744 \ud588\ub2e4. \\n\\n| \uc124\uc815 | \uc124\uba85 |\\n| --- | --- |\\n| server_id | \uac01\uac01\uc758 mysql \ub9c8\ub2e4 \uace0\uc720\ud55c \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. |\\n| log_bin | \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815\uc73c\ub85c \uc808\ub300\uacbd\ub85c\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 /var/lib/mysql \uc544\ub798 \ud574\ub2f9 log_bin\uc5d0 \uc124\uc815\ub41c \uac12\uc73c\ub85c \ub85c\uadf8\uac00 \uc0dd\uc131\ub41c\ub2e4. |\\n| sync_binlog | N\uac1c\uc758 \ud2b8\ub79c\uc7ad\uc158 \ub2f9 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\ub97c \ub514\uc2a4\ud06c\uc640 \ub3d9\uae30\ud654 \uc791\uc5c5\uc744 \ud558\ub3c4\ub85d \ud55c\ub2e4.\xa01\uc740 \uae30\ubcf8\uac12\uc73c\ub85c \uc548\uc815\uc801\uc774\uc9c0\ub9cc, \uac00\uc7a5 \ub290\ub9ac\ub2e4. |\\n| relay_log | \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c \uacbd\ub85c \uc124\uc815 |\\n| relay_log_purge | \ud544\uc694 \uc5c6\ub294 \ub9b4\ub808\uc774 \ub85c\uadf8 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \uc0ad\uc81c\ud558\ub294 \uc635\uc158 |\\n| read_only | \uc77d\uae30 \uc804\uc6a9 \uc124\uc815 |\\n| log_replica_updates | Replication SQL Thread\ub85c \uc778\ud574 \uc2e4\ud589\ub418\ub294 \uc815\ubcf4\ub97c \ubc14\uc774\ub108\ub9ac \ub85c\uadf8\uc5d0 \uae30\ub85d \ucd94\ud6c4\uc5d0 \uc18c\uc2a4 \uc11c\ubc84\ub85c \uc2b9\uaca9\ub418\ub294 \uacbd\uc6b0\ub97c \uace0\ub824\ud558\uba74 \uc124\uc815\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. |\\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```cnf title=\\"/docker/source.cnf\\"\\n[mysqld]\\nserver_id=1\\nlog_bin=mysql-bin\\nsync_binlog=1\\n```\\n\\n\\n\\n\\n\\n```cnf title=\\"/docker/replica.cnf\\"\\n[mysqld]\\nserver_id=2\\nrelay_log=mysql-relay-bin\\nrelay_log_purge=ON\\nread_only\\nlog_replica_updates\\n```\\n\\n\\n\\n\\n### \ub3c4\ucee4 \uc2e4\ud589\\n\\ndocker-compose up \uba85\ub839\uc5b4\ub85c docker-compose \uc124\uc815\uc73c\ub85c docker\ub97c \ub744\uc6b4\ub2e4. \\n-d \uc635\uc158\uc744 \ubd99\uc774\uba74 \ubc31\uadf8\ub77c\uc6b4\ub4dc \ubaa8\ub4dc\ub85c \uc2e4\ud589\ub41c\ub2e4. \\n\\n```\\ndocker-compose up -d\\n```\\n\\n### replication slave \uad8c\ud55c \uc124\uc815\\n\\nREPLICATION SLAVE \uad8c\ud55c\uc774 \uc124\uc815\ub418\uc5b4 \uc788\uc5b4\uc57c replica \uc11c\ubc84\uc5d0\uc11c source \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec \ub85c\uadf8\ub97c \uc77d\uc5b4\uc62c \uc218 \uc788\ub2e4. \\nsource \uc11c\ubc84\uc5d0 \uc811\uadfc\ud558\uc5ec user \uacc4\uc815\uc5d0 \ud574\ub2f9 \uad8c\ud55c\uc744 \uc124\uc815\ud574\uc900\ub2e4. \\n\\nSOURCE \uc811\uc18d\\n\\n```bash\\ndocker exec -it mysql-source mysql -u root -p\\n```\\n\\nuser \uacc4\uc815\uc5d0 REPLICATION SLAVE \uad8c\ud55c \ucd94\uac00\\n\\n```mysql\\nGRANT REPLICATION SLAVE ON *.* TO \'user\'@\'%\';\\nFLUSH PRIVILEGES;\\n```\\n\\n### SOURCE DB \uc815\ubcf4 \ud655\uc778\\n\\nreplica \uc124\uc815\uc5d0 \ud544\uc694\ud55c source db\uc758 \ubc14\uc774\ub108\ub9ac \ub85c\uadf8 \ud30c\uc77c\uba85\uacfc Position\uc744 \ud655\uc778\ud55c\ub2e4. \\nPosition \uac12\uc740 \uc2e4\uc81c \ud30c\uc77c\uc758 \ubc14\uc774\ud2b8 \uc218\ub97c \uc758\ubbf8\ud55c\ub2e4. \\n\ud655\uc778\ud55c File(SOURCE_LOG_FILE)\uacfc Position(SOURCE_LOG_POS) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```mysql\\nSHOW MASTER STATUS;\\n\\n+------------------+----------+--------------+------------------+-------------------+\\n| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |\\n+------------------+----------+--------------+------------------+-------------------+\\n| mysql-bin.000003 | 1082 | | | |\\n+------------------+----------+--------------+------------------+-------------------+\\n```\\n\\n### SOURCE ip \uc8fc\uc18c \ud655\uc778\\n\\ndocker inspect -f \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \ud574\ub2f9 \ucee8\ud14c\uc774\ub108\uc758 \uc138\ubd80 \uc815\ubcf4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud574 docker-compose \ud30c\uc77c\uc5d0 \uc124\uc815\ud574\ub454 mysql_network\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc124 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \ud655\uc778\ud55c\ub2e4. \\n\\n```bash\\ndocker inspect -f \\"{{with index .NetworkSettings.Networks \\\\\\"db-replication_mysql_network\\\\\\"}}{{.IPAddress}}{{end}}\\" mysql-source\\n```\\n\\nip \uc8fc\uc18c\uac00 \ub098\uc624\uc9c0 \uc54a\ub294 \uacbd\uc6b0 docker inspect mysql-source\ub85c \ud655\uc778\ud55c\ub2e4. \\n\ud655\uc778\ud55c IP\uc8fc\uc18c(SOURCE_HOST) \uac12\uc740 replica \uc124\uc815\uc5d0\uc11c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n### replica mysql \uc811\uc18d\\n\\nsource db\uc5d0 \uc811\uc18d\ud588\ub358 \ubc29\ubc95\uacfc \ub3d9\uc77c\ud558\uac8c replica db\uc5d0 \uc811\uc18d\ud55c\ub2e4. \\n\\n```bash\\ndocker exec -it mysql-replica mysql -u root -p\\n```\\n\\n### replica \uc124\uc815\\n\\n\uc774\uc804\uc5d0 source db\uc5d0\uc11c \uc5bb\uc5c8\ub358 \uc815\ubcf4\ub4e4\uc744 \uc0ac\uc6a9\ud558\uc5ec replica \uc124\uc815\uc744 \uc9c4\ud589\ud55c\ub2e4. \\n\uc2e4\uc81c DB \uc11c\ubc84\uc5d0\uc11c \ubcf5\uc81c\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc73c\ub85c source DB\uc758 \ud30c\uc77c\uc744 \ubcf5\uc81c\ud574\uc57c\ud558\uc9c0\ub9cc \ud604\uc7ac \ubcf5\uc81c\ud560 \ub370\uc774\ud130\uac00 \uc5c6\uae30 \ub54c\ubb38\uc5d0 \ud574\ub2f9 \ubd80\ubd84\uc740 \uc0dd\ub7b5\ud588\ub2e4. \\nSOURCE_HOST, SOURCE_LOG_FILE, SOURCE_LOG_POS \ub97c \uc801\uc808\ud788 \ubcc0\uacbd\ud55c\ub2e4.\\n\\n```mysql\\nSTOP REPLICA;\\n\\nCHANGE REPLICATION SOURCE TO \\nSOURCE_HOST=\'172.29.0.2\', \\nSOURCE_USER=\'user\', \\nSOURCE_PASSWORD=\'password\', \\nSOURCE_LOG_FILE=\'mysql-bin.000001\', \\nSOURCE_LOG_POS=0, \\nGET_SOURCE_PUBLIC_KEY=1;\\n\\nSTART REPLICA;\\n```\\n\\n### \uc124\uc815 \ud655\uc778\\n\\n```mysql\\nSHOW REPLICA STATUS;\\n\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Replica_IO_State | Source_Host | Source_User | Source_Port | Connect_Retry | Source_Log_File | Read_Source_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Source_Log_File | Replica_IO_Running | Replica_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Source_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Source_SSL_Allowed | Source_SSL_CA_File | Source_SSL_CA_Path | Source_SSL_Cert | Source_SSL_Cipher | Source_SSL_Key | Seconds_Behind_Source | Source_SSL_Verify_Server_Cert | Last_IO_Errno | Last_IO_Error | Last_SQL_Errno | Last_SQL_Error | Replicate_Ignore_Server_Ids | Source_Server_Id | Source_UUID | Source_Info_File | SQL_Delay | SQL_Remaining_Delay | Replica_SQL_Running_State | Source_Retry_Count | Source_Bind | Last_IO_Error_Timestamp | Last_SQL_Error_Timestamp | Source_SSL_Crl | Source_SSL_Crlpath | Retrieved_Gtid_Set | Executed_Gtid_Set | Auto_Position | Replicate_Rewrite_DB | Channel_Name | Source_TLS_Version | Source_public_key_path | Get_Source_public_key | Network_Namespace |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n| Waiting for source to send event | 172.25.0.3 | user | 3306 | 60 | mysql-bin.000003 | 1082 | mysql-relay-bin.000002 | 868 | mysql-bin.000003 | Yes | Yes | | | | | | | 0 | | 0 | 1082 | 1078 | None | | 0 | No | | | | | | 0 | No | 0 | | 0 | | | 1 | 5a396b02-41c6-11ee-a56d-0242ac190003 | mysql.slave_master_info | 0 | NULL | Replica has read all relay log; waiting for more updates | 86400 | | | | | | | | 0 | | | | | 1 | |\\n+----------------------------------+-------------+-------------+-------------+---------------+------------------+---------------------+------------------------+---------------+-----------------------+--------------------+---------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+-------------------------------+---------------+---------------+----------------+----------------+-----------------------------+------------------+--------------------------------------+-------------------------+-----------+---------------------+----------------------------------------------------------+--------------------+-------------+-------------------------+--------------------------+----------------+--------------------+--------------------+-------------------+---------------+----------------------+--------------+--------------------+------------------------+-----------------------+-------------------+\\n```\\n\\nReplica_IO_Running, Replica_SQL_Running \uac12\uc774 YES\ub77c\uba74 \uc815\uc0c1\uc801\uc73c\ub85c replication \uad6c\uc131\uc774 \uc644\ub8cc\ub41c \uac83\uc774\ub2e4. \\n\\n\uc124\uc815\uc744 \ub9c8\uce5c \ud6c4 source db\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 create table \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud55c\ub2e4. \\nreplica db\uc5d0 \ub3d9\uc77c\ud55c member table\uc774 \uc0dd\uc131\ub41c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nCREATE TABLE member\\n(\\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\\n name VARCHAR(255)\\n);\\n```\\n\\n## \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub85c DB \uc811\uadfc\ud558\uae30\\n\\n\uc77c\ubc18\uc801\uc778 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 source, \uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158\uc778 \uacbd\uc6b0 replica\ub85c \uc694\uccad\uc774 \uac00\ub3c4\ub85d \uad6c\uc131\ud574\ubcf4\uc790. \\n\\n### Environment \uc124\uc815\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 source, replica\ub85c \uad6c\ubd84\ud558\uc5ec \uc124\uc815\ud55c\ub2e4. \\n\\n```yml title=\\"application.yml\\"\\nspring:\\n datasource:\\n source:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13306/db\\n replica:\\n username: user\\n password: password\\n driver-class-name: com.mysql.cj.jdbc.Driver\\n jdbc-url: jdbc:mysql://localhost:13307/db\\n```\\n\\n### DataSourceType \uc124\uc815\\n\\n\ub2e8\uc21c \ubb38\uc790\uc5f4\ub85c\ub3c4 \uad6c\ubd84\ud560 \uc218 \uc788\uc9c0\ub9cc, enum\uc744 \uc774\uc6a9\ud574\uc11c \ud2b8\ub79c\uc7ad\uc158\uc744 \uad6c\ubd84\ud558\ub3c4\ub85d \uc0dd\uc131\ud55c\ub2e4. \\nKey\ub294 \ucd94\ud6c4\uc5d0 \ube48 \uc124\uc815\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n```java title=\\"DataSourceType\\"\\npublic enum DataSourceType {\\n SOURCE(SOURCE_NAME),\\n REPLICA(REPLICA_NAME),\\n ;\\n\\n private final String key;\\n\\n DataSourceType(String key) {\\n this.key = key;\\n }\\n\\n public static class Key {\\n public static final String ROUTING_NAME = \\"ROUTING\\";\\n public static final String SOURCE_NAME = \\"SOURCE\\";\\n public static final String REPLICA_NAME = \\"REPLICA\\";\\n }\\n}\\n```\\n\\n### AbstractRoutingDataSource \uc124\uc815\\n\\n\uc2a4\ud504\ub9c1\uc774 \uc9c0\uc6d0\ud574\uc8fc\ub294 AbstractRoutingDataSource\ub97c \uc0c1\uc18d\ubc1b\uc544 \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSource\ub97c \ud5a5\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub294 Map\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\uc744 \ubc1b\uc544 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setDefaultTargetDataSource: \uae30\ubcf8 \ub370\uc774\ud130 \uc18c\uc2a4\ub97c \uc124\uc815\ud55c\ub2e4. \\n- setTargetDataSources: \ub9f5 \ud615\ud0dc\ub85c \ubc1b\uc740 \ub370\uc774\ud130 \uc18c\uc2a4 \uac12\ub4e4\uc744 \uc124\uc815\ud55c\ub2e4. \\n\\ndetermineCurrentLookupKey\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158\uc758 \uc77d\uae30 \uc5ec\ubd80\uc5d0 \ub530\ub77c \ub2e4\ub978 DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. \\n- isCurrentTransactionReadOnly() \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \ud2b8\ub79c\uc7ad\uc158\uc774 \uc77d\uae30 \uc804\uc6a9\uc778\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n- DataSourceType\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uace0, \ubc18\ud658\ud55c \uac12\uc5d0 \ud574\ub2f9\ud558\ub294 \ub370\uc774\ud130 \uc18c\uc2a4\uac00 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n```java title=\\"RoutingDataSource\\"\\npublic class RoutingDataSource extends AbstractRoutingDataSource {\\n\\n private final Logger log = LoggerFactory.getLogger(getClass());\\n\\n public static RoutingDataSource from(Map dataSources) {\\n RoutingDataSource routingDataSource = new RoutingDataSource();\\n routingDataSource.setDefaultTargetDataSource(dataSources.get(DataSourceType.SOURCE));\\n routingDataSource.setTargetDataSources(dataSources);\\n return routingDataSource;\\n }\\n\\n @Override\\n protected Object determineCurrentLookupKey() {\\n boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();\\n\\n if (readOnly) {\\n log.info(\\"readOnly = true, request to replica\\");\\n return DataSourceType.REPLICA;\\n }\\n log.info(\\"readOnly = false, request to source\\");\\n return DataSourceType.SOURCE;\\n }\\n}\\n```\\n\\n### DataSource \uc124\uc815\\n\\n\uc704\uc5d0\uc11c\ubd80\ud130 \uc21c\uc11c\ub300\ub85c Source, Replica, RoutingDataSource, LazyConnectionDataSourceProxy \uc124\uc815\uc774\ub2e4. \\n\uc2a4\ud504\ub9c1\uc740 \ud2b8\ub79c\uc7ad\uc158 \uc2dc\uc791\uc2dc\uc5d0 \ucee4\ub125\uc158\uc758 \uc0ac\uc6a9\uc5ec\ubd80\uc640 \uc0c1\uad00\uc5c6\uc774 \ucee4\ub125\uc158\uc744 \ud655\ubcf4\ud55c\ub2e4. \\n\ub530\ub77c\uc11c readOnly \ud2b8\ub79c\uc7ad\uc158\uc774 \uc124\uc815\ub41c \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ubbf8\ub9ac \ud655\ubcf4\ub41c \ucee4\ub125\uc158\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 replica db\ub85c \uc694\uccad\uc744 \ud558\uc9c0 \uc54a\uace0 setDefaultTargetDataSource\ub85c \uc124\uc815\ud55c source db\ub85c \uc694\uccad\uc744 \ud55c\ub2e4. \\nLazyConnectionDataSourceProxy\ub97c \uc124\uc815\ud558\ub294 \uacbd\uc6b0 \uc2e4\uc81c DataSource\ub97c \uc0ac\uc6a9\ud558\ub294 \uc2dc\uc810\uc5d0 \ucee4\ub125\uc158\uc744 \ud68d\ub4dd\ud574\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc124\uc815\ud55c\ub300\ub85c replica db\ub85c \uc870\ud68c \uc694\uccad\uc744 \ud55c\ub2e4. \\n\\n```java title=\\"DataSourceConfiguration\\"\\n@Configuration\\npublic class DataSourceConfiguration {\\n\\n @Bean\\n @Qualifier(SOURCE_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.source\\")\\n public DataSource sourceDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(REPLICA_NAME)\\n @ConfigurationProperties(prefix = \\"spring.datasource.replica\\")\\n public DataSource replicaDataSource() {\\n return DataSourceBuilder.create().build();\\n }\\n\\n @Bean\\n @Qualifier(ROUTING_NAME)\\n public DataSource routingDataSource(\\n @Qualifier(SOURCE_NAME) DataSource sourceDataSource,\\n @Qualifier(REPLICA_NAME) DataSource replicaDataSource\\n ) {\\n return RoutingDataSource.from(Map.of(\\n DataSourceType.SOURCE, sourceDataSource,\\n DataSourceType.REPLICA, replicaDataSource\\n ));\\n }\\n\\n @Bean\\n @Primary\\n public DataSource dataSource(\\n @Qualifier(ROUTING_NAME) DataSource routingDataSource\\n ) {\\n return new LazyConnectionDataSourceProxy(routingDataSource);\\n }\\n}\\n```\\n\\n\ucd5c\uc885\uc801\uc73c\ub85c DataSource \ube48\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n DSP[LazyConnectionDataSourceProxy] --\x3e RDS[RoutingDataSource]\\n\\tRDS --\x3e S[SourceDataSource]\\n\\tRDS --\x3e R[ReplicaDataSource]\\n```\\n\\n### \ub3d9\uc791 \ud655\uc778\\n\\n\uac04\ub2e8\ud558\uac8c \ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud574\uc11c \uc124\uc815\ud55c\ub300\ub85c \ub3d9\uc791\uc774 \ub418\ub294\uc9c0 \ud655\uc778\ud574\ubcf4\uc558\ub2e4. \\nsave \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional`, findById \uba54\uc11c\ub4dc\uc758 \uacbd\uc6b0 `@Transactional(readOnly = true)`\uac00 \uc124\uc815\ub418\uc5b4\uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ud1b5\ud574 save\uc758 \uacbd\uc6b0 source db\ub85c findById\uc758 \uacbd\uc6b0 replica db\ub85c \uc694\uccad\uc744 \ud558\ub294 \uac83\uc744 \uc54c \uc218 \uc788\ub2e4. \\n\\n```java title=\\"MemberServiceTest\\"\\n@SpringBootTest\\nclass MemberServiceTest {\\n\\n @Autowired\\n private MemberService memberService;\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc800\uc7a5\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = false\\n memberService.save(\\"bbiac\\");\\n }\\n\\n @Test\\n void \uc0ac\uc6a9\uc790\ub97c_\uc870\ud68c\ud55c\ub2e4() {\\n // RoutingDataSource log: readOnly = true\\n assertThatThrownBy(() -> memberService.findById(MAX_VALUE))\\n .isInstanceOf(NoSuchElementException.class);\\n }\\n}\\n```\\n\\nDB\uc5d0\uc11c\ub294 \ud655\uc778\ud558\ub824\uba74 root \uacc4\uc815\uc73c\ub85c \uc811\uc18d\ud55c \ud6c4 general log\ub97c \ud65c\uc131\ud654 \uc2dc\ud0a8\ub2e4. \\n\\n```sql\\nSET GLOBAL log_output = \'table\';\\nSET GLOBAL general_log = 1;\\n```\\n\\ngeneral log\ub97c \ud65c\uc131\ud654 \ud55c \ud6c4 \uc77d\uae30 \uc804\uc6a9 \uba54\uc11c\ub4dc\ub97c \uc2e4\ud589\ud55c\ub2e4. \\nserver_id, \uc2e4\ud589\ud55c \ucffc\ub9ac\ubb38\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\nSELECT user_host, thread_id, server_id, convert(argument using utf8) FROM mysql.general_log where argument like \'%select%\';\\n\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user_host | thread_id | server_id | convert(argument using utf8) |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n| user[user] @ [172.25.0.1] | 277 | 2 | select m1_0.id,m1_0.name from member m1_0 where m1_0.id=9223372036854775807 |\\n+----------------------------+-----------+-----------+-----------------------------------------------------------------------------+\\n```\\n\\n\ud655\uc778 \ud6c4 general log\ub97c \ube44\ud65c\uc131\ud654 \ud55c \ud6c4 \ube44\ud65c\uc131\ud654 \ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n```sql\\nSET GLOBAL general_log = 0;\\nSHOW VARIABLES LIKE \'%general%\';\\n\\n+------------------+---------------------------------+\\n| Variable_name | Value |\\n+------------------+---------------------------------+\\n| general_log | OFF |\\n| general_log_file | /var/lib/mysql/4b6b9db98290.log |\\n+------------------+---------------------------------+\\n```\\n\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n16\uc7a5 \ubcf5\uc81c, Real MySQL 8.0 - \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Replication, MySQL Docs](https://dev.mysql.com/doc/refman/8.1/en/replication.html) \\n[MySql - Master Slave Replication \uad6c\uc870 \ub9cc\ub4e4\uc5b4\ubcf4\uae30](https://huisam.tistory.com/entry/mysql-replication) \\n[Spring \ub808\ud50c\ub9ac\ucf00\uc774\uc158 \ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac \ubc29\uc2dd](https://cheese10yun.github.io/spring-transaction/) \\n[replication-datasource](https://github.com/kwon37xi/replication-datasource) \\n[Simplified Guide to MySQL Replication with Docker Compose](https://www.linkedin.com/pulse/simplified-guide-mysql-replication-docker-compose-rakesh-shekhawat/) \\n[Dockerfile\uc5d0\uc11c \uc790\uc8fc \uc4f0\uc774\ub294 \uba85\ub839\uc5b4](https://www.daleseo.com/dockerfile/) \\n[CHANGE REPLICATION SOURCE TO Statement](https://dev.mysql.com/doc/refman/8.1/en/change-replication-source-to.html) \\n[LazyConnectionDataSourceProxy](https://kwonnam.pe.kr/wiki/springframework/lazyconnectiondatasourceproxy) \\n[\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ub808\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ud1b5\ud55c \ucffc\ub9ac \uc131\ub2a5 \uac1c\uc120 (feat. Mysql, SpringBoot)](https://hudi.blog/database-replication-with-springboot-and-mysql/) \\n[\ubd80\ud558 \ubd84\uc0b0\uc744 \uc704\ud55c MySQL Replication \uad6c\uc131 \ubc0f \ucffc\ub9ac \uc694\uccad \ubd84\uae30](https://chagokx2.tistory.com/100) \\n[Use Docker Compose, Docker](https://docs.docker.com/get-started/08_using_compose/)"},{"id":"woowacourse-level3-retrospective","metadata":{"permalink":"/woowacourse-level3-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","source":"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","description":"\ud68c\uace0","date":"2023-08-19T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 19\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.945,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","slug":"woowacourse-level3-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30","permalink":"/db-replication"},"nextItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"}},"content":"import logo from \'./logo.png\';\\n\\n### \ud68c\uace0\\n\\n\uc9c0\ub09c 8\uc8fc\ub294 \ub808\ubca8 1, 2 \ub54c\ubcf4\ub2e4 5\ubc30 \uc815\ub3c4 \ube60\ub974\uac8c \uc9c0\ub098\uac04 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3\uc5d0\ub294 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4, \uae30\uc220 \uc678\uc801\uc778 \ubd80\ubd84\uc5d0\uc11c\ub3c4 \ubd80\uc871\ud568\uc774 \ub9ce\uc774 \ubcf4\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc744 \uc54c\uc558\uae30\uc5d0, \uc55e\uc73c\ub85c \ub354\uc6b1 \uc131\uc7a5\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ub0b4\uac00 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \ud300\uc6d0\ub4e4\uc774 \uc798 \ubcf4\ucda9\ud574 \uc918\uc11c \ub4e0\ub4e0\ud588\ub2e4. \\n\\n### \uc544\uc26c\uc6b4 \uc810\\n\\n**\ubb38\uc11c\ud654**\\n\\n\uac1c\uc778\uc801\uc73c\ub85c\ub294 \uae30\uc220 \uc678\uc801\uc73c\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ub0b4\uac00 \ud55c \ubd80\ubd84\uc744 \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c, \uc774\ud574\ud558\uae30 \uc27d\uac8c \ubb38\uc11c\ud654\ub97c \ud588\ub354\ub77c\uba74 \ud300\uc6d0\ub4e4\uc5d0\uac8c \ub354\uc6b1 \ub3c4\uc6c0\uc774 \ub418\uc5c8\uc744 \ud150\ub370 \uc774 \ubd80\ubd84\uc5d0 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ud22c\uc790\ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc5d0\uc11c \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubc29\ud559 \uae30\uac04 \ub3d9\uc548 \ubb38\uc11c\ud654\ub97c \ud558\uc9c0 \ubabb\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc778 \ube14\ub85c\uadf8 \uc62c\ub9ac\uba74\uc11c \uc870\uae08 \ub354 \ucc44\uc6cc\ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n**\ub0b4\uac00 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc774\uc790**\\n\\n\uc798 \ubabb\ud558\ub294 \ubd80\ubd84\uc774\ub77c\uba74 \uc2dc\uac04\uc744 \ub4e4\uc5ec\uc11c\ub77c\ub3c4 \uc911\uac04\uc740 \uac00\ub3c4\ub85d \ud574\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub9d0\uc744 \ud558\uae30 \uc804\uc5d0 \uc815\ub9ac\ud574\uc11c \uc758\uacac\uc744 \ub0b4\ub294 \uac83, \ubc1c\ud45c \uc900\ube44, \uac10\uc815 \uc870\uc808 \ub4f1\ub4f1\\n\ubabb\ud558\ub294 \ubd80\ubd84\uc744 \uc778\uc9c0\ud558\uace0, \uac1c\uc120\ud558\uc790. \\n\\n**\ucef4\ud3ec\ud2b8 \uc874 \ubc97\uc5b4\ub098\uae30**\\n\\n\uc870\uae08 \ub354 \ub3c4\uc804\uc801\uc73c\ub85c \ubaa9\ud45c\ub97c \uc7a1\uc558\uc73c\uba74 \uc88b\uc558\uc744 \uac83 \uac19\ub2e4. \\n\ub9e4\ubc88 \uadfc\uac70\ub97c \uac00\uc9c0\uace0 \uae30\uc220\uc744 \ub3c4\uc785\ud558\uace0, \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub824\uace0 \ud558\ub294 \ubd80\ubd84\uc774 \ub2e4\uc18c \ubd80\uc871\ud588\ub2e4. \\n\\n### \uc88b\uc558\ub358 \uc810\\n\\n**\uc88b\uc558\ub358 \uc810\ub3c4 \ubb38\uc11c\ud654**\\n\\n[\ud300 \ube14\ub85c\uadf8](https://tripdraw.blog)\ub3c4 \uba3c\uc800 \ub3c4\uc785\ud558\uc790\uace0 \uc81c\uc548\ud558\uace0, \ub0b4\uac00 \ud588\ub358 \ubd80\ubd84\uc740 \ubb38\uc11c\ud654\ub97c \uaf64 \ub9ce\uc774 \ud574\uc11c \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud06c\ub8e8 4\uba85\uc774\uc11c \uac19\uc774 \ud55c \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c\ub294 \uae30\ub2a5 \uad6c\ud604\ud55c\ub2e4\uace0 \ubb38\uc11c\ud654\uac00 \uc870\uae08 \ubbf8\ud761\ud574\uc11c \ubcf4\ucda9\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\\n**\ub0b4\uac00 \ub514\uc790\uc778\ud55c \ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0**\\n\\n\\n\\n\ud2b8\ub9bd\ub4dc\ub85c\uc6b0 \ub85c\uace0\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ud300\uc6d0\ub4e4\uc774 \ub300\ud45c \uc0c9\uc0c1(\ud30c\ub780\uc0c9)\uc744 \uc815\ud574\uc92c\uace0, \uc8fc\ub9d0 \ub3d9\uc548 \uc2e0\ub098\uac8c \ub85c\uace0 \ub514\uc790\uc778\uc744 \ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc544\ub798\uc758 D \ubd80\ubd84\uc740 \uc720\ud29c\ube0c \uac15\uc758 \ub4e4\uc73c\uba74\uc11c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\uc11c \ubfcc\ub4ef\ud558\ub2e4. \\n\\n**\uae30\uc220 \uc120\ud0dd\uc758 \uc774\uc720**\\n\\n\uae30\uc220\uc758 \ud559\uc2b5 \ube44\uc6a9, \ud604\uc7ac \uad6c\uc870\uc5d0 \uc801\ud569\ud55c\uc9c0, \uc2e4\uc81c \uac00\uc9c0\uace0 \uc788\ub294 \ub9ac\uc18c\uc2a4\ub97c \uace0\ub824\ud574\uc11c \uae30\uc220 \uc120\ud0dd\uc744 \ud558\uace0, \ub3c4\uc785\ud588\ub358 \ubd80\ubd84\uc774 \uc88b\uc558\ub2e4. \\n100% \uc88b\uc740 \uc120\ud0dd\uc77c \uc21c \uc5c6\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \uc120\ud0dd\uc5d0 \ub300\ud55c \uadfc\uac70\uac00 \uc874\uc7ac\ud55c\ub2e4\uba74 \ud655\ub960\uc744 \ub192\ud600\uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n### \ub9c8\uce58\uba70\\n\\n\ud50c\ub808\uc774\uc2a4\ud1a0\uc5b4\uc5d0 \uc571\uc774 \uc62c\ub77c\uac00 \uc788\ub294 \uac70 \ub108\ubb34 \uc2e0\uae30\ud558\ub2e4. \\n\uc548\ub4dc\ub85c\uc774\ub4dc \ube0c\ub808\uba58 \uc74c\uc545\ub300(\uba67\ub3fc\uc9c0, \uc218\ub2ec, \ud551\uad6c), \uadf8\ub9ac\uace0 \ubc31\uc5d4\ub4dc \ud300\uc6d0\ub4e4(\uccb4\uc778\uc800, \ud6c4\ucd94, \ub9ac\uc624) \ub108\ubb34 \uace0\uc0dd\uc774 \ub9ce\uc558\ub2e4."},{"id":"cloudwatch","metadata":{"permalink":"/cloudwatch","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","source":"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md","title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","description":"CloudWatch","date":"2023-08-17T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 17\uc77c","tags":[{"label":"cloudwatch","permalink":"/tags/cloudwatch"},{"label":"log","permalink":"/tags/log"},{"label":"monitoring","permalink":"/tags/monitoring"}],"readingTime":5.35,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","slug":"cloudwatch","tags":["cloudwatch","log","monitoring"]},"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 3 \ud68c\uace0","permalink":"/woowacourse-level3-retrospective"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"}},"content":"## CloudWatch\\n\\nAWS \ub9ac\uc18c\uc2a4\uc640 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc9c0\ud45c\uc640 \ub85c\uadf8\uc5d0 \ub300\ud55c \ubaa8\ub2c8\ud130\ub9c1\uc744 \uc81c\uacf5\ud558\ub294 \uc11c\ube44\uc2a4\ub2e4. \\n\uc9c0\ud45c\ub97c \uac10\uc2dc\ud558\uc5ec \uc54c\ub9bc\uc744 \ubcf4\ub0b4\ub294 \uae30\ub2a5\ub3c4 \uc81c\uacf5\ud55c\ub2e4. \\n\ud504\ub9ac\ud2f0\uc5b4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \ub300\uc2dc\ubcf4\ub4dc\ub2f9 3$/M \uc758 \ube44\uc6a9\uc774 \uccad\uad6c\ub418\uace0, \uc9c0\ud45c\ub098 \ub85c\uadf8\uc758 \uc591\uc5d0 \ub530\ub77c \ube44\uc6a9\uc774 \ucd94\uac00\uc801\uc73c\ub85c \uccad\uad6c\ub41c\ub2e4. \\n\uc694\uae08 \uc815\ubcf4\uc5d0 \ub300\ud55c \uc790\uc138\ud55c \uc815\ubcf4\ub294 [\ub2e4\uc74c \ub9c1\ud06c](https://aws.amazon.com/ko/cloudwatch/pricing/)\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n## CloudWatch Metrics\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c 5\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \uc218\uc9d1\ub41c\ub2e4. \\n\uc138\ubd80 \ubaa8\ub2c8\ud130\ub9c1(Detailed Monitoring)\uc744 \ud65c\uc131\ud654\ud558\uba74 1\ubd84\ub9c8\ub2e4 \uc9c0\ud45c\ub97c \uc218\uc9d1\ud55c\ub2e4. \\n\ub300\uc2dc\ubcf4\ub4dc\uc5d0\uc11c InstanceId\ub85c \uac80\uc0c9\ud558\uc5ec \uc218\uc9d1\ub41c \uc9c0\ud45c\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch1.png](./cloudwatch1.png)\\n\\nCPUUtilization, NetworkIn, NetworkOut\uacfc \uac19\uc740 \uae30\ubcf8\uc801\uc778 \uc9c0\ud45c\ub97c \uc81c\uacf5\ud558\uace0, \uba54\ubaa8\ub9ac, \ub514\uc2a4\ud06c \uacf5\uac04\uacfc \uac19\uc740 \uc9c0\ud45c\ub97c \ud655\uc778\ud558\ub824\uba74 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\ub97c \uc124\uc815\ud574\uc57c \ud55c\ub2e4.\\n\\n## CloudWatch Agent \uc124\uce58\\n\\nCloudWatch Agent \uc0ac\uc6a9\uc790 \uc9c0\uc815 \uc9c0\ud45c\uc640 \ub85c\uadf8\ub97c \uc218\uc9d1\ud560 \uc218 \uc788\ub2e4. \\n\\n### IAM \uc5ed\ud560 \uc124\uc815\\n\\n\uae30\ubcf8\uc801\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4\uac00 CloudWatchAgentServerPolicy\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\nIAM \u2192 \uc5ed\ud560\uc5d0\uc11c \uc5ed\ud560 \uc0dd\uc131\uc744 \ud074\ub9ad\ud55c\ub2e4.\\n\\n![./cloudwatch2.png](./cloudwatch2.png)\\n\\nCloudWatchAgentServerPolicy \uad8c\ud55c \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uace0, \uc801\ub2f9\ud55c \uc5ed\ud560 \uc774\ub984\uc744 \uc785\ub825\ud574\uc11c \uc5ed\ud560\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\\n![./cloudwatch3.png](./cloudwatch3.png)\\n\\nEC2 \uc778\uc2a4\ud134\uc2a4 \ubaa9\ub85d\uc73c\ub85c \ub4e4\uc5b4\uac00\uc11c, CloudWatch Agent\ub97c \uc124\uce58\ud560 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud074\ub9ad\ud55c\ub2e4. \\n\uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc5d0\uc11c \uc774\uc804\uc5d0 \uc0dd\uc131\ud55c \uc5ed\ud560\uc744 \uc9c0\uc815\ud55c\ub2e4.\\n\\n![./cloudwatch4.png](./cloudwatch4.png)\\n\\n### \uc124\uce58\\n\\n\ud658\uacbd\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\nOS: ubuntu 22.04 \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small (ARM64) \\n\\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uce58\ud55c\ub2e4.\\n\\n```bash\\nwget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb\\nsudo dpkg -i -E ./amazon-cloudwatch-agent.deb\\n```\\n\\n[\uc0ac\uc6a9 \uc124\uba85\uc11c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html)\uc5d0 \uac01 \uc778\uc2a4\ud134\uc2a4 \uc720\ud615\ub9c8\ub2e4 \ub2e4\uc6b4\ub85c\ub4dc \ub9c1\ud06c\uac00 \uc790\uc138\ud558\uac8c \uc548\ub0b4\ub418\uc5b4 \uc788\ub2e4.\\n\\n### Wizard\\n\\nCloudWatch Wizard\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uc124\uc815 \ud30c\uc77c \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \uc218\uc9d1\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub294 \uacbd\uc6b0 Wizard \uc2e4\ud589 \uba85\ub839\uc5b4 \uc785\ub825 \uc804 log \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \ubcf5\uc0ac\ud574\ub450\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec Wizard\ub97c \uc2e4\ud589\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard\\n```\\n\\n\uc124\uc815\uc744 \uc9c4\ud589\ud558\ub2e4 \ubcf4\uba74 \uc124\uc815 \ud30c\uc77c\uc774 \uc5b4\ub5bb\uac8c \uad6c\uc131\ub420\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\ub85c\uadf8\ub97c \ucd94\uac00\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \uc785\ub825\ucc3d\uc774 \ub098\uc624\uba74 \uc900\ube44\ud574\ub480\ub358 \ub85c\uadf8 \ud30c\uc77c\uc758 \uc808\ub300 \uacbd\ub85c\ub97c \uc785\ub825\ud55c\ub2e4. \\n\\n![./cloudwatch5.png](./cloudwatch5.png)\\n\\n\uc911\uac04\uc5d0 SSM parameter store\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \uc800\uc7a5\ud560 \uac83\uc774\ub0d0\uace0 \ubb3c\uc5b4\ubcf4\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4. \\n\\n```bash\\nDo you want to store the config in the SSM parameter store?\\n1. yes\\n2. no\\n```\\n\\n\ucd94\uac00\uc801\uc73c\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 2\ubc88\uc744 \uc120\ud0dd\ud55c\ub2e4. \\nParameter Store \uad00\ub9ac\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 \ub2e4\uc74c\uc758 [\ubb38\uc11c](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac70 \uac19\ub2e4. \\n\uc124\uc815\uc774 \uc644\ub8cc\ub418\uba74 `/opt/aws/amazon-cloudwatch-agent/bin/config.json` \uc5d0 \uc124\uc815\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc774 \uc800\uc7a5\ub41c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc801\uc6a9\\n\\n\uc544\ub798\uc758 \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc124\uc815\ud30c\uc77c\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4. \\nfile \ub4a4\uc5d0\ub294 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \uc808\ub300\uacbd\ub85c(\uc544\ub798 \uba85\ub839\uc5b4 \uae30\uc900 \uae30\ubcf8 \uc0dd\uc131 \uc704\uce58)\ub97c \uc785\ub825\ud558\uba74 \ub41c\ub2e4. \\n\\n```bash\\nsudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json\\n```\\n\\n### types.db: no such file or directory \uc5d0\ub7ec\\n\\n\ub2e4\uc74c\uacfc \uac19\uc740 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud55c\ub2e4\uba74 types.db \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\ub2e4.\\n\\n```bash\\nError running agent: Error loading config file /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml: error parsing socket_listener, open /usr/share/collectd/types.db: no such file or directory\\n```\\n\\ntypes.db \ud30c\uc77c \uc0dd\uc131\\n\\n```bash\\nsudo mkdir /usr/share/collectd\\nsudo touch /usr/share/collectd/types.db\\n```\\n\\n### \uc9c0\ud45c \ud655\uc778\\n\\nCloudWatch Metrics\uc5d0 \uac00\ubcf4\uba74 CWAgent\ub77c\ub294 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\uac00 \ucd94\uac00\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n![./cloudwatch6.png](./cloudwatch6.png)\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ucd94\uac00\ud558\uc5ec \uc9c0\ud45c\uc5d0 \ub300\ud55c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\\n```json\\n{\\n \\"metrics\\": {\\n \\"namespace\\": \\"2023-hello-world\\",\\n ......\\n },\\n} \\n```\\n\\n### \ub85c\uadf8\\n\\nCloudWatch \u2192 \ub85c\uadf8 \uadf8\ub8f9\uc73c\ub85c \uac00\uba74 Wizard\ub85c \ucd94\uac00\ud55c \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.\\n\\n![./cloudwatch7.png](./cloudwatch7.png)\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[CloudWatch\ub780 \ubb34\uc5c7\uc785\ub2c8\uae4c?](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) \\n[Amazon CloudWatch \uc694\uae08](https://aws.amazon.com/ko/cloudwatch/pricing/) \\n[Linux \uc778\uc2a4\ud134\uc2a4 \uc9c0\ud45c](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) \\n[\uc11c\ubc84\uc5d0 CloudWatch \uc5d0\uc774\uc804\ud2b8 \uc124\uce58 \ubc0f \uc2e4\ud589](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-commandline-fleet.html) \\n[CloudWatch Agent\ub97c Parameter Store\uc5d0\uc11c \uad00\ub9ac\ud574 \ubcf4\uae30](https://dev.classmethod.jp/articles/manage-the-cloudwatch-agent-from-the-parameter-store/) \\n[CloudWatch\uc5d0\uc774\uc804\ud2b8 \uad6c\uc131 \ud30c\uc77c](https://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html)"},{"id":"route-image-async-with-event","metadata":{"permalink":"/route-image-async-with-event","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","source":"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","description":"\uc774\uc804 \uae00","date":"2023-08-13T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 13\uc77c","tags":[{"label":"async","permalink":"/tags/async"},{"label":"event","permalink":"/tags/event"}],"readingTime":11.2,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","slug":"route-image-async-with-event","tags":["async","event"]},"prevItem":{"title":"CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131","permalink":"/cloudwatch"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"}},"content":"## \uc774\uc804 \uae00\\n\\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd](./route-image-intro) \\n[\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604](./route-image-implementation)\\n\\n## \uac1c\uc694\\n\\n\ud604\uc7ac \uc5ec\ud589\uc744 \ub9c8\uce58\ub294 \uacbd\uc6b0, \uac10\uc0c1\uc744 \uc0dd\uc131\ud558\ub294 \uacbd\uc6b0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \uc704\uce58 \uc815\ubcf4\uc758 \uac1c\uc218\uc5d0 \uc815\ube44\ub840\ud558\uc5ec \uc0dd\uc131 \uc2dc\uac04\uc774 \uc99d\uac00\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ube44\ub3d9\uae30\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\uc5ec \uc0ac\uc6a9\uc790\uc758 \uacbd\ud5d8\uc744 \uac1c\uc120\uc2dc\ud0ac \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \uc8fc\uae30\ub2a5\uc758 \uc751\ub2f5\uc18d\ub3c4 \uac1c\uc120\\n\\n\uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc774 \uc8fc\uae30\ub2a5\uc774\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ubd80\uae30\ub2a5\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131\uc758 \uc751\ub2f5 \uc18d\ub3c4\uac00 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uace0 \uc788\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uc5ec\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0ac\uc6a9\uc5d0 \ubb38\uc81c\uac00 \ub418\uc9c0 \uc54a\ub294\ub2e4. \\n\uc18c\uc694 \uc2dc\uac04\uc774 1\ucd08 \uc774\uc0c1 \uac78\ub9ac\ub294 \uacbd\uc6b0\uac00 \uc874\uc7ac\ud558\uae30\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ube44\ub3d9\uae30 \ucc98\ub9ac\ud558\uace0 \uc5ec\ud589 \uc885\ub8cc\uc640 \uac10\uc0c1 \uc0dd\uc131 \uae30\ub2a5\uc758 \uc751\ub2f5 \uc2dc\uac04\uc744 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc911\uc694\ud558\ub2e4. \\n\\n### \ud655\uc7a5\uc131 \ub300\ube44\\n\\n\ud604\uc7ac 10\ubd84 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc11c\ubc84\uc5d0 \uc800\uc7a5\ud558\uace0 \uc788\ub2e4. \\n\uc870\uae08 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uadf8\ub9ac\ub294 \uacbd\uc6b0 \ud558\ub098\uc758 \uc5ec\ud589\uc5d0 \ub9ce\uc740 \uc704\uce58 \uc815\ubcf4\uac00 \uc800\uc7a5\ub420 \uc218\ubc16\uc5d0 \uc5c6\uace0 \ub530\ub77c\uc11c \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uac78\ub9ac\ub294 \uc2dc\uac04\uc774 \ub354 \uae38\uc5b4\uc9c8 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ucd94\ud6c4\uc5d0 \ub354 \uc9e7\uc740 \uac04\uaca9\uc73c\ub85c \uc704\uce58 \uc815\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \uacbd\uc6b0\ub97c \ub300\ube44\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \ud569\ub2f9\ud558\ub2e4. \\n\\n## \ube44\ub3d9\uae30 \ucc98\ub9ac\\n\\n@Async\ub97c \uc0ac\uc6a9\ud558\uba74 \uac04\ub2e8\ud558\uac8c \uba54\uc11c\ub4dc\ub97c \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \\n\\n### \ube44\ub3d9\uae30 \uc124\uc815\\n\\n\uc0ac\uc6a9\ud558\uae30 \uc804\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c EnableAsync \uc124\uc815\uc744 \ud574\uc57c\ud55c\ub2e4. \\n\ud574\ub2f9 \uc124\uc815\uc744 \uc801\uc6a9\ud558\uba74 \ube44\ub3d9\uae30\uc801\uc73c\ub85c \uc2e4\ud589\ud558\ub824\ub294 \uba54\uc11c\ub4dc\uc5d0 @Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec\uc8fc\uae30\ub9cc \ud558\uba74 \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud55c\ub2e4. \\n\\n```java title=\\"AsyncConfig\\"\\n@EnableAsync\\n@Configuration\\npublic class AsyncConfig {\\n}\\n```\\n\\n\uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \ud560 \ub54c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc2a4\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ub808\ub4dc \ud480 \uc124\uc815\uc744 \ub530\ub85c \ud574\uc918\uc57c \ud55c\ub2e4. \ud558\uc9c0\ub9cc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 ThreadPoolTaskExecutor\ub97c \ub530\ub85c \uc124\uc815\ud558\uc9c0 \uc54a\uc544\ub3c4 \uae30\ubcf8\uc801\uc73c\ub85c \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uac00 \uc0dd\uc131\uc744 \ub3c4\uc640\uc900\ub2e4. \\n\\n> In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.\\n> 7.7. Task Execution and Scheduling, Spring Boot Docs\\n\\n### @Async \uc801\uc6a9\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\uc5d0 Async \uc560\ub108\ud14c\uc774\uc158\uc744 \ubd99\uc5ec \ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java title=\\"RouteImageGenerator\\"\\n@Async\\npublic void generate(\\n List latitudes,\\n List longitudes,\\n List pointedLatitudes,\\n List pointedLongitudes,\\n Long tripId\\n) {\\n // \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n RouteImageDrawer routeImageDrawer = RouteImageDrawer.from(IMAGE_SIZE);\\n Coordinates coordinates = Coordinates.of(latitudes, longitudes);\\n Coordinates pointedCoordinates = Coordinates.of(pointedLatitudes, pointedLongitudes);\\n drawImage(coordinates, routeImageDrawer, pointedCoordinates);\\n\\n // \uc774\ubbf8\uc9c0 \uc800\uc7a5\\n String imageName = routeImageUploader.upload(routeImageDrawer.bufferedImage());\\n\\n // \uc790\uc6d0 \ud560\ub2f9 \ud574\uc81c\\n routeImageDrawer.dispose();\\n\\n // \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac12 \ubcc0\uacbd\\n Trip trip = tripRepository.findById(tripId)\\n .orElseThrow();\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n}\\n```\\n\\n### \ube44\ub3d9\uae30 \ucc98\ub9ac\uc2dc \ubb38\uc81c\uc810\\n\\n\ud604\uc7ac \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uace0 \uc800\uc7a5 \ud6c4, \uc800\uc7a5 \uacbd\ub85c\ub97c DB\uc5d0 \ubc18\uc601\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ud615\ud0dc\uac00 \ub418\uba70 \uc758\uc874\uc131 \ubc29\ud5a5\uc774 \ubb38\uc81c\uac00 \uc0dd\uae34\ub2e4. \\n\\n```mermaid\\ngraph LR\\n trip[trip: \uc5ec\ud589 \uad00\ub828 \ud328\ud0a4\uc9c0] --\x3e draw[draw: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294 \ud328\ud0a4\uc9c0]\\n draw --\x3e trip\\n```\\n\\n\uc774\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uacfc \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4. \\n\\n```mermaid\\ngraph LR\\n\\tsubgraph draw\\n\\t\\tdirection LR\\n\\t\\tRG[RouteImageGenerator] -- DB \ubc18\uc601 \uc694\uccad --\x3e ILR[ImageLinkTripRepository]\\n\\tend\\n subgraph trip\\n\\t\\tdirection LR\\n\\t\\tTS[TripService] -- \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e RG\\n\\t\\tILRI[ImageLinkTripRepositoryImpl] -- \uad6c\ud604 --\x3e ILR\\n\\tend\\n\\n\\ttrip --\x3e draw\\n```\\n\\n\ud328\ud0a4\uc9c0 \uac04 \uc758\uc874\uc131\uc740 \ud574\uacb0\ub418\uc5c8\uc9c0\ub9cc, \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5\uc744 \uc704\ud574 tripId\ub97c \ubc1b\uc544\uc57c\ud558\ub294 \ub4f1\uc758 \ub17c\ub9ac\uc801\uc778 \uc758\uc874\uc131\uc740 \uc544\uc9c1 \ud574\uacb0\ub418\uc9c0 \uc54a\uc558\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n## \uc774\ubca4\ud2b8 \uc0ac\uc6a9\\n\\n\uc2a4\ud504\ub9c1\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\uba74 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc758 \ube44\uad00\uc2ec\uc0ac(ex. \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131)\uc744 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4.\\n\\n### \uc774\ubca4\ud2b8 \ubc1c\ud589\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \uba3c\uc800 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud574\uc57c \ud55c\ub2e4. \\n\uc2a4\ud504\ub9c1\uc5d0\uc11c\ub294 ApplicationEventPublisher \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \uc218 \uc788\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \ub0b4\ubd80\uc801\uc73c\ub85c ApplicationContext\uac00 \uad6c\ud604\ud558\uc5ec \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud55c\ub2e4. \\n\\n```java title=\\"TripService & TripUpdateEvent\\"\\npublic void updateTripById(LoginUser loginUser, Long tripId, TripUpdateRequest tripUpdateRequest) {\\n ...\\n\\n // \uc774\ubca4\ud2b8 \ubc1c\ud589\\n applicationEventPublisher.publishEvent(new TripUpdateEvent(trip.id()));\\n}\\n\\npublic record TripUpdateEvent(Long tripId) {\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud560 \ub54c \ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc774 \uc911\uc694\ud558\ub2e4. \\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\ub294 \ub3c4\uba54\uc778\uc758 \ud589\uc704\ub97c \ub2f4\uace0 \uc788\ub294 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589(ex. RouteImageGenerateEvent)\ud55c\ub2e4\uba74 \ub17c\ub9ac\uc801\uc778 \uc758\uc874 \uad00\uacc4\uac00 \ub0a8\uc544\uc788\uae30\uc5d0 \uc774\ubca4\ud2b8\ub97c \uc801\uc808\ud788 \uc0ac\uc6a9\ud588\ub2e4\uace0 \ubcf4\uae30 \uc5b4\ub835\ub2e4. \\n\ubc1c\ud589\ud558\ub294 \uc774\ubca4\ud2b8\uba85\uc740 \uc8fc\uae30\ub2a5\uc774 \uc5b4\ub5a4 \ud589\uc704(ex. TripUpdateEvent)\ub97c \ud588\ub294\uc9c0\uc5d0 \ub300\ud55c \uc815\ubcf4\uac00 \ub2f4\uaca8\uc788\ub294 \uc774\ubca4\ud2b8\uba85\uc73c\ub85c \ubc1c\ud589\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4. \\n\\n### \uc774\ubca4\ud2b8 \uad6c\ub3c5\\n\\n\uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc2e4\ud589\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ud558\uae30 \uc704\ud558\uc5ec `@Async` \uc560\ub108\ud14c\uc774\uc158\uc744 \uc801\uc6a9\ud588\ub2e4. \\n\uc774\ubca4\ud2b8\uc758 \uad6c\ub3c5\uc740 \uc5ec\ud589\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc\ub420 \ub54c \uc5ec\ud589\uc5d0 \ub300\ud55c \uc815\ubcf4\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud574 `@TransactionalEventListener`\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n:::note TransactionPhase \uc124\uc815\\nTransactionPhase\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud2b8\ub79c\uc7ad\uc158 \uc774\ubca4\ud2b8\ub97c \uc5b4\ub5a4 \ub2e8\uacc4\uc5d0\uc11c \uc218\uc2e0\ud558\uace0 \ucc98\ub9ac\ud560\uc9c0\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\nAFTER_COMMIT(\uae30\ubcf8\uac12): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \ucee4\ubc0b \ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_ROLLBACK: \ud2b8\ub79c\uc7ad\uc158\uc774 \ub864\ubc31\ub418\ub294 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nAFTER_COMPLETION: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub610\ub294 \ub864\ubc31 \ub418\uc5c8\uc744 \uacbd\uc6b0 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\nBEFORE_COMMIT: \ud2b8\ub79c\uc7ad\uc158\uc774 \ucee4\ubc0b \ub418\uae30 \uc804 \uc774\ubca4\ud2b8 \uc2e4\ud589 \\n:::\\n\\n\uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uae30 \uc704\ud574 @Transactional \uc560\ub108\ud14c\uc774\uc158\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```java title=\\"TripUpdateEventHandler\\"\\n@Component\\npublic class TripUpdateEventHandler {\\n\\n private final RouteImageGenerator routeImageGenerator;\\n private final TripRepository tripRepository;\\n\\n public TripUpdateEventHandler(RouteImageGenerator routeImageGenerator, TripRepository tripRepository) {\\n this.routeImageGenerator = routeImageGenerator;\\n this.tripRepository = tripRepository;\\n }\\n\\n @Async\\n @TransactionalEventListener(phase = AFTER_COMMIT)\\n public void handle(TripUpdateEvent tripUpdateEvent) {\\n Trip trip = tripRepository.getTripWithPoints(tripUpdateEvent.tripId());\\n\\n String imageUrl = routeImageGenerator.generate(\\n trip.getLatitudes(),\\n trip.getLongitudes(),\\n trip.getPointedLatitudes(),\\n trip.getPointedLongitudes()\\n );\\n\\n trip.changeRouteImageUrl(imageUrl);\\n tripRepository.save(trip);\\n }\\n}\\n```\\n\\n\uc774\ubca4\ud2b8\ub97c \uc0ac\uc6a9\ud568\uc73c\ub85c\uc368 \ud328\ud0a4\uc9c0 \uac04 \uc21c\ud658 \ucc38\uc870 \ubb38\uc81c\uac00 \ub2e4\uc74c\uacfc \uac19\uc774 \ud574\uacb0\ub418\uc5c8\ub2e4. \\n\ub610\ud55c \uc8fc\uae30\ub2a5\uacfc \ubd80\uae30\ub2a5\uc744 \ubd84\ub9ac\ud568\uc73c\ub85c\uc368 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\ucd94\uc5c8\ub2e4.\\n\\n```mermaid\\ngraph LR\\n subgraph trip\\n TripServcie -- \ubc1c\ud589 --\x3e TripUpdateEvent\\n TripRepository\\n end\\n\\n subgraph draw\\n TripUpdateEventHandler -- \uad6c\ub3c5 \ud6c4 \uc774\ubbf8\uc9c0 \uc0dd\uc131 --\x3e TripUpdateEvent\\n TripUpdateEventHandler -- \uc0dd\uc131\ub41c \uc774\ubbf8\uc9c0 \uacbd\ub85c \uc800\uc7a5 --\x3e TripRepository\\n end\\n```\\n\\n### \ud14c\uc2a4\ud2b8\\n\\n\ube44\ub3d9\uae30\ub85c \ub3d9\uc791\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \ubc29\ubc95\uc774 \uc788\ub2e4. \\n\\nimport Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\\n\\n\\n```java\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(Mockito.timeout(5000).times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\n@ContextConfiguration(classes = TestSyncConfig.class)\\n@SpringBootTest\\npublic class TripUpdateEventHandlerIntegrationTest {\\n\\n ...\\n\\n @Test\\n void \uc5ec\ud589\uc218\uc815_\uc774\ubca4\ud2b8\ub97c_\ubc1c\uc0dd\uc2dc\ud0a4\uba74_\uc774\ubbf8\uc9c0\ub97c_\uc0dd\uc131_\uc694\uccad\uc744_\ud55c\ub2e4() {\\n // given\\n TripUpdateEvent tripUpdateEvent = new TripUpdateEvent(1L);\\n given(tripRepository.getTripWithPoints(tripUpdateEvent.tripId()))\\n .willReturn(\uc5ec\ud589());\\n\\n // when\\n transactionTemplate.executeWithoutResult(action -> applicationEventPublisher.publishEvent(tripUpdateEvent));\\n\\n // then\\n then(routeImageGenerator)\\n .should(times(1))\\n .generate(any(), any(), any(), any());\\n }\\n}\\n```\\n\\n\\n\\n\\n\ucc98\uc74c\uc5d0\ub294 \ud14c\uc2a4\ud2b8\uc5d0\uc11c\ub9cc \ub3d9\uae30\ub85c \uc124\uc815 \ud6c4 \uac80\uc99d\ud558\ub824\uace0 \ud588\ub2e4. \\n\ud1b5\ud569 \ud14c\uc2a4\ud2b8\uc5d0\uc120 `\ud2b8\ub79c\uc7ad\uc158\uc774 \uc815\uc0c1 \uc885\ub8cc\ub418\uc5c8\uc744 \ub54c \ube44\ub3d9\uae30\ub85c \uc774\ubca4\ud2b8\ub97c \uad6c\ub3c5\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0` \uac80\uc99d\uc774 \ud544\uc694\ud588\uae30 \ub54c\ubb38\uc5d0 \ucd5c\uc885\uc801\uc73c\ub85c `Mockito.timeout` \uba54\uc11c\ub4dc\ub97c \uc0ac\uc6a9\ud558\uc5ec \ube44\ub3d9\uae30 \uba54\uc11c\ub4dc\uac00 \ud1b5\uacfc\ub420 \ub54c\uae4c\uc9c0 \ub300\uae30\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4. \\n\\n## \uacb0\uacfc\\n\\n![./time.png](./time.png)\\n\\n\uc704 \uc751\ub2f5 \uc2dc\uac04\uc740 \uc704\uce58 \uc815\ubcf4 1000\uac1c\ub97c \uae30\uc900\uc73c\ub85c \ud14c\uc2a4\ud2b8\ud55c \uac12\uc774\ub2e4. \\n\uc751\ub2f5 \uc2dc\uac04\uc5d0 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ud3ec\ud568\ub418\uc9c0 \uc54a\uc544\uc11c \uc131\ub2a5\uc774 \uac1c\uc120\ub41c \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[7.7. Task Execution and Scheduling, Spring Boot Docs](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.task-execution-and-scheduling) \\n[Spring Events, Baeldung](https://www.baeldung.com/spring-events) \\n[\ud68c\uc6d0\uc2dc\uc2a4\ud15c \uc774\ubca4\ud2b8\uae30\ubc18 \uc544\ud0a4\ud14d\ucc98 \uad6c\ucd95\ud558\uae30](https://techblog.woowahan.com/7835/)"},{"id":"route-image-implementation","metadata":{"permalink":"/route-image-implementation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","source":"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","description":"\uac1c\uc694","date":"2023-08-02T00:00:00.000Z","formattedDate":"2023\ub144 8\uc6d4 2\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":11.665,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","slug":"route-image-implementation","tags":["image","awt"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac","permalink":"/route-image-async-with-event"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"}},"content":"## \uac1c\uc694\\n\\n\uc5ec\ud589\uc5d0 \ub300\ud55c \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\uae30 \uc704\ud574 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d \ubc0f \uae30\uc220 \uc120\ud0dd\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc740 [\ub9c1\ud06c](./route-image-intro)\uc5d0 \uc788\ub2e4.\\n\\n### \uad6c\ud604 \uacb0\uacfc\\n\\n![./result.png](./result.png)\\n\\n\uc608\uc2dc \ub370\uc774\ud130\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n**\uc11c\uc6b8\uc5ed(\uc810)** \u2192 \uc2e0\uc0ac\uc5ed \u2192 \ub178\ub7c9\uc9c4\uc5ed \u2192 \ud64d\ub300\uc785\uad6c\uc5ed \u2192 \uc885\ub85c3\uac00\uc5ed \u2192 \uc625\uc218\uc5ed \u2192 **\uad6c\ub85c\uc5ed(\uc810)** \u2192 \uc2e0\ub9bc\uc5ed \u2192 \ubc1c\uc0b0\uc5ed\\n\\n```java title=\\"\uc608\uc2dc \ub370\uc774\ud130\\"\\nList x = List.of(\\n 126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,\\n 126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639\\n);\\nList y = List.of(\\n 37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,\\n 37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184\\n);\\nList xPoints = List.of(126.97094933811682, 126.88474839801178);\\nList yPoints = List.of(37.55302829553499, 37.50129417536773);\\n```\\n\\n### IMAGE_SIZE & ROUTE_SIZE\\n\\n```java title=\\"RouteImageGenerator.java\\"\\nprivate static final int IMAGE_SIZE = 800;\\nprivate static final int ROUTE_SIZE = 600;\\n```\\n\\n\ucf54\ub4dc\ub97c \ubcf4\uba74 IMAGE_SIZE\uc640 ROUTE_SIZE\uac00 \uc788\ub2e4. \\nIMAGE_SIZE\ub294 \ub9d0 \uadf8\ub300\ub85c \uc774\ubbf8\uc9c0\uc758 width\uc640 height\ub97c \uc758\ubbf8\ud55c\ub2e4. \\nROUTE_SIZE\uc758 \uacbd\uc6b0 \uc0c1\ud558\uc88c\uc6b0 100px \ub9cc\ud07c\uc758 \uac04\uaca9\uc744 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc2e4\uc81c \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub294 600 * 600 \uc0ac\uc774\uc988\ub85c \uc0dd\uc131\ub41c\ub2e4. \\n\\n![./600.png](./600.png)\\n\\n**\uc0ac\uc774\uc988 \ubcc0\uacbd\uc758 \uc774\uc720**\\n\\n255 * 255 \uc815\ub3c4\uc758 \uc791\uc740 \uc0ac\uc774\uc988\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud574\ubcf4\ub824\uace0 \ud588\ub294\ub370, \uc774\ubbf8\uc9c0\uc758 \uc120\uba85\ub3c4\uac00 \uc88b\uc9c0 \uc54a\uc544 800 * 800 \uc0ac\uc774\uc988\ub85c \ubcc0\uacbd\ud588\ub2e4.\\n\\n## \uc8fc\uc694 \ud074\ub798\uc2a4\\n\\n### \uc694\uc57d\\n\\n| \ud074\ub798\uc2a4\uba85 | \uc124\uba85 | \ud2b9\uc774\uc0ac\ud56d |\\n| --- | --- | --- |\\n| Coordinate | \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \uc704\uce58 \uac12 | \uc88c\ud45c\ub97c \ub73b\ud558\uc9c0\ub9cc \uc5ec\ud589 \ub3c4\uba54\uc778\uc5d0 \ud3ec\ud568\ub41c Point \ud074\ub798\uc2a4\uc640 \uad6c\ubd84\ud558\uae30 \uc704\ud574 longitude, latitude\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 x, y \uc0ac\uc6a9 |\\n| Coordinates | Coordinate\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| Position | \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58 \uac12 | Integer \ud0c0\uc785\uc758 x, y \uc0ac\uc6a9 |\\n| Positions | Positions\uc758 \uc77c\uae09 \uceec\ub809\uc158 | - |\\n| RouteImageDrawer | \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4 BufferedImage, Graphics2D\ub97c \uac00\uc9c0\uace0 \uc788\uc74c | \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc0c1\uc218\uac00 \uc815\uc758\ub418\uc5b4 \uc788\uc74c |\\n| RouteImageUploader | BufferedImage\ub97c \ubc1b\uc544 \uc11c\ubc84\uc5d0 \uc5c5\ub85c\ub4dc \ud558\ub294 \ud074\ub798\uc2a4 | \ud604\uc7ac \uc5c5\ub85c\ub4dc \uc704\uce58\uac00 \uc815\ud574\uc9c0\uc9c0 \uc54a\uc544 \uc77c\ub2e8 \uae30\ubcf8(\ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8) \uc704\uce58\uc5d0 \uc0dd\uc131 |\\n| RouteImageGenerator | \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uace0 \uc5c5\ub85c\ub4dc\ud558\ub294 \uc11c\ube44\uc2a4 | \uc5ec\ud589 \uc885\ub8cc, \uac10\uc0c1 \uc800\uc7a5\uc2dc \ud574\ub2f9 \ud074\ub798\uc2a4\ub97c \ud1b5\ud574 \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad |\\n| BufferedImage(AWT) | \uc774\ubbf8\uc9c0 \ub370\uc774\ud130\ub97c \ucc98\ub9ac\ud558\uace0 \uc870\uc791\ud558\ub294 \ub370 \uc0ac\uc6a9 | \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c\uac00 (0, 0) |\\n| Graphics2D(AWT) | \uc120 \uadf8\ub9ac\uae30, \uc0c9\uc0c1 \uad00\ub9ac \ub4f1\uc744 \uc9c0\uc6d0\ud558\ub294 \ud074\ub798\uc2a4 \uc2e4\uc81c \ud574\ub2f9 \ud074\ub798\uc2a4\uc758 draw \uba54\uc11c\ub4dc\ub97c \uacbd\ub85c\ub97c \uadf8\ub9bc | JDK 1.2 \uc774\ud6c4\uc5d0 \ucd94\uac00\ub428, 2D(\ud3c9\uba74) \uadf8\ub798\ud53d \ud658\uacbd\uc744 \uc9c0\uc6d0, bufferedImage.createGraphics \uba54\uc11c\ub4dc\ub97c \ud1b5\ud574 \uc0dd\uc131 |\\n\\n### \uc758\uc874\uad00\uacc4\\n\\n```mermaid\\ngraph TD\\n C1[Coordinates] --\x3e C[Coordinate]\\n P1[Positions] --\x3e P[Position]\\n\\n\\tRID[RouteImageDrawer] -- \\"\uc911\uc559 \uc815\ub82c\ub41c Positions\ub97c \ubc1b\uc544 \uc774\ubbf8\uc9c0 \uc0dd\uc131\\" --\x3e P1\\n\\tRID --\x3e B[BufferedImage]\\n\\tRID --\x3e G[Graphics2D]\\n\\n\\tC1 -- \\"calculatePositions \uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c \uc704\uce58 \uacc4\uc0b0\\" --\x3e P1\\n\\n\\tRIU[RouteImageUploader] --\x3e B\\n\\tRIG[RouteImageGenerator] --\x3e RID\\n\\tRIG --\x3e RIU\\n\\tRIG --\x3e C1\\n\\tRIG --\x3e P1\\n```\\n\\n### Coordinates(\uc704\ub3c4, \uacbd\ub3c4\uc758 \uc77c\uae09 \uceec\ub809\uc158)\\n\\n`List` 2\uac1c(\uc704\ub3c4, \uacbd\ub3c4)\uc778 \ud615\ud0dc\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc774 \uc788\uc5c8\uc9c0\ub9cc, \uc704\uce58 \uc810\uc744 \uc5ec\ub7ec\uac1c \ucc0d\ub294 \ubd80\ubd84\uc5d0\uc11c \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud574 \uc9c8 \uac83 \uac19\uc544\uc11c Coordinate(x, y)\uc640 \uc77c\uae09 \uceec\ub809\uc158\uc778 Coordinates\ub85c \uad00\ub9ac\ud558\uae30\ub85c \ud588\ub2e4. \\nCoordinates \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub450 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- calculatePositions: \uacbd\ub85c \uc774\ubbf8\uc9c0\uc758 \ud06c\uae30\ub97c \ubc1b\uc544 \uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \uc0ac\uc6a9\ub420 Positions\ub97c \ubc18\ud658\\n- indexOf: \ub2e4\ub978 Coordinates\ub97c \ubc1b\uc544 \ub3d9\uc77c\ud55c \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4\ub97c \ubc18\ud658\ud558\ub294 \\n\\nPositions \uacc4\uc0b0 \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\uc704\ub3c4, \uacbd\ub3c4 \uac01\uac01\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc2dc \ud544\uc694\ud55c \uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n```java title=\\"Coordinates.java\\"\\n// \ud638\ucd9c\\n// List xPositions = toPositions(xValues, maxDifference, routeImageSize);\\n// List yPositions = toPositions(yValues, maxDifference, routeImageSize);\\n\\nprivate List toPositions(List values, Double maxDifference, Integer routeImageSize) {\\n Double minValue = Collections.min(values);\\n return values.stream()\\n .map(value -> normalizeCoordinate(value, maxDifference, minValue))\\n .map(value -> mapToPosition(value, routeImageSize))\\n .toList();\\n}\\n\\nprivate double normalizeCoordinate(Double coordinate, Double maxDifference, Double minValue) {\\n return (coordinate - minValue) / maxDifference;\\n}\\n\\nprivate int mapToPosition(Double coordinate, Integer routeImageSize) {\\n return (int) (coordinate * routeImageSize);\\n}\\n```\\n\\n\uc704\ub3c4\ub85c \uc608\uc2dc\ub4e0 \ub0b4\uc6a9\uc774\ub2e4.\\n\\n1. Collections.min(values) \u2192 \uc704\ub3c4 \ub9ac\uc2a4\ud2b8\uc758 \ucd5c\uc18c\uac12\uc744 \uad6c\ud55c\ub2e4.\\n2. normalizeCoordinate \u2192 \uac01\uac01\uc758 \uc704\ub3c4 \uac12\uc5d0\uc11c \ucd5c\uc18c\uac12\uc744 \ube7c\uace0 0 ~ 1 \uc0ac\uc774 \uac12\uc73c\ub85c \ubcc0\ud658 \ud6c4 **\uc704\uacbd\ub3c4\uc758 \ucd5c\ub300 \ucc28\uc774**\ub85c \ub098\ub208\ub2e4.\\n3. mapToPosition \u2192 \uadf8\ub798\ud504 \ud06c\uae30\ub97c \ubc1b\uc544 0 ~ 1 \uc0ac\uc774 \uac12\uc744 \uc2e4\uc81c \uc774\ubbf8\uc9c0\ub97c \uc704\ud55c \uc704\uce58\uac12\uc73c\ub85c \ubcc0\ud658\ud55c\ub2e4.\\n\\n### Positions(\uc2e4\uc81c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \uc0ac\uc6a9\ud560 \uc704\uce58)\\n\\nPositions \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \ub2e4\uc12f \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- align: \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\uc640 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0ac\uc774\uc988\ub97c \ubc1b\uc544 Position \uac12\ub4e4\uc744 \uc911\uc559 \uc815\ub82c\ud55c\ub2e4.\\n- getPositionsByIndexes: \uc778\ub371\uc2a4 \ub9ac\uc2a4\ud2b8\ub97c \ubc1b\uc544 \uc785\ub825\ubc1b\uc740 \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- size: \ud06c\uae30\ub97c \ubc18\ud658\ud55c\ub2e4.\\n- xPositions: x \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n- yPositions: y \uac12\ub4e4\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n\uc911\uc559 \uc815\ub82c \ub85c\uc9c1\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```java title=\\"Positions.java\\"\\npublic Positions align(int imageSize, int routeSize) {\\n int xOffset = calculateOffset(Position::x, imageSize);\\n int yOffset = calculateOffset(Position::y, imageSize);\\n\\n return items.stream()\\n .map(item -> new Position(item.x() + xOffset, imageSize - (item.y() + yOffset)))\\n .collect(collectingAndThen(toList(), Positions::new));\\n}\\n\\nprivate int calculateOffset(ToIntFunction positionToInteger, int imageSize) {\\n List positions = items.stream()\\n .mapToInt(positionToInteger)\\n .boxed()\\n .toList();\\n\\n int midValue = (Collections.min(positions) + Collections.max(positions)) / 2;\\n return imageSize / 2 - midValue;\\n}\\n```\\n\\n\uc0c1\ud558\uc88c\uc6b0 \uc5ec\ubc31\uc744 \ub3d9\uc77c\ud558\uac8c \uc8fc\uae30 \uc704\ud574\uc11c offset \uac12\uc744 \uad6c\ud574\uc11c x, y \uac12\uc5d0 \uac01\uac01 \ub354\ud558\ub294 \ud615\ud0dc\ub85c \uc911\uc559 \uc815\ub82c\uc744 \uc218\ud589\ud588\ub2e4. \\nBufferedImage\ub97c \uc0ac\uc6a9\ud560 \ub54c \uc67c\ucabd \uc0c1\ub2e8\uc758 \uc88c\ud45c (0, 0) \uae30\uc900\uc73c\ub85c \uc544\ub798\ub85c \ub0b4\ub824\uac08\uc218\ub85d y \uac12\uc774 \ucee4\uc9c0\uace0, \uc624\ub978\ucabd\uc73c\ub85c \uac08 \uc218\ub85d x \uac12\uc774 \ucee4\uc9c4\ub2e4. \\n\\n![./800.png](./800.png)\\n\\n\ub530\ub77c\uc11c \ucd5c\uc885\uc801\uc73c\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30 \uc704\ud55c \uac12\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\ud588\ub2e4.\\n\\nx \uac12 \u2192 \uacc4\uc0b0\ud55c offset \uadf8\ub300\ub85c \ub354\ud55c\ub2e4. \\ny \uac12 \u2192 imageSize(800)\uc5d0\uc11c y + offset \uac12\uc744 \ube80\ub2e4. \\n\\n### RouteImageDrawer(\uc2e4\uc81c \uc774\ubbf8\uc9c0\uc5d0 \uacbd\ub85c\ub97c \uadf8\ub824\uc8fc\ub294 \ud074\ub798\uc2a4)\\n\\nBufferedImage, Graphics2D\ub97c \ud544\ub4dc\ub85c \uac00\uc9c0\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub2e4. \\n\uadf8\ub9bc\uc744 \uadf8\ub9ac\uae30 \uc704\ud574 \uc124\uc815\ud55c \uc0c1\uc218\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4.\\n\\n```java title=\\"RouteImageDrawer.java\\"\\n// RGB\uc5d0 \uac01\uac01 8\ube44\ud2b8\uc529 \ud560\ub2f9\ud55c \uac12\uc744 24\ube44\ud2b8 \ud2b8\ub8e8\uceec\ub7ec\ub77c \ubd80\ub978\ub2e4.\\n// \ud574\ub2f9 \uc124\uc815\uc740 24\ube44\ud2b8 + 8\ube44\ud2b8(alpha, \ud22c\uba85\ub3c4)\ub97c \ucd94\uac00\ud55c 32\ube44\ud2b8 \uc774\ubbf8\uc9c0 \ud0c0\uc785\uc774\ub2e4.\\n// \uc774\ub97c RGBA\ub77c\uace0 \ubd80\ub978\ub2e4.\\nprivate static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;\\n// \ubc30\uacbd \ud22c\uba85\uc0c9\\nprivate static final Color TRANSPARENT = new Color(0, 0, 0, 0);\\n// \uacbd\ub85c\ub97c \uc704\ud55c STROKE\\nprivate static final int LINE_STROKE_WIDTH = 7;\\nprivate static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc704\uce58 \uc810\uc744 \uc704\ud55c STROKE\\nprivate static final int POINT_STROKE_WIDTH = 20;\\nprivate static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);\\n// \uc548\ud2f0\uc568\ub9ac\uc5b4\uc2f1 \ub4f1 \ud654\uc9c8 \uac1c\uc120\uc744 \uc704\ud55c \uc124\uc815\\nprivate static final Map renderingHints = Map.of(\\n RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,\\n RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,\\n RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC\\n);\\n```\\n\\nRouteImageDrawer \ud074\ub798\uc2a4\uc5d0\ub294 \ub2e4\uc74c \uc138 \uac1c\uc758 \uc778\ud130\ud398\uc774\uc2a4\uac00 \uc874\uc7ac\ud55c\ub2e4.\\n\\n- drawLine: \uc120\uc744 \uadf8\ub9b0\ub2e4.\\n- drawPoint: \uc810\uc744 \ucc0d\ub294\ub2e4.\\n- dispose: \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud55c\ub2e4. \\n\\ndispose\uc758 \uacbd\uc6b0 \ub0b4\ubd80\uc5d0\uc11c \uc0dd\uc131\ub41c graphics2D\uc5d0 \ub300\ud55c \uc790\uc6d0 \ud560\ub2f9\uc744 \ud574\uc81c\ud558\ub294 \uba54\uc11c\ub4dc\uc778 graphics2D.dispose\ub97c \ud638\ucd9c\ud55c\ub2e4.\\n\\n## \uc774\ubbf8\uc9c0 \uc0dd\uc131 Flow\\n\\n### 1. \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc900\ube44\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n\\n```\\n\\n### 2. \uc120 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 3. \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n```\\n\\n### 4. \uc5c5\ub85c\ub4dc \uc694\uccad\\n\\n```mermaid\\nsequenceDiagram\\n \\tRouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n \\tRouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n \\tRouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n```\\n\\n### \uc804\uccb4 Flow\\n\\n```mermaid\\nsequenceDiagram\\n \uc678\ubd80 \ud074\ub798\uc2a4 ->> RouteImageGenerator: \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc694\uccad(\uc704\uacbd\ub3c4, \uc704\uce58 \uc810\uc744 \ucc0d\uc744 \uac12 \uc804\ub2ec)\\n RouteImageGenerator->>RouteImageDrawer: ImageSize\ub97c \uc804\ub2ec\ud558\uc5ec \uac1d\uccb4 \uc0dd\uc131, \ub0b4\ubd80\uc5d0\uc11c BufferedImage, Graphincs2D \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc704\uacbd\ub3c4 \uc774\uc6a9\ud558\uc5ec Coordinates1 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates2(\uc704\uce58\uc810): \uc704\uce58\uc810 \uc774\uc6a9\ud558\uc5ec Coordinates2 \uc0dd\uc131\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): \uc815\ub82c\ub41c Positions\ub97c \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc815\ub82c\ub41c Positions \ubc18\ud658\\n RouteImageGenerator->>RouteImageDrawer: \uc815\ub82c\ub41c Positions\ub97c \uacbd\ub85c \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>Coordinates1(\uc704\uacbd\ub3c4): Coordinate2(\uc704\uce58\uc810)\ub97c \uc804\ub2ec\ud558\uace0 \ud574\ub2f9 \uc704\uce58\uc810\uacfc \uc77c\uce58\ud558\ub294 Coordinate\uc758 \uc778\ub371\uc2a4 \uc0dd\uc131 \uc694\uccad\\n Coordinates1(\uc704\uacbd\ub3c4)->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 \uc778\ub371\uc2a4(List) \ubc18\ud658\\n RouteImageGenerator->>\uc815\ub82c\ub41c Positions: \uc778\ub371\uc2a4(List)\ub97c \uc804\ub2ec\ud558\uc5ec \uc778\ub371\uc2a4\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \uc0dd\uc131 \uc694\uccad\\n \uc815\ub82c\ub41c Positions->>RouteImageGenerator: \uc704\uce58\uc810\uc5d0 \ud574\ub2f9\ud558\ub294 Positions \ubc18\ud658(pointPositions)\\n\\n RouteImageGenerator->>RouteImageDrawer: pointPositions\ub97c \uc804\ub2ec\ud558\uc5ec \uc704\uce58 \uc810 \uadf8\ub9ac\uae30 \uc694\uccad\\n RouteImageGenerator->>RouteImageUploader: bufferedImage(RouteImageDrawer\uc5d0\uc11c getter \uc0ac\uc6a9)\ub97c \uc804\ub2ec\ud558\uc5ec \uc774\ubbf8\uc9c0 \uc800\uc7a5 \uc694\uccad\\n RouteImageUploader->>RouteImageGenerator: \uc800\uc7a5 \ud6c4 \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n RouteImageGenerator->>\uc678\ubd80 \ud074\ub798\uc2a4: \uc800\uc7a5\ub41c \uc774\ubbf8\uc9c0\uba85(\ub610\ub294 url) \ubc18\ud658\\n\\t\\n```"},{"id":"route-image-python","metadata":{"permalink":"/route-image-python","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","source":"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","description":"\uac1c\uc694","date":"2023-07-31T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 31\uc77c","tags":[{"label":"Image","permalink":"/tags/image"},{"label":"Python","permalink":"/tags/python"}],"readingTime":6.185,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","slug":"route-image-python","tags":["Image","Python"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604","permalink":"/route-image-implementation"},"nextItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"}},"content":"### \uac1c\uc694\\n\\n\uc774\uc804\uc5d0 \uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\uc0ac\ud558\uba74\uc11c \ud30c\uc774\uc36c\uc744 \uc0ac\uc6a9\ud55c \ub0b4\uc6a9\uc744 \uc815\ub9ac\ud55c \ub0b4\uc6a9\uc774\ub2e4. \\n\\n### \uc0ac\uc6a9 \uae30\uc220\\n\\n\uc5b8\uc5b4: Python 3.10 \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131: matplotlib \\n\uc11c\ube44\uc2a4: AWS Lambda, AWS API Gateway \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \ubc0f URL: AWS S3, AWS CloudFront \\n\\n\ud50c\ub85c\uc6b0\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n```mermaid\\ngraph LR\\n Server -- \uc0dd\uc131 \uc694\uccad --\x3e AG[API Gateway] --\x3e Lambda --\x3e S3\\n Client --\x3e CloudFront --\x3e S3\\n```\\n\\n### \uc694\uad6c\uc0ac\ud56d\\n\\n![./route.png](./route.png)\\n\\n\uc6b0\uce21 \uc0c1\ub2e8\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\ub824\uace0 \ud55c\ub2e4. \\n\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- \uc704\ub3c4, \uacbd\ub3c4\ub85c \uc774\ub8e8\uc5b4\uc9c4 \ubc30\uc5f4\uc744 \uc785\ub825\ubc1b\ub294\ub2e4. \\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n- \uc704\uacbd\ub3c4 \ucc28\uc774\uac00 \ud06c\ub4e0 \uc791\ub4e0 \uc81c\uacf5\ud558\ub294 \uc774\ubbf8\uc9c0 \ub0b4\uc5d0 \uacbd\ub85c\uac00 \ub2e4 \ud3ec\ud568\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\\n\\n1. \uc704\uacbd\ub3c4\ub97c \ucc98\ub9ac\ud55c \uac12\uc73c\ub85c \uc9c1\uc811 \uacbd\ub85c\ub97c \uadf8\ub9b0 \ub2e4\uc74c \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n2. \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac \uc0ac\uc6a9\ud558\uc5ec \uc774\ubbf8\uc9c0 \ud615\ud0dc\ub85c \uc800\uc7a5\\n\\n\uc774\ubbf8\uc9c0 \ucd9c\ub825 \ubc29\uc2dd\uc758 \uacbd\uc6b0 1\ubc88\uacfc 2\ubc88\uc744 \uace0\ubbfc\ud588\uc5c8\ub2e4. \\n\ud30c\uc774\uc36c\uc73c\ub85c\ub294 \ud50c\ub86f\uc744 \uadf8\ub824\uc8fc\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac\uc778 matplotlib\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub85c\uceec\uc5d0\uc11c \uae30\ub2a5 \uad6c\ud604\\n\\n```python\\nimport time\\n\\nimport matplotlib.pyplot as plt\\n\\n\\ndef draw(point):\\n start = time.time()\\n x, y = zip(*point)\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n draw_lines(pixel_x, pixel_y)\\n end = time.time()\\n print(end - start)\\n \\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n return scaled_coordinates\\n\\n\\ndef draw_lines(x, y):\\n figure = plt.gcf()\\n figure.set_size_inches(5, 5)\\n plt.plot(x, y, c = \'w\',linewidth=5)\\n plt.scatter(x[3],y[3], c = \'w\', s = 125)\\n plt.axis(\'off\')\\n plt.savefig(\'name.png\', transparent=True, format=\'png\')\\n\\npoint = [\\n [126.96352960597338, 37.590841000217125],\\n [126.96987292787792, 37.58435564234159],\\n [126.98128481452298, 37.58594375113966],\\n [126.99360339342958, 37.58248524741927],\\n [126.99867565340067, 37.56778118088622],\\n [127.001935378366117, 37.55985240444085],\\n [126.9831048919687, 37.548030119488665],\\n [126.97189273528845, 37.5119879225856],\\n [127.02689859997221, 37.48488593333883]\\n]\\n\\ndraw(point)\\n```\\n\\n\uc0dd\uc131 \uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4. (\uc608\uc2dc\ub97c \uc704\ud574 \uac80\uc740\uc0c9\uc73c\ub85c \ucd9c\ub825)\\n\\n![./routeImage.png](./routeImage.png)\\n\\n### AWS Lambda\\n\\n\uc378\ub124\uc77c \uc0dd\uc131 \uc11c\ubc84\ub97c \ub530\ub85c \ub450\uae30\ub294 \uae30\ub2a5 \ub300\ube44 \ube44\uc6a9\uc774 \ub108\ubb34 \ud074 \uac83\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc11c\ubc84\ub9ac\uc2a4\ub85c \ud30c\uc77c\uc744 \ucc98\ub9ac\ud588\ub2e4. \\n\ucd94\uac00\ub85c s3 \uc811\uadfc\uc740 boto3\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 S3 \uc811\uadfc\uc744 \uc704\ud55c IAM \uc0dd\uc131\\n\\nAmazonS3FullAccess, AmazonS3ObjectLambdaExecutionRolePolicy \ub450\uac00\uc9c0\ub97c \ucd94\uac00\ud574\uc11c Lambda \uc804\uc6a9 \uc5ed\ud560\uc744 \ub9cc\ub4e4\uc5b4 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n### \ub78c\ub2e4 \ubc30\ud3ec\uc6a9 \ucf54\ub4dc\\n\\n\uae30\uc220 \uad6c\ud604 \uac00\ub2a5 \uc5ec\ubd80\ub97c \ud655\uc778\ud560 \ub550 \uc704\uce58 \uc810\uc744 \ucc0d\ub294 \uae30\ub2a5\uc744 \ub78c\ub2e4\uc5d0 \ubc30\ud3ec\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\\n```python\\n\\nimport io\\nimport uuid\\n\\nimport boto3\\nimport matplotlib.pyplot as plt\\n\\nPIXEL = 255\\nBUCKET_NAME = \'image-plot\'\\nS3 = \'s3\'\\n\\ndef lambda_handler(event, context):\\n x = event[\'x\']\\n y = event[\'y\']\\n image_name = str(uuid.uuid4())\\n\\n img_data = draw(x, y)\\n s3 = boto3.client(S3)\\n s3.put_object(Body=img_data.getvalue(), ContentType=\'image/png\', Bucket=BUCKET_NAME, Key=image_name)\\n url = f\'https://{BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/{image_name}\'\\n\\n return {\\n \'statusCode\': 200,\\n \'body\': url\\n }\\n\\ndef draw(x, y):\\n pixel_x, pixel_y = convert_to_pixel_values(x, y)\\n img_data = draw_lines(pixel_x, pixel_y)\\n plt.close()\\n return img_data\\n\\ndef convert_to_pixel_values(x, y):\\n max_diff = max(max(x) - min(x), max(y) - min(y))\\n return scale_to_pixel_values(x, max_diff), scale_to_pixel_values(y, max_diff)\\n\\ndef scale_to_pixel_values(points, max_diff):\\n min_value = min(points)\\n scaled_coordinates = [(p - min_value) / max_diff for p in points]\\n pixel_values = [int(p * PIXEL) for p in scaled_coordinates]\\n return pixel_values\\n\\ndef draw_lines(x, y):\\n plt.plot(x, y, \'k-\', linewidth=10)\\n plt.axis(\'off\')\\n img_data = io.BytesIO()\\n plt.savefig(img_data, transparent=True, format=\'png\')\\n img_data.seek(0)\\n return img_data\\n\\n```\\n\\n### Layer \ucd94\uac00\ub97c \uc704\ud55c zip \ud30c\uc77c \uc0dd\uc131\\n\\nmatplotlib\uc758 \uacbd\uc6b0 \uc678\ubd80 \ub77c\uc774\ube0c\ub7ec\ub9ac\uae30 \ub54c\ubb38\uc5d0 \ub530\ub85c Layer\ub97c \ucd94\uac00\ud574\uc57c \ud55c\ub2e4. \\nzip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc5b4\uc11c \uc5c5\ub85c\ub4dc\ud574\uc57c\ud55c\ub2e4. \\n\uc774\ub54c python\uc758 Lambda \ub7f0\ud0c0\uc784\uc5d0 \ub300\ud55c \uacc4\uce35 \uacbd\ub85c\ub294 python\uc774\ub2e4. \\n\ub530\ub77c\uc11c \uc555\ucd95\ud55c zip \ud30c\uc77c\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \ub744\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```\\npillow.zip\\n\u2502 python/PIL\\n\u2514 python/Pillow-5.3.0.dist-info\\n```\\n\\nUbuntu \uae30\uc900 \ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uc5ec \uc0dd\uc131\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\\n```\\nsudo apt update\\nsudo apt install zip\\nsudo apt install python3-pip\\n\\nmkdir python\\npip3 install matplotlib -t python # pip3 install \uc124\uce58\ud560_\ud328\ud0a4\uc9c0 -t \uc124\uce58_\uacbd\ub85c\\nzip -r my_layer.zip python # zip -r \uc555\ucd95_\ud30c\uc77c\uba85 \uc555\ucd95_\ud30c\uc77c\uc774_\uc874\uc7ac\ud558\ub294_\uacbd\ub85c\\n```\\n\\n### `No module named \'numpy.core._multiarray_umath\'` \uc5d0\ub7ec\\n\\nLayer \ucd94\uac00 \ud6c4 \ub78c\ub2e4 \uc2e4\ud589 \uc2dc \ubc1c\uc0dd\ud55c \uc5d0\ub7ec\uc600\ub2e4. \\n\ucc98\uc74c\uc5d0 mac\uc5d0\uc11c zip \ud30c\uc77c\uc744 \uc0dd\uc131\ud574\uc11c \uc5c5\ub85c\ub4dc\ud588\ub294\ub370 \ud574\ub2f9 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\uc774\ub294 lambda\uac00 \ub3cc\uc544\uac00\ub294 \ub3d9\uc77c\ud55c \ud658\uacbd\uc5d0\uc11c layer\ub97c \uc704\ud55c zip \ud30c\uc77c\uc744 \ub9cc\ub4e4\uc9c0 \uc54a\uc544\uc11c \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub2e4. \\n\uac04\ub2e8\ud558\uac8c ec2 \uc778\uc2a4\ud134\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c \ub530\ub85c Layer\ub97c \uc0dd\uc131\ud558\uba74 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### \uc801\uc815\uae30\uc220\uc5d0 \ub300\ud55c \uc0dd\uac01\\n\\n\ud504\ub85c\uc81d\ud2b8\uc5d0 Lambda\uc640 Python\uc744 \uc0ac\uc6a9\ud558\ub824\uace0 \ud588\uc9c0\ub9cc \uc544\uc27d\uac8c\ub3c4 \ubc18\ub824\ub2f9\ud588\ub2e4. \\nAWS Lambda\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc778\uc2a4\ud134\uc2a4\uc5d0 \ud574\ub2f9 \ucf54\ub4dc\ub97c \ubc30\ud3ec\ud558\ub294 \uac83\ubcf4\ub2e4 \ub354 \ud6a8\uc728\uc801\uc778 \ubc29\ubc95\uc77c \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uac00\uc6a9 \uac00\ub2a5\ud55c \uc790\uc6d0, \uae30\uc220\uc758 \ub09c\uc774\ub3c4, \uc0ac\uc6a9\ud558\ub294 \ud300\uc6d0\uc744 \uace0\ub824\ud55c\ub2e4\uba74 Lambda\ub294 \uc801\uc815\uae30\uc220\uc774 \uc544\ub2d0 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ud574\ub2f9 \uc774\ubbf8\uc9c0 \uc0dd\uc131\uae30\ub97c \uc5b4\ub5bb\uac8c \uc801\uc6a9\ud560\uc9c0 \uc870\uae08 \ub354 \uace0\ub824\ub97c \ud574\uc57c \ub420 \uac83\uc73c\ub85c \ubcf4\uc778\ub2e4. \\n\\n**\ucd5c\uc885\uc801\uc73c\ub85c Java AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.**\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[AWS Lambda](https://aws.amazon.com/ko/lambda/) \\n[Lambda Layer](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/configuration-layers.html) \\n[Python Lambda \ud568\uc218\uc5d0 \ub300\ud55c .zip \ud30c\uc77c \uc544\uce74\uc774\ube0c \uc791\uc5c5](https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html) \\n[No module named \'numpy.core._multiarray_umath\'](https://gist.github.com/ksmin23/0f3f243408a8497f766b43cf589fea7b) \\n[\uc0ac\ub840\ubcc4\ub85c \uc54c\uc544\ubcf8 \uc548\uc804\ud55c S3 \uc0ac\uc6a9 \uac00\uc774\ub4dc](https://techblog.woowahan.com/6217/)"},{"id":"mock-static-method","metadata":{"permalink":"/mock-static-method","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","source":"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx","title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","description":"\uac1c\uc694","date":"2023-07-30T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 30\uc77c","tags":[{"label":"Mockito","permalink":"/tags/mockito"},{"label":"static","permalink":"/tags/static"}],"readingTime":2.635,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","slug":"mock-static-method","tags":["Mockito","static"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c","permalink":"/route-image-python"},"nextItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"}},"content":"### \uac1c\uc694\\n\\n\uc815\uc801 \ud329\ud130\ub9ac \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud55c\ub2e4\ub294 \uac83\uc740 \uac1d\uccb4\uc9c0\ud5a5\uc801\uc778 \uad00\uc810\uc5d0\uc11c \ubcfc \ub54c \uc548\ud2f0\ud328\ud134\uc774\ub2e4. \\n\ud558\uc9c0\ub9cc \ud2b9\uc218\ud55c \uacbd\uc6b0\uc5d0\ub294 \uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc774 \ud544\uc694\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\uc608\ub97c \ub4e4\uc5b4 \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud55c\ub2e4\ub358\uc9c0, IO \uad00\ub828\ud55c \ubd80\ubd84\uc744 \ud14c\uc2a4\ud2b8 \ud560 \ub54c \uc815\ub9d0 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\ub9cc \uc801\uc6a9\ud560 \uc218 \uc788\uc744 \uac83\uc774\ub2e4. \\n\\n\ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba70 ImageIo.write \uba54\uc11c\ub4dc\uac00 \ud638\ucd9c\ub418\ub294 \uc9c0 \uac80\uc99d\uc774 \ud544\uc694\ud588\ub2e4. \\n\ud574\ub2f9 static \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294 \ubd80\ubd84\uc744 \ub530\ub85c RouteImageUploader \ud074\ub798\uc2a4\ub85c \ucd5c\ub300\ud55c \ubd84\ub9ac\ud588\ub2e4. \\n\uc774\ubbf8\uc9c0 \uc800\uc7a5 \uae30\ub2a5 \uc790\uccb4\uac00 \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc774\uace0, \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294\ub370\ub294 mock\uc744 \uc0ac\uc6a9\ud558\ub294\uac8c \uc801\uc808\ud558\ub2e4\uace0 \ud310\ub2e8\ud588\ub2e4. \\n\\n```java\\npublic void upload(BufferedImage bufferedImage) {\\n File file = new File(\ud30c\uc77c\uacbd\ub85c);\\n try {\\n ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);\\n } catch (IOException e) {\\n throw new DrawException(IMAGE_SAVE_FAIL);\\n }\\n}\\n```\\n\\n### Mocking static methods\\n\\nMockito 3.4.0 \uc774\ud6c4\uc5d0\ub294 static method\ub97c \ubaa8\ud0b9\ud560 \uc218 \uc788\ub294 Mockito.mockStatic \uba54\uc11c\ub4dc\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\nmockStatic\uc744 \uc0ac\uc6a9\ud558\uba74 `MockedStatic`\uc774 \ubc18\ud658\ub418\ub294\ub370 \uc0ac\uc6a9 \ud6c4 \uaf2d close\ub97c \ud574\uc918\uc57c \ud55c\ub2e4. \\n\\nJUnit\uc758 @BeforeAll\ub85c \uc124\uc815\ud558\uace0 @AfterAll \uba54\uc11c\ub4dc\ub85c \uc885\ub8cc\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\uc9c0\ub9cc `MockedStatic`\uc758 \uc0c1\uc704 \uc778\ud130\ud398\uc774\uc2a4\uc778 ScopedMock\uc774 AutoCloseable\uc744 \uad6c\ud604\ud558\uace0 \uc788\uae30\uc5d0 try-with-resources\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \ub354\uc6b1 \uc88b\uc740 \uac83 \uac19\ub2e4. \\n\\n```java\\n// given\\nBufferedImage bufferedImage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);\\nRouteImageUploader routeImageUploader = new RouteImageUploader();\\n\\n// expect\\ntry (MockedStatic imageIO = Mockito.mockStatic(ImageIO.class)) {\\n routeImageUploader.upload(bufferedImage);\\n imageIO.verify(\\n () -> ImageIO.write(any(BufferedImage.class), any(String.class), any(File.class)),\\n times(1)\\n );\\n}\\n```\\n\\n### \ub9c8\uce58\uba70\\n\\n\uc815\uc801 \uba54\uc11c\ub4dc\ub97c \ubaa8\ud0b9\ud558\ub294 \uac83\uc740 \uc548\ud2f0\ud328\ud134\uc774\uc73c\ub85c \uc801\uc808\ud55c \ucd94\uc0c1\ud654\ub97c \uc774\uc6a9\ud574 \ud14c\uc2a4\ud2b8 \ud558\uae30 \uc88b\uc740 \ucf54\ub4dc\ub97c \ub9cc\ub4dc\ub294 \uc5f0\uc2b5\uc744 \ud558\uc790. \\n\ud558\uc9c0\ub9cc \ucd94\uc0c1\ud654\ub97c \ud558\uba74 \ud560 \uc218\ub85d \ucf54\ub4dc\uc758 \ubcf5\uc7a1\ub3c4\ub294 \uc99d\uac00\ud55c\ub2e4. \\n\ud56d\uc0c1 \uc0c1\ud669\uc744 \uace0\ub824\ud558\uace0 \uac04\uacb0\ud568\uc744 \ud3ec\uae30\ud560 \ub9cc\ud07c \uc911\uc694\ud55c \ubd80\ubd84\uc778\uc9c0 \uc801\uc808\ud55c \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uace0\ub824\ud558\uc790. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Mocking static methods](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocks) \\n[Mockito mock static methods](https://www.baeldung.com/mockito-mock-static-methods) \\n[Enable mocking static methods in Mockito](https://github.com/mockito/mockito/issues/1013)"},{"id":"route-image-intro","metadata":{"permalink":"/route-image-intro","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","source":"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx","title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","description":"./route.png","date":"2023-07-27T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 27\uc77c","tags":[{"label":"image","permalink":"/tags/image"},{"label":"awt","permalink":"/tags/awt"}],"readingTime":5.865,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","slug":"route-image-intro","tags":["image","awt"]},"prevItem":{"title":"Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30","permalink":"/mock-static-method"},"nextItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"}},"content":"![./route.png](./route.png)\\n\\n### \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc758 \ucc45\uc784\\n\\n\uc704 \uc640\uc774\uc5b4 \ud504\ub808\uc784\uc5d0\uc11c `\uc5ec\ud589 \ud788\uc2a4\ud1a0\ub9ac`\uc640 `\uc5ec\ud589\uc5d0 \ub300\ud55c \uac10\uc0c1\uc744 \uc704\ud55c \uacbd\ub85c \uc774\ubbf8\uc9c0`\uc758 \uacbd\uc6b0 \ub124\uc774\ubc84 \uc9c0\ub3c4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ud574\ub2f9 \uae30\ub2a5\uc744 \uad6c\ud604\ud560 \uc218 \uc5c6\uc73c\ub2c8 \ub2f9\uc5f0\ud788 \ub9f5 API\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub3c4\ud615 \uadf8\ub9ac\uae30 API(\ub124\uc774\ubc84 \ub9f5 API \uae30\uc900 Polyline)\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ub2e4. \\n\ub530\ub77c\uc11c \uc774\ubbf8\uc9c0\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uac70\ub098, \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \uc9c1\uc811 \uc704\uacbd\ub3c4\ub97c \uc774\uc6a9\ud558\uc5ec \uadf8\ub824\uc57c \ud55c\ub2e4.\\n\\n\ud574\ub2f9 \uc694\uad6c\uc0ac\ud56d\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uae30\ub2a5\uc744 \uac00\uc9c4 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud544\uc694\ud558\ub2e4.\\n\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131\\n- \uc120\uacfc \uc810 \ud45c\ud604\\n- \ud22c\uba85\ud55c \ubc30\uacbd\uc0c9\\n\\n\ud604\uc7ac \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \ubc14\uc05c \uc77c\uc815\uacfc \uae30\ub2a5 \uad6c\ud604\uc5d0 \uc788\uc5b4 \uc57d\uac04\uc758 \uc5f0\uc0b0\uc774 \ub4e4\uc5b4\uac04\ub2e4\ub294 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uc5ec \ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud558\uae30\ub85c \uacb0\uc815\uc744 \ub0b4\ub838\ub2e4.\\n\\n### \uace0\ub824\ud55c \uae30\uc220\\n\\n\ubc31\uc5d4\ub4dc\uc5d0\uc11c \uc774\ubbf8\uc9c0 \uc0dd\uc131\uc744 \ud558\uae30 \uc704\ud574 \ub2e4\uc74c\uacfc \uac19\uc740 \ub77c\uc774\ube0c\ub7ec\ub9ac \ub610\ub294 \uae30\uc220\ub4e4\uc744 \ud655\uc778\ud574 \ubcf4\uc558\ub2e4. \\n\\n- Python\uc758 Matplotlib\\n- **AWT(Abstract Window Toolkit) [\ucd5c\uc885 \uc120\ud0dd]**\\n- \uc774\ubbf8\uc9c0 \ucc98\ub9ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ubc0f Java\uc5d0\uc11c \ub0b4\ubd80\uc801\uc73c\ub85c Matplotlib \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac (\uc6d0\ud558\ub294 \uae30\ub2a5 \uc5c6\uc74c)\\n- Java Swing, Java FX (\ub2e8\uc21c\ud55c \uc120 \uadf8\ub9ac\uae30 + \uc810 \ucc0d\uae30\ub77c \ubd88\ud544\uc694)\\n\\n## Python & Matplotlib\\n\\n\ub370\uc774\ud130 \uc2dc\uac01\ud654 \ub77c\uc774\ube0c\ub7ec\ub9ac \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 0.2\ucd08 \\n\\n- \ucf54\ub4dc\uac00 \uac04\ub2e8\ud574\uc11c \uc720\uc9c0 \ubcf4\uc218\uc131\uc774 \uc88b\ub2e4. \\n- AWS Lambda \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ucef4\ud4e8\ud305 \uc11c\ube44\uc2a4\ub098 FastAPI\uc640 \uac19\uc740 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\ub85c \ucd94\uac00\uc801\uc778 API\ub97c \uad6c\ud604\ud574\uc57c \ud55c\ub2e4.\\n- Spring Boot\uc5d0\uc11c \ucd94\uac00\uc801\uc778 API \ud638\ucd9c\uc744 \ud574\uc57c\ud558\uace0, \ud655\uc7a5\uc131\uacfc \ube44\ub3d9\uae30 \ucc98\ub9ac \ub4f1 \uace0\ub824 \ud574\uc57c \ud560 \ubd80\ubd84\uc774 \ub9ce\ub2e4.\\n\\n### Java AWT \uc774\uc678\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\\n\\nPython\uc774 \uc544\ub2cc Java\uc5d0\uc11c\uc758 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub3c4 \uace0\ub824\ub97c \ud574\ubd24\uc9c0\ub9cc \uc694\uad6c\uc0ac\ud56d\uc5d0 \uc801\ud569\ud558\uc9c0 \uc54a\uac70\ub098, \uc801\uc740 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac70\uc6b4 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub4e4\uc774 \ub9ce\uc544\uc11c \uc81c\uc678\ud588\ub2e4.\\n\\n\ub77c\uc774\ube0c\ub7ec\ub9ac | \uc124\uba85 | \uc81c\uc678 \uc774\uc720\\n-- | -- | --\\nSwing | AWT \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, \ub124\uc774\ud2f0\ube0c UI\ub97c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 \ubaa8\ub4e0 \uc6b4\uc601\uccb4\uc81c \uc0c1\uc5d0\uc11c \ub3d9\uc77c\ud55c UI\ub97c \uac00\uc9c0\ub3c4\ub85d \ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\nJavaFX | Swing \uc774\ud6c4\uc5d0 \ub098\uc628 GUI \ub77c\uc774\ube0c\ub7ec\ub9ac, 3\ucc28\uc6d0 \uadf8\ub798\ud53d\uc744 \uc9c0\uc6d0\ud568 | \uc694\uad6c\uc0ac\ud56d\uc5d0 \ube44\ud574 \ubb34\uac81\uace0 \ubcf5\uc7a1\ub3c4\uac00 \ub192\uc74c\\n[simple-java-plot](https://github.com/yuriy-g/simple-java-plot) | AWT\ub85c \uad6c\ud604\ub41c \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac | AWT \uae30\ubc18\uc774\uae34 \ud558\uc9c0\ub9cc \uc9c1\uc811 AWT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc5d0 \ube44\ud574 \uba54\ub9ac\ud2b8\uac00 \uc5c6\uc74c, \ucee4\uc2a4\ud140 \uc124\uc815 \uae30\ub2a5\uc774 \uc5c6\uc74c\\n[matplotlib4j](https://github.com/sh0nk/matplotlib4j) | Matplotlib\ub97c Java\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uac8c \ud558\ub294 \ub77c\uc774\ube0c\ub7ec\ub9ac | \ub0b4\ubd80\uc801\uc73c\ub85c \ud30c\uc774\uc36c \uc0ac\uc6a9\ud558\uae30\uc5d0 \ubb34\uac70\uc6c0, \ubc30\uacbd \ud22c\uba85\ud654 \uae30\ub2a5 \uc5c6\uc74c\\n\\n### Java & AWT(Abstract Window Toolkit)\\n\\n\uadf8\ub798\ud53d\uacfc \uc774\ubbf8\uc9c0\ub97c \uadf8\ub9ac\uae30 \uc704\ud55c \ub3c4\uad6c \\n\uc774\ubbf8\uc9c0 \uc0dd\uc131 \ubc0f \ub85c\uceec\uc5d0 \uc800\uc7a5\uae4c\uc9c0 \uac78\ub9ac\ub294 \uc2dc\uac04: 1.75\ucd08 \\n\\n- \ud50c\ub85c\ud305 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ubcf4\ub2e4 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc874\uc7ac\ud55c\ub2e4.\\n- \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub2e4\uc18c \uc18c\uc694\ub418\uae30 \ub54c\ubb38\uc5d0 \ube60\ub978 \uc751\ub2f5 \ubc18\ud658\uc744 \uc704\ud574 \ube44\ub3d9\uae30 \ucc98\ub9ac\ub97c \uace0\ub824\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4.\\n- \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n\\n### \uae30\uc220 \uc120\ud0dd\\n\\nAWT\uc758 \uacbd\uc6b0 Matplotlib\uc5d0 \ube44\ud574 \uad6c\ud604\uc758 \ub09c\uc774\ub3c4\uac00 \ub2e4\uc18c \uc788\uace0, \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uc2dc\uac04\uc774 \ub354 \ub9ce\uc774 \uac78\ub9ac\ub294 \ub2e8\uc810\uc774 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc \ucd94\uac00\uc801\uc778 api \ud638\ucd9c\uc744 \ud558\uc9c0 \uc54a\uc544\ub3c4 \ub418\ub294 \ubd80\ubd84, Python\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ucd94\uac00\uc801\uc778 \uc6f9 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uace0\ub824\ud558\uc5ec AWT\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4.\\n\\n### \uc720\uc9c0 \ubcf4\uc218\\n\\nAWT\ub77c\ub294 \uc0dd\uc18c\ud55c \uae30\uc220\uc744 \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uc720\uc9c0 \ubcf4\uc218\uc131\uc744 \uc704\ud574 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\ud558\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub530\ub77c\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ubc29\ubc95\uc73c\ub85c \uacf5\uc720\ud558\uae30\ub85c \ud588\ub2e4. \\n\\n1. \ucf54\ub4dc \ub9ac\ubdf0\uc640 PR\uc744 \ud1b5\ud574 \uc791\uc131\ud55c AWT \ucf54\ub4dc\uc5d0 \ub300\ud55c \uc124\uba85 \ubc0f \ub9ac\ubdf0 \ubc1b\ub294\ub2e4. \\n2. AWT\ub97c \uc0ac\uc6a9\ud55c \ubd80\ubd84\uc744 \ubb38\uc11c\ud654\ud558\uc5ec \uacf5\uc720\ud55c\ub2e4.\\n\\n### \ub808\ubca8 3\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70 \ub0b4\uc6a9 \ucd94\uac00\\n\\n\uae30\uc220 \uc120\ud0dd\uc744 \ud558\uae30 \uc704\ud55c \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815\uc5d0 \uc624\ub958\uac00 \uc788\uc5c8\ub2e4. \\nAWT\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc2e4\ud589 \uc2dc\uac04\uc744 \uc81c\uc678\ud558\uba74 \ud30c\uc774\uc36c\uacfc \ube44\uc2b7\ud55c \uc2dc\uac04\uc548\uc5d0 \uc774\ubbf8\uc9c0\ub97c \uc0dd\uc131\ud560 \uc218 \uc788\uc5c8\ub2e4."},{"id":"java-spring-springboot","metadata":{"permalink":"/java-spring-springboot","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","source":"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx","title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","description":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","date":"2023-07-24T00:00:00.000Z","formattedDate":"2023\ub144 7\uc6d4 24\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Spring Boot","permalink":"/tags/spring-boot"},{"label":"Spring","permalink":"/tags/spring"}],"readingTime":4.725,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","slug":"java-spring-springboot","tags":["Java","Spring Boot","Spring"]},"prevItem":{"title":"\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd","permalink":"/route-image-intro"},"nextItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"}},"content":"## \uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\\n\\n\ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1\uc744 \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\ub2e4. \\n2.7 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218\ub3c4 \uc788\uc5c8\uc9c0\ub9cc LTS \uae30\uac04\uacfc \ucde8\uc57d\uc810 \ud328\uce58\ub85c \uc778\ud55c \ubc84\uc804\uc5c5 \ub4f1\uc744 \uace0\ub824\ud588\uc744 \ub54c 3.1\uacfc \uc790\ubc14 17\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \ub354 \ud6a8\uc728\uc801\uc774\ub77c\uace0 \ud310\ub2e8\ud588\ub2e4.\\n\\n## \uc790\ubc14 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2\uae4c\uc9c0\ub294 \uc790\ubc14 11\uc744 \uc0ac\uc6a9\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc790\ubc14 11\ubd80\ud130 \uc790\ubc14 17\uae4c\uc9c0\uc758 \ubcc0\uacbd\uc0ac\ud56d\uc744 \uc815\uc2dd \ub9b4\ub9ac\uc988 \uae30\uc900\uc73c\ub85c \uc815\ub9ac\ud574\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### Switch Expressions(Java 14)\\n\\nJava 14\uc5d0\uc11c\ub294 \uae30\uc874\uc758 Switch \ubb38\uc744 \uac04\uacb0\ud558\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub294 Switch \uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n```java\\nenum RESULT {\\n WIN, LOSE, DRAW\\n}\\n\\nRESULT result = RESULT.WIN;\\n\\nint prize = switch (result) {\\n case WIN -> 10_000_000;\\n case LOSE, DRAW -> 5_000_000;\\n\\tdefault -> 0;\\n};\\n```\\n\\n\uc8fc\uc694 \ud2b9\uc9d5\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.\\n\\n- `->` \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uac01 case\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc14\ub85c \ubc18\ud658\ud560 \uc218 \uc788\ub2e4.\\n- case\ub97c \ucf64\ub9c8(`,`)\ub85c \uc5f0\uacb0\ud558\uc5ec \ud558\ub098\uc758 case\uc5d0 \uc5ec\ub7ec \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n- break \ubb38\uc774 \ud544\uc694 \uc5c6\ub2e4.\\n- default \ube14\ub85d\uc744 \ud1b5\ud574 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4.\\n\\n### Text Block(Java 15)\\n\\nJava 15\uc5d0\ub294 \uc0c8\ub85c\uc6b4 \ubb38\uc790\uc5f4 \ud45c\ud604\ubc29\uc2dd\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uae34 \ubb38\uc790\uc5f4\uc744 + \uc5f0\uc0b0\uc790\uc758 \ub3c4\uc6c0 \uc5c6\uc774 \uac00\ub3c5\uc131\uc788\uac8c \uc791\uc131\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@Repository\\npublic interface PostRepository extends JpaRepository {\\n @Query(\\"\\"\\"\\n SELECT p FROM Post p\\n WHERE p.title LIKE %:keyword%\\n OR p.content LIKE %:keyword%\\n \\"\\"\\")\\n List findPostsByTitleOrContentContainingKeyword(String keyword);\\n}\\n```\\n\\n### NPE \uba54\uc2dc\uc9c0(Java 15)\\n\\n```java\\nString name = null;\\nname.chars();\\n\\n/** \\n# before\\njava.lang.NullPointerException\\n\\tat com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)\\n\\n# after\\nCannot invoke \\"String.chars()\\" because \\"name\\" is null\\njava.lang.NullPointerException: Cannot invoke \\"String.chars()\\" because \\"name\\" is null\\n*/\\n```\\n\\n### Record(Java 16)\\n\\nLombok\uc758 `@Data`, kotlin\uc758 data \ud074\ub798\uc2a4\uc640 \uc720\uc0ac\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nRecord\ub97c \uc120\uc5b8\ud558\ub294 \uacbd\uc6b0 \uc811\uadfc\uc790, \uc0dd\uc131\uc790, equals & hashcode, toString\uc774 \uc81c\uacf5\ub41c\ub2e4. \\n\ub370\uc774\ud130 \uc804\uc1a1 \uc6a9\ub3c4\ub85c \uc801\ud569\ud574 \ubcf4\uc778\ub2e4. \\n\\n```java\\npublic record PostDto(String title, String content) {\\n}\\n```\\n\\n### \ucd94\uac00\uc801\uc778 \ubcc0\uacbd\uc0ac\ud56d\\n\\n\uc774\uc678\uc5d0\ub3c4 stream\uc758 toList, \uc778\uc2a4\ud134\uc2a4\uc758 \ud0c0\uc785\uc744 \uac04\ud3b8\ud558\uac8c \uccb4\ud06c\ud558\ub294 Pattern Matching Instanceof, Sealed class \ub4f1\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n## \uc2a4\ud504\ub9c1, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ubcc0\uacbd \uc0ac\ud56d\\n\\n\uc2a4\ud504\ub9c1\uacfc \uc2a4\ud504\ub9c1 \ubd80\ud2b8\uc5d0\ub3c4 \ub9ce\uc740 \ubcc0\uacbd \uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ud544\uc694\ud574\ubcf4\uc774\ub294 \uba87\uac1c \uc815\ub3c4\ub9cc \uc815\ub9ac\ud588\ub2e4. \\n\\n### \uc2a4\ud504\ub9c1 \uc694\uad6c\uc0ac\ud56d\\n\\nJava 17, Jakarta EE 9 \uc774\uc0c1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n### \ub124\uc784\uc2a4\ud398\uc774\uc2a4 \ubcc0\uacbd\\n\\nJakarta EE 9\uac00 \uc801\uc6a9\ub418\uba74\uc11c \ub124\uc784\uc2a4\ud398\uc774\uc2a4\ub3c4 \uc804\ubc18\uc801\uc73c\ub85c javax -> jakarta\ub85c \ubcc0\uacbd\ub418\uc5c8\ub2e4. \\n\\n### PathPatternParser - trailing slash \ud5c8\uc6a9\ud558\uc9c0 \uc54a\uc74c\\n\\n6.0 \uc774\uc804\uc758 \uacbd\uc6b0 \uae30\ubcf8 \uc124\uc815 \uae30\uc900\uc73c\ub85c `@GetMapping(\\"/hello\\")`\uc640 `@GetMapping(\\"/hello/\\")`\uac00 \ub3d9\uc77c\ud588\ub2e4. \\n6.0 \uc774\ud6c4\uc758 PathPatternParser\uac00 \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\uace0, `/hello`\uc640 `/hello/`\ub294 \uc11c\ub85c \ub2e4\ub978 URL\ub85c \ub9e4\uce6d\ub41c\ub2e4. \\n\\n> PathPatternParser used by default (with the ability to opt into PathMatcher). \\n\\n### HTTP interface client\\n\\n\uc790\ubc14 \uc778\ud130\ud398\uc774\uc2a4\uc640 \uc5b4\ub178\ud14c\uc774\uc158\uc744 \uc774\uc6a9\ud558\uc5ec HTTP \uc694\uccad\uc744 \uc704\ud55c \uc11c\ube44\uc2a4\ub97c \uc815\uc758\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [\ud1a0\ube44\ub2d8\uc758 \uac15\uc758](https://www.youtube.com/watch?v=Kb37Q5GCyZs)\ub97c \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ucd5c\uc18c \uc694\uad6c\uc0ac\ud56d\\n\\nGradle 7.3, Java 17, Kotlin 1.6, Jakarta EE 9, Spring Framework 6 \\n\uc774\uc678\uc5d0\ub3c4 \uc11c\ub4dc\ud30c\ud2f0\ub4e4\uc758 \ucd5c\uc2e0 \ub9b4\ub9ac\uc988 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud568\uc73c\ub85c, \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ubc84\uc804\uc5d0 \ub9de\ub294 \ub9b4\ub9ac\uc988 \ub178\ud2b8\ub97c \ucc38\uace0\ud560 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n[\uc5b4\ub290\xa0\uc6d4\uae09\uc7c1\uc774\uac1c\ubc1c\uc790\xa0\uc758 \uc2a4\ud504\ub9c1 \ubd80\ud2b8 \ub530\ub77c\uc7a1\uae30](https://www.youtube.com/watch?v=1WT6oxchM9M) \\n[\uc790\ubc14 9-16 \uc8fc\uc694 \ud2b9\uc9d5 \ubcf5\uc2b5\ud558\uae30](https://www.youtube.com/watch?v=7SlDdzVk6GE) \\n[Java EE\uc5d0\uc11c Jakarta EE\ub85c\uc758 \uc804\ud658](https://www.samsungsds.com/kr/insights/java_jakarta.html) \\n[Spring 6\uc758 \uc0c8\ub85c\uc6b4 HTTP Interface\uc640 3 \uac00\uc9c0 REST Clients \ub77c\uc774\ube0c \ucf54\ub529](https://www.youtube.com/watch?v=Kb37Q5GCyZs) \\n[What\'s New in Spring Framework 6.x](https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-Spring-Framework-6.x) \\n[Spring Boot 3.0 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes) \\n[Spring Boot 3.1 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.1-Release-Notes)"},{"id":"websocket","metadata":{"permalink":"/websocket","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-26-WebSocket.mdx","source":"@site/blog/2023-2/2023-06-26-WebSocket.mdx","title":"\uc6f9\uc18c\ucf13","description":"\uc6f9\uc18c\ucf13","date":"2023-06-26T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 26\uc77c","tags":[{"label":"WebSocket","permalink":"/tags/web-socket"}],"readingTime":4.165,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9\uc18c\ucf13","slug":"websocket","tags":["WebSocket"]},"prevItem":{"title":"\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1","permalink":"/java-spring-springboot"},"nextItem":{"title":"Docusaurus","permalink":"/docusaurus"}},"content":"### \uc6f9\uc18c\ucf13\\n\\n\ub2e8\uc77c TCP \uc5f0\uacb0\uc744 \ud1b5\ud574 \ud074\ub77c\uc774\uc5b8\ud2b8\uc640 \uc11c\ubc84 \uac04 \uc804\uc774\uc911 \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\ud1a0\ucf5c \\n\uc6f9 \ud658\uacbd\uc5d0\uc11c \uc5f0\uc18d\ub41c \ub370\uc774\ud130\ub97c \uc2e4\uc2dc\uac04\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\\n\uc6f9\uc18c\ucf13\uc740 HTTP\uc758 \ud3ec\ud2b8\ub97c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud558\uace0 \uac01\uac01 \ud3ec\ud2b8 80\uacfc \ud3ec\ud2b8 443\uc744 \uc0ac\uc6a9\ud558\uc5ec HTTP(ws://) \ubc0f HTTPS(wss://)\ub85c \uc11c\ubc84\uc5d0 \uc5f0\uacb0\ud55c\ub2e4. \\n\\n### \uc6f9\uc18c\ucf13 \ub4f1\uc7a5 \ubc30\uacbd\\n\\n\uc6f9\uc18c\ucf13\uc774 \ub4f1\uc7a5\ud558\uae30 \uc774\uc804, \uc2e4\uc2dc\uac04\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 Polling, Long polling, Streaming \uac19\uc740 \uae30\uc220\uc744 \uc0ac\uc6a9\ud588\uc5b4\uc57c \ud588\ub2e4. \\n\uc774\ub294 \uc2e4\uc2dc\uac04\uc131\uc774\ub098 \uc591\ubc29\ud5a5\uc131\uc744 \ub9cc\uc871\uc2dc\ud0a4\uc9c0 \ubabb\ud588\uace0, HTTP\ub97c \uc774\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 \uacfc\ub3c4\ud55c \uc624\ubc84\ud5e4\ub4dc\uac00 \ubc1c\uc0dd\ud588\ub2e4. \\n\\n:::note polling, long polling, streaming\\n\\nPolling: \uc8fc\uae30\uc801\uc73c\ub85c \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ubcf4\ub0b4 \uc218\uc2e0\ud560 \uc815\ubcf4\uac00 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubc29\ubc95\\n- \uc11c\ubc84\uc5d0\uc11c \ubcf4\ub0bc \ub0b4\uc6a9\uc774 \uc5c6\uc5b4\ub3c4 \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc54c \uc218 \uc5c6\ub2e4. \\n- \uacc4\uc18d\ud574\uc11c \uc694\uccad\uc744 \ubcf4\ub0b4 \ud655\uc778\uc744 \ud574\uc57c\ud558\uae30 \ub54c\ubb38\uc5d0 \uc11c\ubc84\uc5d0 \ubd88\ud544\uc694\ud55c \ubd80\ud558\ub97c \uc8fc\uc5b4\uc57c \ud55c\ub2e4. \\n\\nLong Polling: \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc694\uccad\uc5d0 \ub300\ud574 \uc751\ub2f5\uc744 \ubcf4\ub0b4\uc9c0 \uc54a\uace0 \uc788\ub2e4\uac00 \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud588\uc744\ub54c \uc751\ub2f5\ud558\ub294 \ubc29\ubc95\\n- \ud3f4\ub9c1 \ubc29\uc2dd\ubcf4\ub2e4 \uc11c\ubc84\uc5d0 \uc801\uc740 \ubd80\ud558\ub97c \uc904 \uc218 \uc788\uc9c0\ub9cc, \uc694\uccad\uc758 \uc8fc\uae30\uac00 \uc9e7\uc73c\uba74 \ud3f4\ub9c1\uacfc \ucc28\uc774\uac00 \uc5c6\uc5b4\uc9c4\ub2e4.\\n\\nStreaming: \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 request\ub97c \ubcf4\ub0b4\uba74 \ucee4\ub125\uc158\uc744 \ub9fa\uace0, \uc774 \ucee4\ub125\uc158\uc744 \uc720\uc9c0\ud558\uba74\uc11c \uc11c\ubc84\uac00 \uacc4\uc18d \ub370\uc774\ud130\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n- \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc11c\ubc84\uc5d0 \uc694\uccad\uc744 \ud558\uace0 \uc2f6\ub2e4\uba74 \uc0c8\ub85c\uc6b4 \ucee4\ub125\uc158\uc744 \ub9fa\uc5b4\uc57c \ud55c\ub2e4. \\n:::\\n\\n### \uc6f9\uc18c\ucf13\uc758 \ub3d9\uc791\\n\\n```mermaid\\nsequenceDiagram\\n participant Client\\n participant Server\\n Client->>Server: Handshake - Upgrade\ub97c \uc774\uc6a9\ud55c WebSocket \uc804\ud658 \uc694\uccad\\n Server->>Client: Handshake - HttpStatus 101(Switching Protocols)\\n\\n Client->>Server: \uc591\ubc29\ud5a5 \ud1b5\uc2e0\\n Server->>Client: \\n\\n Client->>Server: \uc885\ub8cc\\n Server->>Client: \\n```\\n\\n### 1. Upgrade \uc694\uccad\\n\\nWebSocket \ud504\ub85c\ud1a0\ucf5c\ub85c \uc804\ud658\ud558\ub294 HTTP \uc694\uccad\uc744 \ubcf4\ub0b8\ub2e4. \\n\uc774\ub294 HTTP\uc640 \uac19\uc774 80, 443 \ud3ec\ud2b8\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uc6f9\uc18c\ucf13\uc73c\ub85c \uc804\ud658\ud558\uae30 \uc704\ud574\uc11c\ub294 Upgrade: websocket, Connection: Upgrade \ud5e4\ub354\uac00 \ud544\uc694\ud558\ub2e4. \\nSec-WebSocket-Key\ub294 \uc11c\ubc84\uc5d0\uc11c Sec-WebSocket-Accept\ub97c \uacc4\uc0b0\ud558\uc5ec \uc751\ub2f5\ud558\uace0 \uc774 \uac12\uc774 \uc608\uc0c1\ud55c \uac12\uacfc \ub2e4\ub974\uba74 \uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uc9c0 \uc54a\ub294\ub2e4. \\nSec-WebSocket-Protocol\uc758 \uacbd\uc6b0 \uc11c\ube0c\ud504\ub85c\ud1a0\ucf5c\uc758 \ubaa9\ub85d\uc73c\ub85c \uc11c\ubc84 \uce21\uc5d0\uc11c\ub294 \ud574\ub2f9 \ubaa9\ub85d \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud558\uc5ec \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ub9cc\uc57d \uc11c\ubc84\uce21\uc5d0\uc11c \uc5ec\ub7ec \uac1c \uc9c0\uc6d0\uc774 \uac00\ub2a5\ud55c \uacbd\uc6b0 \uc9c0\uc6d0 \uac00\ub2a5\ud55c \ud504\ub85c\ud1a0\ucf5c \uc911 \uccab\ubc88\uc9f8 \ud504\ub85c\ud1a0\ucf5c\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uce21\uc73c\ub85c \ubcf4\ub0b8\ub2e4. \\n\\n```\\nGET /chats HTTP/1.1\\nHost: localhost:8080\\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==\\nSec-WebSocket-Protocol: v10.stomp, v11.stomp\\nSec-WebSocket-Version: 13\\nOrigin: http://localhost:8080\\n```\\n\\n### 2. Switching Protocols\\n\\n\uc11c\ubc84\ub294 101 Switching Protocols \uc751\ub2f5\uc744 \ubc18\ud658\ud55c\ub2e4. \\nSec-WebSocket-Accept\uc740 Sec-WebSocket-Key \ub4a4\uc5d0 `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`\ub97c \ubd99\uc774\uace0 SHA1\ub85c \ud574\uc2f1 \ud6c4 Base64\ub85c \uc778\ucf54\ub529\ud558\uc5ec \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub294 \uc11c\ubc84 \uc6f9\uc18c\ucf13 \ud504\ub85c\ud1a0\ucf5c\uc758 \uc9c0\uc6d0 \uc5ec\ubd80\ub97c \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \uba85\ud655\ud788 \uc54c\ub9ac\uae30 \uc704\ud574 \uc874\uc7ac\ud55c\ub2e4. \\n\\n```\\nHTTP/1.1 101 Switching Protocols \\nUpgrade: websocket\\nConnection: Upgrade\\nSec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=\\nSec-WebSocket-Protocol: v10.stomp\\n```\\n\\n### 3. \ud1b5\uc2e0 \ud6c4 \uc885\ub8cc\\n\\n\uc5f0\uacb0\uc774 \uc218\ub9bd\ub418\uba74 \uc6f9\uc18c\ucf13 \ud504\ub808\uc784 \ub2e8\uc704\ub85c \uc591\ubc29\ud5a5 \ud1b5\uc2e0\uc744 \ud55c\ub2e4. \\n\uc5f0\uacb0 \uc885\ub8cc\ub97c \uc6d0\ud558\ub294 \uacbd\uc6b0 \ud074\ub77c\uc774\uc5b8\ud2b8, \uc11c\ubc84 \ubaa8\ub450 \uc5f0\uacb0 \uc885\ub8cc\ub97c \uc694\uccad\ud560 \uc218 \uc788\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\nhttps://datatracker.ietf.org/doc/html/rfc6455 \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications \\nhttps://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers \\nhttps://docs.spring.io/spring-framework/reference/web/websocket.html"},{"id":"docusaurus","metadata":{"permalink":"/docusaurus","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","source":"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx","title":"Docusaurus","description":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4.","date":"2023-06-18T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 18\uc77c","tags":[{"label":"Documentation","permalink":"/tags/documentation"}],"readingTime":10.095,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Docusaurus","slug":"docusaurus","tags":["Documentation"]},"prevItem":{"title":"\uc6f9\uc18c\ucf13","permalink":"/websocket"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"}},"content":"\ud300 \ube14\ub85c\uadf8 \ub610\ub294 \ubb38\uc11c\ud654\ub97c \uc704\ud574 Docusaurus\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc744 \uc815\ub9ac\ud558\ub824\uace0 \ud55c\ub2e4. \\n\\n## \uc124\uce58\\n\\n[\uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://docusaurus.io/docs/installation)\uc5d0 \ub4e4\uc5b4\uac00\uc11c \ucd5c\uc2e0 \ubc84\uc804\uc744 \uc124\uce58\ud55c\ub2e4. \\n\\n```bash\\nyarn create docusaurus\\n````\\n\\n## \ubc30\ud3ec\\n\\n[\ubc30\ud3ec \uc548\ub0b4 \ubb38\uc11c](https://docusaurus.io/docs/next/deployment#deploying-to-github-pages) \\nnetlify\ub098 vercel \uac19\uc740 \uc11c\ubc84\ub9ac\uc2a4 \ud50c\ub7ab\ud3fc\uc744 \ucd94\ucc9c\ud558\uace0 \uc788\uace0, \uac04\ub2e8\ud558\uace0, \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \ubc30\ud3ec\ub97c \ud560 \uc218 \uc788\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 github pages\ub97c \uc774\uc6a9\ud574\uc11c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud55c\ub2e4.\\n\\n### \ub808\ud3ec\uc9c0\ud1a0\ub9ac \uc0dd\uc131\\n\\ngithub pages\ub97c \uc774\uc6a9\ud558\ub824\uba74 [\uc608\uc2dc](https://github.com/greeng00se/greeng00se.github.io)\uc640 \uac19\uc774 `username.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\n\uc774\ub54c organization\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 `organization.github.io` \ud615\ud0dc\uc758 \ub808\ud3ec\uc9c0\ud1a0\ub9ac\ub97c \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n### \uc124\uc815 \ud30c\uc77c \uc218\uc815\\n\\n```js title=\\"docusaurus.config\\"\\nmodule.exports = {\\n // ...\\n url: \'https://greeng00se.github.io\',\\n baseUrl: \'/\',\\n projectName: \'greeng00se.github.io\',\\n organizationName: \'greeng00se\',\\n trailingSlash: false,\\n // ...\\n};\\n```\\n\\n### \ud1a0\ud070 \uc124\uc815\\n\\ngithub action\uc744 \uc704\ud574 \ubc30\ud3ec\uc6a9 \ud1a0\ud070\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uc5ec \uc0dd\uc131\ud55c \ub808\ud3ec\uc9c0\ud1a0\ub9ac\uc5d0 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \ud1a0\ud070\uc744 \ud074\ub798\uc2dd \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ud588\uace0 \uc2a4\ucf54\ud504\ub294 [repo, user, workflow] \uc744 \uc124\uc815\ud588\ub2e4. \\n\\n![github](./github.png)\\n\\n### \ube0c\ub79c\uce58 \uc0dd\uc131\\n\\ngithub\uc5d0\uc11c gh-pages \ube0c\ub79c\uce58\ub97c \ud558\ub098 \uc0dd\uc131\ud55c\ub2e4. \\nrepository -> settings -> pages -> branch\uc5d0\uc11c \uc0dd\uc131\ud55c gh-pages\ub85c \ube0c\ub79c\uce58\ub97c \ubcc0\uacbd\ud55c\ub2e4. \\n\uc124\uc815\ud55c \ube0c\ub79c\uce58\uac00 \ubc30\ud3ec \ube0c\ub79c\uce58\uac00 \ub418\uba70, \ud574\ub2f9 \ube0c\ub79c\uce58\uc5d0 \uc788\ub294 \ud30c\uc77c\ub4e4\uc744 \uc774\uc6a9\ud574\uc11c \uc815\uc801 \uc6f9\uc0ac\uc774\ud2b8\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\\n### \uc6cc\ud06c\ud50c\ub85c \uc791\uc131\\n\\nDocusaurus 2.0 \uae30\uc900 Node.js 16.14 \uc774\uc0c1\uc758 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud574\uc57c \ud569\ub2c8\ub2e4. \\n\ubc30\ud3ec\uc2dc\uc5d0\ub294 Repository secrets\uc73c\ub85c \uc124\uc815\ud55c DEPLOY_TOKEN \uc744 \uc774\uc6a9\ud569\ub2c8\ub2e4. \\n\\n```yml title=\\".github/workflows/deploy.yml\\"\\nname: blog\\n\\non:\\n push:\\n branches: [main]\\n\\njobs:\\n deploy:\\n name: Deploy to GitHub Pages\\n runs-on: ubuntu-latest\\n steps:\\n - uses: actions/checkout@v2\\n - uses: actions/setup-node@v3\\n with:\\n node-version: 18\\n cache: yarn\\n\\n - name: Install dependencies\\n run: yarn install --frozen-lockfile\\n - name: Build website\\n run: yarn build\\n\\n - name: Deploy to GitHub Pages\\n uses: peaceiris/actions-gh-pages@v3\\n with:\\n github_token: ${{ secrets.DEPLOY_TOKEN }}\\n publish_dir: ./build\\n user_name: github-actions[bot]\\n user_email: 41898282+github-actions[bot]@users.noreply.github.com\\n```\\n\\n## \ub313\uae00 \uae30\ub2a5\\n\\ngiscus\ub97c \uc774\uc6a9\ud558\uc5ec \ub313\uae00 \uae30\ub2a5\uc744 \ucd94\uac00\ud55c\ub2e4. \\n\\n### giscus \uc124\uc815\\n\\n1. \uacf5\uac1c \uc800\uc7a5\uc18c\uc5ec\uc57c \ud55c\ub2e4.\\n2. giscus \uc571\uc774 \uc124\uce58\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n3. Discussions \uae30\ub2a5\uc774 \ud574\ub2f9 \uc800\uc7a5\uc18c\uc5d0\uc11c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc5b4\uc57c \ud55c\ub2e4.\\n\\n\uc790\uc138\ud55c \ub0b4\uc6a9\uc740 [giscus](https://giscus.app/ko)\ub97c \ud655\uc778\ud558\uc790.\\n\\n### docusaurus \uc124\uc815\\n\\n[swizzling](https://docusaurus.io/ko/docs/next/swizzling)\uc744 \uc774\uc6a9\ud558\uc5ec \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac10\uc2fc\ub2e4. \\n\uae30\uc874\uc5d0 \uac8c\uc2dc\ubb3c\uc744 giscus\uac00 \ud3ec\ud568\ub41c \ub9ac\uc561\ud2b8 \ucef4\ud3ec\ub10c\ud2b8\ub85c \uac10\uc2f8\ub294 \ud615\ud0dc\uac00 \ub41c\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec BlogPostItem\uc744 \ucd94\ucd9c\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nyarn run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap\\n```\\n\\n\uba85\ub839\uc5b4\ub97c \uc785\ub825\ud558\uba74 `/src/theme/BlogPostItem/index.js` \uc704\uce58\uc5d0 \ud30c\uc77c\uc774 \uc0dd\uc131\ub41c\ub2e4. \\n\ud30c\uc77c\uc758 \ub0b4\uc6a9\uc744 \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud558\uace0, \uc774\ub54c setAttribute \ubd80\ubd84\uc740 \uc801\uc808\ud558\uac8c \uc790\uc2e0\uc758 giscus \uc124\uc815\uc744 \uc774\uc6a9\ud55c\ub2e4. \\n\\n```js title=\\"/src/theme/BlogPostItem/index.js\\"\\nimport OriginalBlogPostItem from \\"@theme-original/BlogPostItem\\";\\nimport React, { useEffect, useRef } from \\"react\\";\\n// @ts-expect-error internal code\\nimport { useColorMode } from \\"@docusaurus/theme-common\\";\\nimport { useBlogPost } from \\"@docusaurus/theme-common/internal\\";\\n\\nconst giscusSelector = \\"iframe.giscus-frame\\";\\n\\nfunction BlogPostItem(props) {\\n const { colorMode } = useColorMode();\\n const { isBlogPostPage } = useBlogPost();\\n const giscusTheme = colorMode === \\"dark\\" ? \\"dark\\" : \\"light\\";\\n const containerRef = useRef(null);\\n\\n useEffect(() => {\\n if (!isBlogPostPage) return;\\n\\n const giscusEl = containerRef.current.querySelector(giscusSelector);\\n\\n const createGiscusEl = () => {\\n const script = document.createElement(\\"script\\");\\n\\n script.src = \\"https://giscus.app/client.js\\";\\n script.setAttribute(\\"data-repo\\", \\"teco-chat/teco-chat.github.io\\");\\n script.setAttribute(\\"data-repo-id\\", \\"R_kgDOJZ5j0Q\\");\\n script.setAttribute(\\"data-category\\", \\"Announcements\\");\\n script.setAttribute(\\"data-category-id\\", \\"DIC_kwDOJZ5j0c4CXS_Q\\");\\n script.setAttribute(\\"data-mapping\\", \\"pathname\\");\\n script.setAttribute(\\"data-strict\\", \\"0\\");\\n script.setAttribute(\\"data-reactions-enabled\\", \\"1\\");\\n script.setAttribute(\\"data-emit-metadata\\", \\"0\\");\\n script.setAttribute(\\"data-input-position\\", \\"bottom\\");\\n script.setAttribute(\\"data-theme\\", giscusTheme);\\n script.setAttribute(\\"data-lang\\", \\"ko\\");\\n script.crossOrigin = \\"anonymous\\";\\n script.async = true;\\n \\n containerRef.current.appendChild(script);\\n };\\n\\n const postThemeMessage = () => {\\n const message = {\\n setConfig: {\\n theme: giscusTheme,\\n }\\n };\\n\\n giscusEl.contentWindow.postMessage({ giscus: message }, \\"https://giscus.app\\");\\n };\\n\\n giscusEl ? postThemeMessage() : createGiscusEl();\\n }, [giscusTheme]);\\n\\n return (\\n <>\\n \\n {isBlogPostPage &&
}\\n \\n );\\n}\\n\\nexport default BlogPostItem;\\n```\\n\\n## \uc54c\uace0\ub9ac\uc544 \uc124\uc815 \ubc0f \uc9c1\uc811 \uad00\ub9ac\ud558\uae30\\n\\n\uc54c\uace0\ub9ac\uc544\ub97c \uc0ac\uc6a9\ud558\uba74 \uac80\uc0c9 \uae30\ub2a5\uc744 \ucd94\uac00\ud560 \uc218 \uc788\ub2e4. \\n\uc720\ub8cc \ud50c\ub79c\uc774\ub098 netlify\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ud06c\ub864\ub7ec\ub97c \ub530\ub85c \uc81c\uacf5\ud574 \uc8fc\ub294 \uac83 \uac19\ub2e4. \\n\\n\ubb34\ub8cc \ud50c\ub79c\uc740 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uacfc, [docsearch](https://docsearch.algolia.com/)\ub97c \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4. \\ndocsearch\uc5d0 \ub4f1\ub85d\ud55c\ub2e4\uba74 \uc77c\uc8fc\uc77c\uc5d0 \ud55c \ubc88\uc529 \ud06c\ub864\ub9c1\uc774 \uc9c4\ud589\ub41c\ub2e4. \\n\uc774 \uae00\uc5d0\uc11c\ub294 \uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\ub294 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n- [\uc9c1\uc811 \uc778\ub371\uc2a4 \uc218\uc9d1](https://docsearch.algolia.com/docs/legacy/run-your-own/) \\n- [\uc124\uc815 \ud30c\uc77c](https://docsearch.algolia.com/docs/legacy/config-file)\\n\\n### \uc54c\uace0\ub9ac\uc544 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131 \ubc0f \ud0a4 \ud655\uc778\\n\\n\ud68c\uc6d0\uac00\uc785\uc744 \ud558\uace0 \uc0c8\ub85c\uc6b4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \uc0dd\uc131\uc744 \ub204\ub978\ub2e4. \\n\uc0dd\uc131\uc744 \ub2e4 \ub9c8\uce58\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 api \ud0a4\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n![algolia](./algolia.png)\\n\\n### \ud0a4 \uc0dd\uc131\\n\\n\uc9c1\uc811 \uc778\ub371\uc2a4\ub97c \uc218\uc9d1\ud558\uae30 \uc704\ud55c \ud0a4\ub97c \uc0dd\uc131\ud55c\ub2e4. \\naddObject, editSettings, deleteIndex acl(\uc811\uadfc \uc81c\uc5b4 \ubaa9\ub85d)\uc774 \uc788\uc73c\uba74 \ub41c\ub2e4. \\n\\n![key](./key.png)\\n\\n### .env \ud30c\uc77c \uc0dd\uc131\\n\\n\ud504\ub85c\uc81d\ud2b8 \ud3f4\ub354 \uc0c1\ub2e8\uc5d0 .env \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\\n```bash title=\\".env\\"\\nAPPLICATION_ID=MVIU5UEMOM\\nAPI_KEY=\uc778\ub371\uc2a4_\uc0dd\uc131\uc6a9_\ud0a4\\n```\\n\\n### config \ud30c\uc77c \uc0dd\uc131\\n\\n\ub9c8\ucc2c\uac00\uc9c0\ub85c \ucd5c\uc0c1\ub2e8\uc5d0 config.json \ud30c\uc77c\uc744 \uc0dd\uc131\ud55c\ub2e4.\\n\uc124\uc815 \ud30c\uc77c\uc740 \ud574\ub2f9 [\ub9c1\ud06c](https://docsearch.algolia.com/docs/legacy/config-file)\ub97c \ucc38\uace0\ud55c\ub2e4. \\n\ub610\ub294 Docusaurus\uc758 [\uc124\uc815 \ud30c\uc77c](https://github.com/algolia/docsearch-configs/blob/master/configs/docusaurus-2.json)\uc744 \ucc38\uace0\ud55c\ub2e4.\\n\\n```json title=\\"config.json\\"\\n{\\n \\"index_name\\": \\"teco\\",\\n \\"start_urls\\": [\\n \\"https://teco-chat.github.io/\\"\\n ],\\n \\"sitemap_urls\\": [\\n \\"https://teco-chat.github.io/sitemap.xml\\"\\n ],\\n \\"sitemap_alternate_links\\": true,\\n \\"stop_urls\\": [\\n \\"/tests\\"\\n ],\\n \\"selectors\\": {\\n \\"lvl0\\": {\\n \\"selector\\": \\"(//ul[contains(@class,\'menu__list\')]//a[contains(@class, \'menu__link menu__link--sublist menu__link--active\')]/text() | //nav[contains(@class, \'navbar\')]//a[contains(@class, \'navbar__link--active\')]/text())[last()]\\",\\n \\"type\\": \\"xpath\\",\\n \\"global\\": true,\\n \\"default_value\\": \\"Documentation\\"\\n },\\n \\"lvl1\\": \\"header h1\\",\\n \\"lvl2\\": \\"article h2\\",\\n \\"lvl3\\": \\"article h3\\",\\n \\"lvl4\\": \\"article h4\\",\\n \\"lvl5\\": \\"article h5, article td:first-child\\",\\n \\"lvl6\\": \\"article h6\\",\\n \\"text\\": \\"article p, article li, article td:last-child\\"\\n },\\n \\"strip_chars\\": \\" .,;:#\\",\\n \\"custom_settings\\": {\\n \\"separatorsToIndex\\": \\"_\\",\\n \\"attributesForFaceting\\": [\\n \\"language\\",\\n \\"version\\",\\n \\"type\\",\\n \\"docusaurus_tag\\"\\n ],\\n \\"attributesToRetrieve\\": [\\n \\"hierarchy\\",\\n \\"content\\",\\n \\"anchor\\",\\n \\"url\\",\\n \\"url_without_anchor\\",\\n \\"type\\"\\n ]\\n },\\n \\"conversation_id\\": [\\n \\"833762294\\"\\n ],\\n \\"nb_hits\\": 46250\\n}\\n```\\n\\n### docker \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\\n\\ndocker\uc640 jq\uac00 \ud544\uc694\ud558\ub2e4. \\njq\uac00 \uc124\uce58\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc73c\uba74 mac \uae30\uc900 brew\ub97c \uc774\uc6a9\ud574\uc11c \uc124\uce58\ud560 \uc218 \uc788\ub2e4. \\n\\n```bash\\nbrew install jq\\n```\\n\\n\ub2e4\uc74c \uba85\ub839\uc5b4\ub97c \uc774\uc6a9\ud558\uc5ec .env\uc640 config.json\uc744 \uc774\uc6a9\ud558\uc5ec \ud06c\ub864\ub9c1\uc744 \ud55c\ub2e4. \\n\\n```bash\\ndocker run -it --env-file=.env -e \\"CONFIG=$(cat ./config.json | jq -r tostring)\\" algolia/docsearch-scraper\\n```\\n\\n### docusaurus \uc124\uc815\\n\\n\uc804\uc5d0 \ud655\uc778\ud55c APP ID, Search-Only API KEY, IndexName\uc744 \uc774\uc6a9\ud558\uc5ec docusaurus.config \ud30c\uc77c\uc5d0 \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n algolia: {\\n appId: \'MVIU5UEMOM\', // Application ID\\n apiKey: \'b68f378013817d9a190df88cdde226a0\', // Search-Only API Key\\n indexName: \'teco\', // config.json\uc5d0 \uc124\uc815\ud55c \uc778\ub371\uc2a4\uba85\\n contextualSearch: true,\\n },\\n })\\n```\\n\\n## \ubd80\uac00 \uc124\uc815\\n\\n### \ud654\uba74 \uc0c1\ub2e8 Github Icon\\n\\n\ud30c\uc77c \ucd5c\ud558\ub2e8\uc5d0 \uc544\ub798 css \uad6c\ubb38\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```css title=\\"/src/css/custom.css\\"\\n.header-github-link:hover {\\n opacity: 0.6;\\n}\\n\\n.header-github-link:before {\\n content: \'\';\\n width: 24px;\\n height: 24px;\\n display: flex;\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n\\nhtml[data-theme=\'dark\'] .header-github-link:before {\\n background: url(\\"data:image/svg+xml,%3Csvg viewBox=\'0 0 24 24\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath fill=\'white\' d=\'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\'/%3E%3C/svg%3E\\")\\n no-repeat;\\n}\\n```\\n\\nthemeconfig -> navbar\uc5d0 github link\ub97c \uc124\uc815\ud55c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nnavbar: {\\n title: \'HELLO\',\\n items: [\\n {\\n href: \'https://github.com/greeng00se\',\\n position: \'right\',\\n className: \'header-github-link\',\\n \'aria-label\': \'GitHub repository\',\\n },\\n ],\\n},\\n```\\n\\n### \ucf54\ub4dc\ube14\ub7ed\\n\\njava\ub098 kotlin\uc758 \uacbd\uc6b0 \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ub77c\uc774\ud305\uc744 \uc9c0\uc6d0\ud574 \uc8fc\uc9c0 \uc54a\ub294\ub2e4. \\nprism \uc124\uc815\uc744 \uc544\ub798\uc640 \uac19\uc774 \ubcc0\uacbd\ud574 \uc900\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nprism: {\\n theme: lightCodeTheme,\\n darkTheme: darkCodeTheme,\\n additionalLanguages: [\'java\', \'kotlin\'],\\n}\\n```\\n\\n### mermaid\\n\\nmermaid\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 `@docusaurus/theme-mermaid` \ub97c \uc124\uce58\ud574\uc57c \ud55c\ub2e4.\\n\\n```bash\\nyarn add @docusaurus/theme-mermaid\\n```\\n\\n\uc124\uce58 \ud6c4 \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\uc744 \ucd94\uac00\ud55c\ub2e4.\\n\\n```js title=\\"docusaurus.config\\"\\nconst config = {\\n ...\\n markdown: {\\n mermaid: true,\\n },\\n themes: [\\n \'@docusaurus/theme-mermaid\'\\n ],\\n};\\n```\\n\\nthemeConfig\uc5d0\uc11c mermaid\uc758 \ud14c\ub9c8\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\nthemeConfig:\\n /** @type {import(\'@docusaurus/preset-classic\').ThemeConfig} */\\n ({\\n ...\\n mermaid: {\\n theme: {\\n light: \'neutral\', \\n dark: \'dark\'\\n },\\n },\\n }),\\n```\\n\\n### \uad6d\uc81c\ud654 \uc124\uc815\\n\\n\uad6d\uc81c\ud654 \uc124\uc815\uc744 \ud55c\ub2e4\uba74 `Older Entries` \ud615\ud0dc\uc758 \uc124\uba85\uc774 `\ub2e4\uc74c \ud398\uc774\uc9c0` \ub85c \ubcc0\uacbd\ub41c\ub2e4. \\n\uc124\uc815\ud30c\uc77c\uc5d0\uc11c i18n\uc5d0 \uc788\ub294 \ub85c\ucf00\uc77c \uc124\uc815\uc744 ko\ub85c \ubcc0\uacbd\ud558\uba74 \ub41c\ub2e4. \\n\\n```js title=\\"docusaurus.config\\"\\ni18n: {\\n defaultLocale: \\"ko\\",\\n locales: [\\"ko\\"],\\n},\\n```\\n\\n### \ube14\ub85c\uadf8 \uae00 author\\n\\n\ud300\uc6d0 \ubcc4\ub85c \ubb38\uc11c\ub97c \uad00\ub9ac\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc5b4\ub5a4 \ud300\uc6d0\uc774 \uae00\uc744 \uc791\uc131\ud588\ub294\uc9c0 \uc124\uc815\ud574\uc57c \ud55c\ub2e4. \\n\\n![author](./author.png)\\n\\n`authors.yml` \ud30c\uc77c\uc744 \uc774\uc6a9\ud558\uc5ec \uc0ac\uc6a9\uc790\uc5d0 \ub300\ud55c \uae30\ubcf8 \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n```yml title=\\"/blog/authors.yml\\"\\nherb:\\n name: \ud5c8\ube0c\\n title: Backend\\n url: https://github.com/greeng00se\\n image_url: https://github.com/greeng00se.png\\n\\nmallang:\\n name: \ub9d0\ub791\\n title: Backend\\n url: https://github.com/shin-mallang\\n image_url: https://github.com/shin-mallang.png\\n```\\n\\n\ube14\ub85c\uadf8 \uae00\uc744 \uc791\uc131\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc774 authors\uc5d0 \ub123\uc5b4\uc8fc\uae30\ub9cc \ud558\uba74 \ub41c\ub2e4. \\n\\n```mdx\\n---\\nslug: 1\\ntitle: Hello World\\nauthors: [herb, mallang]\\ntags: [hello, docusaurus]\\n---\\n\\n\uccab \ubc88\uc9f8 \ubb38\uc11c \ub0b4\uc6a9\\n```"},{"id":"woowacourse-level2-retrospective","metadata":{"permalink":"/woowacourse-level2-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","description":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4.","date":"2023-06-11T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 11\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":2.545,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","slug":"woowacourse-level2-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"Docusaurus","permalink":"/docusaurus"},"nextItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"}},"content":"23\ub144\uc758 6\uc6d4\uc774 \uc624\uace0, \ub808\ubca8 2\uac00 \ub05d\ub0ac\ub2e4. \\n\ube60\ub974\uac8c \uc9c0\ub098\uac00\uc11c \uc870\uae08 \uc544\uc27d\ub2e4. \\n\\n### \ud559\uc2b5\\n\\n\ud68c\uace0\ub97c \uc791\uc131\ud558\uae30 \uc804\uc5d0 \ub808\ubca8 2 \ub3d9\uc548 \ubcf4\ub0c8\ub358 PR\uacfc \ud68c\uace0\ub97c \ucb49 \uc77d\uc5b4\ubd24\ub2e4. \\n\ud56d\uc0c1 \uc544\uc26c\uc6b4 \uacf3\uc740 \uc788\uae30 \ub9c8\ub828\uc774\uc9c0\ub9cc, \uc798 \ud559\uc2b5\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc744 \ud558\uba74\uc11c \uae30\uc220\uc744 \uc5b4\ub5bb\uac8c \uc120\ud0dd\ud558\uace0, \uc801\uc6a9\ud560 \uac83\uc778\uc9c0 \uace0\ubbfc\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \uaf64\ub098 \ub9ce\uc740 \uc131\uc7a5\uc744 \ud55c \uac83 \uac19\ub2e4. \\n\\n\uace0\ubbfc\uc740 \uae4a\uc5c8\uc9c0\ub9cc \uc774\ub860\uc801\uc778 \ud559\uc2b5\uc774 \ubd80\uc871\ud55c \ub808\ubca8 2\uc600\ub2e4. \\n\ubc29\ud559 \uadf8\ub9ac\uace0 \ub808\ubca8 3 \ub54c\ub294 \uc870\uae08 \ub354 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc744 \ud559\uc2b5\ud558\ub294\ub370 \uc9d1\uc911\ud574\uc57c\uaca0\ub2e4. \\n\\n\uc810\ucc28 \ud559\uc2b5 \ubc94\uc704\uac00 \ub113\uc5b4\uc9c0\uba74\uc11c \uc790\uc5f0\uc2a4\ub7fd\uac8c \ubaa8\ub974\ub294 \ub0b4\uc6a9\uc774 \uc313\uc5ec\uac04\ub2e4. \\n\ud544\uc694\ud55c \ub0b4\uc6a9\uc740 \uc55e\uc73c\ub85c \ucc9c\ucc9c\ud788 \ud559\uc2b5\ud558\uba74 \ub418\ub2c8\uae4c \uc870\uae09\ud574\uc9c0\uc9c0 \ub9d0\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc218\uba74\\n\\n\ub808\ubca8 2\ub97c \uc9c4\ud589\ud558\ub294 \ub3d9\uc548 \uc218\uba74\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\uc5c8\uace0, \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \uadf8\ub0a0\uc758 \ucee8\ub514\uc158\uc744 \ub9ce\uc774 \uc88c\uc6b0\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc218\uba74 \uc2dc\uac04\uc744 \ub298\ub9ac\uace0, \uc88b\uc740 \uc218\uba74 \uc2b5\uad00\uc744 \uac00\uc9c0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### \ud611\uc5c5\\n\\n\ub808\ubca8 2 \ub9c8\uc9c0\ub9c9\uc5d0 \ud611\uc5c5 \ubbf8\uc158\uc774 \uc788\uc5c8\ub2e4. \\n\uc9c0\uae08\uae4c\uc9c0\ub294 \ubc31\uc5d4\ub4dc \ud06c\ub8e8\ub4e4\uacfc \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud558\uba74\uc11c \ud611\uc5c5\uc744 \uacbd\ud5d8\ud588\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ud504\ub7f0\ud2b8\uc5d4\ub4dc \ud06c\ub8e8\uc640 \ud611\uc5c5\uc744 \ud588\ub2e4. \uc18c\ud1b5\uc740 \uc798 \ub41c \uac83 \uac19\uc9c0\ub9cc API \uba85\uc138\ub97c \uc815\ud558\ub294 \ubd80\ubd84\uc774 \uc544\uc9c1 \ubbf8\uc219\ud55c \uac83 \uac19\ub2e4. \\n\\n\ub808\ubca8 3 \ub54c\ubd80\ud130 \ubcf8\uaca9\uc801\uc73c\ub85c \ud504\ub85c\uc81d\ud2b8\uac00 \uc2dc\uc791\ub41c\ub2e4. \\n\ud300\uc744 \uc704\ud574 \uc5b4\ub5a4 \uac83\uc744 \ud560 \uc218 \uc788\uc744\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 2\ub97c \ub9c8\ubb34\ub9ac\ud558\uba70\\n\\n\ud68c\uace0 \uc791\uc131\ud558\uba74\uc11c \ub808\ubca8 2\uc5d0\uc11c \ud588\ub358 \uac83\ub4e4\uc744 \ubc18\ucd94\ud574 \ubd24\ub294\ub370 \ubd80\uc871\ud55c \uc810\uc740 \ub9ce\uc558\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \uac00\uace0 \uc788\ub294 \uac83 \uac19\ub2e4.\\n\uc77d\uace0 \uc2f6\uc740 \ucc45\ub3c4 \uc77d\uace0, \ubd80\uc871\ud55c \ubd80\ubd84 \ucc44\uc6b0\uba74\uc11c \uc26c\uc5b4\uc57c\uaca0\ub2e4."},{"id":"level2-interview-retrospective","metadata":{"permalink":"/level2-interview-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx","title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","description":"\ub808\ubca8 \uc778\ud130\ubdf0","date":"2023-06-08T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 8\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.435,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","slug":"level2-interview-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 2 \ud68c\uace0","permalink":"/woowacourse-level2-retrospective"},"nextItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"}},"content":"### \ub808\ubca8 \uc778\ud130\ubdf0\\n\\n\ub808\ubca8 1 \ub54c\ub294 \uc900\ube44\ud574\ub454 \ub0b4\uc6a9\uc73c\ub85c \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud574\uc11c \uadf8\ub807\uac8c \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc774 \uc5c6\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \ub808\ubca8 1 \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0\ub294 \ub808\ubca8 1 \ud68c\uace0\ub97c \uc791\uc131\ud560 \ub54c \ub07c\uc6cc\ub123\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \ubc94\uc704\ub3c4 \uc81c\ud55c\ub418\uc5b4 \uc788\uc5b4 \uc5b4\ub5bb\uac8c \uc900\ube44\ud574\uc57c \ud560\uc9c0 \ub2f9\ud669\ud588\uace0, \ub2f5\ubcc0\uc5d0\ub3c4 \ubd80\uc871\ud55c \ubd80\ubd84\uc774 \ub9ce\uc558\uc5c8\ub2e4. \\n\uae30\uc5b5\uc774 \uc0ac\ub77c\uc9c0\uae30 \uc804\uc5d0 \ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\ud55c \ub0b4\uc6a9\uc744 \uc81c\uc678\ud558\uace0, \uae30\uc5b5 \ub0a8\ub294 \uac83 \uc704\uc8fc\ub85c \uc791\uc131\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### API \ubb38\uc11c \ub3c4\uad6c \uc120\ud0dd\\n\\n\ud070 \ubb38\uc81c \uc5c6\uc774 \ub2f5\ubcc0\uc744 \ud588\ub294\ub370 \uc55e\uc73c\ub85c\ub3c4 \ud300 \ud504\ub85c\uc81d\ud2b8\ub97c \ud558\uba74\uc11c \ub3c4\uc6c0 \ub420 \uac83 \uac19\uc740 \ub0b4\uc6a9\uc774 \uc788\uc5b4\uc11c \ub0a8\uaca8\ub450\ub824\uace0 \ud55c\ub2e4. \\n\ubc31\uc5d4\ub4dc \ud300\uc6d0\uc774 \ud568\uaed8 \uc758\uc0ac\uacb0\uc815\uc744 \ud588\uace0, \ubbf8\uc158 \uae30\uac04\uc774 \uc9e7\uc740 \ub9cc\ud07c \ud300 \ucc28\uc6d0\uc5d0\uc11c \ube44\uad50\uc801 \ud559\uc2b5\ud558\uae30 \uc26c\uc6b4 Swagger\ub97c \uc120\ud0dd\ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub4e4\uc5b4\uac00\ub294 \uc2dc\uac04 \ub300\ube44 \ud558\uc774 \ub9ac\ud134\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4\uace0 \ub2f5\ubcc0\ud588\ub2e4.\\n\\n\ud300 \ucc28\uc6d0\uc758 \ud559\uc2b5 \ube44\uc6a9\uc744 \uc5b8\uae09\ud574\uc11c, \ub2e4\uc74c\uacfc \uac19\uc740 \uc88b\uc740 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4.\\n\\n> \ud2b9\ud788 \ud300\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\ud558\ub294 \uacfc\uc815\uc744 \uacf5\uc720\ud574 \uc900 \uc810\uc774 \uc88b\uc558\uace0 \uae30\uc220\uc801 \uc758\uc0ac\uacb0\uc815 \uacfc\uc815\uc5d0\uc11c \ud300\uc758 \ud559\uc2b5\ube44\uc6a9\uc744 \uace0\ub824\ud55c \uc810\uc774 \uc88b\uc558\uc74c. \\n> \uc55e\uc73c\ub85c\ub3c4 \ud559\uc2b5 \ube44\uc6a9\uc740 \uc8fc\uc694\ud558\uac8c \uace0\ub824\ud574\uc57c \ud560 \uc0ac\ud56d\\n>\\n\\n### PUT\uacfc PATCH & \ud1a0\ud070\uacfc \uc138\uc158\\n\\nPUT\uacfc PATCH \ucc28\uc774\ub97c \uc124\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c\ub294 PATCH\ub97c \uc0ac\uc6a9\ud560 \ub54c \ud398\uc774\ub85c\ub4dc\uac00 \uc801\uc5b4\uc9c4\ub2e4\ub294 \ub0b4\uc6a9\uc744 \ube7c\uba39\uace0 \ub2f5\ubcc0\uc744 \ud588\ub2e4. \\n\ud1a0\ud070\uacfc \uc138\uc158\uc758 \uacbd\uc6b0 \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud574\ub2ec\ub77c\ub294 \uc81c\uc57d\uc870\uac74\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\n\\n\ud574\ub2f9 \ub0b4\uc6a9\uc744 \ub2f5\ubcc0\ud558\uba74\uc11c \uae30\uc220\uc801\uc778 \uae4a\uc774\uac00 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc2e4\uc81c\ub85c \ub808\ubca8 2 \ub54c \uc774\ub860\uc801\uc778 \ud559\uc2b5 \uc2dc\uac04\uc774 \ub9e4\uc6b0 \uc801\uc5c8\uace0, \uc9d1\uc911\ub825\ub3c4 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc55e\uc73c\ub85c \uc5b4\ub5bb\uac8c \uae4a\uc774\ub97c \ucc44\uc6b8\uc9c0 \uace0\ubbfc\uc744 \ud560 \uc218 \uc788\ub294 \uc9c8\ubb38\ub4e4\uc774\uc5c8\ub2e4. \\n\\n\ucd94\uac00\ub85c \uae30\uc220\uc744 \uc798 \ubaa8\ub974\ub294 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\ud558\ub294 \uac00\uc815\uc744 \ub450\uace0 \ud559\uc2b5\uc744 \ud55c\ub2e4\uba74 \ud070 \ub3c4\uc6c0\uc774 \ub420 \uac70\ub77c\ub294 \ud53c\ub4dc\ubc31\uc744 \ubc1b\uc558\ub2e4. \\n\\n### \uadf8 \uc678 \uac1c\uc120\ud560 \uc810\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ud2b9\uc720\uc758 \ub9d0\ubc84\ub987\uc744 \uac1c\uc120\ud558\uae30 \\n\uc0dd\uac01\ud560 \uc2dc\uac04\uc744 \uac00\uc84c\uc744 \ub54c \\"\ub2e4\uc2dc \ub9d0\uc500\ub4dc\ub824\ub3c4 \ub420\uae4c\uc694?\\"\ub77c\uace0 \ub9d0\ud558\uace0 \ub2f5\ubcc0\uc744 \uc774\uc5b4\ub098\uac00\uae30 \\n\uae30\uc220\uc801\uc73c\ub85c \uae4a\uc774\uac00 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc774 \ub9ce\uc774 \ub4e4\uc5b4\uc11c \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\uae30 \\n\uc774\uc804\uc5d0 \uacf5\ubd80\ud588\ub358\uac70 \ub418\ub3cc\uc544 \ubcf4\ub294 \uc2dc\uac04 \uac00\uc9c0\uae30"},{"id":"order-retrospective","metadata":{"permalink":"/order-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","description":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158","date":"2023-06-04T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 4\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.595,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","slug":"order-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0","permalink":"/level2-interview-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"}},"content":"### \uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158\\n\\n\ubc30\ud3ec \ubc0f \ud611\uc5c5\uc744 \ud560 \uc218 \uc788\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n\ub9c8\ucf54, \uc6b0\uac00, \uc6b0\ucf54, \uc6b0\uc2a4 \uadf8\ub9ac\uace0 \ub098\uae4c\uc9c0 \ud569\uccd0\uc11c 5\uba85\uc774 \ud55c \ud300\uc774 \ub418\uc5c8\ub2e4. \\n\\n### \ubc30\ud3ec\\n\\n\uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac AWS\ub97c \uc774\uc6a9\ud574 \ubc30\ud3ec\ub97c \ud574\uc57c \ud588\ub2e4. \\n\uac01\uc790 \ud558\ub098\uc758 EC2 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc744 \uc218 \uc788\uc5c8\uace0, \ud300 \ubcc4\ub85c DB\ub97c \uc704\ud55c \ucd94\uac00 \uc778\uc2a4\ud134\uc2a4\ub97c \uc81c\uacf5\ubc1b\uc558\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc791\uc131\ud558\ub294 \uacbd\ud5d8\uc744 \ud574\ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\ubc30\ud3ec \uc2a4\ud06c\ub9bd\ud2b8\uc5d0 \uc2dc\uac04\uc744 \ub9ce\uc774 \ud22c\uc790\ud558\uc9c4 \uc54a\uc558\uace0, \ub2e4\uc74c\uacfc \uac19\uc774 \uac04\ub2e8\ud558\uac8c \uc791\uc131\ud588\ub2e4.\\n\\n```bash\\necho \\"Start Deploy Script\\"\\nREPOSITORY_NAME=/home/ubuntu/jwp-shopping-order\\nPROJECT_NAME=jwp-shopping-order\\n\\necho \\"Change Directory\\"\\ncd $REPOSITORY_NAME\\n\\necho \\"Git Pull\\"\\ngit pull origin step2\\n\\necho \\"Build\\"\\n./gradlew bootJar\\n\\necho \\"Copy, Start Server\\"\\nmv ./build/libs/$PROJECT_NAME.jar .\\n\\nPID=$(pgrep -f $PROJECT_NAME)\\n\\nif [ -n $PID ]; then\\n kill -9 $PID\\n\\tsleep 5\\nfi\\n\\nnohup java -Dspring.profiles.active=prod -jar $PROJECT_NAME.jar 1>stdout.txt 2>err.txt &\\n```\\n\\n### \ud611\uc5c5\\n\\n\uc77c\ub2e8 \uc6b0\uc2a4\ub791 \uc6b0\ucf54\uac00 \uba3c\uc800 \uc7a0\uc2e4\ub85c \uc640\uc918\uc11c \ub108\ubb34 \uac10\uc0ac\ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uac00 \uc544\ub2cc \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \ud574\ubcf4\ub294 \uccab \ud611\uc5c5\uc774\ub77c \uc57d\uac04 \ub450\uadfc\uac70\ub838\ub2e4. \\n\uc608\uc0c1\uc678\ub85c \ub300\ud654\uac00 \uc798 \ub418\uc5b4\uc11c, \ube60\ub974\uac8c \uba85\uc138\ub97c \uc815\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc5ec\ub7ec\uac00\uc9c0 \ubc29\ubc95\uc5d0 \ub300\ud55c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud574\ubcf4\uae30**\\n\\n\ubc31\uc5d4\ub4dc\uc640 \ud14c\uc774\ube14 \uba85\uc138\ub098 \ucfe0\ud3f0 \uad6c\ud604\uc5d0 \ub300\ud574\uc11c \uc774\uc57c\uae30\ud560 \ub54c \uc7a5\ub2e8\uc5d0 \ub300\ud574 \ub9ce\uc774 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub9ce\uc774 \ub4e4\uc5ec\uc11c \uc7a5\ub2e8\uc810\uc744 \uace0\ub824\ud588\ub2e4\uba74 \ub354 \uc88b\uc740 \uacb0\uacfc\ubb3c\uc774 \ub098\uc624\uc9c0 \uc54a\uc558\uc744\uae4c? \\n\uc55e\uc73c\ub85c \uc120\ud0dd\uc758 \uc21c\uac04\uc5d0\uc11c \uc870\uae08 \ub354 \uc2dc\uac04\uc744 \ub4e4\uc5ec\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ubc30\uc6b4 \ubd80\ubd84\\n\\n**expose headers**\\n\\n\uc6f9 \ud398\uc774\uc9c0\uc5d0\uc11c Location \ud5e4\ub354\ub97c \ubc1b\uc744 \uc218 \uc5c6\ub294 \ubb38\uc81c\uac00 \uc788\uc5c8\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c [\ud5c8\uc6a9 \ubaa9\ub85d\uc5d0 \uc874\uc7ac\ud558\ub294 \uc751\ub2f5\ud5e4\ub354](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header)\ub9cc \ubc18\ud658\ud55c\ub2e4\ub294 \uac83\uc744 \ubaa8\ub974\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ub97c expose headers \uc124\uc815\uc744 \ud1b5\ud574 \ud574\uacb0\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nnginx \uc124\uc815\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \ucd94\uac00\ud574 \uc8fc\uc5c8\ub2e4. \\n\\n```bash\\nadd_header \'Access-Control-Expose-Headers\' \'Location\'\\n```\\n\\n**\uc77d\uae30 \uc804\uc6a9 \ud2b8\ub79c\uc7ad\uc158** \\n\\n\ub2e8\uc21c \uc870\ud68c \uc694\uccad\uc5d0 \ub300\ud55c \uc131\ub2a5\uc744 \ud5a5\uc0c1\uc2dc\ucf1c\uc900\ub2e4\ub294 \uac83\uc774\ub77c\uace0 \uac04\ub2e8\ud788\ub9cc \uc54c\uace0 \uc788\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0 \ucf54\uba58\ud2b8\uac00 \ub2ec\ub824\uc11c \uc870\uae08 \ub354 \uc790\uc138\ud788 \uacf5\ubd80\ud574 \ubcf4\uae30\ub85c \ud588\ub2e4. \\nTransactional(readOnly = true)\ub97c \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc774 \ub3d9\uc791\ud55c\ub2e4.\\n\\nsetReadOnly(true) \uc124\uc815\uc774 \ub41c Connection\uc73c\ub85c \uc5f0\uacb0\uc744 \uc2dc\ub3c4\ub97c \ud55c\ub2e4. \uc774 \uc124\uc815\uc744 \ud558\ub294 \uacbd\uc6b0 DB\ub9c8\ub2e4 \ub2e4\ub974\uac8c \ub3d9\uc791\ud55c\ub2e4.\\n- h2\uc758 Connection \uad6c\ud604\uccb4\ub294 readOnly \uc124\uc815\uc744 \ubb34\uc2dc\ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uad6c\ud604\ub418\uc5b4 Transactional \uc801\uc6a9\ub418\uc9c0 \uc54a\ub294\ub2e4. \\n- MySQL 8.0(InnoDB \uc0ac\uc6a9 \uc2dc)\uc758 \uacbd\uc6b0 \uc77d\uae30 \uc804\uc6a9\uc73c\ub85c \uc54c\ub824\uc9c4 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \ud2b8\ub79c\uc7ad\uc158 ID\ub97c \uc124\uc815\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uc870\ud68c \uc18d\ub3c4\uac00 \ub354 \ube68\ub77c\uc9c4\ub2e4.\\n\\nORM \ud504\ub808\uc784\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 prepareTransactionalConnection\ub97c \ud638\ucd9c\ud55c\ub2e4\uace0 \ud55c\ub2e4. \\n\ucd94\uac00\ub85c \ud604\uc5c5\uc5d0\uc11c\ub294 \uace0\uac00\uc6a9\uc131 \ub0b4\uacb0\ud568\uc131 \ub4f1\uc744 \uc704\ud558\uc5ec \ud074\ub7ec\uc2a4\ud130\ub97c \uad6c\uc131\ud558\uc5ec \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uace0, \uc774 \uacbd\uc6b0 readOnly \uc124\uc815\uc774 \ub418\uc5b4\uc788\ub2e4\uba74 \uc77d\uae30 \uc804\uc6a9 DB\ub85c \uc9c8\uc758\uac00 \ub4e4\uc5b4\uac00\uc11c \ubd80\ud558 \ubd84\uc0b0\uc758 \ud6a8\uacfc\uac00 \uc788\ub2e4\uace0 \ud55c\ub2e4. \\n\\n**DAO\uc5d0 `@Transactional` \uc801\uc6a9** \\n\\nDAO\uc5d0 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \ubcf4\ub294 \uac74 \uc5b4\ub5bb\uaca0\ub0d0\uace0 \ub9ac\ubdf0\uac00 \ub2ec\ub824\uc11c \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nService \uacc4\uce35\uc5d0 \uc774\ubbf8 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud574 \uc8fc\uace0 \uc788\uae30\uc5d0 \ud544\uc694 \uc5c6\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\nDAO\ub97c \ub2e4\ub978 \uacf3\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub354\ub77c\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574(\ud655\uc7a5\uc131 \uace0\ub824) `@Transactional`\uc744 \uc801\uc6a9\ud558\ub294 \uac83\ub3c4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4."},{"id":"tecochat-retrospective-3","metadata":{"permalink":"/tecochat-retrospective-3","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","source":"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx","title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","description":"\uac1c\uc694","date":"2023-06-01T00:00:00.000Z","formattedDate":"2023\ub144 6\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.005,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","slug":"tecochat-retrospective-3","tags":["TecoChat","Retrospective"]},"prevItem":{"title":"\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0","permalink":"/order-retrospective"},"nextItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"}},"content":"### \uac1c\uc694\\n\\n\uc6d0\ub798 \ubaa9\uc801\uc778 `\ud06c\ub8e8\ub4e4\uc758 \ud559\uc2b5\uc5d0 \ub3c4\uc6c0`\uc744 \uc8fc\uae30 \uc704\ud574 \uc5b4\ub5a4 \uae30\ub2a5\uc744 \ucd94\uac00\ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub808\ubca8 2\uac00 \uac70\uc758 \ub05d\ub098\uac00\ub294 \uc2dc\uc810, \uadf8\ub3d9\uc548 \ud588\ub358 \uac83\uc744 \uc815\ub9ac\ud574 \ubcf4\ub824\uace0 \ud55c\ub2e4. \\n\\n### \ub098\uc758 \ucc44\ud305 \ud655\uc778\ud558\uace0 \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\nGPT\uc5d0\ub3c4 \uc788\ub294 \uae30\ub2a5\uc778\ub370, \ub0b4\uac00 \uc774\uc804\uc5d0 \ud588\ub358 \ucc44\ud305\uc744 \uc774\uc5b4\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\uc608\uc804\uc5d0 \uc5b4\ub5a4 \uc9c8\ubb38\uc744 \ub0a8\uacbc\ub294\uc9c0, \ub610\ud55c \ud574\ub2f9 \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub2e4. \\n\\n![chat1](./chat1.png)\\n\\n### \uc88b\uc544\uc694\uc640 \ub313\uae00 \uae30\ub2a5\\n\\n\ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc5d0 \ubc18\uc751\ud560 \uc218 \uc788\ub294 \ubb34\uc5b8\uac00\uac00 \uc788\uc5c8\uc73c\uba74 \uc88b\uaca0\ub2e4\ub294 \uc758\uacac\ub4e4\uc774 \ub9ce\uc558\ub2e4. \\n\ub204\uac00 \uc88b\uc544\uc694\ub97c \ub20c\ub800\ub294\uc9c0, \uc5b4\ub5a4 \ucc44\ud305\uc774 \uc88b\uc544\uc694\ub97c \uac00\uc7a5 \ub9ce\uc774 \ubc1b\uc558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ub610\ud55c \ub313\uae00 \ucd94\uac00 \ubc0f \uc0ad\uc81c \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4.\\n\\n### \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\\n\\n\uc5b4\ub5bb\uac8c \ud0a4\uc6cc\ub4dc \ucd94\ucd9c\uc744 \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub294\ub370, \uc77c\ub2e8 GPT\ub97c \uc774\uc6a9\ud574\uc11c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\uae30\ub85c \ud588\ub2e4. \\n\ud574\ub2f9 \ubd80\ubd84\uc740 \uccab \uc9c8\ubb38\uc5d0 \ub300\ud55c \ud0a4\uc6cc\ub4dc\ub9cc \ucd94\ucd9c\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\ubc31\uc5d4\ub4dc\uc5d0\uc120 \ub9d0\ub791\uc774 \uc774\ubca4\ud2b8 \uc774\uc6a9\ud574\uc11c \uccab \ucc44\ud305 \uc694\uccad\uc774 \uc774\ub8e8\uc5b4\uc9c0\uba74, \ube44\ub3d9\uae30\ub85c \ud0a4\uc6cc\ub4dc\ub97c \ucd94\ucd9c\ud558\ub294 \uc9c8\ubb38\uc744 \ucd94\uac00\ub85c \ub0a0\ub9ac\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\nCSV \ud615\uc2dd\uc73c\ub85c GPT\uc5d0\uac8c \ub2f5\ubcc0\uc744 \uc785\ub825\ud574\ub2ec\ub77c\uace0 \uc694\uccad\ubc1b\ub294\ub370, \uc774 \ubd80\ubd84\uc774 \ubb38\uc81c(\ud504\ub86c\ud504\ud2b8 \uc5d4\uc9c0\ub2c8\uc5b4\ub9c1 \ubd80\ubd84\uc774 \ubc18\ud658\ub41c\ub2e4.)\uac00 \uc880 \uc788\ub294 \uac83 \uac19\uc544\uc11c \uac1c\uc120\uc774 \ud544\uc694\ud55c \uac83 \uac19\ub2e4. \\n\\n![chat2](./chat2.png)\\n\\n### \ub2e4\ub978 \ud06c\ub8e8\uc758 \ucc44\ud305 \ubcf5\uc0ac\ud574\uc11c \uc774\uc5b4\ud558\ub294 \uae30\ub2a5\\n\\n\ub2e4\ub978 \ud06c\ub8e8\ub4e4\uc758 \ucc44\ud305\uc744 \uc77d\ub2e4\uac00 \uad81\uae08\ud55c \uc810\uc774 \uc788\ub2e4\uba74 \ubcf5\uc0ac\ud574\uc11c \ubc14\ub85c \uc9c8\ubb38\uc744 \ud560 \uc218 \uc788\ub294 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\ub2e4. \\n\ucc44\ud305\uc774 \ubcf5\uc0ac\ub41c \ud6c4 \ubc14\ub85c GPT\uc640 \ub300\ud654\ub97c \ud560 \uc218 \uc788\ub294 \uba54\uc778 \ud654\uba74\uc73c\ub85c \uc774\ub3d9\ud55c\ub2e4. \\n\\n### \uc0ac\uc6a9\uc131 \uace0\ub824\ud558\uae30\\n\\n![chat3](./chat3.png)\\n\\n\uc704 \ud654\uba74\uc740 \ud68c\uc6d0\uac00\uc785 \ucc3d\uc774\ub2e4. \\n\uc0ac\uc2e4 \uac00\uc7a5 \ub9c8\uc74c\uc5d0 \ub4dc\ub294 \ubd80\ubd84\uc774\uace0, \ud68c\uc6d0\uac00\uc785(\ub2c9\ub124\uc784\ub9cc \uc785\ub825\ud558\uc9c0\ub9cc)\ud560 \ub54c \uc775\uba85\uc744 \uc6d0\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uace0\ubbfc\uc744 \ub3c4\uc640\uc8fc\uac8c \ub054 \uc74c\uc2dd, \uacfc\uc77c, \uacfc\uc790 \ub4f1\uc758 \uc694\uc18c\ub4e4\uc744 \uc785\ub825\ud558\ub3c4\ub85d \uc720\ub3c4\ud588\ub2e4!\\n\ucd94\uac00\ub85c GPT\uc758 \ub2f5\ubcc0\uc774 \uc624\uba74 \uc790\ub3d9\uc73c\ub85c \ud654\uba74\uc744 \uc2a4\ud06c\ub864 \ud574\uc8fc\ub294 \uac83\uacfc \uac19\uc774 \uc0ac\uc6a9\uc131\uc744 \uac1c\uc120\ud574 \ubcf4\ub824\uace0 \ub178\ub825\ud588\uc9c0\ub9cc \uc27d\uc9c0 \uc54a\uc558\ub2e4. \\n\uc81c\uc77c \ud558\uace0 \uc2f6\uc740 \uac83\uc740 \uc2e4\uc81c GPT\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\ucc98\ub7fc stream/text \uac12\uc744 \ucc98\ub9ac\ud558\uace0 \uc2f6\uc740\ub370 \uc774 \ubd80\ubd84\uc740 \ubc29\ud559 \ub54c \uae30\ud68c\uac00 \ub418\uba74 \ub3c4\uc804\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\\n### \ud5a5\ud6c4 \uacc4\ud68d\\n\\n\uc2e4\uc81c \ud06c\ub8e8\ub4e4\uc774 \uc0ac\uc6a9\ud574 \uc8fc\ub294 \uc11c\ube44\uc2a4\ub97c \uc9c1\uc811 \ub9cc\ub4e4\uc5b4\ubcf4\uba74\uc11c \uc0ac\uc6a9\uc790\uc758 \uc785\uc7a5\uc5d0\uc11c \uace0\ubbfc\ub3c4 \ud558\uac8c \ub418\ub294 \uac83 \uac19\ub2e4. \\n\ud06c\ub8e8\ub4e4\uc774 \uc9c1\uc811 \uc0ac\uc6a9\ud574 \uc8fc\ub2c8\uae4c \ub108\ubb34 \uace0\ub9d9\uace0, \ud55c\ud3b8\uc73c\ub85c\ub294 \uc2e0\uae30\ud558\ub2e4. \\n\uc77c\ub2e8 \ubc29\ud559 \ub54c stream/text \uad00\ub828\ub41c \ubd80\ubd84 \ub3d9\uc791\ub418\ub3c4\ub85d \uad6c\ud604\ud574\ubcf4\ub824\uace0 \ud558\uace0, \uadf8 \uc678\uc758 \ubd80\ubd84\uc740 \uc870\uae08 \ub354 \uace0\ubbfc\ud574\uc57c\ub420 \uac83 \uac19\ub2e4."},{"id":"composite","metadata":{"permalink":"/composite","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","source":"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx","title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","description":"\uc694\uad6c\uc0ac\ud56d","date":"2023-05-26T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 26\uc77c","tags":[{"label":"Pattern","permalink":"/tags/pattern"},{"label":"Composite","permalink":"/tags/composite"}],"readingTime":4.74,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","slug":"composite","tags":["Pattern","Composite"]},"prevItem":{"title":"[\ud14c\ucf54\ucc57] 3. \uae30\ub2a5 \uad6c\ud604","permalink":"/tecochat-retrospective-3"},"nextItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"}},"content":"### \uc694\uad6c\uc0ac\ud56d\\n\\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.\\n\\n- \uac70\ub9ac\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \ub178\uc120\ubcc4 \ucd94\uac00 \uc694\uae08 \uc815\ucc45\\n- \uc5f0\ub839\ubcc4 \uc694\uae08 \ud560\uc778 \uc815\ucc45\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc0ac\uc6a9\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc778\ud130\ud398\uc774\uc2a4\ub85c \ud45c\ud604\ud560 \uc218 \uc788\ub2e4. \\n\uc694\uae08\uc744 \uacc4\uc0b0\ud558\ub294 \uba54\uc11c\ub4dc\ub294 \ucd5c\ub2e8 \uacbd\ub85c \uacc4\uc0b0\uc758 \uacb0\uacfc, \uc0ac\uc6a9\uc790\uc758 \uc815\ubcf4, \uc694\uae08\uc744 \ubc1b\uc544 \uc694\uae08\uc744 \uacc4\uc0b0\ud55c\ub2e4.\\n\\n```java\\npublic interface FarePolicy {\\n int calculate(Path path, Passenger passenger, int fare);\\n}\\n\\npublic class BaseFarePolicy implements FarePolicy { ... }\\npublic class DistanceFarePolicy implements FarePolicy { ... }\\npublic class AgeDiscountFarePolicy implements FarePolicy { ... }\\n```\\n\\n![composite1](./composite1.png)\\n\\n### \ubaa8\ub4e0 \uc694\uae08 \uc815\ucc45\uc744 \ud3ec\ud568\ud558\ub294 \uc0c8\ub85c\uc6b4 \uc694\uae08 \uc815\ucc45 \ub9cc\ub4e4\uae30\\n\\n\ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub97c \ubaa8\ub450 \uac00\uc9c0\uace0 \uc788\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\ub97c \ub9cc\ub4e4\uc5c8\ub2e4. \\n\uc774 \ub610\ud55c FarePolicy\ub97c \uad6c\ud604\ud55c \ud615\ud0dc\uac00 \ub418\uace0, \ud544\ub4dc\ub85c\ub294 \ub098\uba38\uc9c0 \uad6c\ud604\uccb4\ub4e4\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n```java\\npublic class SubwayFarePolicy implements FarePolicy {\\n\\n private final List farePolicies;\\n\\n public SubwayFarePolicy(final List farePolicies) {\\n this.farePolicies = farePolicies;\\n }\\n\\n @Override\\n public int calculate(final Path path, final Passenger passenger, final int fare) {\\n int calculatedFare = fare;\\n for (FarePolicy farePolicy : farePolicies) {\\n calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);\\n }\\n return calculatedFare;\\n }\\n}\\n```\\n\\n\ub530\ub77c\uc11c \uadf8\ub9bc\uc73c\ub85c \ubcf8\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\uac00 \ub41c\ub2e4.\\n\\n![composite2](./composite2.png)\\n\\n### \uc815\ucc45\uc758 \uc21c\uc11c\\n\\n\uc9c0\ud558\ucca0 \uc694\uad6c\uc0ac\ud56d\uc740 \uc21c\uc11c\uac00 \uc911\uc694\ud588\ub2e4. \\n\uae08\uc561\uc758 \ucd1d\ud569\uc744 \uad6c\ud558\uace0, \uadf8 \ud6c4\uc5d0 \ud560\uc778 \uc815\ucc45\uc774 \ub4e4\uc5b4\uac00\uc57c\ud588\ub2e4. \\n\ub530\ub77c\uc11c \uc790\uc2dd\ub4e4\uc758 \uc21c\uc11c\ub97c \uad00\ub9ac\ud560 \ub54c \uc8fc\uc758\ub97c \uae30\uc6b8\uc5ec\uc57c \ud588\ub2e4. \\nConfiguration \ud074\ub798\uc2a4\uc5d0 \ub2e4\uc74c\uacfc \uac19\uc774 \uc21c\uc11c\ub97c \uc9c1\uc811 \uc801\uc6a9\uc2dc\ucf30\ub2e4. \\n\\n```java\\n@Configuration\\npublic class FareConfiguration {\\n\\n @Bean\\n public FarePolicy farePolicy() {\\n return new SubwayFarePolicy(List.of(\\n new BaseFarePolicy(),\\n new DistanceFarePolicy(),\\n new AgeDiscountFarePolicy()\\n ));\\n }\\n}\\n```\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc774\ub780?\\n\\n![composite3](./composite3.png)\\n\\nGOF\uc758 \ub514\uc790\uc778 \ud328\ud134 \ucc45\uc5d0\uc11c\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n> \ubd80\ubd84\uacfc \uc804\uccb4\uc758 \uacc4\uce35\uc744 \ud45c\ud604\ud558\uae30 \uc704\ud574 \uac1d\uccb4\ub4e4\uc744 \ubaa8\uc544 \ud2b8\ub9ac \uad6c\uc870\ub85c \uad6c\uc131\ud569\ub2c8\ub2e4. \\n\uc0ac\uc6a9\uc790\ub85c \ud558\uc5ec\uae08 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ubcf5\ud569 \uac1d\uccb4\ub97c \ubaa8\ub450 \ub3d9\uc77c\ud558\uac8c \ub2e4\ub8f0 \uc218 \uc788\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc785\ub2c8\ub2e4.\\n> \\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774 \ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uad6c\uc131\uc694\uc18c\\n\\nComponent\\n\\n- \uc9d1\ud569 \uad00\uacc4\uc5d0 \uc815\uc758\ub420 \ubaa8\ub4e0 \uac1d\uccb4\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4 \\n- ex) \uc694\uae08 \uc815\ucc45(FarePolicy) \\n\\nLeaf\\n\\n- \uac1c\ubcc4 \uac1d\uccb4, \uac1d\uccb4 \ud569\uc131\uc5d0 \uae30\ubcf8\uc774 \ub418\ub294 \uac1d\uccb4\uc758 \ud589\ub3d9 \\n- ex) \uac70\ub9ac \ubcc4 \uc694\uae08 \uc815\ucc45(DistanceFarePolicy) \\n\\nComposite\\n\\n- \uc5ec\ub7ec \uac1c\uc758 \uac1c\ubc1c \uac1d\uccb4\ub97c \ud3ec\ud568\ud558\ub294 \ud569\uc131 \uac1d\uccb4 \\n- ex) \uc9c0\ud558\ucca0 \uc694\uae08 \uc815\ucc45(SubwayFarePolicy) \\n\\nClient\\n\\n- \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\\n\\n### \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc758 \uc0ac\uc6a9\uacfc \uc8fc\uc694 \ubaa9\ud45c\\n\\n\ubd80\ubd84 - \uc804\uccb4\uc758 \uad00\uacc4\ub97c \ud45c\ud604\ud558\uace0 \uc2f6\uc744 \ub54c \\nClient \uae30\uc900\uc73c\ub85c Composite\uc640 Leaf\uc758 \ucc28\uc774\ub97c \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc798 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \ud574\uc57c\ub420 \ub54c\\n\\n### \ud328\ud134 \uc0ac\uc6a9\uc2dc \uc8fc\uc758\ud574\uc57c\ud560 \ubd80\ubd84\\n\\n\ud328\ud134\uc740 \uacf5\ud1b5\uc73c\ub85c \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc758 \ud15c\ud50c\ub9bf\uc774\ub2e4. \\n\ubc18\ubcf5\ub418\ub294 \ubb38\uc81c\ub97c \ud6a8\uc728\uc801\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc788\uc9c0\ub9cc \ud328\ud134\uc5d0 \ub9e4\ubab0\ub418\uc11c\ub294 \uc548\ub41c\ub2e4. \\n\ud328\ud134\uc744 \ub9f9\ubaa9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548\ub418\uace0, \ud604\uc7ac\uc758 \uc694\uad6c\uc0ac\ud56d\uc5d0 \ub530\ub77c \ud328\ud134\uc744 \uc720\ub3d9\uc801\uc73c\ub85c \uc218\uc815\ud574\uac00\uba74\uc11c \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ud56d\uc0c1 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\ub97c \uc0dd\uac01\ud558\uc790!\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134, GoF\uc758 \ub514\uc790\uc778 \ud328\ud134 \\n\ub514\uc790\uc778 \ud328\ud134\uacfc \ud504\ub808\uc784\uc6cc\ud06c, \uc624\ube0c\uc81d\ud2b8"},{"id":"subway-retrospective","metadata":{"permalink":"/subway-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","description":"\uc9c0\ud558\ucca0 \ubbf8\uc158","date":"2023-05-25T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 25\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.91,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","slug":"subway-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30","permalink":"/composite"},"nextItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"}},"content":"### \uc9c0\ud558\ucca0 \ubbf8\uc158\\n\\n\uc810\uc810 \uc77c\uc815\uc774 \ub9ce\uc544\uc9c0\ub294 \ub290\ub08c\uc774 \ub4e4\uba74\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc9c4\ub2e4. \\n\uc9c0\ud558\ucca0 \ubbf8\uc158\uc740 \ubc00\ub9ac\ub791 \ud398\uc5b4\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uac04\ub2e8\ud55c CRUD\ub9cc \uc788\ub358 \uc774\uc804 \ubbf8\uc158\ub4e4\uacfc \ub2ec\ub9ac, \uc870\uae08 \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778 \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc774\ub54c API, \ud14c\uc774\ube14, \ub3c4\uba54\uc778 \uc124\uacc4\ub97c \ud574\uc57c \ud588\ub294\ub370 \uc5b4\ub5a4 \uac83\ubd80\ud130 \ud574\uc57c \ud560\uc9c0 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\nAPI\uc640 \ud14c\uc774\ube14 \uad6c\uc870\ub97c \uc6b0\ub9ac\uac00 \uc815\ud560 \uc218 \uc788\ub294 \uc0c1\ud669\uc774\uc5c8\uace0, \ub3c4\uba54\uc778 \ub85c\uc9c1\uc774 \ubcf5\uc7a1\ud588\uae30 \ub54c\ubb38\uc5d0 \ub3c4\uba54\uc778\uc744 \uba3c\uc800 \uad6c\ud604\ud588\ub2e4.\\n\\n**\ub178\uc120\uc758 \uad6c\uac04 \ucd94\uac00 \ubc0f \uc0ad\uc81c**\\n\\n\ub178\uc120\uc744 \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc5d0 \ub300\ud574\uc11c \ubc00\ub9ac\uc640 \uc774\uc57c\uae30\ub97c \ub098\ub234\ub2e4.\\n\\n1. \uad6c\uac04\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uc804\ubd80 \uc81c\uac70\ud558\uace0 \uc804\ubd80 \ucd94\uac00\ud558\ub294 \ubc29\ubc95\\n2. \ubcc0\uacbd\ub41c \uc694\uc18c\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ubc18\uc601\ud558\ub294 \ubc29\ubc95\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc774 \uc9e7\uc544\uc11c \ub354\uc6b1 \uac04\ub2e8\ud55c 1\ubc88\uc744 \uc120\ud0dd\ud588\uace0, \uc2dc\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\uc2dc\ud0a4\uae30 \uc704\ud574 \ub354 \uac04\ub2e8\ud558\uac8c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud558\ub294 \uac83\ub3c4 \uc88b\uc740 \ud2b8\ub808\uc774\ub4dc\uc624\ud504\uc600\ub358 \uac83 \uac19\ub2e4. \\n\ucd94\ud6c4 \ud398\uc5b4\uac00 \ub05d\ub098\uace0 \ub9ac\ubdf0\uc5b4\uc778 \uc11c\ube0c\uc6e8\uc774\uac00 \uc77c\ubd80\ubd84\ub9cc \ubc18\uc601\ud558\ub294 \uac83\uc73c\ub85c \uac1c\uc120\ud574 \ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4\uace0 \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ucd94\uac00 \ubc0f \uc81c\uac70\ub41c \uc694\uc18c\ub9cc \ubc18\uc601\ud558\ub3c4\ub85d \ubcc0\uacbd\ud588\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ubbf8\uc158\uc758 \ub09c\uc774\ub3c4\uac00 \uc62c\ub77c\uac04 \ub9cc\ud07c, \ud398\uc5b4 \ud560 \ub550 \ucee8\ub514\uc158 \uad00\ub9ac\ub3c4 \uc798\ud558\ub824\uace0 \ub178\ub825\ud558\uace0 \ubbf8\uc158 \ud560 \ub54c\ub3c4 \uc9d1\uc911\ud574\uc11c \uc798 \ub05d\ub0b8 \uac83 \uac19\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uc54c\uc544\uc57c \ud558\ub294 \uac8c \ub9ce\uc544\uc9c0\uba74\uc11c \uac00\ub054 \uc870\ubc14\uc2ec\uc744 \uac00\uc9c8 \ub54c\uac00 \uc788\ub294 \uac83 \uac19\uc740\ub370, \uc870\ubc14\uc2ec\uc744 \uacbd\uacc4\ud560 \ud544\uc694\uac00 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ubd80\uc871\ud55c \ubd80\ubd84\uc740 \uc778\uc815\ud558\uace0, \uc55e\uc73c\ub85c \ub098\uc544\uac00\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654**\\n\\n\uc694\uae08 \uc815\ucc45\uc740 \uae30\ubcf8\uc694\uae08 \uc815\ucc45, \uac70\ub9ac\ubcc4 \uc694\uae08 \uc815\ucc45, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uae08\uc744 \ub354\ud558\ub294 \ubd80\ubd84\uacfc, \ud560\uc778\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5b4\uc11c \uc774 \ub458\uc744 \ubd84\ub9ac\ud560\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc, \uc774 \uc815\ub3c4 \ud06c\uae30\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c\ub294 \uc624\ud788\ub824 \ubd84\ub9ac\ud558\uc9c0 \uc54a\uace0 \ud558\ub098\ub85c \ud569\uce58\ub294 \uac8c \ub354 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ub610\ud55c \ubd84\ub9ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \uc815\ucc45\uc758 \uc21c\uc11c\uac00 \uc911\uc694\ud55c\ub370, \uc5f0\ub839\ubcc4 \ud560\uc778 \uc815\ucc45\uc744 \ub9c8\uc9c0\ub9c9\uc5d0 \ub450\uc5b4\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ucc45\uc784 \uc5f0\uc1c4 \ud328\ud134\ub3c4 \uace0\ub824\ub97c \ud588\uc9c0\ub9cc \uc870\uae08 \ub354 \uac04\uacb0\ud574 \ubcf4\uc774\ub294 \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc744 \uc120\ud0dd\ud588\ub2e4.\\n\\n**\ub3c4\uba54\uc778\uc5d0 \ud2b9\uc815 \uae30\uc220\uc758 \uc758\uc874\uc131\uc744 \ubd84\ub9ac**\\n\\n\ucc98\uc74c\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uc5d0 jgrapht \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc758\uc874\ud558\uace0 \uc788\ub294 \ud074\ub798\uc2a4\ub97c \ub450\uc5b4\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0\uac00 jgrapht\uc640 \uac15\uacb0\ud569\uc774 \ub418\uc5b4\ubc84\ub838\ub2e4. \\n\ub530\ub77c\uc11c \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\uc5d0\ub294 \uacbd\ub85c \uac80\uc0c9\uc5d0 \ub300\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0, \uc138\ubd80 \uad6c\ud604\uc740 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \uc678\ubd80\ub85c \ubd84\ub9ac\ud588\ub2e4. \\n\ucd5c\ub300\ud55c \uac04\uacb0\ud558\uac8c \uad6c\ud604\ud55c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud574\ub3c4, \uc774\ub7f0 \ubd80\ubd84\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uc5b4 \uacb0\ud569\uc744 \ud53c\ud558\ub294 \uac83\uc774 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n:::note \ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\\n\\n\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc740 \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud55c \uac1c\ubcc4 \uac1d\uccb4\uac00 \uc874\uc7ac\ud558\uace0, \uadf8 \uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\ub294 \ud558\ub098\uc758 \uad6c\ud604\uccb4\uac00 \ub530\ub85c \uc874\uc7ac\ud558\ub294 \ud328\ud134\uc774\ub2e4. \\n\uc774\ub54c \uc0ac\uc6a9\uc790\ub294 \uac1c\ubcc4 \uac1d\uccb4\uc640 \ud569\uc131 \uac1d\uccb4(\uac1c\ubcc4 \uac1d\uccb4\ub4e4\uc744 \ud3ec\ud568\ud558\uace0 \uc788\ub294)\ub97c \ub611\uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n:::\\n\\n**\uc778\uc218 \ud14c\uc2a4\ud2b8 \uc791\uc131**\\n\\n\uc778\uc218 \ud14c\uc2a4\ud2b8\ub294 \uc0ac\uc6a9\uc790 \uc2a4\ud1a0\ub9ac \uc2dc\ub098\ub9ac\uc624 \uae30\ubc18 \ud14c\uc2a4\ud2b8\ub2e4. \\n\ube0c\ub77c\uc6b4\uc774 \ud574\uc8fc\uc2e0 \uac15\uc758 + \uc720\ud29c\ube0c\uc5d0 \uc788\ub294 \ube0c\ub77c\uc6b4\uc758 \uac15\uc758\ub97c \ubcf4\uace0 \uc9c0\ud558\ucca0 \ubbf8\uc158\uc5d0 \uc778\uc218 \ud14c\uc2a4\ud2b8\ub97c \uc801\uc6a9\ud574 \ubcf4\uc558\ub2e4. \\n\uba54\uc11c\ub4dc, \ubcc0\uc218\uba85\uc744 \uc804\ubd80 \ud55c\uae00\ub85c \uc791\uc131\ud588\ub294\ub370 \uc804\uccb4\uc801\uc778 \ud750\ub984\uc744 \uc54c\uae30 \ud3b8\ud558\uace0 \uc77d\uae30\ub3c4 \uc88b\uc558\ub2e4. \\n\uadf8\ub9ac\uace0 \uc778\uc218 \ud14c\uc2a4\ud2b8\uc5d0 \ud544\uc694\ud55c Steps\ub97c \ub9cc\ub4dc\ub294 \uacfc\uc815\uc774 \ub108\ubb34 \uc7ac\ubc0c\uc5c8\ub2e4.\\n\\n\uacb0\uacfc\ub294 \uc544\ub798\uc640 \uac19\ub2e4.\\n\\n```java\\n@Nested\\npublic class \ub178\uc120\uc744_\uc804\uccb4_\uc870\ud68c\ud560_\ub54c {\\n\\n @Test\\n void \uc0c1\ud589\uc885\uc810\uc5ed_\ubd80\ud130_\ud558\ud589\uc885\uc810\uc5ed\uc73c\ub85c_\uc815\ub82c\ub41c_\uacb0\uacfc\ub97c_\ubc18\ud658\ud55c\ub2e4() {\\n // given\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", 5);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"2\ud638\uc120\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \uc624\ub978\ucabd, 5);\\n\\n \ub178\uc120_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0);\\n \ub178\uc120\uc5d0_\uad6c\uac04\uc774_\uc874\uc7ac\ud558\uc9c0_\uc54a\uc744_\ub54c_\ucd08\uae30_\uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", 3);\\n \uad6c\uac04_\uc0dd\uc131_\uc694\uccad(\\"9\ud638\uc120\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\", \uc624\ub978\ucabd, 7);\\n\\n // when\\n final var \uc870\ud68c_\uacb0\uacfc = \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uc694\uccad();\\n\\n // then\\n \uc694\uccad_\uacb0\uacfc\uc758_\uc0c1\ud0dc\ub97c_\uac80\uc99d\ud55c\ub2e4(\uc870\ud68c_\uacb0\uacfc, \uc815\uc0c1_\uc694\uccad);\\n \ub178\uc120_\uc804\uccb4_\uc870\ud68c_\uacb0\uacfc\ub97c_\ud655\uc778\ud55c\ub2e4(\\n \uc870\ud68c_\uacb0\uacfc,\\n \ub178\uc120_\uc815\ubcf4(\\"2\ud638\uc120\\", \\"\ucd08\ub85d\\", 0, \\"\uc7a0\uc2e4\\", \\"\uc7a0\uc2e4\uc0c8\ub0b4\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\"),\\n \ub178\uc120_\uc815\ubcf4(\\"9\ud638\uc120\\", \\"\uace0\ub3d9\\", 0, \\"\ubd09\uc740\uc0ac\\", \\"\uc885\ud569\uc6b4\ub3d9\uc7a5\\", \\"\uc0bc\uc804\\")\\n );\\n }\\n}\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc758\uacac \uc870\uc728\ud558\uae30**\\n\\n\ubc00\ub9ac\uac00 \ud544\uc694\ud55c \ubd80\ubd84\uc5d0\uc11c \uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \uc9c4\ud589\uc774 \uc218\uc6d4\ud588\ub2e4. \\n\uc758\uc0ac\uc18c\ud1b5\uc774 \ub9e4\uc6b0 \uc798 \ub3fc\uc11c \uc88b\uc558\uace0 \ub355\ubd84\uc5d0 \uc2dc\uac04 \ub0b4\uc5d0 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574 \ubbf8\uc158\uc744 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\ud558\uae30**\\n\\n\ubc00\ub9ac\ub294 \ucf54\ub529\uc744 \uc5c4\uccad \uaf3c\uaf3c\ud558\uac8c \ud558\ub294 \uac83 \uac19\ub2e4. \\n\ubcc0\uc218\uba85, \uba54\uc11c\ub4dc\uba85\uc744 \uc911\uc694\ud558\uac8c \uc0dd\uac01\ud588\uace0, \uc88b\uc740 \ubcc0\uc218\uba85\uc744 \uc798 \uc9d3\ub294 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ucf54\ub529\ud560 \ub54c \ub0b4\uac00 \ud3c9\uc18c\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub529 \ucee8\ubca4\uc158\uc5d0 \ub9de\ucdb0\uc8fc\ub294 \uac83 \uac19\uc544\uc11c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud588\ub2e4! \\n\\n**\ud3b8\ud55c \ubd84\uc704\uae30**\\n\\n\uc804\uccb4\uc801\uc73c\ub85c \ud398\uc5b4 \ud560 \ub54c \ud3b8\ud558\uac8c \uc9c4\ud589\ud588\ub358 \uac83 \uac19\ub2e4. \\n\uc77c\uc815\ub3c4 \uadf8\ub807\uace0, \ud398\uc5b4 \uc9c4\ud589\ud560 \ub54c\ub3c4 \uadf8\ub807\uace0 \ud070 \ubb38\uc81c\uac00 \uc5c6\uc5c8\ub358 \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub098\ub294 \uacfc\uc5f0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc5d0\uac8c \ud3b8\ud55c \uc0ac\ub78c\uc77c\uae4c?"},{"id":"accidental-duplication","metadata":{"permalink":"/accidental-duplication","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","source":"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx","title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","description":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4.","date":"2023-05-24T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 24\uc77c","tags":[{"label":"DTO","permalink":"/tags/dto"}],"readingTime":7.525,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","slug":"accidental-duplication","tags":["DTO"]},"prevItem":{"title":"\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0","permalink":"/subway-retrospective"},"nextItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"}},"content":"\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\uc694\uccad\uc5d0 \ub2f4\uae34 Body\ub97c \ud1b5\ud574 \uc804\ub2ec\ubc1b\uc740 \uac12\uc744 DTO\ub85c \ub9e4\ud551\ud558\uc5ec \ucd94\uac00\uc640 \uc218\uc815\uc744 \ud588\ub2e4.\\n\\n### \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\uc758 \uc0c1\ud488 \ucd94\uac00 \ubc0f \uc218\uc815\\n\\n![\uc911\ubcf51](./\uc911\ubcf51.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d\ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0\uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\uc704 \uacbd\uc6b0\ub294 \uc911\ubcf5\uc77c\uae4c? \uc911\ubcf5\uc774 \uc544\ub2d0\uae4c?\\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub2e4\uc74c\uacfc \uac19\uc740 \ub9ac\ubdf0\ub97c \ubc1b\uc558\ub2e4.\\n\\n> `ProductSaveRequest`\uc640 `ProductUpdateRequest`\uac00 \uc644\uc804\ud788 \ub3d9\uc77c\ud55c\ub370, \uc7ac\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc744\uae4c? \ub77c\ub294 \ub9ac\ubdf0\ub97c \ub0a8\uacbc\uc5c8\uc5b4\uc694. \uc0ac\uc2e4 \uc0dd\uc131\uacfc \uc218\uc815\uc740 \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac1c\uc5f0\uc131\uc774 \ub192\uc544\uc11c \ubbf8\ub9ac \ubd84\ub9ac\ud574\ub193\ub294 \uac8c \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\uae34 \ud55c\ub370, \uadf8\ub798\ub3c4 \uc911\ubcf5\uc740 \uc2eb\uc5b4\uc11c \uc800\ub3c4 \uc694\uc998 \uc774\ub7f0\uc800\ub7f0 \ubc29\ubc95\ub4e4\uc744 \uc2dc\ub3c4\ud574\ubcf4\ub294 \uc911 \uc785\ub2c8\ub2e4. \ud5c8\ube0c\ub294 \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc5b4\ub5a4 \uc0dd\uac01\uc744 \uac00\uc9c0\uace0 \uc788\uc744\uc9c0 \uad81\uae08\ud558\ub124\uc694 \u314e\u314e\\n> \\n\\n\uc9c8\ubb38\uc5d0 \ub300\ud574 \uc544\ub798\uc640 \uac19\uc774 \ub2f5\ubcc0\uc744 \ud588\ub2e4.\\n\\n> \uc800\uc7a5\uacfc \uc218\uc815\ud560 \ub54c \ud544\uc694\ud55c \ud544\ub4dc\uac12\uc774 \ub3d9\uc77c\ud558\uc5ec \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c\ub294 \ud558\ub098\ub85c \uc0ac\uc6a9\ud574\ub3c4 \ub41c\ub2e4\uace0 \uc0dd\uac01\uc744 \ud558\uc9c0\ub9cc, \ub9d0\uc500\ud574\uc8fc\uc2e0\ub300\ub85c \uc694\uad6c\uc0ac\ud56d\uc774 \ubcc0\uacbd\ub41c\ub2e4\uba74 \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\ub2e4\uace0 \ud310\ub2e8\ud558\uc600\uc2b5\ub2c8\ub2e4!\\n> \\n\\n### \uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5\\n\\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec\uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4.\\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uac70\uc9d3\ub41c \uc911\ubcf5, \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131\uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4.\\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc704 \uc0c1\ud669\uc740 \uc6b0\ubc1c\uc801 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc778\ub2e4. \uadf8\ub798\ub3c4 \uc911\ubcf5\uc744 \uc81c\uac70\ud574\ubcfc \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n### \ud558\ub098\ub85c \uc0ac\uc6a9\ud558\ub294 \uac74 \uc548\uc88b\uc544\ubcf4\uc774\uace0, \uc911\ubcf5\uc740 \uc81c\uac70\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\\n\\n\uc9c0\uae08\uc740 \ucd94\uac00, \uc218\uc815 2\uac00\uc9c0 \uacbd\uc6b0 \ubc16\uc5d0 \uc5c6\uc9c0\ub9cc \uc870\uae08 \ub354 \ubcf5\uc7a1\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc8fc\uc5b4\uc838\uc11c 10\uac00\uc9c0 \uacbd\uc6b0\ub85c \uc785\ub825\uc744 \ubc1b\uc73c\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c\ud560\uae4c? \\n\uc11c\ube44\uc2a4 \uacc4\uce35\uc5d0\uc11c\ub3c4 \uacc4\uce35\uc758 \ubd84\ub9ac\ub97c \uc704\ud574\uc11c \ub2e4\ub978 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uba74 20\uac1c\uc758 DTO\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud560\uae4c? \\n\ub9ac\ubdf0\uc5b4\uac00 \uc54c\ub824\uc900 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud55c \ubc29\ubc95\uc744 \ud1b5\ud574 \uc774\ub97c \ud574\uacb0\ud574\ubcf4\uc790! \\n\\n### \uc911\ubcf5 \uc81c\uac70 \uc804 \ucf54\ub4dc\\n\\n\ud604\uc7ac \ucf54\ub4dc\uc5d0\uc11c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\ub2e4. \\nController\uc640 Service\uc5d0\uc11c \uc800\uc7a5, \uc218\uc815\ud560 \ub54c \uac01\uac01\uc758 DTO\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4.\\n\ud604\uc7ac DTO\ub294 controller, service \ud328\ud0a4\uc9c0 \ub0b4\uc5d0 \uc788\ub294 \uac83\uc774 \uc544\ub2c8\ub77c dto\ub77c\ub294 \ud328\ud0a4\uc9c0\uc5d0 \uc704\uce58\ud558\uace0 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductService\\n\u251c\u2500\u2500 dto\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n![\uc911\ubcf52](./\uc911\ubcf52.png)\\n\\n### \uc778\ud130\ud398\uc774\uc2a4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf53](./\uc911\ubcf53.png)\\n\\n\uc11c\ube44\uc2a4 \ub808\uc774\uc5b4\uc5d0\uc11c \ud544\uc694\ub85c \ud558\ub294 \uac12\ub4e4\uc744 \uc778\ud130\ud398\uc774\uc2a4\ub85c \uc815\uc758\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\ub294 \uc11c\ube44\uc2a4\uc5d0\uc11c \uc0ac\uc6a9\ud558\uae30 \ub54c\ubb38\uc5d0 service \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub85c \uc62e\uaca8\uc900\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductController\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic interface ProductSaveRequest {\\n\\n String getName();\\n\\n String getImage();\\n\\n Long getPrice();\\n}\\n\\n// ProductService\\npublic Long save(final ProductSaveRequest request) {\\n final Product product = new Product(request.getName(), request.getImage(), request.getPrice());\\n return productDao.saveAndGetId(product);\\n}\\n```\\n\\n### \uad6c\ud604\uccb4 \uc791\uc131\ud558\uae30\\n\\n![\uc911\ubcf54](./\uc911\ubcf54.png)\\n\\n\uc704\uc5d0\uc11c \uc791\uc131\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc791\uc131\ud55c\ub2e4. \\n\uc694\uccad\uc740 ProductRequest \ud074\ub798\uc2a4\ub85c \ubc1b\uace0, \uc11c\ube44\uc2a4\uc5d0 \uc804\ub2ec\ud560 \ub550 \ud574\ub2f9 \uc778\ud130\ud398\uc774\uc2a4\uc758 \uba85\uc138\ub9cc \ub9de\ucd94\uba74 \ubb38\uc81c\uc5c6\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n\u251c\u2500\u2500 controller\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductController\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductRequest\\n\u251c\u2500\u2500 service\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductService\\n\u2502\xa0\xa0 \u251c\u2500\u2500 ProductSaveRequest\\n\u2502\xa0\xa0 \u2514\u2500\u2500 ProductUpdateRequest\\n```\\n\\n```java\\npublic class ProductRequest implements ProductSaveRequest, ProductUpdateRequest {\\n\\n @NotBlank(message = \\"\uc774\ub984\uc740 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n @Size(min = 1, max = 100, message = \\"\uc774\ub984\uc740 \ucd5c\uc18c {min}\uc790 \uc774\uc0c1, {max}\uc790 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final String name;\\n\\n @NotBlank(message = \\"\uc774\ubbf8\uc9c0\ub294 \uacf5\ubc31\uc77c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\")\\n private final String image;\\n\\n @Range(message = \\"\uac00\uaca9\uc740 \ucd5c\uc18c {min}\uc6d0 \uc774\uc0c1, {max}\uc6d0 \uc774\ud558\uc5ec\uc57c \ud569\ub2c8\ub2e4.\\")\\n private final long price;\\n\\n public ProductRequest(final String name, final String image, final long price) {\\n this.name = name;\\n this.image = image;\\n this.price = price;\\n }\\n\\n @Override\\n public String getName() {\\n return name;\\n }\\n\\n @Override\\n public String getImage() {\\n return image;\\n }\\n\\n @Override\\n public long getPrice() {\\n return price;\\n }\\n}\\n\\n// ProductController\\n@PostMapping(\\"/products\\")\\npublic ResponseEntity save(@Valid @RequestBody final ProductRequest request) {\\n final Long id = productService.save(request);\\n return ResponseEntity.created(URI.create(\\"/products/\\" + id)).build();\\n}\\n```\\n\\n### \uc815\ub9ac\\n\\n\uc704\uc640 \uac19\uc774 \uad6c\ud604\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\\n1. Service\uc5d0\uc11c \ubaa8\ub4e0 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc5d0 \ub300\ud55c DTO\ub97c \uc54c\uc9c0 \uc54a\uc544\ub3c4 \ub41c\ub2e4.\\n2. \uacf5\ud1b5\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\ub294 DTO\ub97c \uc81c\uc678\ud558\uace0 DTO \ud328\ud0a4\uc9c0\uc5d0 \ub300\ud55c \uacb0\ud569\ub3c4\uac00 \ub0ae\uc544\uc9c0\uace0, \uac01 \ub808\uc774\uc5b4\uc758 \uc751\uc9d1\ub3c4\uac00 \uc99d\uac00\ud55c\ub2e4.\\n3. \uc694\uccad \uac1d\uccb4\ub9cc \ub2e4\ub974\uace0 \uc11c\ube44\uc2a4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ud589\uc704\ub97c \uc218\ud589\ud558\ub294 \uacbd\uc6b0 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc704 \ubc29\ubc95\uc744 \uc9c0\uae08 \ubbf8\uc158\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560\uae4c \ud558\ub2e4\uac00, \ub098\uc911\uc5d0 \ud544\uc694\ud560 \ub54c \uc801\uc6a9\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\uc544\uc11c \ubbf8\uc158\uc5d0\ub294 \uc801\uc6a9\ud558\uc9c0 \uc54a\uc558\ub2e4. \\n\uc0c1\ud669\uc5d0 \ub9de\ucdb0 \uc801\uc7ac\uc801\uc18c\uc5d0 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud574\ubcf4\ub294 \uac83\ub3c4 \uc88b\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98 16\uc7a5 \ub3c5\ub9bd\uc131, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n[https://techblog.woowahan.com/2647/](https://techblog.woowahan.com/2647/) \\n[https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/](https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/)"},{"id":"shopping-cart-retrospective","metadata":{"permalink":"/shopping-cart-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","description":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158","date":"2023-05-12T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 12\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.78,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","slug":"shopping-cart-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5","permalink":"/accidental-duplication"},"nextItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"}},"content":"### \uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc740 \ube14\ub799\ucea3\uc774\ub791 \uc9c4\ud589\ud588\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d\uc774 \uc5c4\uccad \ubcf5\uc7a1\ud55c \ubbf8\uc158\uc740 \uc544\ub2c8\uc5c8\uace0, \uc2a4\ud504\ub9c1\uc744 \uc0ac\uc6a9\ud558\uc5ec \uae30\ubcf8\uc801\uc778 CRUD\ub97c \uad6c\ud604\ud558\ub294 \ubbf8\uc158\uc774\uc5c8\ub2e4. \\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 Basic \uc778\uc99d\uc744 \ud1b5\ud574 \uc790\uc2e0\uc758 \uc7a5\ubc14\uad6c\ub2c8\uc5d0\ub9cc \uc0c1\ud488\uc744 \ub2f4\uace0, \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \uad6c\ud604\ud558\ub294 \uc694\uad6c\uc0ac\ud56d\uc774 \ucd94\uac00\ub418\uc5c8\ub2e4. \\nInterceptor\ub098 Argument Resolver\uc5d0 \ub300\ud55c \uc774\ud574\ub3c4\uac00 \ub192\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc870\uae08 \ub354 \uc54c\uc544\uac04 \ub290\ub08c\uc774\ub2e4. \\n\uc774\uc804\uc5d0 \uc2a4\ud504\ub9c1 \uc0ac\uc6a9\ud560 \ub54c\ub294 \uc544\ubb34 \uc0dd\uac01 \uc5c6\uc774 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub294\ub370, \ucf54\ub4dc\ub97c \uc791\uc131\ud560 \ub54c \uadfc\uac70\uac00 \uc0dd\uae30\uace0 \uc788\ub294 \uac83 \uac19\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DTO \uc6b0\ubc1c\uc801 \uc911\ubcf5**\\n\\n\uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc0c1\ud488 \ucd94\uac00\uc640 \uc0c1\ud488 \uc218\uc815\uc5d0 \ub300\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc5c8\ub2e4. \\n\\n![dto1](./dto1.png)\\n\\n\ud074\ub798\uc2a4\uba85\uc744 \uc81c\uc678\ud558\uace0 \ud544\ub4dc\uc640 \uac80\uc99d \ub85c\uc9c1 \uadf8 \uc678 \ubaa8\ub4e0 \uac8c \uac19\uc740 DTO\ub97c \ubcf4\uba70 \uc911\ubcf5\uc774\ub77c\uace0 \uc0dd\uac01\uc744 \ud588\uace0, \ubc18\ub300\ub85c \uc6a9\ub3c4\uac00 \ub2e4\ub974\uae30 \ub54c\ubb38\uc5d0 \uc911\ubcf5\uc774 \uc544\ub2c8\ub77c\uace0 \uc0dd\uac01\ud558\uae30\ub3c4 \ud588\ub2e4. \\n\ub85c\ubc84\ud2b8 \ub9c8\ud2f4\ub2d8\uc774 \uc9d1\ud544\ud558\uc2e0 \ud074\ub9b0 \uc544\ud0a4\ud14d\ucc98\ub294 \uc544\ub798\uc640 \uac19\uc774 \uc911\ubcf5\uc744 \uc5ec\ub7ec \uac00\uc9c0 \uc885\ub958\ub85c \ub098\ub204\uc5b4 \uc124\uba85\ud558\uace0 \uc788\ub2e4. \\n\\n- \uc9c4\uc9dc \uc911\ubcf5: \ud55c \uc778\uc2a4\ud134\uc2a4\uac00 \ubcc0\uacbd\ub418\uba74, \ub3d9\uc77c\ud55c \ubcc0\uacbd\uc744 \uadf8 \uc778\uc2a4\ud134\uc2a4\uc758 \ubaa8\ub4dc \ubcf5\uc0ac\ubcf8\uc5d0 \ubc18\ub4dc\uc2dc \uc801\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n- \uc6b0\ubc1c\uc801 \uc911\ubcf5: \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\ub294 \ub450 \ucf54\ub4dc \uc601\uc5ed\uc774 \uac01\uc790\uc758 \uacbd\ub85c\ub85c \ubc1c\uc804\ud55c\ub2e4\uba74, \uc989 \uc11c\ub85c \ub2e4\ub978 \uc18d\ub3c4\uc640 \ub2e4\ub978 \uc774\uc720\ub85c \ubcc0\uacbd\ub41c\ub2e4\uba74 \uc774 \ub450 \ucf54\ub4dc\ub294 \uc9c4\uc9dc \uc911\ubcf5\uc774 \uc544\ub2c8\ub2e4.\\n\\n\ucd94\uac00\uc640 \uc218\uc815\uc740 \ucd08\uae30\uc5d0\ub294 \uc911\ubcf5\uc73c\ub85c \ubcf4\uc774\uc9c0\ub9cc \ucd08\uae30 \uc0dd\uc131 \uc2dc\uc5d0\ub9cc \uae30\uc785\ud558\ub294 \ub370\uc774\ud130\ub4e4\uc774 \ucd94\uac00\ub418\uac70\ub098, \uc2dc\uac04\uc774 \uc9c0\ub098\uba74\uc11c \uc11c\ub85c \ub2ec\ub77c\uc9c8 \uac00\ub2a5\uc131\uc774 \ub192\uc544\uc9c4\ub2e4. \\n\ub530\ub77c\uc11c \ub9ac\ubdf0\uc5b4 \uc6e8\uc9c0\uac00 \uc544\ub798\uc640 \uac19\uc774 \uc758\uc874 \uc5ed\uc804\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\uace0 \uc54c\ub824\uc8fc\uc168\ub2e4. \\n\\n![dto2](./dto2.png)\\n\\n**Interceptor\uc5d0\uc11c \uc778\uc99d\ud55c \uac12 \uc7ac\uc0ac\uc6a9**\\n\\n\uc0ac\uc2e4 \uc870\ud68c\ub97c \ub450 \ubc88 \ud558\uae30 \uc2eb\uc5b4\uc11c \ub2e4\uc591\ud55c \ubc29\ubc95\uc744 \uc0dd\uac01\ud588\uc5c8\ub294\ub370 \uc774\ubc88 \ubbf8\uc158\uc5d0\uc11c\ub294 ThreadLocal\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\n\uc77c\ub2e8 Tomcat\uc740 \uc694\uccad\ub9c8\ub2e4 \ub2e4\ub978 \uc2a4\ub808\ub4dc\ub97c \uc0ac\uc6a9\ud558\uace0, Interceptor\uc5d0\uc11c \uc870\ud68c\ud574\uc11c \ub9cc\ub4e0 Credential\uc744 ThreadLocal\uc5d0 \ub123\uc5b4\ub450\uc5c8\ub2e4\uac00 ArgumentResolver\uc5d0\uc11c \uaebc\ub0b8 \ub2e4\uc74c ThreadLocal\uc744 clear \ud558\uba74 \ubb38\uc81c\uac00 \uc5c6\uc744 \uac70\ub77c \ud310\ub2e8\ud588\ub2e4. \\n\\n\ub9ac\ubdf0\uc5b4\uc778 \uc6e8\uc9c0\uc5d0\uac8c\ub3c4 \uc5b4\ub5a4 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560\uc9c0 \uad81\uae08\uc99d\uc744 \uc791\uc131\ud588\uc5c8\ub2e4. \\n\uc6e8\uc9c0\ub294 email\uc5d0 index\ub97c \uac78\uc5b4\ub450\uace0 dao \uc7ac\uc870\ud68c\ub97c \uc0ac\uc6a9\ud560 \uac83\uc774\ub77c\uace0 \ud588\ub2e4. \\n\uc7ac\uc0ac\uc6a9\ud558\uc9c0 \uc54a\uace0 db\uc5d0 \uc778\ub371\uc2a4\ub97c \uac78 \uc0dd\uac01\uc740 \ud558\uc9c0 \ubabb\ud588\ub294\ub370, \uc81c\uc77c \uc9c1\uad00\uc801\uc774\uace0 \uc88b\uc740 \ubc29\ubc95\uc774\ub77c\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uae30\ub85d**\\n\\n\ube14\ub799\ucea3\uc740 \uae30\ub85d\uc744 \uad49\uc7a5\ud788 \uc798 \ud558\ub294 \ud06c\ub8e8\uc600\ub2e4. \\n\ub178\uc158\uc5d0 \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \ud588\ub358 \ub0b4\uc6a9 + \uace0\ubbfc\ud588\ub358 \ubd80\ubd84 + \ud68c\uace0\ub97c \uaf3c\uaf3c\ud558\uac8c \uae30\ub85d\ud574\uc11c \uacf5\uc720\ud574 \uc8fc\uc5c8\ub2e4. \\n\ucd94\uac00\uc801\uc73c\ub85c \uc774\ubaa8\uc9c0\ub97c \uc801\uadf9\uc801\uc73c\ub85c \uc0ac\uc6a9\ud558\uc5ec \ub354\uc6b1 \uc88b\uc558\ub2e4!\\n\\n**\uc758\uacac \uc77c\uce58\uc2dc\ud0a4\uae30**\\n\\n\ud398\uc5b4 \uc2dc\uac04\uc740 \ud55c\uc815\ub418\uc5b4 \uc788\uace0, \uae30\uac04 \ub0b4 \uc694\uad6c\uc0ac\ud56d\uc744 \ub9cc\uc871\ud574\uc57c \ud55c\ub2e4. \\n\ub530\ub77c\uc11c \uc801\ub2f9\ud788 \ud0c0\ud611\uc744 \ubd10\uc11c \uc758\uacac\uc744 \ube60\ub974\uac8c \uc218\uc6a9\ud574 \ub370\ub4dc\ub77c\uc778\uc744 \ub9de\ucd94\ub294 \uac83\ub3c4 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ube14\ub799\ucea3\uc740 \ub0b4 \uc758\uacac\uc744 \uc798 \ub4e4\uc5b4\uc92c\uace0, \ub355\ubd84\uc5d0 \ub9c9\ud788\ub294 \ubd80\ubd84 \uc5c6\uc774 \ube60\ub974\uac8c \ubbf8\uc158\uc744 \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ube68\ub9ac \uce5c\ud574\uc84c\uace0, \uc758\uc0ac\uc18c\ud1b5\uc774 \uc798 \ub3fc\uc11c \uc7ac\ubc0c\uac8c \ucf54\ub529\ud560 \uc218 \uc788\uc5c8\ub2e4!"},{"id":"web-racing-car-retrospective","metadata":{"permalink":"/web-racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","description":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158","date":"2023-05-02T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 2\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.535,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","slug":"web-racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0","permalink":"/shopping-cart-retrospective"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"}},"content":"### \uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\\n\\n\uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud55c\ub2e4\uace0 \uc2dc\uac04\uc774 \ub9ce\uc774 \uc5c6\uc5b4\uc11c \ud68c\uace0\uac00 \ub2a6\uc5b4\uc84c\ub2e4. \\n\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158\uc5d0\uc11c\ub294 \ube44\ubc84\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c \uc9c4\ud589\ud558\ub294 \uccab \ubbf8\uc158\uc774\ub77c \ub9ce\uc774 \uae34\uc7a5\ub418\uc5c8\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ube44\ubc84\ub791 \ucd08\ubc18\uc5d0 \ub9db\uc788\ub294 \uac83\ub3c4 \ub9ce\uc774 \uba39\uc73c\uba74\uc11c \ube68\ub9ac \uce5c\ud574\uc838\uc11c \uc7ac\ubc0c\uac8c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc2a4\ud504\ub9c1\uc744 \uc870\uae08 \uc0ac\uc6a9\ud560 \uc904 \uc54c\uc544\uc11c, \ube44\ubc84\ub791 \uac19\uc774 \ud559\uc2b5\ud558\uba74\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud588\ub2e4. \\n\uccab \ubbf8\uc158\uc774\ub77c \uadf8\ub7f0\uc9c0 \ud2b9\ubcc4\ud55c \ubd80\ubd84\uc740 \uc5c6\uc5c8\uace0, \ucd5c\ub300\ud55c \uae54\ub054\ud558\uac8c \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub09c\uc774\ub3c4 \ub192\uc740 \ubbf8\uc158\uc774 \uc544\ub2c8\uc5c8\uc9c0\ub9cc \ub9ac\ubdf0\uc5b4\uc778 \ub77c\ube48\uc5d0\uac8c \uce6d\ucc2c\uc744 \ub9ce\uc774 \ubc1b\uc544\uc11c \uae30\ubd84\uc774 \uc88b\uc558\ub2e4. \\n\ub77c\ube48 \uac10\uc0ac\ud569\ub2c8\ub2e4! \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ucee8\ub514\uc158\ub3c4 \uc88b\uc9c0 \uc54a\uace0 \uc5f4\uc815\ub3c4 \uc2dd\uc740 \uac83 \uac19\uc740 \ub290\ub08c\uc774 \ub4e4\uc5c8\ub2e4. \\n\ubbf8\uc158\uc774 \ub2e4\uc18c \uc5ec\uc720\ub86d\ub2e4\uace0 \ub290\uaef4\uc838\uc11c, \uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ubd84\ub3c4 \uc798 \uad00\ub9ac\ud558\uc9c0 \ubabb\ud55c \uac83 \uac19\ub2e4. \\n\ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud574\uc11c \ud398\uc5b4\uc5d0\uac8c \ub9ce\uc774 \ubbf8\uc548\ud588\uace0, \ub098 \uc790\uc2e0\uc5d0\uac8c \uc544\uc26c\uc6e0\ub358 \ubd80\ubd84\uc774 \ub9ce\uc558\ub2e4. \\n\\n\uc9c0\ub09c\ubc88 \ud68c\uace0\ub97c \ub2e4\uc2dc \ubcf4\ub294\ub370 \uc9d1\uc911\uc744 \uc798 \ubabb\ud55c \uacbd\uc6b0\uac00 \ub9ce\uc740 \uac83 \uac19\ub2e4. \\n\ub3c4\uc804\uc801\uc774\uc9c0 \uc54a\uac70\ub098 \uc2dc\uac04\uc774 \ubd80\uc871\ud558\uc9c0 \uc54a\uc73c\uba74 \uc9d1\uc911\uc744 \uc798 \ubabb\ud558\ub294 \uac83 \uac19\ub2e4. \\n\uba38\ub9bf\uc18d\uc5d0\uc11c \uc2dc\uac04\uc801 \uc5ec\uc720\uac00 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \ub54c\uac00 \uac00\uc7a5 \uc704\ud5d8\ud55c \uc21c\uac04\uc778 \uac83 \uac19\ub2e4. \\n\\n\ud568\uaed8 \uc790\ub77c\uae30\uc5d0\uc11c \ub098\uc628 `\ub09c\uc774\ub3c4 \ub192\uc774\uae30`\uac00 \ud544\uc694\ud574\uc9c0\ub294 \uc21c\uac04\uc774\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc911\uc694\ub3c4\uac00 \uc788\ub294 \uc5b4\ub178\ud14c\uc774\uc158\ubd80\ud130 \ud074\ub798\uc2a4 \uc774\ub984\uc5d0 \uac00\uae5d\uac8c \uba85\uc2dc\ud558\uae30**\\n\\n```java\\n@SuppressWarnings(\\"NonAsciiCharacters\\")\\n@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)\\n@Transactional\\n@AutoConfigureMockMvc\\n@SpringBootTest\\npublic class RacingGameIntegrationTest {\\n```\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ube44\ubc84\uc758 \uc131\uaca9** \\n\ube44\ubc84\uac00 \uc131\uaca9\uc774 \uc88b\uc544\uc11c \ud3b8\ud558\uac8c \ud398\uc5b4\ub97c \ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc131\uae09\ud558\uc9c0 \uc54a\uace0 \uc5ec\uc720\ub85c\uc6cc\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ubbf8\uc158\uc5d0 \uc9d1\uc911\ud558\ub294 \ubd80\ubd84** \\n\ub0b4\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud558\uc9c0 \ubabb\ud588\ub294\ub370\ub3c4 \uac19\uc774 \ud398\uc5b4\ub97c \uc798 \uc9c4\ud589\ud55c \uac83 \uac19\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ube44\ubc84\uac00 \ubbf8\uc158\uc5d0 \uc798 \uc9d1\uc911\ud574\uc11c \uadf8\ub807\uc9c0 \uc54a\uc558\ub098 \uc0dd\uac01\ud588\ub2e4. \\n\uadfc\uc721\ub9e8 \ube44\ubc84\ub77c \uadf8\ub7f0\uc9c0 \uccb4\ub825\uc774 \uc88b\uc544\uc11c \uadf8\ub7f0\uac00? \\n\uc911\uac04\uc5d0 \uc798 \uc548 \uc26c\uace0\ub3c4 \uc9d1\uc911\ud574\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \uac78 \ubcf4\uace0 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n**\ud559\uc2b5\uc5d0 \ub300\ud55c \uc5f4\uc815** \\n\ucd94\uac00\uc801\uc73c\ub85c \uc54c\uace0 \uc2f6\uc740 \ubd80\ubd84\uc744 \ub530\ub85c \ud559\uc2b5\ud558\ub294 \uc5f4\uc815\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\ube44\ubc84\uc640 \uc2a4\ud504\ub9c1\uc5d0 \ub300\ud574 \uc54c\uc544\uac00\ub294 \uc2dc\uac04\uc744 \ub9ce\uc774 \uac00\uc9c4 \ubd80\ubd84\uc774 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\ub098\ub3c4 5\uc6d4\ubd80\ud130 \uc870\uae08 \ub354 \ud654\uc774\ud305 \ud574\uc57c\uaca0\ub2e4."},{"id":"tecochat-retrospective-2","metadata":{"permalink":"/tecochat-retrospective-2","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","source":"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx","title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","description":"\ud504\ub860\ud2b8\uc5d4\ud2b8","date":"2023-05-01T00:00:00.000Z","formattedDate":"2023\ub144 5\uc6d4 1\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":4.67,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","slug":"tecochat-retrospective-2","tags":["TecoChat","Retrospective"]},"prevItem":{"title":"\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0","permalink":"/web-racing-car-retrospective"},"nextItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"}},"content":"### \ud504\ub860\ud2b8\uc5d4\ud2b8\\n\\n\ub2c9\ub124\uc784\uc744 \uc785\ub825\ud558\uc5ec \uac04\ub2e8\ud788 \ub85c\uadf8\uc778\ud558\ub294 \ud654\uba74, \ucc44\ud305 \ubaa9\ub85d\uc744 \ubcf4\uc5ec\uc8fc\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\uace0 \ub2e8\uc77c \ucc44\ud305\uc744 \ud655\uc778\ud560 \uc218 \uc788\ub294 \ud654\uba74\ub3c4 \ub9cc\ub4e4\uc5c8\ub2e4. \\n\ucd94\uac00\ub85c \ucc44\ud305\uc744 \uc774\uc5b4\ub098\uac08 \uc218 \uc788\uac8c \ud558\ub294 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud588\ub2e4. \\n\uc790\uc798\ud558\uac8c \uc2e0\uacbd \uc4f8 \ubd80\ubd84\uc774 \ub9ce\uc544\uc11c, \ud504\ub860\ud2b8\uc5d4\ub4dc \ud558\ub294 \uc0ac\ub78c\ub4e4\uc774 \ub300\ub2e8\ud558\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\uc5ec\uc720\uac00 \ub41c\ub2e4\uba74 \uc790\uc2e0\uc758 \ucc44\ud305\uc744 \ubcfc \uc218 \uc788\ub294 \uae30\ub2a5\uc774\ub098, \ucc44\ud305\uc744 \uc774\uc5b4\uc11c \ud560 \uc218 \uc788\ub294 \uae30\ub2a5, \ub313\uae00 \uae30\ub2a5\ub3c4 \ucd94\uac00\ud560 \uc608\uc815\uc774\ub2e4. \\n\\n### \ubc31\uc5d4\ub4dc\\n\\n\ucd5c\ub300\ud55c \ube68\ub9ac \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uae30\ub85c \uc815\ud574\uc11c, \ubc31\uc5d4\ub4dc\ub294 \ub9d0\ub791\uc774 \uc77c\ub2e8 \ub2e4 \ub9cc\ub4e4\uace0 \uc788\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c \ubd80\ubd84\uc774 \ub108\ubb34 \ub9ce\uc544\uc11c \ub0b4\uac00 \ubabb \ub530\ub77c\uac00\ub294 \uac83 \uac19\ub2e4. \\n\ub098\uc911\uc5d0 \ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc774\ud574\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Http Request Header\\n\\n\uc544\uc9c1 \uc778\uc99d\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ud558\uc9c0 \uc54a\uc544\uc11c \uc694\uccad \ud5e4\ub354\uc5d0 \uc774\ub984\uc744 \ubcf4\ub0b4\uae30\ub85c \ud588\ub2e4. \\n\ub9d0\ub791\uc774 \ud55c\uae00\uc740 \uc548\ub41c\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c Base64\ub85c \uc778\ucf54\ub529\ud558\uace0, \ubc31\uc5d4\ub4dc\uc5d0\uc11c \ub514\ucf54\ub529 \ud558\uc5ec \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc544\ub798\ub294 pinia\uc5d0 \uc788\ub294 name \uac12\uc744 \uc778\ucf54\ub529 \ud558\ub294 \ucf54\ub4dc\ub2e4. deprecated \ub418\uc5c8\ub2e4\ub294\ub370, \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud560 \uc904 \ubab0\ub77c\uc11c \uc77c\ub2e8 \uc774\uac78 \uc0ac\uc6a9\ud588\ub2e4. \\n\\n```ts\\nconst encodedName = () => {\\n const uriComponent = unescape(encodeURIComponent(name.value));\\n return btoa(uriComponent);\\n};\\n```\\n\\n### Elastic Beanstalk\\n\\n\uac00\uc7a5 \ube60\ub974\uac8c \ubc31\uc5d4\ub4dc\ub97c \ubc30\ud3ec\ud560 \uc218 \uc788\ub294 \ubc29\ubc95\uc774 \ubb58\uc9c0 \uace0\ubbfc\ud558\ub2e4\uac00 Elastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\ub2e4. \\nElastic Beanstalk\ub97c \uc0ac\uc6a9\ud558\uba74 \uc778\ud504\ub77c\uc5d0 \ub300\ud574 \uc798 \uc54c\uc9c0 \ubabb\ud574\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube60\ub974\uac8c \ubc30\ud3ec\ud558\uace0 \uad00\ub9ac\ud560 \uc218 \uc788\ub2e4. \\n\ubaa8\ub2c8\ud130\ub9c1, \ub85c\uae45, \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud55c\ub2e4. \\n\\n### Elastic Beanstalk RDS \uc124\uc815 \ud6c4 \ubd84\ub9ac\\n\\n\ucd08\uae30 \uc124\uc815 \uc2dc RDS\ub97c \uc5f0\uacb0\ud558\uace0 \uc124\uc815 \uc644\ub8cc \ud6c4 \ubd84\ub9ac\ud55c\ub2e4\uba74, Beanstalk \uc778\uc2a4\ud134\uc2a4 -> RDS \uc694\uccad \uc2dc \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc744 \uc548 \ud574\ub3c4 \ub41c\ub2e4. \\nRDS \ubd84\ub9ac \uc2dc Beanstalk\uc5d0 \uae30\ubcf8\uc801\uc73c\ub85c \uc124\uc815\ub418\uc5b4 \uc788\ub294 RDS_HOSTNAME, RDS_PORT, RDS_USERNAME, RDS_PASSWORD\uc640 \uac19\uc740 \ud658\uacbd \ubcc0\uc218\uac00 \uac19\uc774 \uc81c\uac70\ub41c\ub2e4. \\n\ucd94\uac00\ub85c Elastic Beanstalk\ub85c RDS\ub97c \uc124\uc815\ud558\uba74 \uae30\ubcf8 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uba85\uc740 ebdb\ub2e4. \\n\\n### Elastic Beanstalk nginx \uc124\uc815\\n\\n\uc5c5\ub85c\ub4dc\ud558\ub294 zip \ud30c\uc77c \ub0b4\ubd80\uc5d0 `.platform/nginx/conf.d/` \uacbd\ub85c\uc5d0 \uc124\uc815 \ud30c\uc77c\uc744 \ucd94\uac00\ud558\uba74 nginx \uc124\uc815\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### Jenkins\\n\\n\ubc31\uc5d4\ub4dc \ucf54\ub4dc\ub97c \uc77c\uc77c\ud788 \ubc30\ud3ec\ud558\uae30 \ubd88\ud3b8\ud574\uc11c Jenkins\ub97c \uc774\uc6a9\ud558\uc5ec Repository\uc5d0 \ucf54\ub4dc\ub97c push \ud560 \ub54c \uc790\ub3d9\uc73c\ub85c \ubc30\ud3ec\uac00 \ub418\uac8c \uc124\uc815\ud558\uae30\ub85c \ud588\ub2e4. \\n\uc791\ub144\uc5d0 \ud655\uc778\ud588\uc744 \ub550 2022\ub144 12\uc6d4 31\uc77c\uae4c\uc9c0 EC2 ARM \uae30\ubc18 t4g.small\uc774 \ubb34\ub8cc\uc600\ub294\ub370, \ub2e4\uc2dc \ub4e4\uc5b4\uac00 \ubcf4\ub2c8 2023\ub144\uae4c\uc9c0 12\uc6d4 31\uc77c\uae4c\uc9c0 t4g.small\uc744 \ubb34\ub8cc\ub85c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5c8\ub2e4. \\nt4g.small\uc740 \ub7a8\uc774 2G\uc778\ub370, \uc608\uc804\uc5d0\ub294 \ubd80\uc871\ud558\uc9c0 \uc54a\uc558\ub2e4\uace0 \uc0dd\uac01\ud588\ub294\ub370 Java 17\uc744 \uc368\uc11c \uadf8\ub7f0\uac00 \ube4c\ub4dc \ud560 \ub54c \ub7a8\uc774 \ub9ce\uc774 \ubd80\uc871\ud55c \uac83 \uac19\uc544\uc11c Swap \uba54\ubaa8\ub9ac 2\uae30\uac00\ub97c \ucd94\uac00\ub85c \uc124\uc815\ud588\ub2e4. \\n\ucd94\uac00\ub85c build.gradle\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \uc124\uc815\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8 \uc2dc \uc0ac\uc6a9\ud558\ub294 \ub7a8\uc744 \ub298\ub9b4 \uc218 \uc788\ub2e4. \uae30\ubcf8\uac12\uc740 512MB\ub77c\uace0 \ud55c\ub2e4. \\n\\n```groovy\\ntest {\\n maxHeapSize = \\"1024m\\"\\n}\\n```\\n\\n### Jenkins Blue Ocean\\n\\nBlue Ocean\uc740 Jenkins Pipeline\uc744 \uad6c\uc131\ud558\ub294 \ub370\uc5d0 \uc788\uc5b4 \ud3b8\ub9ac\ud558\uac8c \ud574\uc8fc\ub294 \ub3c4\uad6c\ub2e4. \\n\uc2dc\uac01\ud654\ub3c4 \uc798 \ub418\uc5b4\uc788\uace0, \uc124\uc815\ub3c4 \ud3b8\ub9ac\ud55c \uac83 \uac19\ub2e4. \\n\uc624\ub298 \uc801\uc6a9\ud574 \ubcf4\ub2c8 \ub7a8\uc774 \ubd80\uc871\ud558\uc5ec \uc911\uac04\uc5d0 \uc798 \uc548\ub418\uae30\ub3c4 \ud558\uace0 \uadf8\ub798\uc11c \uadf8\ub0e5 \\"Pipeline\ub9cc \uc0ac\uc6a9\ud560 \uac78 \uadf8\ub7ac\ub098?\\" \ub77c\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Elastic Beanstalk, AWS](https://docs.aws.amazon.com/ko_kr/elasticbeanstalk/latest/dg/Welcome.html) \\n[EC2 AWS Graviton, AWS](https://aws.amazon.com/ko/ec2/graviton/) \\n[Default Memory Settings, AWS](https://docs.gradle.org/current/userguide/upgrading_version_4.html#rel5.0:default_memory_settings)"},{"id":"jenkins","metadata":{"permalink":"/jenkins","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","source":"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx","title":"Jenkins\ub85c CI/CD \uc124\uc815","description":"\uc124\uc815 \ud658\uacbd","date":"2023-04-30T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 30\uc77c","tags":[{"label":"Jenkins","permalink":"/tags/jenkins"},{"label":"Elastic Beanstalk","permalink":"/tags/elastic-beanstalk"}],"readingTime":7.495,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","slug":"jenkins","tags":["Jenkins","Elastic Beanstalk"]},"prevItem":{"title":"[\ud14c\ucf54\ucc57] 2. \ubc30\ud3ec","permalink":"/tecochat-retrospective-2"},"nextItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"}},"content":"### \uc124\uc815 \ud658\uacbd\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc774\ubbf8\uc9c0: Amazon Linux 2023 AMI \\n\uc544\ud0a4\ud14d\uccd0: ARM \\n\uc778\uc2a4\ud134\uc2a4 \uc720\ud615: t4g.small \\n\ud658\uacbd \uad6c\uc131\uc774 \uc644\ub8cc\ub41c Elastic Beanstalk \\n\ub2e8\uc77c Spring Boot \ud504\ub85c\uc81d\ud2b8\uac00 \uc874\uc7ac\ud558\ub294 Github Repository\\n\\n### \\\\[EC2 CLI\\\\] Swap \uba54\ubaa8\ub9ac \uc124\uc815\\n\\nt4g.small\uc774 \ub7a8\uc774 2G\uc778\ub370 \ub7a8\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \ub290\uaef4\uc838\uc11c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud588\ub2e4. \\n\uc544\ub798 \uba85\ub839\uc5b4\ub97c \ub530\ub77c swap \uba54\ubaa8\ub9ac\ub97c \uc124\uc815\ud558\uace0 free -h \uba85\ub839\uc5b4\ub97c \ud1b5\ud574 \uc798 \uc124\uc815\ub418\uc5c8\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n``` bash\\n# fallocate \uc774\uc6a9\ud558\uc5ec \uc2a4\uc651 \ud30c\uc77c \uc0dd\uc131\\nsudo fallocate -l 2G /swapfile\\n\\n# \uad8c\ud55c \uc124\uc815\\nsudo chmod 600 /swapfile\\n\\n# \ud30c\uc77c\uc744 Swap \ud3ec\ub9f7\uc73c\ub85c \ubcc0\uacbd \ud6c4 \uc2dc\uc2a4\ud15c\uc5d0 \ub4f1\ub85d\\nsudo mkswap /swapfile\\nsudo swapon /swapfile\\n\\n# Swap \uba54\ubaa8\ub9ac \ubd80\ud305\uc2dc \uc790\ub3d9\uc73c\ub85c \ub9c8\uc6b4\ud2b8\ud558\ub3c4\ub85d \uc801\uc6a9\\n# \ucd5c\ud558\ub2e8\uc5d0 \ub2e4\uc74c \uad6c\ubb38 \uc124\uc815 -> /swapfile swap swap defaults 0 0\\nsudo vim /etc/fstab\\n```\\n\\n\\n### \\\\[EC2 CLI\\\\] jenkins \uc124\uce58\\n\\n```bash\\nsudo wget -O /etc/yum.repos.d/jenkins.repo \\\\\\n https://pkg.jenkins.io/redhat-stable/jenkins.repo\\nsudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key\\nsudo yum upgrade\\nsudo yum install java-17-amazon-corretto-devel\\nsudo yum install jenkins\\nsudo systemctl daemon-reload\\n```\\n\\n[Jenkins \uacf5\uc2dd \ud648\ud398\uc774\uc9c0](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \ub97c \ucc38\uace0\ud558\uc5ec \uc124\uce58\ud558\ub294 \uac8c \uc88b\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] Jenkins \uc2dc\uc791\\n\\n```bash\\nsudo systemctl enable jenkins\\nsudo systemctl start jenkins\\n```\\n\\nenable\ub85c \uc124\uc815\ud558\uc5ec \ubd80\ud305\uc2dc \uc790\ub3d9\uc2dc\uc791 \ub418\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx & git \uc124\uce58\\n\\n```bash\\nsudo yum install nginx\\nsudo systemctl enable nginx\\nsudo systemctl start nginx\\n\\nsudo yum install git\\n```\\n\\nnginx\uc640 \ucf54\ub4dc\ub97c \ubd88\ub7ec\uc62c \ub54c \uc0ac\uc6a9\ud560 git\uc744 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[EC2 CLI\\\\] nginx \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc \uc124\uc815\\n\\n\uc544\ub798 \uc124\uc815 \ud30c\uc77c\uc740 \uacf5\uc2dd \ud648\ud398\uc774\uc9c0\uc5d0\uc11c \uc548\ub0b4\ud55c \uae30\ubcf8\uc801\uc778 \uc124\uc815 \ud30c\uc77c\uc774\ub2e4.\\n\\n```bash\\nupstream jenkins {\\n keepalive 32; # keepalive connections\\n server 127.0.0.1:8080; # jenkins ip and port\\n}\\n\\n# Required for Jenkins websocket agents\\nmap $http_upgrade $connection_upgrade {\\n default upgrade;\\n \'\' close;\\n}\\n\\nserver {\\n listen 80; # Listen on port 80 for IPv4 requests\\n\\n server_name jenkins.example.com; # replace \'jenkins.example.com\' with your server domain name\\n\\n # this is the jenkins web root directory\\n # (mentioned in the output of \\"systemctl cat jenkins\\")\\n root /var/run/jenkins/war/;\\n\\n access_log /var/log/nginx/jenkins.access.log;\\n error_log /var/log/nginx/jenkins.error.log;\\n\\n # pass through headers from Jenkins that Nginx considers invalid\\n ignore_invalid_headers off;\\n\\n location ~ \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)$\\" {\\n # rewrite all static files into requests to the root\\n # E.g /static/12345678/css/something.css will become /css/something.css\\n rewrite \\"^/static/[0-9a-fA-F]{8}\\\\/(.*)\\" /$1 last;\\n }\\n\\n location /userContent {\\n # have nginx handle all the static requests to userContent folder\\n # note : This is the $JENKINS_HOME dir\\n root /var/lib/jenkins/;\\n if (!-f $request_filename){\\n # this file does not exist, might be a directory or a /**view** url\\n rewrite (.*) /$1 last;\\n break;\\n }\\n sendfile on;\\n }\\n\\n location / {\\n sendfile off;\\n proxy_pass http://jenkins;\\n proxy_redirect default;\\n proxy_http_version 1.1;\\n\\n # Required for Jenkins websocket agents\\n proxy_set_header Connection $connection_upgrade;\\n proxy_set_header Upgrade $http_upgrade;\\n\\n proxy_set_header Host $host;\\n proxy_set_header X-Real-IP $remote_addr;\\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\\n proxy_set_header X-Forwarded-Proto $scheme;\\n proxy_max_temp_file_size 0;\\n\\n #this is the maximum upload size\\n client_max_body_size 10m;\\n client_body_buffer_size 128k;\\n\\n proxy_connect_timeout 90;\\n proxy_send_timeout 90;\\n proxy_read_timeout 90;\\n proxy_buffering off;\\n proxy_request_buffering off; # Required for HTTP CLI commands\\n proxy_set_header Connection \\"\\"; # Clear for keepalive\\n }\\n\\n}\\n```\\n\\nJenkins\ub294 8080 \ud3ec\ud2b8\ub85c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubc84\uc2a4 \ud504\ub85d\uc2dc\ub97c \uc124\uc815\ud574\uc900\ub2e4. \\n`/etc/nginx/conf.d`\xa0\uc544\ub798\xa0`default.conf`\xa0\ud30c\uc77c\uc744 \ud558\ub098 \uc0dd\uc131\ud558\uace0 \uc704\uc640 \uac19\uc774 \uc785\ub825\ud558\uace0 \uc800\uc7a5\ud55c\ub2e4. \\nnginx\uc758 \uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\uc5d0 \uc874\uc7ac\ud558\ub294\xa0`include /etc/nginx/conf.d/*.conf;`\xa0\uc124\uc815 \ub54c\ubb38\uc5d0\xa0`.conf`\xa0\ub85c \ub05d\ub09c\ub2e4\uba74 \uc124\uc815\uc774 \uc801\uc6a9\ub41c\ub2e4. \\n\uc124\uc815 \ud6c4\xa0`sudo nginx -t`\ub85c \uc124\uc815\ud30c\uc77c\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud558\uace0,\xa0`sudo systemctl restart nginx`\xa0\uba85\ub839\uc5b4\ub85c nginx\ub97c \uc7ac\uc2dc\uc791\ud55c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins \uc811\uc18d\\n\\nJenkins\ub97c \uc124\uce58\ud55c EC2 \uc778\uc2a4\ud134\uc2a4 \uc778\ubc14\uc6b4\ub4dc \uc124\uc815\uc5d0 80\ubc88 \ud3ec\ud2b8\uac00 \uc5f4\ub824\uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\nEC2\uc758 \uc544\uc774\ud53c \uc8fc\uc18c\ub97c \uc785\ub825\ud558\uace0 \ub4e4\uc5b4\uac00\uba74 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\ub294 \ucc3d\uc774 \ub098\uc628\ub2e4.\\n\\n![jenkins-start](./jenkins-start.png)\\n\\n\ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc57c \ud558\ub294\ub370 `sudo cat /var/lib/jenkins/secrets/initialAdminPasswor` \ub97c \uc785\ub825\ud574 \ucd08\uae30 \ube44\ubc00\ubc88\ud638\ub97c \uc5bb\uc744 \uc218 \uc788\ub2e4. \\n\ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\uba74 \ud50c\ub7ec\uadf8\uc778 \uc124\uc815 \ucc3d\uc774 \ub098\uc62c\ud150\ub370 `install suggested plugins`\uc744 \ud074\ub9ad\ud558\uc5ec Jenkins\uac00 \ucd94\ucc9c\ud558\ub294 \uae30\ubcf8 \ud50c\ub7ec\uadf8\uc778\ub4e4\uc744 \uc124\uce58\ud558\uba74 \ub41c\ub2e4. \\n\ud50c\ub7ec\uadf8\uc778\uc744 \uc124\uce58\ud558\uba74 \uacc4\uc815 \ubc0f \uc8fc\uc18c \uc124\uc815\uc744 \ud574\uc57c\ud558\ub294\ub370 \uc774\uac74 \ud3b8\ud558\uac8c \uc124\uc815\ud558\uba74 \ub41c\ub2e4. \\n\\n### \\\\[Jenkins\\\\] Jenkins Blue Ocean \uc124\uce58\\n\\nJenkins \uad00\ub9ac \u2192 Plugin Manager\uc5d0\uc11c Blue Ocean\uc744 \uac80\uc0c9\ud574 \uc124\uce58\ud55c\ub2e4.\\n\\n### \\\\[AWS IAM & EC2\\\\] IAM\uc73c\ub85c EC2 \uc778\uc2a4\ud134\uc2a4 \uad8c\ud55c \uc124\uc815\ud558\uae30\\n\\nS3\uc640 Elastic Beanstalk\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc744 \ubd80\uc5ec\ud558\ub824\uba74 AmazonS3FullAccess, AdministratorAccess-AWSElasticBeanstalk \ub450 \uac1c\uc758 \uc815\ucc45\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uc5ed\ud560\uc744 \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4. \\nIAM\uc5d0\uc11c \ub2e4\uc74c\uacfc \uac19\uc774 \uc5ed\ud560\uc744 \ud558\ub098 \uc0c8\ub85c \uc0dd\uc131\ud55c\ub2e4.\\n\\n1. \uc5d4\ud130\ud2f0 \uc120\ud0dd\\n\\n![aws-iam1](./aws-iam1.png)\\n\\n2. \uad8c\ud55c \ucd94\uac00\\n\\n![aws-iam2](./aws-iam2.png)\\n\\n3. \uc774\ub984 \uc9c0\uc815, \uac80\ud1a0 \ubc0f \uc0dd\uc131\\n\\n![aws-iam3](./aws-iam3.png)\\n\\n4. \uc0dd\uc131\ud55c IAM EC2 Jenkins \uc778\uc2a4\ud134\uc2a4\ub97c \uc120\ud0dd\ud558\uace0, \uc791\uc5c5 \u2192 \ubcf4\uc548 \u2192 IAM \uc5ed\ud560 \uc218\uc815\uc744 \ub20c\ub7ec Role \uc124\uc815\\n\\n![aws-iam4](./aws-iam4.png)\\n\\n### \\\\[AWS S3\\\\] Jar \ud30c\uc77c\uc744 \uc5c5\ub85c\ub4dc \ud560 S3 \ubc84\ud0b7 \uc0dd\uc131\\n\\n\ubc84\ud0b7\uc744 \uc0dd\uc131\ud560 \ub54c \ub2e4\uc74c \uc124\uc815\uc744 \uc81c\uc678\ud558\uace0 \ubaa8\ub450 \ucc28\ub2e8 \ud65c\uc131\ud654\ub97c \ud574\uc900\ub2e4.\\n\\n- `\uc0c8 ACL(\uc561\uc138\uc2a4 \uc81c\uc5b4 \ubaa9\ub85d)\uc744 \ud1b5\ud574 \ubd80\uc5ec\ub41c \ubc84\ud0b7 \ubc0f \uac1d\uccb4\uc5d0 \ub300\ud55c \ud37c\ube14\ub9ad \uc561\uc138\uc2a4 \ucc28\ub2e8`\\n\\n![aws-s3](./aws-s3.png)\\n\\n### \\\\[Github\\\\] Blue Ocean\uc5d0\uc11c \ud30c\uc774\ud504\ub77c\uc778 \uc0dd\uc131\uc5d0 \ud544\uc694\ud55c Github Token \uc0dd\uc131\\n\\nrepo, user:email \uad8c\ud55c\uc774 \uc788\ub294 \ud1a0\ud070\uc774 \ud544\uc694\ud558\ub2e4. \\n\\n### \\\\[Jenkins\\\\] \ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\\n\\n![jenkins-blue-ocean1](./jenkins-blue-ocean1.png)\\n\\n\ube14\ub8e8 \uc624\uc158 \uc5f4\uae30\ub85c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc0dd\uc131\ud55c\ub2e4. \\n\ud1a0\ud070 \uc785\ub825 \u2192 \uc870\uc9c1 \uc120\ud0dd \u2192 CI/CD \uc124\uc815\ud560 Repository \uc120\ud0dd\uc744 \ud558\uba74 \ud30c\uc774\ud504\ub77c\uc778 \ucc3d\uc73c\ub85c \ub118\uc5b4\uac04\ub2e4. \\nJenkinsfile\uc744 \uc9c1\uc811 \uc791\uc131\ud558\uc5ec \uc124\uc815\ud558\uae30 \uc704\ud574 \uac04\ub2e8\ud558\uac8c print \ud558\ub098 \ucd9c\ub825\ud558\ub294 \uac83\uc73c\ub85c \uc124\uc815\ud588\ub2e4. \\n\\n![jenkins-blue-ocean2](./jenkins-blue-ocean2.png)\\n\\n\ud30c\uc774\ud504\ub77c\uc778\uc774 \uc2e4\ud589\ub420 \ud150\ub370 pipeline status\uc5d0\uc11c \uc544\ub798\uc640 \uac19\uc774 \ucd08\ub85d\ubd88\uc774 \ub728\uba74 \ub41c\ub2e4.\\n\\n![jenkins-blue-ocean3](./jenkins-blue-ocean3.png)\\n\\n### \\\\[Github Repsoitory\\\\] Jenkinsfile \uc124\uc815\\n\\n\ube14\ub8e8 \uc624\uc158 \uc2dc\uc791\uc744 \ud1b5\ud574 \uc124\uc815\ud558\uba74 Jenkinsfile\uc774 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc9c0\uace0, \uc544\ub798\uc640 \uac19\uc774 \uc6d0\ud558\ub294 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n```bash\\npipeline {\\n agent any\\n stages {\\n stage(\'build and test\') {\\n steps {\\n sh \'/gradlew clean build\'\\n }\\n }\\n stage(\'zip\') {\\n steps {\\n sh \'mv ./build/libs/woowachat.jar .\'\\n sh \'zip -r woowachat.zip .platform delivery.jar Procfile\'\\n }\\n }\\n stage(\'upload\') {\\n steps {\\n sh \'aws s3 cp woowachat.zip s3://woowa-chat/woowachat.zip --region ap-northeast-2\'\\n }\\n }\\n stage(\'deploy\') {\\n steps {\\n sh \'aws elasticbeanstalk create-application-version --region ap-northeast-2 --application-name woowachat --version-label ${BUILD_TAG} --source-bundle S3Bucket=\\"woowa-chat\\",S3Key=\\"woowachat.zip\\"\'\\n sh \'aws elasticbeanstalk update-environment --region ap-northeast-2 --environment-name Woowachat-env --version-label ${BUILD_TAG}\'\\n }\\n }\\n }\\n}\\n```\\n\\n### \\\\[Github\\\\] Webhooks \uc124\uc815\\n\\n![github-hook](./github-hook.png)\\n\\npush \uc774\ubca4\ud2b8\uac00 \ubc1c\uc0dd\ud560 \ub54c `http://Jenkins\uc8fc\uc18c/github-webhook/` \ub85c post request\ub97c \ud558\ub3c4\ub85d \uc6f9\ud6c5\uc744 \uc124\uc815\ud55c\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n[Install Jenkins - CentOS, Jenkins](https://www.jenkins.io/doc/book/installing/linux/#red-hat-centos) \\n[Nginx Reverse Proxy Configuration, Jenkins](https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-nginx/) \\n[Amazon Corretto 17 JDK Install, AWS](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html) \\n[Amazon Linux 2023 packages, AWS](https://docs.aws.amazon.com/linux/al2023/release-notes/all-packages-al2023-20230419.html)"},{"id":"tecochat-retrospective-1","metadata":{"permalink":"/tecochat-retrospective-1","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx","title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","description":"4\uc6d4 21\uc77c \uae08\uc694\uc77c","date":"2023-04-22T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 22\uc77c","tags":[{"label":"TecoChat","permalink":"/tags/teco-chat"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.68,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","slug":"tecochat-retrospective-1","tags":["TecoChat","Retrospective"]},"prevItem":{"title":"Jenkins\ub85c CI/CD \uc124\uc815","permalink":"/jenkins"},"nextItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"}},"content":"### 4\uc6d4 21\uc77c \uae08\uc694\uc77c\\n\\n\ub808\ubca8 2\ub97c \uc2dc\uc791\ud55c \ub4a4 \ub0b4\uac00 \ud559\uc2b5\uc5d0 \ub300\ud55c \ubc29\ud5a5\uc744 \uc783\uc5b4\ubc84\ub838\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5c8\ub2e4. \\n\ub808\ubca8 3, 4\uc5d0\uc11c \ub098\ub9cc\uc758 \uac15\uc810\uc744 \uac00\uc9c0\uace0 \uc2f6\uc5b4 \uace0\ubbfc\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\ub2e8\uc21c\ud788 \uc2a4\ud504\ub9c1\uc744 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ud6a8\uc728\uc774 \ub9ce\uc774 \ub5a8\uc5b4\uc9c4\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uae00\uc4f0\uae30 \uc218\uc0c1\uc73c\ub85c \ubc1b\uc740 \ucfe0\ud3f0\uc744 \uc0ac\uc6a9\ud574 \ube0c\ub77c\uc6b4\uc5d0\uac8c \ucee4\ud53c\ucc57\uc744 \uc2e0\uccad\ud588\uace0, \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \ud574\ubcf4\ub77c\ub294 \ub2f5\uc744 \ubc1b\uc558\ub2e4. \\n\\n\ub098\ub294 \uc544\uc774\ub514\uc5b4\ub97c \ubabb\ub0b4\ub294 \ud3b8\uc778\ub370 \ube0c\ub77c\uc6b4\uc774 \uc544\uc774\ub514\uc5b4\uae4c\uc9c0 \ub358\uc838\uc8fc\uc168\ub2e4. \\n`Chat-GPT \uc11c\ube44\uc2a4\ub97c \ud06c\ub8e8\ub4e4\uc5d0\uac8c \uc81c\uacf5\ud558\uace0, \ud574\ub2f9 \ud06c\ub8e8\ub4e4\uc774 \uc9c8\ubb38\ud55c \ub0b4\uc6a9\uc744 \uacf5\uc720\ud560 \uc218 \uc788\ub294 \uac74 \uc5b4\ub5a4\uc9c0?` \\n\\n\uae30\uc220\uc774 \ubaa9\uc801\uc778 \uc0ac\uc774\ub4dc \ud504\ub85c\uc81d\ud2b8\ub97c \uc9c4\ud589\ud558\uba74 \uc88b\uc744 \uac83 \uac19\ub2e4\ub294 \ub2f5\ubcc0\uc744 \ub4e4\uc5c8\uace0, \ud63c\uc790 \uc544\ub2c8\uba74 \ud398\uc5b4\ud560 \uc218 \uc788\uc744 \uc815\ub3c4\uc758 \uc778\uc6d0\uc73c\ub85c \uc9c4\ud589\ud558\uba74 \uc88b\uaca0\ub2e4\uace0 \ud558\uc168\ub2e4. \\n\ud504\ub860\ud2b8\ub791 \uac04\ub2e8\ud558\uac8c \ubc30\ud3ec\uae4c\uc9c0 \ud574\ubcf8 \uacbd\ud5d8\uc774 \uc788\uc5b4\uc11c \ud63c\uc790\ud574\ub3c4 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc744 \uac83 \uac19\uc544\uc11c \ud63c\uc790 \ud558\uae30\ub85c \ub9c8\uc74c\uc744 \uba39\uc5c8\ub2e4. \\n\\n\uc774\uac74 \ubabb\ucc38\uc9c0\\n\\n### \ub3c4\uba54\uc778 \uad6c\uc785 \uc131\uacf5?\\n\\n\ucee4\ud53c\ucc57\uc774 \ub05d\ub098\uace0 \uc9d1\uc73c\ub85c \ub3cc\uc544\uac00\ub294 \uae38\uc5d0 \ubc14\ub85c \ub3c4\uba54\uc778\uc744 \uad6c\ub9e4\ud558\ub824\uace0 namecheap\uc5d0\uc11c \uc801\ub2f9\ud55c \ub3c4\uba54\uc778\uc774 \uc5c6\uc744\uae4c \uac80\uc0c9\uc744 \uacc4\uc18d\ud588\ub2e4. \\n\ub9c8\uce58 \uc5b4\ub9b4 \ub54c \ud588\ub358 \uac8c\uc784 \ub2c9\ub124\uc784 \uc815\ud558\ub294 \uac83\ucc98\ub7fc \uc2dc\uac04\uc774 \uc624\ub798 \uac78\ub838\ub2e4. \\ndev, io, chat \ub3c4\uba54\uc778\uc774 \ud6c4\ubcf4\uc600\uace0 \uc9d1 \uac00\ub294 \uae38\uc5d0 \uacb0\uc815\ub9cc \ud558\ub2e4\uac00 \uad6c\ub9e4\ud558\uc9c0 \ubabb\ud588\ub2e4.\\n\\n### \ub9d0\ub791\uc758 DM\\n\\n\uc9d1\uc5d0 \uac00\uc11c \ubc25\uc744 \uba39\uace0 \ub9d0\ub791\uc774\ub791 DM \ud558\ub2e4 \ud504\ub85c\uc81d\ud2b8\ub97c \uac19\uc774 \ud558\uc790\ub294 \uc774\uc57c\uae30\uac00 \ub098\uc654\ub2e4. \\n\uc6b0\ud14c\ucf54 \ucd5c\uace0 \uace0\uc218 \ub9d0\ub791\uc758 \uc694\uad6c\ub77c \uc218\ub77d\ud558\uc9c0 \uc54a\uc73c\uba74 \ud6c4\ud3ed\ud48d\uc744 \uac10\ub2f9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\\n\uc774\ub7f0\uc800\ub7f0 \ub300\ud654\ub97c \ub098\ub204\ub2e4\uac00 \ub09c \ube60\ub974\uac8c \ud504\ub85c\ud1a0\ud0c0\uc785\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uace0 \uc2f6\uc5b4\uc11c \ud504\ub860\ud2b8\ub97c \uad6c\ud604\ud55c\ub2e4\uace0 \ud588\uace0, \ub9d0\ub791\uc740 GPT api\ub97c \uc870\uc0ac\ud558\uae30\ub85c \ud588\ub2e4. \\n\ucd94\uac00\ub85c \ub3c4\uba54\uc778\uc5d0 \uad00\ud55c \uc774\uc57c\uae30\ub97c \ud558\ub2e4\uac00 woowachat\uc774 \uc5b8\uae09\ub418\uc5c8\uace0, namecheap\uc5d0\uc11c chat \ub3c4\uba54\uc778\uc744 \uc0ac\uc6a9\ud55c woowa.chat\uc73c\ub85c \uad6c\ub9e4\ud588\ub2e4. \\n\uc774\ud6c4\uc5d0 teco.chat\uc73c\ub85c \ubcc0\uacbd\ud588\ub2e4!\\n\\n### \ub3c4\uba54\uc778 \uc124\uc815 \ubc0f \ubc30\ud3ec\\n\\n\ud1a0\uc694\uc77c\uc5d0 \uad6c\ub9e4\ud55c \ub3c4\uba54\uc778\uc744 CDN, \ubcf4\uc548 \ub4f1 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 Cloudflare\uc5d0 \ub3c4\uba54\uc778 \ub4f1\ub85d\uc744 \ud588\ub2e4. \\n\ub098\uc5d0\uac8c \uc775\uc219\ud55c Nuxt3\ub97c \uc0ac\uc6a9\ud558\uae30\ub85c \ud588\uace0, Cloudflare Pages\ub97c \uc774\uc6a9\ud558\uc5ec \ubc30\ud3ec\ud588\ub2e4. \\n\\n### GPT\\n\\n\ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud558\ub2c8 api limit\uc774 \uc788\uc5b4 \ubd84\ub2f9 3\ubc88\ubc16\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc77c\ub2e8 \ubc31\uc5d4\ub4dc\ub97c \uad6c\ucd95\ud558\uae30 \uc804\uc5d0\ub294 \ubb34\ub8cc \ud06c\ub808\ub527\uc744 \uc0ac\uc6a9\ud560 \uc0dd\uac01\uc774\ub2e4. \\n\\n### Sonarcloud\\n\\n\uc815\uc801 \ucf54\ub4dc \ubd84\uc11d \ub3c4\uad6c\ub85c Sonarcloud\ub97c \uc801\uc6a9\ud588\ub2e4. \\nSonarcloud\ub294 SonarQube\uc758 SaaS \ubc84\uc804\uc774\uace0 \uc0ac\uc6a9\uc774 \ub9e4\uc6b0 \ud3b8\ud558\ub2e4. \\n\uc608\uc804\uc5d0 Sonarcloud\ub97c \uc0ac\uc6a9\ud560 \ub550 \ubc84\ud2bc \uba87 \ubc88 \ub204\ub974\uba74 \uc801\uc6a9\ud560 \uc218 \uc788\uc5c8\ub294\ub370, \uc774\ubc88\uc5d0\ub294 \ubc14\ub85c github action\uc744 \uc0ac\uc6a9\ud558\ub77c\ub294 \uc548\ub0b4 \ud398\uc774\uc9c0\ub85c \uc774\ub3d9\ud588\ub2e4. \\nSonarcloud\uac00 \uc790\uccb4\uc801\uc73c\ub85c github repository\uc5d0 push \ud558\uba74 \uc815\uc801 \ubd84\uc11d\uc744 \ud574\uc8fc\ub294 \uae30\ub2a5\uc744 \uc6d0\ud588\uace0, Administration -> Analysis Method\uc5d0 Automatic Analysis\ub97c \uc124\uc815\ud558\ub2c8 \ub418\uc5c8\ub2e4. \\n\ub108\ubb34 \uaf41\uaf41 \uc228\uaca8\uc838\uc788\ub124\\n\\n### Tiptap\\n\\n\ucf54\ub4dc \ud558\uc774\ub77c\uc774\ud305 \uae30\ub2a5\uc744 \ub123\uace0 \uc2f6\uc5b4\uc11c Tiptap\uc744 \uc0ac\uc6a9\ud588\ub2e4. \\nTiptap\uc740 Headless WYSIWYG \uc5d0\ub514\ud130\ub85c \uc0ac\uc6a9\uc790 \uc815\uc758 \uae30\ub2a5\uc5d0 \ud2b9\ud654\ub418\uc5b4\uc788\ub294 \uc5d0\ub514\ud130\ub2e4. \\n\uc544\uc9c1 Tiptap\uc774 \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uae30\ub2a5\uc744 \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc0ac\uc6a9\ud558\uc9c0\ub294 \ubabb\ud558\uc9c0\ub9cc CodeBlockLowlight \ud50c\ub7ec\uadf8\uc778\uc744 \uc0ac\uc6a9\ud558\uc5ec \ucf54\ub4dc \ube14\ub85d\uc744 \uc608\uc058\uac8c \ucd9c\ub825\ud560 \uc218 \uc788\uc5c8\ub2e4. \\napi \ubc18\ud658\uac12 \uadf8\ub300\ub85c tiptap\uc758 content\uc5d0 \uc124\uc815\ud588\ub354\ub2c8 \ucf54\ub4dc \ube14\ub85d\uc774 \uc124\uc815\ub418\uc9c0 \uc54a\uc544\uc11c \ubc31 \ud2f1 3\uac1c\ub97c `
`\ub85c \ubcc0\ud658\ud588\ub2e4.  \\n\ucd94\uac00\ub85c \ub744\uc5b4\uc4f0\uae30\ub3c4 \uc801\uc6a9\ub418\uc9c0 \uc54a\uc544\uc11c `\\\\n`\ub97c `
`\ud0dc\uadf8\ub85c \ubcc0\ud658\ud588\ub2e4. \\n\ubcc0\ud658\ud558\ub294 \ub85c\uc9c1\uc740 GPT\uc758 \ub3c4\uc6c0\uc744 \ub9ce\uc774 \ubc1b\uc558\ub2e4. \\n\\n```ts\\nconst replaceCodeFences = (input: String) => {\\n const codeFencesRegex = /```([\\\\w-]*)\\\\n([\\\\s\\\\S]*?)\\\\n```/g;\\n return input\\n .replace(codeFencesRegex, (match, p1, p2) => {\\n const languageClass = p1 ? ` class=\\"language-${p1}\\"` : \\"\\";\\n return `
${p2}
`;\\n })\\n .replace(/\\\\n/g, \\"
\\");\\n};\\n```\\n\\nTiptap\uc744 \uc801\uc6a9\ud558\ub2c8 \ub2e4\uc74c\uacfc \uac19\uc774 \uae54\ub054\ud55c \ucf54\ub4dc \ube14\ub85d\uc744 \ubcfc \uc218 \uc788\uc5c8\ub2e4. \\n\\n![tecochat](./teco-chat.png)\\n\\n### \ud3f0\ud2b8 \ubc0f favicon \uc801\uc6a9\\n\\n\ud0c0\uc774\ud2c0\uc740 \ubc30\ub2ec\uc758\ubbfc\uc871 \ub3c4\ud604\uccb4, \ub0b4\uc6a9\uc740 IBM Plex Sans\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\ucd94\uac00\ub85c favicon\ub3c4 \uac04\ub2e8\ud558\uac8c \uc801\uc6a9\ud574\uc11c \ub9cc\uc871\uc2a4\ub7ec\uc6e0\ub2e4."},{"id":"book-leadership-and-self-deception","metadata":{"permalink":"/book-leadership-and-self-deception","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","source":"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx","title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","description":"\ucc45 \uc815\ubcf4","date":"2023-04-08T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 8\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.16,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","slug":"book-leadership-and-self-deception","tags":["Book"]},"prevItem":{"title":"[\ud14c\ucf54\ucc57] 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30","permalink":"/tecochat-retrospective-1"},"nextItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c \\n> \uc544\ube48\uc800\uc5f0\uad6c\uc18c\\n> \\n\\n### \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\\n\\n\ucc45\uc5d0\uc11c\ub294 \uc790\uae30\uae30\ub9cc\uacfc \uc790\uae30\ubc30\ubc18\uc5d0 \ub300\ud55c \ub0b4\uc6a9\uc744 \ub2e4\ub8ec\ub2e4. \\n- \uc790\uae30\uae30\ub9cc: \uc790\uc2e0\uc758 \ubb38\uc81c\ub97c \uc778\uc815\ud558\uc9c0 \uc54a\ub294 \uac83 \\n- \uc790\uae30\ubc30\ubc18: \ub2e4\ub978 \uc0ac\ub78c\uc744 \uc704\ud574 \ubb34\uc5b8\uac00 \ud574\uc57c\ub9cc \ud55c\ub2e4\ub294 \uc0dd\uac01\uc744 \ubc18\ud558\ub294 \ud589\uc704\\n\\n\uc790\uae30\ubc30\ubc18\uc744 \ud55c\ub2e4\uba74 \uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\uc790\uae30\uae30\ub9cc \uc0c1\ud0dc\uc5d0 \ube60\uc9c0\ub294 \uac83\uc744 \ucc45\uc5d0\uc11c\ub294 \uc0c1\uc790 \uc548\uc5d0 \ub4e4\uc5b4\uac04\ub2e4\uace0 \ud45c\ud604\ud55c\ub2e4. \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\ucd5c\uadfc\uc5d0 \uc77d\uc740 \ucc45 \uc911 \uac00\uc7a5 \ub9c8\uc74c\uc774 \ubd88\ud3b8\ud588\ub2e4. \\n\uadf8\ub807\uae30\uc5d0 \ub354\ub354\uc6b1 \ub098\uc5d0\uac8c \ud544\uc694\ud55c \ub0b4\uc6a9\uc774 \ub2f4\uaca8\uc788\uc5c8\ub2e4. \\n\\n\uc0b4\uba74\uc11c \ub9ce\uc740 \uc120\ud0dd\uc758 \uc21c\uac04\uc774 \uc874\uc7ac\ud588\uace0, \uadf8 \uc21c\uac04\ub9c8\ub2e4 \uc790\uae30\ubc30\ubc18\uc744 \ud0dd\ud558\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\uc791\uac8c\ub294 \uc9d1\uc548\uc77c\uc744 \ud574\uc57c \ud558\ub294\ub370 \ubab8\uc774 \uc870\uae08 \ud798\ub4e4\ub2e4\uace0 \ud558\uc9c0 \uc54a\uac70\ub098 \\n\ud06c\uac8c\ub294 \uc798\ubabb\uc744 \uc778\uc815\ud574\uc57c \ud558\ub294 \uc0c1\ud669\uc5d0\uc11c \uadf8\ub7ec\uc9c0 \uc54a\uc740 \uacbd\uc6b0\uac00 \uc788\uc5c8\ub2e4. \\n\uc774\ub7f0 \uc0c1\ud669\uc774 \ubc18\ubcf5\ub418\uc5b4 \uacb0\uad6d \uc0c1\uc790 \uc548\uc5d0 \ub098 \uc790\uc2e0\uc744 \uac00\ub450\ub294 \uacbd\uc6b0\uac00 \ub9ce\uc558\ub2e4. \\n\\n\ub354 \ub098\uc740 \uc0b6\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \uc9c0\uc18d\uc801\uc73c\ub85c \ud655\uc778\ud558\uace0, \uc0c1\uc790 \ubc16\uc73c\ub85c \ub098\uac00\ub824\ub294 \uc5f0\uc2b5\uc744 \ud574\uc57c\uaca0\ub2e4. \\n\ub113\uc740 \uc2dc\uc120\uc744 \uac00\uc9c0\uace0, \ud56d\uc0c1 \ub0b4\uac00 \ud2c0\ub9b4 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc0dd\uac01\ud558\uace0 \uc0b4\uc544\uac00\uc790. \\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uc6b0\ub9ac\uc758 \uc0dd\uac01\uc740 \uc9c0\uc2dd\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc9c0\uc2dd\uc740 \uc0ac\ub791\ubcf4\ub2e4 \uc791\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc0ac\ub791\uc740 \uc874\uc7ac\ubcf4\ub2e4 \uc791\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc0dd\uac01\ud558\ub294 \ub098\ub294 \uc2e4\uc81c\uc758 \ub098\ubcf4\ub2e4 \uadf8\ub9cc\ud07c \uc791\ub2e4. \\nR. D. \ub7ad \\np.19\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc678\uc801\uc73c\ub85c \uc5b4\ub5a4 \ud589\ub3d9\uc744 \ud558\ub4e0\uc9c0 \uac04\uc5d0, \uc0ac\ub78c\ub4e4\uc740 \uc6b0\ub9ac \ub9c8\uc74c\uc5d0\uc11c \uadf8\ub4e4\uc744 \uc5b4\ub5bb\uac8c \ub300\ud558\uace0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \uc8fc\ub85c \ubc18\uc751\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uc0ac\ub78c\ub4e4\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \ub290\ub07c\uac8c \ub418\ub294\uc9c0\ub294 \uc6b0\ub9ac\uac00 \uc0c1\uc790 \uc548\uc5d0 \uc788\ub294\uc9c0 \ud639\uc740 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294\uc9c0\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c0\uac8c \ub429\ub2c8\ub2e4. \\np.66\\n>\\n\\n> \ube44\ub09c\uc740 \uac10\uc815\uc5d0 \uc18d\ud558\uace0 \ub099\uad00\uc740 \uc758\uc9c0\uc5d0 \uc18d\ud55c\ub2e4. \\n\uc778\uac04\uc740 \uac10\uc815\ubcf4\ub2e4 \ub354 \ud070 \uc874\uc7ac\uc774\ub2e4. \\n\uc54c\ub7ad, \ud0c1\ub2db\ud55c \\np.103\\n>\\n\\n> \uc6b0\ub9ac\uac00 \uc790\uc2e0\uc5d0\uac8c\ub9cc \uc9d1\uc911\ud558\uace0 \uc788\ub294 \ud55c, \ud63c\uc790\uc11c \uc77c\ud558\ub294 \uac83 \uc774\uc0c1\uc758 \ucc3d\uc870\uc801\uc778 \uacb0\uacfc\ub098 \ud611\ub825\uc744 \uc774\ub04c\uc5b4 \ub0b8\ub2e4\ub294 \uac83\uc740 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4. \\n\uc624\ub298\ub0a0 \uacbd\uc81c \ud658\uacbd\uc5d0\uc11c\ub294 \ud63c\uc790\uc11c\ub294 \uc77c\uc758 \uacb0\uacfc\ub97c \ud0c1\uc6d4\ud558\uac8c \ub9cc\ub4e4\uc5b4 \ub0b4\uae30\uac00 \uc5b4\ub835\uc2b5\ub2c8\ub2e4. \\n\ub0b4\uac00 \uc911\uc2ec\uc774\uc5b4\uc57c \ub41c\ub2e4\ub294 \ud3d0\uc1c4\uc801\uc778 \uc0ac\uace0\ub294 \ud568\uaed8 \uc77c\ud558\ub294 \uc0ac\ub78c\ub4e4\uc758 \uc5f4\uc815\uc744 \ubd88\ub7ec\uc624\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\np.175\\n> \\n\\n> \uc194\uc9c1\ud568\uc740 \uc6b0\ub9ac\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\ub294 \uc5f4\uc1e0\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\uc740 \uc790\uc2e0\uc758 \ud589\ub3d9\uacfc \uad00\ub828\ub41c \uc0ac\ub78c\uc5d0 \ub300\ud574 \uae30\uaebc\uc774 \uc0ac\uacfc\ub97c \ud558\ub294 \uac83\uc785\ub2c8\ub2e4. \\n\uadf8\uac83\ub9cc\uc774 \uc2e4\ud0c0\ub798\ucc98\ub7fc \uc5c9\ud0a8 \uad00\uacc4\uc758 \ubb38\uc81c\ub97c \ud574\uacb0\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\uc8e0. \\np.188\\n> \\n\\n> \ub204\uad70\uac00\ub97c \ub098\uc640 \uac19\uc774 \ub3d9\uc77c\ud55c \uac00\uce58\ub97c \uc9c0\ub2cc \ud55c \uc778\uac04\uc73c\ub85c \uc0dd\uac01\ud574\uc11c \uadf8 \uc0ac\ub78c\uc744 \uc704\ud574 \ub0b4\uac00 \uc0c1\uc790 \ubc16\uc5d0 \uacc4\uc18d \uba38\ubb34\ub974\uace0 \uc2f6\uc740 \uc5f4\ub9dd\uc774 \uc0dd\uae38 \ub54c, \ub098\ub294 \uc774\ubbf8 \uadf8 \uc0ac\ub78c\uc5d0 \ub300\ud574 \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub2e4. \\np.214\\n> \\n\\n> \ub300\ubd80\ubd84\uc758 \uc0ac\ub78c\ub4e4\uc774 \uad00\uacc4 \uae30\uc220\uc744 \uac00\uc9c0\uace0 \uadf8\ub4e4\uc774 \uacaa\uace0 \uc788\ub294 \ubb38\uc81c\ub97c \ubc14\ub85c\uc7a1\uc73c\ub824\uace0 \ud558\ub294 \ub178\ub825\uc774 \uacb0\uc2e4\uc744 \uc5bb\uc9c0 \ubabb\ud558\ub294 \uac83\uc740 \uacb0\ucf54 \uadf8\ub7ec\ud55c \uae30\uc220 \ubd80\uc871 \ub54c\ubb38\uc5d0 \uc0dd\uae30\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4. \\n\uadf8\uac83\ub4e4\uc740 \uc790\uae30\ubc30\ubc18 \ub54c\ubb38\uc5d0 \uc0dd\uaca8\ub0a9\ub2c8\ub2e4. \\np.224\\n>\\n\\n> \uc6b0\ub9ac\ub294 \ud568\uaed8 \uc77c\ud558\uace0 \uc6b0\ub9ac\uc640 \ud568\uaed8 \uc0b4\uc544\uac00\ub294 \uc0ac\ub78c\uc774 \uc9c4\uc815\uc73c\ub85c \ub204\uad6c\uc778\uc9c0 \uc54c\uc9c0 \ubabb\ud569\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uac00 \uadf8\ub4e4\uacfc \uc9c4\uc815\uc73c\ub85c \ud568\uaed8 \uc18c\ud1b5\ud558\uae30 \uc804\uae4c\uc9c0\ub294 \uc6b0\ub9ac\ub294 \uadf8\ub4e4\uc758 \uac00\uce58\ub97c \uc798 \ubaa8\ub985\ub2c8\ub2e4. \\n\uc6b0\ub9ac\uc758 \uc704\ub300\ud568\uc774\ub780 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uc758 \uc704\ub300\ud55c \uc810\uc744 \ubc1c\uacac\ud574 \uc8fc\ub294 \uac83\uc5d0 \uc788\uc2b5\ub2c8\ub2e4. \\np.280\\n>"},{"id":"innodb-lock","metadata":{"permalink":"/innodb-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-07T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 7\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"InnoDB","permalink":"/tags/inno-db"}],"readingTime":5.805,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"innodb-lock","tags":["DataBase","Lock","InnoDB"]},"prevItem":{"title":"[\ucc45] \uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c","permalink":"/book-leadership-and-self-deception"},"nextItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"}},"content":"## InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08\uacfc \ubcc4\uac1c\ub85c \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub0b4\ubd80\uc5d0\uc11c \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ubcf4\ud1b5 \uba85\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ub294 \uacbd\uc6b0\ub294 \ub4dc\ubb3c\uace0, \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ubb35\uc2dc\uc801\uc73c\ub85c \uc7a0\uae08\uc774 \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n\ub3d9\uc2dc\uc131 \uc81c\uc5b4 \ubc29\uc2dd\uc5d0\ub294 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uacfc \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc774 \uc788\ub2e4. \\nInnoDB\ub294 \uae30\ubcf8\uc801\uc73c\ub85c MVCC(\ub2e4\uc911 \ubc84\uc804 \ub3d9\uc2dc\uc131 \uc81c\uc5b4)\ub97c \ud1b5\ud574 \ub099\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud558\uace0 \ub77d\uc744 \ud1b5\ud574 \ud2b9\uc815 \uc0c1\ud669\uc5d0\uc11c \ube44\uad00\uc801\uc778 \ubc29\uc2dd\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n:::note \ub099\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(OCC, Optimistic concurrency control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc11c\ub85c \ucda9\ub3cc\ud558\uc9c0 \uc54a\ub294\ub2e4\uace0 \uac00\uc815\ud558\ub294 \ubc29\uc2dd \\n\\n:::\\n\\n:::note \ube44\uad00\uc801 \ub3d9\uc2dc\uc131 \uc81c\uc5b4(PCC, Pessimistic Concurrency Control)\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ucda9\ub3cc\ud558\ub294 \uac00\uc815\ud558\uc5d0 \uc7a0\uae08\uc744 \uac70\ub294 \ubc29\uc2dd \\n\uc77c\ubc18\uc801\uc73c\ub85c\xa0Shared Lock, Exclusive Lock\uc744 \ud1b5\ud574 \uc774\ub97c \uad6c\ud604\ud55c\ub2e4.\\n\\n:::\\n\\n### Shared & Exclusive Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704\uc758 \uc7a0\uae08\uc744 \uc218\ud589\ud560 \ub54c \uacf5\uc720 \uc7a0\uae08\uacfc \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\\n**\uacf5\uc720 \uc7a0\uae08(S, shared lock)**\\n\\n\ub370\uc774\ud130 \uc870\ud68c\ub97c \uc704\ud55c \ub77d, \uc77d\uae30 \uc7a0\uae08(read lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uae30\uac00 \uac00\ub2a5\ud558\uc9c0\ub9cc, \uc4f0\uae30\ub294 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;`\\n\\n**\ubc30\ud0c0\uc801 \uc7a0\uae08(X, exclusive lock)** \\n\\n\ub370\uc774\ud130 \ubcc0\uacbd\uc744 \uc704\ud55c \ub77d, \uc4f0\uae30 \uc7a0\uae08(write lock)\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\ub77d\uc744 \uac74 \ud2b8\ub79c\uc7ad\uc158\ub9cc\uc774 \ud574\ub2f9 \ub370\uc774\ud130\uc5d0 \uc811\uadfc \uac00\ub2a5\ud558\ub2e4. \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc758 \uacbd\uc6b0 \uc77d\uae30, \uc4f0\uae30\uac00 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc608) `SELECT * FROM table_name WHERE id = 1 FOR UPDATE;`\\n\\n### Intention Locks\\n\\nInnoDB\ub294 \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uacfc \ud14c\uc774\ube14 \uc7a0\uae08\uc758 \uacf5\uc874\uc744 \uc704\ud574 \uc778\ud14d\uc158 \uc7a0\uae08\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \\n\ud14c\uc774\ube14\uc5d0 \uc788\ub294 \ub85c\uc6b0\uc5d0 \ub300\ud574\uc11c \ub098\uc911\uc5d0 \uc694\uccad\ub418\ub294 \uac83\uc774 \uc5b4\ub5a4 \ud615\ud0dc\uc758 \uc7a0\uae08\uc778\uc9c0 \uac00\ub9ac\ud0a4\uae30 \uc704\ud574 \uc0ac\uc6a9\ub41c\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \ub85c\uc6b0 \ub2e8\uc704 \uc7a0\uae08\uc744 \uc218\ud589\ud558\uae30 \uc804\uc5d0 \uc778\ud150\uc158 \uc7a0\uae08\uc744 \uba3c\uc800 \ud68d\ub4dd\ud55c\ub2e4. \\n\uc778\ud150\uc158 \ub77d\uc740 \uae30\ubcf8\uc801\uc73c\ub85c \ucda9\ub3cc\uc744 \ubc29\uc9c0\ud558\uace0 \ub370\ub4dc\ub77d\uc744 \ubc29\uc9c0\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n**\uc778\ud150\uc158 \uacf5\uc720 \uc7a0\uae08(IS, intention shared lock)**\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \uacf5\uc720 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n**\uc778\ud150\uc158 \ubc30\ud0c0\uc801 \uc7a0\uae08(IX, intention exclusive lock)** \\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \ud14c\uc774\ube14\uc758 \uac1c\ubcc4 \ub85c\uc6b0\uc5d0 \ub300\ud55c \ubc30\ud0c0\uc801 \uc7a0\uae08\uc744 \uc218\ud589\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.\\n\\n** \uc7a0\uae08\uac04\uc758 \ud638\ud658\uc131 **\\n\\n| | X | IX | S | IS |\\n| --- | --- | --- | --- | --- |\\n| X | Conflict | Conflict | Conflict | Conflict |\\n| IX | Conflict | Compatible | Conflict | Compatible |\\n| S | Conflict | Conflict | Compatible | Compatible |\\n| IS | Conflict | Compatible | Compatible | Compatible |\\n\\n### Record Locks\\n\\n\ub808\ucf54\ub4dc \uc790\uccb4\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc740 \ub808\ucf54\ub4dc \uc790\uccb4\uac00 \uc544\ub2c8\ub77c \uc778\ub371\uc2a4\uc758 \ub808\ucf54\ub4dc\ub97c \uc7a0\uadfc\ub2e4. \\n\\n### Gap Locks\\n\\n\ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub808\ucf54\ub4dc\uc640 \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\uc5d0 \uc0c8\ub85c\uc6b4 \ub808\ucf54\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \uc81c\uc5b4\ud558\uace0, \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc758 \uc77c\ubd80\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### Next-Key Locks\\n\\n\ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4. \\n`REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ud32c\ud140 \ub9ac\ub4dc\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud55c \uc7a0\uae08\uc774\ub2e4. \\n\\n### AUTO-INC Locks\\n\\n`AUTO_INCREMENT` \uce7c\ub9bc\uc774 \uc0ac\uc6a9\ub41c \ud14c\uc774\ube14\uc5d0 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \ub808\ucf54\ub4dc\uac00 `INSERT`\ub418\ub294 \uacbd\uc6b0, \uac01 \ub808\ucf54\ub4dc\ub294 \uc911\ubcf5\ub418\uc9c0 \uc54a\uace0 \uc800\uc7a5\ub41c \uc21c\uc11c\ub300\ub85c \uc99d\uac00\ud558\ub294 \uc77c\ub828\ubc88\ud638 \uac12\uc744 \uac00\uc838\uc57c \ud55c\ub2e4. \\nInnoDB \ub294 \ub0b4\ubd80\uc801\uc73c\ub85c AUTO-INC \ub77d\uc774\ub77c\uace0 \ud558\ub294 \ud14c\uc774\ube14 \uc218\uc900\uc758 \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uacfc \uad00\uacc4 \uc5c6\uc774 `INSERT`\ub098 `REPLACE` \ubb38\uc7a5\uc5d0\uc11c `AUTO_INCREMENT` \uac12\uc744 \uac00\uc838\uc624\ub294 \uc21c\uac04\ub9cc \ub77d\uc774 \uac78\ub838\ub2e4\uac00 \ud574\uc81c\ub41c\ub2e4.\\n\\n### \uc7a0\uae08 \uc608\uc2dc\\n\\n```sql\\n-- \ub808\ucf54\ub4dc\ub294 id \uae30\uc900 10, 20, 30, 40, 50\uc774 \uc788\ub2e4\uace0 \uac00\uc815\\n-- Record Locks: 10\uc5d0 \ub300\ud574 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id = 10 for update;\\n\\n-- Gap Locks: 51\ubd80\ud130 PositiveInfinity\uae4c\uc9c0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id > 100 for update;\\n\\n-- Next-Key Locks: 21\ubd80\ud130 30, 31\ubd80\ud130 40\uc5d0 \ub77d\uc774 \uac78\ub9b0\ub2e4.\\nSELECT * FROM table_name where id BETWEEN 25 AND 35 for update;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Optimistic and Pessimistic record locking, IBM](https://www.ibm.com/docs/en/rational-clearquest/9.0.0?topic=clearquest-optimistic-pessimistic-record-locking) \\n[MySQL Innodb Locks, cecil1018](https://cecil1018.wordpress.com/2016/06/18/mysql-innodb-locks/) \\n[MySQL 8.0 InnoDB Locks, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html) \\n[Locks Set by Different SQL Statements in InnoDB, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html)"},{"id":"mysql-lock","metadata":{"permalink":"/mysql-lock","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","source":"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx","title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","description":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","date":"2023-04-06T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 6\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Lock","permalink":"/tags/lock"},{"label":"MySQL","permalink":"/tags/my-sql"}],"readingTime":4.405,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","slug":"mysql-lock","tags":["DataBase","Lock","MySQL"]},"prevItem":{"title":"InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/innodb-lock"},"nextItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"}},"content":"## MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08\\n\\nMySQL\uc5d0\uc11c\uc758 \ub77d\uc740 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4 \ub808\ubca8\uacfc, MySQL \uc5d4\uc9c4 \ub808\ubca8\ub85c \ub098\ub20c \uc218 \uc788\ub2e4. \\nMySQL \uc5d4\uc9c4 \ub808\ubca8\uc758 \uc7a0\uae08\uc740 \ubaa8\ub4e0 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce5c\ub2e4. \\n\\n### \uae00\ub85c\ubc8c \ub77d(Global lock)\\n\\nMySQL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc7a0\uae08 \uc911 \uac00\uc7a5 \ub113\uc740 \ubc94\uc704\ub97c \uac00\uc9c0\uace0 \uc788\ub294 \uc7a0\uae08\uc774\ub2e4. \\n - \uc601\ud5a5\uc744 \ubbf8\uce58\ub294 \ubc94\uc704\ub294 \ud574\ub2f9 \uc11c\ubc84 \uc804\uccb4\uc774\ub2e4.\\n - \uc791\uc5c5 \ub300\uc0c1 \ud14c\uc774\ube14, \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0c1\uad00 \uc5c6\uc774 \ub3d9\uc77c\ud558\uac8c \uc601\ud5a5\uc744 \ubc1b\ub294\ub2e4.\\n\\n\ud55c \uc138\uc158\uc5d0\uc11c \uae00\ub85c\ubc8c \ub77d\uc744 \ud68d\ub4dd\ud558\uba74 \ud574\uc81c \ub420 \ub54c \uae4c\uc9c0 \uc870\ud68c\ub97c \uc81c\uc678\ud55c \ub300\ubd80\ubd84\uc758 \uba85\ub839\uc774 \ub300\uae30 \uc0c1\ud0dc\uac00 \ub41c\ub2e4. \\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc874\uc7ac\ud558\ub294 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub300\ud574 \uc77c\uad00\ub41c \ubc31\uc5c5\uc744 \ubc1b\uc544\uc57c\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\nInnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c\ub294 \ubc31\uc5c5 \uc2dc \uc870\uae08 \ub354 \uac00\ubcbc\uc6b4 \ubc31\uc5c5 \ub77d\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- GLOBAL LOCK\\nFLUSH TABLES WITH READ LOCK;\\n-- UNLOCK\\nUNLOCK TABLES;\\n\\n-- BACKUP LOCK\\nLOCK INSTANCE FOR BACKUP;\\n-- UNLOCK\\nUNLOCK INSTANCE;\\n```\\n\\n:::note MyISAM\\n\\nMySQL 5.5 \ubc84\uc804 \uc774\uc804\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, SELECT \uc791\uc5c5 \uc18d\ub3c4\uac00 \ube60\ub974\ub2e4.\\n\\n:::\\n\\n### \ud14c\uc774\ube14 \ub77d(Table lock)\\n\\n\uac1c\ubcc4 \ud14c\uc774\ube14 \ub2e8\uc704\ub85c \uc124\uc815\ub418\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801 \ub610\ub294 \ubb35\uc2dc\uc801\uc73c\ub85c \ud2b9\uc815 \ud14c\uc774\ube14\uc758 \ub77d\uc744 \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4. \\n\ubb35\uc2dc\uc801 \ub77d\uc740 MyISAM\uc774\ub098 MEMORY \ud14c\uc774\ube14\uc5d0 \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub294 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\uba74 \ubc1c\uc0dd\ud55c\ub2e4. \\nInnoDB \ud14c\uc774\ube14\uc5d0\ub294 DML \ucffc\ub9ac\ub294 \ubb34\uc2dc\ub418\uace0 DDL \uc77c \uacbd\uc6b0\uc5d0\ub9cc \ubb35\uc2dc\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud55c\ub2e4.\\n\\n```sql\\n-- TABLE LOCK\\nLOCK TABLES table_name [ READ | WRITE ]\\n\\n-- UNLOCK\\nUNLOCK TABLES;\\n```\\n\\n### \ub124\uc784\ub4dc \ub77d(Named lock)\\n\\n\uc784\uc758\uc758 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \uc124\uc815\ud560 \uc218 \uc788\ub294 \uc7a0\uae08\uc73c\ub85c \uc720\uc800 \ub808\ubca8 \ub77d\uc73c\ub85c\ub3c4 \ubd88\ub9b0\ub2e4. \\n\uc5ec\ub7ec \uc2a4\ub808\ub4dc\ub098 \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc77c\ud55c \ub370\uc774\ud130\ub97c \uc218\uc815\ud558\ub824\ub294 \uacbd\uc6b0, \ub3d9\uc2dc\uc5d0 \uc218\uc815\ud558\uc9c0 \ubabb\ud558\ub3c4\ub85d \ubcf4\ud638\ud560 \uc218 \uc788\ub2e4. \\n\\n```sql\\n-- aGVyYg== \ub77c\ub294 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08 \ud68d\ub4dd, \uc774\ubbf8 \uc7a0\uae08\uc744 \uc0ac\uc6a9\uc911\uc778 \uacbd\uc6b0 1\ucd08 \ub3d9\uc548\ub9cc \ub300\uae30\\nSELECT GET_LOCK(\'aGVyYg==\', 1);\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc774 \uc124\uc815\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4.\\nSELECT IS_FREE_LOCK(\'aGVyYg==\');\\n\\n-- \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4.\\nSELECT RELEASE_LOCK(\'aGVyYg==\');\\n\\n-- \uc704 3\uac1c \ud568\uc218 \ubaa8\ub450 \uc815\uc0c1\uc801\uc73c\ub85c \ub77d\uc744 \ud68d\ub4dd\ud558\uac70\ub098 \ud574\uc81c\ud55c \uacbd\uc6b0\uc5d0 1\uc744, \uc544\ub2c8\uba74 0\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n-- \ubaa8\ub4e0 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud55c \uc7a0\uae08\uc744 \ud574\uc81c\ud55c\ub2e4. \ud574\uc81c\ub41c \uc7a0\uae08\uc758 \uac1c\uc218\ub97c \ubc18\ud658\ud55c\ub2e4.\\nSELECT RELEASE_ALL_LOCKS();\\n```\\n\\n### \uba54\ud0c0\ub370\uc774\ud130 \ub77d(Metadata lock)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uac1d\uccb4\uc758 \uc774\ub984\uc774\ub098 \uad6c\uc870\ub97c \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \ud68d\ub4dd\ud558\ub294 \uc7a0\uae08\uc774\ub2e4. \\n\uba85\uc2dc\uc801\uc73c\ub85c \ud68d\ub4dd \ub610\ub294 \ud574\uc81c \ud560 \uc218 \uc5c6\uc9c0\ub9cc \ud14c\uc774\ube14\uc758 \uc774\ub984\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \uc2e4\uc2dc\uac04\uc73c\ub85c \ud14c\uc774\ube14\uc744 \ubc14\uafd4\uc57c\ud558\ub294 \uacbd\uc6b0\uc5d0 \uc0ac\uc6a9\ub41c\ub2e4.\\n\\n```sql\\n-- \ubc30\uce58 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ubcc4\ub3c4\uc758 \uc784\uc2dc \ud14c\uc774\ube14\uc5d0 \uc11c\ube44\uc2a4\uc6a9 \ub7ad\ud0b9 \ub370\uc774\ud130 \uc0dd\uc131 \ud6c4 \uae30\uc874 \ud14c\uc774\ube14\uc744 \ubc31\uc5c5\ud558\ub294 \uacbd\uc6b0\\n-- \uc544\ub798 \uad6c\ubb38 \uc2e4\ud589 \uc2dc \uba54\ud0c0\ub370\uc774\ud130 \ub77d\uc744 \uc790\ub3d9\uc73c\ub85c \ud68d\ub4dd\ud55c\ub2e4.\\nRENAME TABLE rank TO rank_backup, rank_new TO rank;\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[MySQL\uc758 User Level Lock\ub97c \ud65c\uc6a9\ud55c\ub2e4\uba74?, gywndi](https://gywn.net/2013/12/mysql-user-level-lock/) \\n[Locking Functions, MySQL 5.7 Reference](https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html#function_release-all-locks) \\n[Locking Functions, MySQL 8.0 Reference](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_release-all-locks)"},{"id":"transaction-and-isolation","metadata":{"permalink":"/transaction-and-isolation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","source":"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx","title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","description":"\ud2b8\ub79c\uc7ad\uc158(Transaction)","date":"2023-04-05T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 5\uc77c","tags":[{"label":"DataBase","permalink":"/tags/data-base"},{"label":"Transaction","permalink":"/tags/transaction"},{"label":"Isolation","permalink":"/tags/isolation"}],"readingTime":9.68,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","slug":"transaction-and-isolation","tags":["DataBase","Transaction","Isolation"]},"prevItem":{"title":"MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08","permalink":"/mysql-lock"},"nextItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"}},"content":"## \ud2b8\ub79c\uc7ad\uc158(Transaction)\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ub17c\ub9ac\uc801 \uae30\ub2a5\uc744 \uc218\ud589\ud558\uae30 \uc704\ud55c \uc791\uc5c5\uc758 \ub2e8\uc704\ub97c \ub9d0\ud55c\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uc791\uc5c5\uc758 \uc644\uc804\uc131\uacfc \ub370\uc774\ud130\uc758 \uc815\ud569\uc131\uc744 \ubcf4\uc7a5\ud574 \uc900\ub2e4. \\n\ub17c\ub9ac\uc801\uc778 \uc791\uc5c5 \uc14b\uc744 \uc644\ubcbd\ud558\uac8c \ucc98\ub9ac\ud558\uac70\ub098, \uc624\ub958 \uc2dc \uc791\uc5c5\uc758 \uc77c\ubd80\ub9cc \uc801\uc6a9\ub418\ub294 \ud604\uc0c1\uc744 \ub9c9\uc544\uc900\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158\uc758 \uc18d\uc131(ACID)\\n\\n\uc6d0\uc790\uc131(Atomicity): \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \uc2e4\ud589\ub41c \uc791\uc5c5\ub4e4\uc740 \ubaa8\ub450 \uc131\uacf5\ud558\uac70\ub098, \uc2e4\ud328\ud574\uc57c \ud55c\ub2e4. \\n\uc77c\uad00\uc131(Consistency): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc218\ud589\ub418\uae30 \uc804\uacfc \ud6c4\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uac00 \uc77c\uad00\ub41c \uc0c1\ud0dc\ub97c \uc720\uc9c0\ud574\uc57c \ud55c\ub2e4. \\n\uaca9\ub9ac\uc131(Isolation): \uac01\uac01\uc758 \ud2b8\ub79c\uc7ad\uc158\uc740 \ub3c5\ub9bd\uc801\uc774\ub77c \uc11c\ub85c\uc5d0\uac8c \uc601\ud5a5\uc744 \uc8fc\uc9c0 \uc54a\uc544\uc57c \ud55c\ub2e4. \\n\uc9c0\uc18d\uc131(Durability): \ud2b8\ub79c\uc7ad\uc158\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c\ub2e4\uba74 \uc601\uad6c\uc801\uc73c\ub85c \uacb0\uacfc\uc5d0 \ubc18\uc601\ub418\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### \ud2b8\ub79c\uc7ad\uc158 \uc8fc\uc758\uc0ac\ud56d\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc740 \uaf2d \ud544\uc694\ud55c \ucd5c\uc18c\uc758 \ucf54\ub4dc\uc5d0\ub9cc \uc801\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.(\ud2b8\ub79c\uc7ad\uc158\uc758 \ubc94\uc704\ub97c \ucd5c\uc18c\ud654\ud558\ub77c) \\n\uad6c\ud604\ud574\uc57c \ud558\ub294 \uc5c5\ubb34\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158\uc744 \ubb36\uac70\ub098 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc81c\uc678\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\ub294 \uacbd\uc6b0 \ubc18\ub4dc\uc2dc \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\\n:::info \uc65c \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc788\uc744 \ub54c \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubc30\uc81c\ud574\uc57c \ud560\uae4c? \ud83e\udd14\\n\\n\ub370\uc774\ud130\uc758 \uc77c\uad00\uc131\uacfc \uc548\uc804\uc131\uc744 \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \ubc30\uc81c\ud574\uc57c \ud55c\ub2e4. \\n\ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc744 \ud2b8\ub79c\uc7ad\uc158 \ub0b4\ubd80\uc5d0 \ud3ec\ud568\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \\n- \ub124\ud2b8\uc6cc\ud06c \uc791\uc5c5\uc774 \uc911\uac04\uc5d0 \uc2e4\ud328\ud560 \uac00\ub2a5\uc131(\uc548\uc804\uc131 X)\\n- \ud1b5\uc2e0\uc73c\ub85c \uc778\ud574 \ub370\uc774\ud130\uac00 \ubcc0\uacbd\ub420 \uc218 \uc788\ub294 \ubd80\ubd84(\uc77c\uad00\uc131 X)\\n\\n:::\\n\\n## \uaca9\ub9ac \uc218\uc900(Isolation level)\\n\\n\uc5ec\ub7ec \ud2b8\ub79c\uc7ad\uc158\uc774 \ub3d9\uc2dc\uc5d0 \ucc98\ub9ac\ub420 \ub54c \ud2b9\uc815 \ud2b8\ub79c\uc7ad\uc158\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\uc758 \uc870\ud68c \ubc0f \ubcc0\uacbd\uc744 \ud5c8\uc6a9\ud560\uc9c0 \uacb0\uc815\ud558\ub294 \uac83\uc744 \ub9d0\ud55c\ub2e4. \\n\uaca9\ub9ac \uc218\uc900\uc774 \ub192\uc544\uc9c8 \uc218\ub85d \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\uc774 \ub5a8\uc5b4\uc9c0\ub294 \uac83\uc774 \uc77c\ubc18\uc801\uc774\uc9c0\ub9cc, `SERIALIZABLE`\uc774 \uc544\ub2c8\ub77c\uba74 \ud06c\uac8c \uc131\ub2a5\uc758 \uc800\ud558\uac00 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\n### READ UNCOMMITTED\\n\\n\uac01 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\uc758 \ubcc0\uacbd \ub0b4\uc6a9\uc774 `COMMIT`\uc774\ub098 `ROLLBACK` \uc5ec\ubd80\uc5d0 \uc0c1\uad00\uc5c6\uc774 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcf4\uc778\ub2e4. \\n\ub354\ud2f0 \ub9ac\ub4dc \ud604\uc0c1\uc774 \ubc1c\uc0dd\ud558\uae30 \ub54c\ubb38\uc5d0 \uc815\ud569\uc131\uc758 \ubb38\uc81c\uac00 \ub9ce\uc740 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMySQL \uc0ac\uc6a9\uc2dc \ucd5c\uc18c `READ COMMITTED` \uc774\uc0c1\uc758 \uaca9\ub9ac \uc218\uc900 \uc0ac\uc6a9\uc744 \uad8c\uc7a5\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ UNCOMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: INSERT(Alice)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: COMMIT(Alice)\\n```\\n\\n### READ COMMITTED\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ub370\uc774\ud130\ub97c \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub370\uc774\ud130\ub9cc \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\n\uc624\ub77c\ud074 DBMS\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uba70, \uc628\ub77c\uc778 \uc11c\ube44\uc2a4\uc5d0\uc11c \uac00\uc7a5 \ub9ce\uc774 \uc120\ud0dd\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\n`REPEATABLE READ`\uac00 \ubcf4\uc7a5\ub418\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 `NON-REPEATABLE READ` \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: READ COMMITTED\\n---\\nsequenceDiagram\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n Alice->>Database: COMMIT\\n```\\n\\n### REPEATABLE READ\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc774 \uc2dc\uc791\ub418\uae30 \uc804\uc5d0 `COMMIT`\uc774 \uc644\ub8cc\ub41c \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub9cc \uc870\ud68c\ud560 \uc218 \uc788\ub2e4. \\nMySQL\uc758 InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc5d0\uc11c \uae30\ubcf8\uc73c\ub85c \uc0ac\uc6a9\ub418\ub294 \uaca9\ub9ac \uc218\uc900\uc774\ub2e4. \\nMVCC\ub97c \uc774\uc6a9\ud574 \uc5b8\ub450(Undo) \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \uc774\uc804 \ub370\uc774\ud130\ub97c \uc774\uc6a9\ud574 \ub3d9\uc77c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c\ub294 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc5ec\uc904 \uc218 \uc788\uac8c \ubcf4\uc7a5\ud55c\ub2e4. \\n\ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubcf4\uc7a5\ud558\ub294 \ubc29\ubc95\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n - \ubaa8\ub4e0 InnoDB \ud2b8\ub79c\uc7ad\uc158\uc740 \uc21c\ucc28\uc801\uc73c\ub85c \uc99d\uac00\ud558\ub294 \uace0\uc720\ud55c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ub97c \uac00\uc9c4\ub2e4.\\n - Undo \uc601\uc5ed\uc5d0 \ubc31\uc5c5\ub41c \ub808\ucf54\ub4dc\uc5d0\ub294 \ubcc0\uacbd\uc744 \ubc1c\uc0dd\uc2dc\ud0a8 \ud2b8\ub79c\uc7ad\uc158\uc758 \ubc88\ud638\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\ub2e4.\\n - Undo \uc601\uc5ed\uc758 \ubc31\uc5c5\ub41c \ub370\uc774\ud130\ub294 \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc774 \ubd88\ud544\uc694\ud558\ub2e4\uace0 \ud310\ub2e8\ud558\ub294 \uacbd\uc6b0 \uc0ad\uc81c\ub41c\ub2e4.\\n - `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c\ub294 MVCC\ub97c \ubcf4\uc7a5\ud558\uae30 \uc704\ud574 \uac00\uc7a5 \uc624\ub798\ub41c \ud2b8\ub79c\uc7ad\uc158 \ubc88\ud638\ubcf4\ub2e4 \uc55e\uc120 Undo \uc601\uc5ed\uc758 \ub370\uc774\ud130\ub294 \uc0ad\uc81c\ud558\uc9c0 \uc54a\ub294\ub2e4. \\n\\nInnoDB\uc5d0\uc11c\ub294 \uac2d \ub77d\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d\uc744 \uc774\uc6a9\ud558\uc5ec \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc744 \ubc29\uc9c0\ud55c\ub2e4. \\n\\n```mermaid\\n---\\ntitle: REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice(Undo log)\\n```\\n\\n:::note \uac2d \ub78d(Gap lock)\uacfc \ub125\uc2a4\ud2b8 \ud0a4 \ub77d(Next-key lock)\\n\\n\uac2d \ub77d: \ub808\ucf54\ub4dc\uc640 \ubc14\ub85c \uc778\uc811\ud55c \ub808\ucf54\ub4dc \uc0ac\uc774\uc758 \uac04\uaca9\ub9cc\uc744 \uc7a0\uadf8\ub294 \ub77d\uc774\ub2e4. \\n\ub125\uc2a4\ud2b8 \ud0a4 \ub77d: \ub808\ucf54\ub4dc \ub77d\uacfc \uac2d \ub77d\uc744 \ud569\uccd0\ub193\uc740 \ud615\ud0dc\uc758 \uc7a0\uae08\uc73c\ub85c \ub808\ucf54\ub4dc\uc640 \uadf8 \ub808\ucf54\ub4dc \uc55e\uc758 \uac2d \ub77d\uc744 \ud3ec\ud568\ud55c\ub2e4.\\n\\n:::\\n\\n:::note MVCC(Multi Version Concurrency Control)\\n\\n\ub3d9\uc2dc\uc131\uc744 \uc81c\uc5b4\ud558\ub294 \ubc29\ubc95 \uc911 \ud558\ub098\ub85c \ud558\ub098\uc758 \ub808\ucf54\ub4dc\uc5d0 \ub300\ud574 \uc5ec\ub7ec \uac1c\uc758 \ubc84\uc804\uc774 \ub3d9\uc2dc\uc5d0 \uad00\ub9ac\ub418\ub294 \uac83\uc774\ub2e4.\\n - PostgreSQL\uc740 \ub2e4\uc911 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub97c \uc800\uc7a5\ud558\ub294 \uac83\uc73c\ub85c MVCC\ub97c \uad6c\ud604\ud55c\ub2e4.\\n - Oracle, InnoDB\ub294 `Undo log`\ub97c \uc774\uc6a9\ud574 \uc774 \uae30\ub2a5\uc744 \uad6c\ud604\ud55c\ub2e4.(\ucd5c\uc2e0 \ubc84\uc804\uc758 \ub370\uc774\ud130\ub9cc DB\uc5d0 \uc800\uc7a5)\\n\\n\uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc77d\uad00\ub41c \uc77d\uae30\ub97c \uc81c\uacf5\ud558\ub294 \uac83\uc774 \ubaa9\uc801\uc774\ub2e4.\\n\\n:::\\n\\n### SERIALIZABLE\\n\\n\ud2b8\ub79c\uc7ad\uc158\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc9c4\ud589\uc2dc\ud0a4\ub294 \uaca9\ub9ac \uc218\uc900\uc774\uace0 \ub530\ub77c\uc11c \ub3d9\uc2dc \ucc98\ub9ac \uc131\ub2a5\ub3c4 \ub2e4\ub978 \uaca9\ub9ac \uc218\uc900\ubcf4\ub2e4 \ub5a8\uc5b4\uc9c4\ub2e4. \\n\ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uc77d\uace0 \uc4f0\ub294 \ub808\ucf54\ub4dc\ub97c \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c\ub294 \uc811\uadfc\ud560 \uc218 \uc5c6\uace0 \ub2e8\uc21c\ud55c \uc77d\uae30 \uc791\uc5c5\ub3c4 \uacf5\uc720 \uc7a0\uae08(\uc77d\uae30 \uc7a0\uae08)\uc744 \ud68d\ub4dd\ud574\uc57c\ub9cc \ud55c\ub2e4. \\nInnoDB\uc5d0\uc11c\ub294 \ud32c\ud140 \ub9ac\ub4dc \ud604\uc0c1\uc774 `REPEATABLE READ` \uaca9\ub9ac \uc218\uc900\uc5d0\uc11c \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 \uad73\uc774 \uc0ac\uc6a9\ud560 \ud544\uc694\ub294 \uc5c6\ub2e4. \\n\\n## \uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub978 \ubd80\uc815\ud569 \ubb38\uc81c\\n\\n\uaca9\ub9ac \uc218\uc900\uc5d0 \ub530\ub77c \ub354\ud2f0 \ub9ac\ub4dc, \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c, \ud32c\ud140 \ub9ac\ub4dc \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n| \uaca9\ub9ac \uc218\uc900 / \ubd80\uc815\ud569 \ubb38\uc81c | \ub354\ud2f0 \ub9ac\ub4dc | \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c | \ud32c\ud140 \ub9ac\ub4dc |\\n| --- | --- | --- | --- |\\n| READ UNCOMMITTED | O | O | O |\\n| READ COMMITTED | X | O | O |\\n| REPEATABLE READ | X | X | O(InnoDB\ub294 X) |\\n| SERIALIZABLE | X | X | X |\\n\\n### \ub354\ud2f0 \ub9ac\ub4dc(Dirty read)\\n\\n\uc5b4\ub5a4 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c \uc791\uc5c5\uc774 \uc644\ub8cc\ub418\uc9c0 \uc54a\uc558\uc5b4\ub3c4 \ub2e4\ub978 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ubcfc \uc218 \uc788\ub294 \ud604\uc0c1 \\n\ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \uc218\uc900\uc774 READ UNCOMMITTED\uc77c \ub54c \ubc1c\uc0dd\ud55c\ub2e4. \\n\uc608) B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uace0 \ucee4\ubc0b\uc744 \ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, A\uac00 \ud574\ub2f9 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud560 \uc218 \uc788\ub294 \uacbd\uc6b0\\n\\n### \ubc18\ubcf5 \uac00\ub2a5\ud558\uc9c0 \uc54a\uc740 \uc870\ud68c(Non-repeatable read)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc758 \uac19\uc740 \ud589\uc5d0 \ub450 \ubc88 \uc774\uc0c1 \uc870\ud68c\uac00 \ubc1c\uc0dd\ud588\ub294\ub370, \uadf8 \uac12\uc774 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc5ec\ub7ec \ubc88 \uc870\ud68c\ud558\ub358 \uc911 B\uac00 \ub808\ucf54\ub4dc\ub97c \ubcc0\uacbd\ud558\uc5ec A\uac00 \uc870\ud68c\ud55c \uac12\uc774 \ub2ec\ub77c\uc9c0\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: NON REPEATABLE READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN\\n Bob->>Database: SELECT\\n Database->>+Bob: Alice\\n Alice->>Database: BEGIN\\n Alice->>Database: UPDATE(Alice to Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT\\n Database->>+Bob: Bob\\n```\\n\\n### \ud32c\ud140 \ub9ac\ub4dc(Phantom read, Phantom row)\\n\\n\ud55c \ud2b8\ub79c\uc7ad\uc158 \ub0b4\uc5d0\uc11c \ub3d9\uc77c\ud55c \ucffc\ub9ac \uc218\ud589\uc2dc, \uc218\ud589 \uacb0\uacfc\uac00 \ub2e4\ub978 \ud604\uc0c1 \\n\uc608) A\uac00 \ub808\ucf54\ub4dc\ub97c \uc870\ud68c\ud558\uace0 B\uac00 \ub808\ucf54\ub4dc\ub97c \ucd94\uac00\ud558\uc5ec A\uac00 \ub2e4\uc2dc \uc870\ud68c\ud560 \ub54c \uc874\uc7ac\ud558\uc9c0 \uc54a\uc740 \ub808\ucf54\ub4dc\uac00 \uc870\ud68c\ub418\ub294 \uacbd\uc6b0 \\n\\n```mermaid\\n---\\ntitle: PHANTOM READ\\n---\\nsequenceDiagram\\n participant Alice\\n participant Database\\n participant Bob\\n Bob->>Database: BEGIN(TRX-ID: 1)\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 1\\n Alice->>Database: BEGIN(TRX-ID: 2)\\n Alice->>Database: INSERT(Bob)\\n Alice->>Database: COMMIT\\n Bob->>Database: SELECT COUNT\\n Database->>+Bob: 2\\n```\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\nReal My SQL 8.0 - 5\uc7a5 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc7a0\uae08, \ubc31\uc740\ube48, \uc774\uc131\uc6b1 \\n[Isolation Level, MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)"},{"id":"test-double","metadata":{"permalink":"/test-double","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","source":"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx","title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","description":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?","date":"2023-04-04T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 4\uc77c","tags":[{"label":"Test","permalink":"/tags/test"},{"label":"Mock","permalink":"/tags/mock"}],"readingTime":4.52,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","slug":"test-double","tags":["Test","Mock"]},"prevItem":{"title":"\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900","permalink":"/transaction-and-isolation"},"nextItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"}},"content":"### \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub780?\\n\\n\ubaa8\ub4e0 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \uac00\uc9dc \uc758\uc874\uc131\uc744 \uc758\ubbf8\ud558\uace0, \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud589\ub420 \ub54c \ub2e4\ub978 \uac1d\uccb4\ub97c \ub300\uc2e0\ud55c\ub2e4. \\nGerard Meszaros\uc758 xUnit Test Patterns\ub77c\ub294 \ucc45\uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ub2e4\uc12f \uac00\uc9c0(\ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774, \ubaa9, \ud398\uc774\ud06c)\ub85c \uad6c\ubd84\ud55c\ub2e4.\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \uae30\ubcf8 \uba54\ucee4\ub2c8\uc998\uc740 \ub2e4\ud615\uc131\uc744 \uc774\uc6a9\ud558\ub294 \ubc29\ubc95\uc774\ub2e4. \\n\uc678\ubd80 \uc11c\ube44\uc2a4\ub97c \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uacbd\uc6b0, \uc778\ud130\ud398\uc774\uc2a4\ub97c \uc815\uc758\ud558\uace0 \uc678\ubd80 \uc11c\ube44\uc2a4 \ub300\uc2e0 \ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\uc758 \uad6c\ud604\uccb4\ub97c \uc0dd\uc131\ud558\ub294 \uac83\uc774\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc758 \ud0c0\uc785 \uacc4\uce35 \uad6c\uc870**\\n\\n```mermaid\\nflowchart LR\\n Mock --\x3e Spy --\x3e Stub --\x3e Dummy --\x3e TestDouble\\n Fake --\x3e TestDouble\\n```\\n\\n### \ub354\ubbf8(Dummy)\\n\\n\uac00\uc7a5 \ub2e8\uc21c\ud558\uace0, \uc6d0\uc2dc\uc801\uc778 \uc720\ud615\uc758 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc774\ub2e4. \\n\uae30\ubcf8\uc801\uc73c\ub85c \uc544\ubb34 \uc77c\ub3c4 \ud558\uc9c0 \uc54a\ub294 \uad6c\ud604\uccb4\ub85c \uc778\uc2a4\ud134\uc2a4\ud654\uac00 \ud544\uc694\ud55c \uacbd\uc6b0 \uc0ac\uc6a9\ud55c\ub2e4. \\n\ub9cc\uc57d \uba54\uc11c\ub4dc\uac00 \ubb34\uc5b8\uac00 \ubc18\ud658\uc744 \ud574\uc57c\ud558\ub294 \uacbd\uc6b0 0, null\uacfc \uac19\uc740 \uac12\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n### \uc2a4\ud141(Stub)\\n\\n\uc2dc\ub098\ub9ac\uc624\ub9c8\ub2e4 \ub2e4\ub978 \uac12(\ubbf8\ub9ac \uc900\ube44 \ub41c \uacb0\uacfc)\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\uc774\ub97c \ud1b5\ud574 \ud2b9\uc815 \uc870\uac74\uc5d0\uc11c \uba54\uc11c\ub4dc\uac00 \uc608\uc0c1\ud55c\ub300\ub85c \ub3d9\uc791\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4. \\n\\n### \uc2a4\ud30c\uc774(Spy)\\n\\n\uc2a4\ud141\uacfc \uc720\uc0ac\ud558\uc9c0\ub9cc \ud638\ucd9c \uc5ec\ubd80\ub97c \uae30\ub85d\ud558\uac70\ub098 \ud638\ucd9c\ud560 \ub54c \uc804\ub2ec\ud55c \uc778\uc790\uac12\uc744 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4. \\n\uc608) \uba54\uc77c \uc804\uc1a1 \uae30\ub2a5\uc744 \uac00\uc9c4 \uac1d\uccb4\ub97c \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc73c\ub85c \uad6c\ud604\ud588\uc744 \ub54c \uba54\uc77c \uc804\uc1a1 \ud69f\uc218\ub97c \uae30\ub85d\ud55c\ub2e4. \\n\\n### \ubaa9, \ubaa8\uc758 \uac1d\uccb4(Mock)\\n\\n\ubaa9\uc740 \ub354\ubbf8, \uc2a4\ud141, \uc2a4\ud30c\uc774\ub97c \ud3ec\ud568\ud55c\ub2e4. \\n\ud638\ucd9c \uc2dc \uc0ac\uc804\uc5d0 \uc815\uc758\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud558\uace0, \uc608\uc0c1\uce58 \ubabb\ud55c \ud638\ucd9c\uc774 \uc788\uc744 \uacbd\uc6b0 \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\ub610\ud55c \ud638\ucd9c\uc5d0 \ub300\ud55c \uac80\uc99d\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\\n### \uac00\uc9dc(Fake)\\n\\nDOC\uc640 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\uc9c0\ub9cc, \ub354\uc6b1 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ub41c \uac83\uc774\ub2e4. \\n\uc608) \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc720\uc0ac\ud558\uac8c \ub3d9\uc791\ud558\ub294 \uac00\uc9dc \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note DOC(depended-on component)\\n\\n\uc758\uc874 \uad6c\uc131 \uc694\uc18c, DOC\ub97c \ud14c\uc2a4\ud2b8 \ub354\ube14\ub85c \ub300\uccb4\ud560 \uc218 \uc788\ub2e4. \\n\ud14c\uc2a4\ud2b8 \ub354\ube14\uc740 DOC\uc640 \ub3d9\uc77c\ud55c API\ub97c \uc81c\uacf5\ud574\uc57c \ud55c\ub2e4. \\n\\n:::\\n\\n### \uc0c1\ud638\uc791\uc6a9\uc5d0 \ub530\ub978 \ubaa9\uacfc \uc2a4\ud141 \uad6c\ubd84\\n\\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 p.149 \uc5d0\uc11c\ub294 \ud14c\uc2a4\ud2b8 \ub300\uc5ed\uc744 \ud06c\uac8c \ubaa9\uacfc \uc2a4\ud141\uc73c\ub85c \uad6c\ubd84\ud55c\ub2e4. \\n\ubaa9\uc740 SUT\uc640 \uad00\ub828\ub41c \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ubc18\uba74, \uc2a4\ud141\uc740 \ub2e8\uc21c \ubaa8\ubc29\ub9cc \ud55c\ub2e4. \\n\\n| TestDouble | Mock | Stub |\\n| --- | --- | --- |\\n| \ud3ec\ud568 \uc720\ud615 | \ubaa9, \uc2a4\ud30c\uc774 | \uc2a4\ud141, \ub354\ubbf8, \ud398\uc774\ud06c |\\n| \uc6a9\ub3c4 | \uc678\ubd80\ub85c \ub098\uac00\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\uace0 \uac80\uc0ac\ud558\ub294 \ub370 \uc0ac\uc6a9 | \ub0b4\ubd80\ub85c \ub4e4\uc5b4\uc624\ub294 \uc0c1\ud638\uc791\uc6a9\uc744 \ubaa8\ubc29\ud558\ub294 \ub370 \uc0ac\uc6a9 |\\n| \uc124\uba85 | SUT\uac00 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9 | SUT\uac00 \uc785\ub825 \ub370\uc774\ud130\ub97c \uc5bb\uae30 \uc704\ud55c \uc758\uc874\uc131\uc744 \ud638\ucd9c\ud558\ub294 \uac83\uc5d0 \ud574\ub2f9\\n| \uc608\uc2dc | \uc774\uba54\uc77c \ubc1c\uc1a1 | \ub370\uc774\ud130 \uac80\uc0c9 |\\n\\n:::note SUT(system under test)\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1 \uc2dc\uc2a4\ud15c \\n\ud14c\uc2a4\ud2b8\ub97c \ud558\ub824\ub294 \ub300\uc0c1\\n\\n:::\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc7a5\uc778 \uc815\uc2e0 \uc774\uc57c\uae30 - 3\uc7a5 \uace0\uae09 \ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c, \ub85c\ubc84\ud2b8 C. \ub9c8\ud2f4 \\n\ub2e8\uc704 \ud14c\uc2a4\ud2b8 - 5\uc7a5 \ubaa9\uacfc \ud14c\uc2a4\ud2b8 \ucde8\uc57d\uc131, \ube14\ub77c\ub514\ubbf8\ub974 \ucf54\ub9ac\ucf54\ud504 \\n\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c \uc2dc\uc791\ud558\uae30 - 7\uc7a5 \ub300\uc5ed, \ucd5c\ubc94\uade0 \\n[\ud14c\uc2a4\ud2b8 \ub354\ube14, Martin Fowler](https://www.martinfowler.com/bliki/TestDouble.html) \\n[\ud14c\uc2a4\ud2b8 \uad00\ub828 \uc6a9\uc5b4 \uc815\ub9ac, Johngrib](https://johngrib.github.io/wiki/test-terms/) \\n[Test Double, Gerard Meszaros](http://xunitpatterns.com/Test%20Double.html)"},{"id":"java-class-file","metadata":{"permalink":"/java-class-file","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","source":"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx","title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","description":"\ud074\ub798\uc2a4 \ud30c\uc77c","date":"2023-04-03T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 3\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Class","permalink":"/tags/class"}],"readingTime":5.63,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","slug":"java-class-file","tags":["Java","Class"]},"prevItem":{"title":"\ud14c\uc2a4\ud2b8 \ub300\uc5ed","permalink":"/test-double"},"nextItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"}},"content":"### \ud074\ub798\uc2a4 \ud30c\uc77c\\n\\n\uc790\ubc14 \uc18c\uc2a4\ucf54\ub4dc\uac00 \uc2e4\ud589\uc774 \ub418\ub824\uba74 \uc790\ubc14 \ucef4\ud30c\uc77c\ub7ec(javac)\ub97c \ud1b5\ud574 \uc18c\uc2a4\ucf54\ub4dc\ub97c \ud074\ub798\uc2a4\ud30c\uc77c\ub85c \ubcc0\ud658\ud574\uc57c \ud55c\ub2e4. \\n\ucef4\ud30c\uc77c\ub41c \ud074\ub798\uc2a4\ud30c\uc77c\uc740 \uc5b4\ub5a4 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744\uae4c?\\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \ub370\uc774\ud130 \ud615\uc2dd\\n\\n8\ube44\ud2b8 \ubc14\uc774\ud2b8\uc758 \uc2a4\ud2b8\ub9bc\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4. \\n16\ube44\ud2b8 \ubc0f 32\ube44\ud2b8\uc758 \ub370\uc774\ud130\ub294 \uac01\uac01 2\uac1c, 4\uac1c\uc758 \uc5f0\uc18d\ub41c 8\ube44\ud2b8\ub97c \uc77d\uc5b4\uc11c \uad6c\uc131\ub41c\ub2e4. \\n\uba40\ud2f0\ubc14\uc774\ud2b8\uc758 \uacbd\uc6b0 \ud56d\uc0c1 big endian \uc21c\uc11c\ub85c \uc800\uc7a5\ub41c\ub2e4. \\n\\nu1 \u2192 unsigned 1byte \\nu2 \u2192 unsigned 2byte \\nu4 \u2192 unsigned 4byte \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870\\n\\n```\\nClassFile {\\n u4 magic;\\n u2 minor_version;\\n u2 major_version;\\n u2 constant_pool_count;\\n cp_info constant_pool[constant_pool_count-1];\\n u2 access_flags;\\n u2 this_class;\\n u2 super_class;\\n u2 interfaces_count;\\n u2 interfaces[interfaces_count];\\n u2 fields_count;\\n field_info fields[fields_count];\\n u2 methods_count;\\n method_info methods[methods_count];\\n u2 attributes_count;\\n attribute_info attributes[attributes_count];\\n}\\n```\\n\\n### \ub9e4\uc9c1\ub118\ubc84\\n\\n\ubaa8\ub4e0 \ud074\ub798\uc2a4 \ud30c\uc77c\uc740 0xCAFEBABE\ub77c\ub294 \ub9e4\uc9c1\ub118\ubc84\ub85c \uc2dc\uc791\ud55c\ub2e4. \\n\ubcf4\ud1b5 \ub9e4\uc9c1\ub118\ubc84\ub294 \ud30c\uc77c \uc885\ub958\ub97c \uc2dd\ubcc4\ud558\ub294 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ub41c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud3ec\ub9f7 \ubc84\uc804\\n\\n\ud074\ub798\uc2a4 \ud30c\uc77c \ubc84\uc804 \uac12\uc740 \ud074\ub798\uc2a4\ub85c\ub354\uc758 \ud638\ud658\uc131 \ubcf4\uc7a5\uc744 \uc704\ud574 \uaf2d \ud544\uc694\ud55c \uac12\uc774\ub2e4. \\n- Java 17 \ubc84\uc804\uc73c\ub85c \ube4c\ub4dc\ud55c\ub2e4\uba74 class version 61 ex) 00 00 00 3D\\n\\n\ud638\ud658\ub418\uc9c0 \uc54a\ub294 \ubc84\uc804\uc758 \ud074\ub798\uc2a4 \ud30c\uc77c\uc744 \ub85c\ub529\ud558\ub824\uace0 \ud558\ub294 \uacbd\uc6b0 \ub7f0\ud0c0\uc784\uc5d0 `UnsupportedClassVersionError` \uc608\uc678\uac00 \ubc1c\uc0dd\ud55c\ub2e4. \\n\\n**class\xa0file format major versions**\\n\\n| Java SE | Released | Major | Supported majors |\\n| --- | --- | --- | --- |\\n| 8 | March 2014 | 52 | 45 .. 52 |\\n| 9 | September 2017 | 53 | 45 .. 53 |\\n| 10 | March 2018 | 54 | 45 .. 54 |\\n| 11 | September 2018 | 55 | 45 .. 55 |\\n| 12 | March 2019 | 56 | 45 .. 56 |\\n| 13 | September 2019 | 57 | 45 .. 57 |\\n| 14 | March 2020 | 58 | 45 .. 58 |\\n| 15 | September 2020 | 59 | 45 .. 59 |\\n| 16 | March 2021 | 60 | 45 .. 60 |\\n| 17 | September 2021 | 61 | 45 .. 61 |\\n\\n### \uc0c1\uc218 \ud480\\n\\n2\ubc14\uc774\ud2b8\uc758 \uc0c1\uc218\uc758 \uac1c\uc218\uac12\uc774 \uba3c\uc800\uc624\uace0 \uadf8 \ub4a4\ub85c \ucf54\ub4dc\uc5d0 \ub4f1\uc7a5\ud558\ub294 \uc0c1\uc218\uac12\uc774 \ubaa8\uc5ec\uc788\ub2e4. \\n\ud074\ub798\uc2a4\uba85, \uc0c1\uc218\uba85, \uc0c1\uc218 \uac12, \ud544\ub4dc\uba85, \uba54\uc11c\ub4dc\uba85\uacfc \uac19\uc740 \uac12\ub4e4\uc774 \uc874\uc7ac\ud55c\ub2e4. \\nJVM\uc740 \ucf54\ub4dc \uc2e4\ud589 \uc2dc \ub7f0\ud0c0\uc784\uc5d0 \ubc30\uce58\ub41c \uba54\ubaa8\ub9ac\uac00 \uc544\ub2c8\ub77c, \ud574\ub2f9 \uc0c1\uc218 \ud480 \ud14c\uc774\ube14\uc744 \ucc3e\uc544\ubcf4\uace0 \ud544\uc694\ud55c \uac12\uc744 \ucc38\uc870\ud55c\ub2e4.\\n\\n### \uc561\uc138\uc2a4 \ud50c\ub798\uadf8\\n\\n\ud074\ub798\uc2a4, \uc778\ud130\ud398\uc774\uc2a4\uc640 \uac19\uc740 \ud30c\uc77c\uc758 \uc18d\uc131\uc744 \ud45c\uc2dc\ud55c\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 public interface\ub85c \uc815\uc758\ub41c \uc778\ud130\ud398\uc774\uc2a4\uc758 \ud50c\ub798\uadf8\ub294 0x0601\uc774\ub2e4. \\n- \uacc4\uc0b0\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. `ACC_PUBLIC` xor `ACC_INTERFACE` xor `ACC_ABSTRACT`\\n\\n\uacf5\uc2dd\ubb38\uc11c\uc5d0 \ub4e4\uc5b4\uac00\uba74 \uac01 \ud50c\ub798\uadf8\uc5d0 \ub300\ud55c \uc124\uba85 + \ud50c\ub798\uadf8 \uc124\uc815\uc2dc \ub3d9\uc2dc\uc5d0 \uc124\uc815\ub418\uba74 \uc548\ub418\ub294 \ud50c\ub798\uadf8\uc640 \uac19\uc740 \uc124\uba85\uc774 \uc790\uc138\ud558\uac8c \ub098\uc640\uc788\ub2e4.\\n\\n**Class access and property modifiers**\\n\\n| Flag Name | Value | Interpretation |\\n| --- | --- | --- |\\n| ACC_PUBLIC | 0x0001 | Declared\xa0public; may be accessed from outside its package. |\\n| ACC_FINAL | 0x0010 | Declared\xa0final; no subclasses allowed. |\\n| ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the\xa0invokespecial\xa0instruction. |\\n| ACC_INTERFACE | 0x0200 | Is an interface, not a class. |\\n| ACC_ABSTRACT | 0x0400 | Declared\xa0abstract; must not be instantiated. |\\n| ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |\\n| ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |\\n| ACC_ENUM | 0x4000 | Declared as an\xa0enum\xa0type. |\\n| ACC_MODULE | 0x8000 | Is a module, not a class or interface. |\\n\\n### this_class\\n\\n\ud074\ub798\uc2a4\uba85\uacfc \uac19\uc740 \uc774\ub984\uc744 \ud45c\ud604\ud558\ub294 \uac12\uc73c\ub85c, \uc0c1\uc218 \ud480\uc5d0\uc11c \ud074\ub798\uc2a4\uba85\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\ud574\ub2f9 \uc778\ub371\uc2a4\uc758 \ud56d\ubaa9\uc740 `CONSTANT_Class_infoclass` \ud615\uc2dd\uc758 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\\n### super_class\\n\\n\uc0c1\uc218 \ud480\uc5d0\uc11c \uc288\ud37c \ud074\ub798\uc2a4\uc758 \uc774\ub984\uacfc \uc77c\uce58\ud558\ub294 \ud56d\ubaa9\uc758 \uc778\ub371\uc2a4\ub97c \ucc38\uc870\ud55c\ub2e4. \\n\uc544\ubb34\uac83\ub3c4 \uc0c1\uc18d\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\uc758 \uacbd\uc6b0 `java.lang.Object`\uc758 \uc778\ub371\uc2a4 \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4.\\n\\n### interface, field, method\\n\\n\uac01\uac01\uc758 \uac1c\uc218\uc640, \uc815\ubcf4\uc5d0 \ub300\ud55c \uac12\uc774 \ub4e4\uc5b4\uc788\ub2e4. \\ninterface, field, method\ub97c \ud45c\uc2dc\ud558\ub294 \ubc29\ubc95\uc774 \uac01\uac01 \ub2e4\ub974\uace0, \uc811\uadfc\uc790\uc5d0 \ub300\ud55c \ud50c\ub798\uadf8\ub3c4 \uac01\uac01 \ub2e4\ub974\ub2e4.\\n\\n### attributes\\n\\n\ud574\ub2f9 \ud074\ub798\uc2a4 \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ucd94\uac00 \uc815\ubcf4\uc758 \ubaa8\uc74c\uc774\ub2e4. \uc608) \uc18c\uc2a4\ud30c\uc77c\uba85 \\n\uc815\ud574\uc9c4 \ud074\ub798\uc2a4 \ud30c\uc77c\uc758 \uad6c\uc870\ub97c \ud655\uc7a5\ud558\ub294 \uc5ed\ud560\uc744 \ud55c\ub2e4. \\n\\n### \ud074\ub798\uc2a4 \ud30c\uc77c \ud655\uc778\ud558\uba74\uc11c \uc0ac\uc6a9\ud55c \ud234\\n\\nIntelliJ plugin - BinEd \\nIntelliJ plugin - jclasslib Bytecode Viewer\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n2\uc7a5 JVM \uc774\uc57c\uae30, \uc790\ubc14 \ucd5c\uc801\ud654 \\n[Class file in Java, File Format](https://docs.fileformat.com/ko/programming/class/) \\n[java se11 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html) \\n[java se17 Class \ud30c\uc77c \ud615\uc2dd, Oracle](https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html)"},{"id":"custom-jdbc-template","metadata":{"permalink":"/custom-jdbc-template","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","source":"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx","title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","description":"\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4.","date":"2023-04-02T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 2\uc77c","tags":[{"label":"JDBC","permalink":"/tags/jdbc"},{"label":"Java","permalink":"/tags/java"}],"readingTime":9.025,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","slug":"custom-jdbc-template","tags":["JDBC","Java"]},"prevItem":{"title":"\uc790\ubc14 \ud074\ub798\uc2a4 \ud30c\uc77c \uad6c\uc870","permalink":"/java-class-file"},"nextItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\uc11c\ub294 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uac00\uc838\uc624\uae30 \uc704\ud574 DAO\ub97c \uc0ac\uc6a9\ud588\ub2e4. \\n\uc774 \ub54c JDBC\ub97c \uc0ac\uc6a9\ud560 \ub54c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \ucee4\ub125\uc158\uc744 \uc5bb\uace0, try-with-resource\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84\uc774 \ubc18\ubcf5\ub418\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc744 \uc774\uc6a9\ud558\uc5ec \ub098\ub9cc\uc758 JdbcTemplate\uc744 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4. \\n\\n### \uae30\uc874 \ucf54\ub4dc\\n\\n\\n\\n\\n```java\\npublic class User {\\n private final int id;\\n private final String name;\\n\\n public User(final int id, final String name) {\\n this.id = id;\\n this.name = name;\\n }\\n\\n public int getId() {\\n return id;\\n }\\n\\n public String getName() {\\n return name;\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final ConnectionPool connectionPool;\\n\\n public UserDao(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void insert(final String name) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setString(1, name);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public void delete(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"DELETE FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public User findById(final int userId) {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n preparedStatement.setInt(1, userId);\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n if (resultSet.next()) {\\n return new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n );\\n }\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n return null;\\n }\\n\\n public List findAll() {\\n final Connection connection = connectionPool.getConnection();\\n final String query = \\"SELECT * FROM user\\";\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n final ResultSet resultSet = preparedStatement.executeQuery();\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(new User(\\n resultSet.getInt(\\"id\\"),\\n resultSet.getString(\\"name\\")\\n ));\\n }\\n return result;\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n\\n\\n\\n```java\\npublic class ConnectionPool {\\n private static final String SERVER = \\"localhost:13306\\";\\n private static final String DATABASE = \\"chess\\";\\n private static final String OPTION = \\"?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true\\";\\n private static final String URL = \\"jdbc:mysql://\\" + SERVER + \\"/\\" + DATABASE + OPTION;\\n private static final String USERNAME = \\"root\\";\\n private static final String PASSWORD = \\"root\\";\\n\\n private final AtomicInteger index = new AtomicInteger();\\n private final List connections;\\n\\n public ConnectionPool(final int connectionCount) {\\n connections = generateConnections(connectionCount);\\n }\\n\\n private List generateConnections(final int connectionCount) {\\n return Stream.generate(this::generateConnection)\\n .limit(connectionCount)\\n .collect(toList());\\n }\\n\\n private Connection generateConnection() {\\n try {\\n return DriverManager.getConnection(URL, USERNAME, PASSWORD);\\n } catch (SQLException e) {\\n throw new IllegalStateException(\\"\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\\");\\n }\\n }\\n\\n public Connection getConnection() {\\n int currentIndex = index.getAndIncrement();\\n return connections.get(currentIndex % connections.size());\\n }\\n}\\n```\\n\\n\\n\\n\\n### SELECT, DELETE \uc911\ubcf5 \uc81c\uac70\\n\\n\ubcc0\ud558\uc9c0 \uc54a\ub294 \ubd80\ubd84: try-with-resource, preparedStatement\ub97c \uc0ac\uc6a9\ud558\ub294 \ubd80\ubd84, executeUpdate\ub85c \uc2e4\ud589 \ub4f1\ub4f1 \\n\ubcc0\ud558\ub294 \ubd80\ubd84: SQL Query, \ub9e4\uac1c\ubcc0\uc218 \\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 \ucffc\ub9ac\ub97c \uc2e4\ud589\ud558\ub294 \ubd80\ubd84\uc744 \ubd84\ub9ac\ud558\uace0 \uac00\ubcc0\uc778\uc218\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 SELECT\uc640 DELETE\uc758 \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n```java\\npublic void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n executeUpdate(query, name);\\n}\\n\\npublic void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n executeUpdate(query, userId);\\n}\\n\\nprivate void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 1. \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4 \uc815\uc758\\n\\n\uc870\ud68c\ub294 INSERT, DELETE\uc640 \ub2ec\ub9ac \uac12\uc744 \ubc18\ud658\ubc1b\uc544\uc57c \ud558\uae30 \ub54c\ubb38\uc5d0 \ub2e4\ub978 \ubc29\ubc95\uc744 \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4. \\n\uc774 \ub54c \ucf5c\ubc31\uc774\ub77c\ub294 \uac83\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\\n:::note \ucf5c\ubc31(Callback)\\n\\n\ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c \ucf5c\ubc31\uc740 \ub2e4\ub978 \ucf54\ub4dc\uc758 \uc778\uc218\ub85c \ub118\uaca8\uc8fc\ub294 \uc2e4\ud589 \uac00\ub2a5\ud55c \ucf54\ub4dc\ub97c \ub73b\ud55c\ub2e4. \\n\uc790\ubc14\uc5d0\uc11c\ub294 \ub78c\ub2e4\ub098 \uc775\uba85 \ud074\ub798\uc2a4\ub97c \ub118\uaca8\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n```mermaid\\nflowchart LR\\n \ud074\ub77c\uc774\uc5b8\ud2b8 -- \ucf5c\ubc31\uc804\ub2ec --\x3e \uba54\uc11c\ub4dc\\n \uba54\uc11c\ub4dc -- \ub0b4\ubd80\ud638\ucd9c --\x3e \uc804\ub2ec\ubc1b\uc740\ucf5c\ubc31\\n```\\n\\n:::\\n\\n\\n\ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \uac12\uc744 \uc870\ud68c\ud558\uace0, \ud574\ub2f9 \uac12\uc744 \uac1d\uccb4\ub85c \ub9e4\ud551\ud558\uc5ec \uac12\uc744 \ubc18\ud658\ud574\uc57c \ud55c\ub2e4. \\nexecuteQuery\ub85c \uc870\ud68c\ud55c \uac12\uc740 ResultSet \uc548\uc5d0 \ub4e4\uc5b4\uac00\uc788\ub2e4. \\n\uc774\ub97c \uc6d0\ud558\ub294 \ud0c0\uc785\uc758 \uac12\uc73c\ub85c \ubcc0\ud658\ud574\uc57c\ud558\ub2c8 \uc77c\ub2e8 \ucf5c\ubc31\uc744 \uc704\ud55c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub9cc\ub4e4\uc5b4\uc57c \ud55c\ub2e4. \\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n User mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 2. \ub2e8\uac74 \uc870\ud68c\\n\\n\uc704\uc5d0\uc11c \uc815\uc758\ud55c RowMapper\ub97c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc5b4\ub5bb\uac8c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c? \\n\uc544\ub798\uc640 \uac19\uc774 SQL \ucffc\ub9ac, RowMapper, \ud30c\ub77c\ubbf8\ud130\ub97c \ubd84\ub9ac\ud55c \uba54\uc11c\ub4dc\uc5d0 \ub118\uaca8\uc8fc\uace0 \ucffc\ub9ac \uc2e4\ud589 \ud6c4 \ub9e4\ud551\ud55c \uac12\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud55c\ub2e4. \\n\\n```java\\npublic User findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return queryForSingleResult(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n }, userId);\\n}\\n\\nprivate User queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return rowMapper.mapRow(resultSet);\\n }\\n return null;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc870\ud68c \ubd84\ub9ac\ud558\uae30 - 3. \ub2e4\uac74 \uc870\ud68c\\n\\n\ub2e8\uac74 \uc870\ud68c\uc640 \uc720\uc0ac\ud558\ub2e4.\\n\\n```java\\npublic List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return query(query, resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n });\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n}\\n\\nprivate ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n}\\n```\\n\\n### \uc81c\ub124\ub9ad \uc0ac\uc6a9\ud558\uae30\\n\\n\uc704\uc758 \ucf54\ub4dc\ub294 User\ub97c \uc870\ud68c\ud560 \ub54c\ub9cc \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4. \\n\uc544\ub798\uc640 \uac19\uc774 \uc81c\ub124\ub9ad\uc744 \uc801\uc6a9\ud558\uc5ec \ub2e4\ub978 Dao\uc5d0\uc11c\ub3c4 \uc0ac\uc6a9 \uac00\ub2a5\ud558\ub3c4\ub85d \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\n@FunctionalInterface\\npublic interface RowMapper {\\n T mapRow(final ResultSet resultSet) throws SQLException;\\n}\\n\\nprivate List query(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\nprivate T queryForSingleResult(final String query, final RowMapper rowMapper, final Object... parameters) {...}\\n```\\n\\n### \uba54\uc11c\ub4dc \ubd84\ub9ac\ud55c \ubd80\ubd84 \ud074\ub798\uc2a4\ub85c \ubd84\ub9ac\ud558\uae30 + Optional \uc0ac\uc6a9\ud558\uae30\\n\\n\uba54\uc11c\ub4dc\ub85c \ubd84\ub9ac\ud55c \ubd80\ubd84\uc744 JdbcTemplate\uc774\ub77c\ub294 \ud074\ub798\uc2a4\ub97c \ub9cc\ub4e4\uc5b4 \uc62e\uae34\ub2e4. \\n\ub610\ud55c null\uc744 \ubc18\ud658\ud558\uae30 \ubcf4\ub2e8 Optional\ub85c \uac10\uc2f8\uc11c \ubc18\ud658\ud558\ub3c4\ub85d \ubcc0\uacbd\ud55c\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc740 \ucf54\ub4dc\uac00 \uc644\uc131\ub41c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic class UserDao {\\n private final RowMapper rowMapper = resultSet -> {\\n final int id = resultSet.getInt(\\"id\\");\\n final String name = resultSet.getString(\\"name\\");\\n return new User(id, name);\\n };\\n private final JdbcTemplate jdbcTemplate;\\n\\n public UserDao(final JdbcTemplate jdbcTemplate) {\\n this.jdbcTemplate = jdbcTemplate;\\n }\\n\\n public void insert(final String name) {\\n final String query = \\"INSERT INTO User (name) VALUES (?)\\";\\n jdbcTemplate.executeUpdate(query, name);\\n }\\n\\n public void delete(final int userId) {\\n final String query = \\"DELETE FROM user WHERE user_id = ?\\";\\n jdbcTemplate.executeUpdate(query, userId);\\n }\\n\\n public Optional findById(final int userId) {\\n final String query = \\"SELECT * FROM user WHERE id = ?\\";\\n return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);\\n }\\n\\n public List findAll() {\\n final String query = \\"SELECT * FROM user\\";\\n return jdbcTemplate.query(query, rowMapper);\\n }\\n}\\n```\\n\\n\\n\\n\\n```java\\npublic class JdbcTemplate {\\n private final ConnectionPool connectionPool;\\n\\n public JdbcTemplate(final ConnectionPool connectionPool) {\\n this.connectionPool = connectionPool;\\n }\\n\\n public void executeUpdate(final String query, final Object... parameters) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n preparedStatement.executeUpdate();\\n } catch (final SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n public Optional queryForSingleResult(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n if (resultSet.next()) {\\n return Optional.of(rowMapper.mapRow(resultSet));\\n }\\n return Optional.empty();\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n\\n private ResultSet executeQuery(\\n final PreparedStatement preparedStatement,\\n final Object[] parameters\\n ) throws SQLException {\\n for (int i = 1; i <= parameters.length; i++) {\\n preparedStatement.setObject(i, parameters[i - 1]);\\n }\\n return preparedStatement.executeQuery();\\n }\\n\\n public List query(\\n final String query,\\n final RowMapper rowMapper,\\n final Object... parameters\\n ) {\\n final Connection connection = connectionPool.getConnection();\\n try (final PreparedStatement preparedStatement = connection.prepareStatement(query);\\n final ResultSet resultSet = executeQuery(preparedStatement, parameters)) {\\n final List result = new ArrayList<>();\\n while (resultSet.next()) {\\n result.add(rowMapper.mapRow(resultSet));\\n }\\n return result;\\n } catch (SQLException e) {\\n throw new IllegalArgumentException(e.getMessage());\\n }\\n }\\n}\\n```\\n\\n\\n"},{"id":"woowacourse-level1-retrospective","metadata":{"permalink":"/woowacourse-level1-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","source":"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx","title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","description":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4.","date":"2023-04-01T00:00:00.000Z","formattedDate":"2023\ub144 4\uc6d4 1\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.48,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","slug":"woowacourse-level1-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30","permalink":"/custom-jdbc-template"},"nextItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"}},"content":"\ub808\ubca8 1\uc774 \ub05d\ub0ac\ub2e4. \\n\uc6b0\ud14c\ucf54\ub97c \uc2dc\uc791\ud558\uae30 \uc804 \ub0b4\uac00 \uc815\ud574\ub450\uc5c8\ub358 \ubaa9\ud45c \uc774\uc0c1\uc73c\ub85c \ub2ec\uc131\ud588\uae30 \ub54c\ubb38\uc5d0 \ub9e4\uc6b0 \ub9cc\uc871\uc2a4\ub7fd\ub2e4. \\n\ud63c\uc790 \ub3c5\ud559\uc744 \ud560 \ub550 \uc774 \ubc29\ud5a5\uc73c\ub85c \uacf5\ubd80\ud558\ub294 \uac8c \ub9de\ub294\uc9c0 \uacc4\uc18d \ubc18\ucd94\ud558\ub2e4 \uacb0\uad6d \ubb34\uae30\ub825\ud568\uc5d0 \ube60\uc838\ub4e4\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uc774\uc81c\ub294 \uac19\uc774 \uacf5\ubd80\ud560 \uc0ac\ub78c\ub3c4 \uc788\uace0, \uc774\uc57c\uae30\ud560 \uc0ac\ub78c\ub3c4 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc990\uae30\ub294 \uc77c\ub9cc \ub0a8\uc740 \uac83 \uac19\ub2e4. \\n\\n### Keep\\n\\n**\ub098\ub9cc\uc758 \ub8e8\ud2f4 \ub9cc\ub4e4\uae30** \\n\\n\uc2a4\uc2a4\ub85c\uac00 \uc678\ubd80\uc758 \uc601\ud5a5\uc744 \ub9ce\uc774 \ubc1b\ub294\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ucd5c\ub300\ud55c \uafb8\uc900\ud788 \ud560 \uc218 \uc788\ub294 \uc2dc\uac04\uc744 \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\\n\ub9e4\uc77c 8\uc2dc\uc5d0 \ub3c4\ucc29\ud558\uc5ec \uc544\uce68\uc5d0 \ud574\uc57c \ud560 \uc77c\uc744 \uc815\ub9ac\ud558\uac70\ub098, \uc6b0\uc120\uc21c\uc704\uc5d0 \ub530\ub77c \ucc98\ub9ac\ud558\uace0 \\n\uc18c\ud654\ub2a5\ub825\uc774 \ubd80\uc871\ud558\uae30 \ub54c\ubb38\uc5d0 \uc810\uc2ec\uc740 \ub3c4\uc2dc\ub77d(\uadf8\ub798\ubd24\uc790 \uacc4\ub7802\uac1c)\uc744 \uc900\ube44\ud558\uace0 \\n\ud56d\uc0c1 \ub611\uac19\uc740 \ucee8\ub514\uc158\uc744 \uc720\uc9c0\ud558\uae30 \uc704\ud574 \ud56d\uc0c1 6\uc2dc\uc5d0 \uc9d1\uc5d0 \uac04\ub2e4. \\n\uc774\uc81c \ubc14\ube60\uc9c8 \ud14c\ub2c8 \uc77c\ucc0d \uc9d1\uc5d0 \uac00\ub294 \uc77c\uc740 \uc5b4\uca54 \uc218 \uc5c6\uc774 \uc904\uc5b4\ub4e4\uaca0\uc9c0\ub9cc\ud83d\ude22 \\n\\n\uc120\ud0dd\ub3c4 \ube44\uc6a9\uc774\ub2e4. \uc55e\uc73c\ub85c \uc758\uc0ac\uacb0\uc815\uc774 \ud544\uc694 \uc5c6\ub294 \ubd80\ubd84\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\ub4e4\uc5b4\uc57c\uaca0\ub2e4. \\n\\n**\ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uae30** \\n\\n10\uba85 \uc815\ub3c4\uc758 \ud06c\ub8e8\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b0\uace0 \uce5c\ud558\uac8c \uc9c0\ub0b8\ub2e4\uba74 \uc131\uacf5\uc801\uc774\ub77c\uace0 \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \ub354 \ub9ce\uc740 \ud06c\ub8e8\ub4e4\uc758 \ub2c9\ub124\uc784\uc744 \uc678\uc6b4 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c\ub3c4 \ud06c\ub8e8\ub4e4\uacfc \uce5c\ud558\uac8c \uc9c0\ub0b4\uace0 \uc544\ubb34 \ub54c\ub098 \ub9d0\uc744 \uac78 \uc218 \uc788\ub294 \ud06c\ub8e8\uac00 \ub298\uc5b4\ub098\uae38 :) \\n\\n**\uae00\uc4f0\uae30** \\n\\n\uae00\uc744 \uc798 \uc4f0\ub294 \ud3b8\uc740 \uc544\ub2c8\uc9c0\ub9cc \uafb8\uc900\ud788 \uc791\uc131\ud558\ub824\uace0 \ub178\ub825\ud588\ub2e4. \\n\ub9e4 \ubbf8\uc158\ub9c8\ub2e4 \ud68c\uace0\ub97c \uc791\uc131\ud558\ub2c8 \uc0dd\uac01\ub3c4 \uc815\ub9ac\ub418\uace0 \uac1c\uc120\uc810\ub3c4 \ucc3e\uc744 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\ub2e4. \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\uc5d0\ub294 \ub808\ubca8\ub9c8\ub2e4 \uae00\uc4f0\uae30\ub97c \uc9c4\ud589\ud558\ub294\ub370, \uc6b4\uc774 \uc88b\uac8c \uae00\uc4f0\uae30 \uc0c1\uc744 \ubc1b\uc558\ub2e4. \\n\uc0ac\uc2e4 \uac89\uc73c\ub85c \ub4dc\ub7ec\ub0b4\uc9c0 \uc54a\uc558\uc9c0\ub9cc \uaf2d \ubc1b\uc544\ubcf4\uace0 \uc2f6\uc5c8\ub2e4. \\n\uae00\uc4f0\uae30 \uc870\uc6d0, \ud22c\ud45c\ud574 \uc900 \ud06c\ub8e8\ub4e4\uc5d0\uac8c \ub108\ubb34 \uac10\uc0ac\ud558\ub2e4. \\n\\n**\ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514** \\n\\n\ub204\ub204, \uc8fc\ub178, \ub2e4\uc990, \ub9d0\ub791, \ubc15\uc2a4\ud130, \uc624\uc789, \uae43\uc9f1\uc640 \ucf54\ub4dc \ub9ac\ubdf0 \uc2a4\ud130\ub514\ub97c \uc9c4\ud589\ud588\ub2e4. \\n\uacfc\uc5f0 \ub3c4\uc6c0\uc774 \ub420\uae4c \uc0dd\uac01\ud588\uc9c0\ub9cc \uacb0\uacfc\uc801\uc73c\ub85c\ub294 \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud558\uba74\uc11c \uc131\uc7a5\uc744 \ub9ce\uc774 \ud55c \uac83 \uac19\ub2e4. \\n\ud22c\uc790\ud55c \uc2dc\uac04 \ub300\ube44 \uac00\uc131\ube44\uac00 \uc88b\uc740 \ud65c\ub3d9\uc774\uc5c8\ub2e4. \\n\ub204\ub204\uac00 \uc2a4\ud130\ub514\uc7a5\uc778\ub370 \uacfc\uc5f0 \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00\ub824\ub098? \\n\\n**\ub808\ubca8 \uc778\ud130\ubdf0**\\n\\n\uc778\ud130\ubdf0\ud560 \ub54c \ub9ce\uc774 \ub5a8\uc9c0 \uc54a\uc544\uc11c \uc88b\uc558\ub2e4. \\n\ub0a8\ub4e4 \uc55e\uc5d0\uc11c \uc774\uc57c\uae30\ub97c \ud558\uac70\ub098, \uba74\uc811\uc744 \ubcf4\uba74 \ud56d\uc0c1 \uc5c4\uccad \ub5a8\uc5b4\uc11c \uac71\uc815\ud588\ub294\ub370 \\n\uae30\uc220\uc801\uc778 \uc9c8\ubb38\uc744 \ubc1b\uc558\uc744 \ub54c \ub5a8\uc9c0 \uc54a\uace0 \uc798 \ub300\ub2f5\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \ub2e4\ub978 \ud06c\ub8e8\uac00 \uc9c8\ubb38\ud588\uc744 \ub54c, \ucd5c\ub300\ud55c \uc774\ud574\ud558\uae30 \uc27d\uac8c \uc124\uba85\ud558\ub824\uace0 \ud588\ub358 \uacbd\ud5d8\uc774 \ub3c4\uc6c0\uc774 \ub41c \uac83 \uac19\ub2e4. \\n\uc774\ud6c4 \ub808\ubca8 \uc778\ud130\ubdf0\ub97c \uc9c4\ud589\ud560 \ub54c \ub2e4\uc74c\uacfc \uac19\uc740 \ubd80\ubd84\uc744 \uace0\ub824\ud558\uba74 \ub354 \uc88b\uc744 \uac83 \uac19\ub2e4. \\n- \ub300\ub2f5\ud558\uba74\uc11c \uc9c8\ubb38\uc744 \uacc4\uc18d \uc0dd\uac01\ud558\uba70 \uc78a\uc5b4\ubc84\ub9ac\uc9c0 \ub9d0\uae30 \\n- \ub450\uad04\uc2dd \ud45c\ud604\\n- \uc124\uba85\ud558\ub2e4\uac00 \uc798\ubabb \uc124\uba85\ud55c \uac83 \uac19\uc73c\uba74 \ub2e4 \ub04a\uace0 \ub2e4\uc2dc \uc774\uc57c\uae30\ud574\ub3c4 \ub420\uc9c0 \ubb3c\uc5b4\ubcf4\uae30 \\n- \uc124\uba85\ud560 \uc218 \uc788\uc744\ub9cc\ud07c \uc2dc\uac04 \ucda9\ubd84\ud788 \uac00\uc9c0\uae30\\n- \uc778\ud130\ubdf0\uc5b4\uc758 \uc9c8\ubb38 \uc758\ub3c4\ub97c \uba85\ud655\ud788 \uc774\ud574\ud558\uc9c0 \ubabb\ud588\ub2e4\uba74 \uc758\ub3c4 \ub2e4\uc2dc \ubb3c\uc5b4\ubcf4\uae30\\n- \ub05d\ub9fa\ub294 \ubd80\ubd84 \uc5f0\uc2b5\ud558\uae30(\uc790\uc2e0\uac10 \uc788\uac8c)\\n- \uae30\uc220\uc801\uc778 \uc9d1\ucc29\uac00\uc9c0\uae30\\n- \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud788 \uc900\ube44\ud588\uc73c\uba74 \ud611\uc5c5 \uad00\ub828 \uc9c8\ubb38\ub3c4 \uc900\ube44\ud558\uae30\\n\\n### Problem\\n\\n**\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4\ub97c \uc9c4\ud589\ud558\uba74\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ud65c\ub3d9 \uc911 \ud558\ub098\ub77c\uace0 \uc0dd\uac01\ud55c\ub2e4. \\n\ud398\uc5b4\ub294 \ub9e4\ubc88 \ubc14\ub00c\uace0, \ubbf8\uc158\uc758 \ubcf5\uc7a1\ub3c4\ub3c4 \uc99d\uac00\ud558\uae30 \ub54c\ubb38\uc778 \uac83 \uac19\ub2e4. \\n\uc18c\ud1b5 \ub2a5\ub825, \uc2dc\uac04\uad00\ub9ac\uac00 \ubd80\uc871\ud588\uace0, \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\uc558\ub2e4. \\n\ud558\uc9c0\ub9cc \ud398\uc5b4\ub97c \uc9c4\ud589\ud558\uace0, \ud68c\uace0\ub97c \ud558\ub2e4 \ubcf4\ub2c8 \ub098\ub9cc\uc758 \ub178\ud558\uc6b0\uac00 \uc313\uc774\ub294 \ub290\ub08c\uc774\ub2e4. \\n\ub808\ubca8 2\uc5d0\uc11c\ub294 \ubd80\uc871\ud588\ub358 \ubd80\ubd84\uc744 \uac1c\uc120\ud558\uc5ec \ud568\uaed8\ud558\uace0 \uc2f6\uc740 \ud398\uc5b4\uac00 \ub418\uace0 \uc2f6\ub2e4. \\n\\n**\uc9d1\uc911\ud558\ub294 \uc2dc\uac04\u23f1\ufe0f \ubd80\uc871** \\n\\n\ub808\ubca8 1\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc9d1\uc911\ud558\ub294 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud588\ub2e4. \\n\uc774\ub978 \uc544\uce68\uacfc \uc624\ud6c4\uc5d0 \uac1c\uc778\uc801\uc73c\ub85c \uc9d1\uc911\ud560 \uc218 \uc788\ub294 \uacf5\uac04\uc744 \uc608\uc57d\ud574\uc11c \uc628\uc804\ud788 \ub098\ub9cc\uc758 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### Try\\n\\n**\ud5c8\ube0c\ud83c\udf3f\uc640\uc758 \ud2f0\ud0c0\uc784?** \\n\\n\uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc744 \ub298\ub9b4 \ubc29\ubc95\uc744 \uc0dd\uac01\ud558\ub2e4\uac00 \ub300\ud654\ub97c \ub098\ub204\uc9c0 \ubabb\ud55c \ub2e4\ub978 \ud06c\ub8e8\ub4e4\uacfc \uae5c\uc9dd \ucee4\ud53c\ucc57\uc744 \ud558\uba74 \uc5b4\ub5a8\uae4c \uc0dd\uac01\ud588\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc7a1\ub2f4\ubc29\uc5d0 `\uc800\uc640 \ucee4\ud53c\ucc57 \ud558\uc2e4 \ubd84 :)` \ud558\uba74\uc11c \uc62c\ub9b4 \uc218 \uc788\uc744 \uac83 \uac19\ub2e4. \\n\ucc38\uc5ec\ud558\ub294 \uc0ac\ub78c\uc774 \uc788\uc744\uc9c0, \uc548 \uc88b\uac8c \ubcf4\ub294 \uac8c \uc544\ub2d0\uc9c0 \uac71\uc815\ub418\uc9c0\ub9cc \uadf8\ub798\ub3c4 \uc7ac\ubc0c\uc744 \uac83 \uac19\ub2e4. \\n\uc800\ub791 \ud5c8\ube0c\ud2f0 \ud55c\uc794 \ud558\uc2e4\ub798\uc694? \\n\\n**\uae30\uc220\uc801\uc778 \ubd80\ubd84** \\n\\n\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \uc0dd\ud65c\uc744 \ud558\uba74\uc11c \uc18c\ud504\ud2b8 \uc2a4\ud0ac\uc5d0 \uc870\uae08 \ub354 \ubb34\uac8c\ub97c \ub450\ub2e4 \ubcf4\ub2c8 \uc774\ub860\uc801\uc778 \ubd80\ubd84\uc774 \ubd80\uc871\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc2dc\uac04\uc758 \uc5ec\uc720\uac00 \ub420 \ub54c \ucc45\uc744 \uc870\uae08\uc529 \uc77d\uc5b4\uc57c\uaca0\ub2e4. \\n\ube14\ub85c\uadf8\uc5d0 \uae30\uc220\uc801\uc778 \ubd80\ubd84\uc744 \ub9ce\uc774 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc870\uae08 \ub354 \uae4a\uac8c \uacf5\ubd80\ud558\uace0 \uc815\ub9ac\ud558\ub294 \uc2dc\uac04\ub3c4 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \ub808\ubca8 1\uc744 \ub9c8\ubb34\ub9ac\ud558\uba70 \\n\\n\uc2dc\uac04\uc774 \ube60\ub974\uac8c \ud758\ub7ec\uac14\ub2e4. \\n\ud0c0\uc778\uc5d0\uac8c \uc88b\uc740 \uc601\ud5a5\uc744 \uc8fc\uae30\uc704\ud574, \ubc29\ud559\ub3d9\uc548 \ub098\ub97c \ucc59\uae30\ub294 \uc2dc\uac04\uc744 \uac00\uc838\uc57c\uaca0\ub2e4. \\n\ub610\ud55c \ud568\uaed8 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc744 \ubaa9\ud45c\ub85c \uc55e\uc73c\ub85c\ub3c4 \uafb8\uc900\ud788 \uc758\uc2dd\uc801 \ub178\ub825\uc744 \ud574\uc57c\uaca0\ub2e4."},{"id":"chess-retrospective","metadata":{"permalink":"/chess-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","description":"\uccb4\uc2a4","date":"2023-03-31T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 31\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.63,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","slug":"chess-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca8 1 \ud68c\uace0","permalink":"/woowacourse-level1-retrospective"},"nextItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"}},"content":"### \uccb4\uc2a4\\n\uccb4\uc2a4 \ubbf8\uc158\uc5d0\ub294 \uac00\ube44\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4! \\n\uccb4\uc2a4\ub294 \uc774\uc804 \ubbf8\uc158\ub4e4\ubcf4\ub2e4 \ud6e8\uc52c \ubcf5\uc7a1\ud55c \ub3c4\uba54\uc778\uc774\uc5c8\ub2e4. \\n\ud558\uc9c0\ub9cc \uac00\ube44\uc640 \ub098\ub294 \uccb4\uc2a4 \ub3c4\uba54\uc778\uc774 \uc775\uc219\ud574\uc11c \ub354 \ud3b8\ud55c \ub9c8\uc74c\uc73c\ub85c \uc2dc\uc791\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc5b4\ub824\uc6e0\ub358 \ubd80\ubd84\uc740 \uae30\ubb3c\uc758 \uc774\ub3d9, \uc774\ub3d9\uc2dc \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\ub294\uc9c0 \ud655\uc778\ud558\ub294 \ubd80\ubd84\uc774\uc5c8\ub2e4. \\n \\n\uac00\ube44\uac00 \uc9d1\uc5d0\uac00\uc11c\ub3c4 \uae30\ubb3c\uc758 \uc774\ub3d9 \uad00\ub828\ud574 \uc0dd\uac01 \uc815\ub9ac\ud55c \uae00\uc744 \ubcf4\ub0b4\uc918\uc11c \ub354\uc6b1 \ube68\ub9ac \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ucd5c\uc885\uc801\uc73c\ub85c \uacb0\uc815\ud55c \ubd80\ubd84\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n\\n**\uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5\uc5ec\ubd80** \\nRank\uc640 File\uc740 \uac01\uac01 \uc704\uce58\uac12\uc744 \uac00\uc9c0\uace0 \uc788\uace0, \uac12\uc758 \ucc28\uc774\ub97c \uc774\uc6a9\ud574\uc11c \uac01 \uae30\ubb3c\uc758 \uc774\ub3d9 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uacc4\uc0b0\ud588\ub2e4. \\n\uc9c1\uc120 \u2192 Rank\uc640 File \ucc28\uc774 \uc911 \ud558\ub098\uac00 0\uc774\uc5b4\uc57c \ud55c\ub2e4. \\n\ub300\uac01\uc120 \u2192 Rank\uc640 File \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \uac19\uc544\uc57c \ud55c\ub2e4. ex) abs(-2) == abs(2) \\n\ub098\uc774\ud2b8 \u2192 \ucc28\uc774\uc758 \uc808\ub300\uac12\uc774 \ud558\ub098\ub294 2 \ub098\uba38\uc9c0 \ud558\ub098\ub294 1\uc774\uc5b4\uc57c \ud55c\ub2e4.\\n\\n**\ub3c4\ucc29 \uce78\uc758 \uae30\ubb3c \uc5ec\ubd80** \\n\uc544\uad70 \u2192 \uc774\ub3d9\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4. \\n\uc801\uad70 \u2192 \uc774\ub3d9\uc774 \uac00\ub2a5\ud558\ub2e4. \uc801\uad70\uc744 \uc7a1\ub294\ub2e4. \\n\\n**\uc911\uac04\uc5d0 \uae30\ubb3c \uc874\uc7ac \uc5ec\ubd80** \\n\uc774\ub3d9 \uacbd\ub85c\uc5d0 \uae30\ubb3c\uc774 \uc874\uc7ac\ud558\uba74 \uc548\ub41c\ub2e4. \\n\\n**\ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9** \\n\uccb4\uc2a4 \ubbf8\uc158\uc740 \ud2b9\ubcc4\ud558\uac8c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc5f0\uacb0\ud558\ub294 \ubd80\ubd84\uc774 \uc788\uc5c8\ub2e4. \\n\uccb4\uc2a4 \uac8c\uc784\uc758 \uc0c1\ud0dc\ub97c \ub2e4\uc74c\uc758 \ub450\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uc815\ud560 \uc218 \uc788\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n- \uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95 \\n- \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\uace0 \uac8c\uc784\uc744 \ubd88\ub7ec\uc640 \uae30\ubcf4\ub300\ub85c \uc774\ub3d9\uc2dc\ud0a4\ub294 \ubc29\ubc95 \\n\\n\uae30\ubb3c\uc774 \uc774\ub3d9\ud560 \ub54c\ub9c8\ub2e4 \uac12\uc744 \uc800\uc7a5\ud558\uace0 \uc2f6\uc5c8\uace0, \uae30\ubcf4\ub97c \uc800\uc7a5\ud558\ub294 \ubc29\ubc95\uc744 \uc120\ud0dd\ud588\ub2e4. \\n\uae30\ubb3c \uc804\uccb4\ub97c \uc800\uc7a5\ud558\uc9c0 \uc54a\uc740 \uc774\uc720\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4. \\n- \ud134\uacfc \uac19\uc740 \ubd80\uac00\uc801\uc778 \uc694\uc18c\ub97c \uc800\uc7a5\ud574\uc57c \ud55c\ub2e4. \\n- \uc774\ub3d9\uc744 \ud560 \ub54c \uae30\ubb3c\uc774 \uc7a1\ud788\ub294 \uacbd\uc6b0 update \ucffc\ub9ac(\uc774\ub3d9 \uae30\ubb3c)\uc640 delete(\uc7a1\ud78c \uae30\ubb3c) 2\uac1c\uc758 \ucffc\ub9ac\ub97c \ub0a0\ub824\uc57c \ud55c\ub2e4. \\n- \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ub3c4\uba54\uc778\uc758 \ubcc0\uacbd\uc774 \ud06c\uac8c(\ucd08\uae30 \uc0c1\ud0dc\ub97c \uad6c\uc131\ud558\ub294 \ubd80\ubd84) \uc77c\uc5b4\ub098\uc57c \ud55c\ub2e4. \\n\\n\uc815\ub9ac\ud558\uc790\uba74 \uae30\ubb3c \uc804\uccb4 \uc800\uc7a5\uacfc \uae30\ubcf4 \uc800\uc7a5\uc740 \ub2e4\uc74c\uacfc \ucc28\uc774\uac00 \uc788\ub2e4. \\n\ubcf4\ub4dc\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc\uc5d0\uc11c 32\uac1c\uc758 Insert \ucffc\ub9ac(\uae30\ubb3c\uc758 \uc704\uce58) + \uae30\ubb3c \uc774\ub3d9 \uc2dc \uc6c0\uc9c1\uc784 \ubcc0\uacbd(\uc7a1\ud788\ub294 \uacbd\uc6b0 2\uac1c\uc758 \ucffc\ub9ac) \\n\uae30\ubcf4\uc800\uc7a5: \ucd08\uae30\uc0c1\ud0dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uad6c\uc131 + \uc800\uc7a5\ub41c \uae30\ubcf4\ub97c select \ucffc\ub9ac\ub85c \uc870\ud68c\ud574\uc11c \uc0ac\uc6a9(1\ud68c) + insert \ucffc\ub9ac(\uc774\ub3d9 \ub2f9 1\ud68c)\\n\\n\ucd94\uac00\ub85c \uae30\ubcf4\uc800\uc7a5\uc774 \uad6c\ud604\ub3c4 \ub354\uc6b1 \uac04\ub2e8\ud558\ub2e4. \ud83d\udc4d \\n\\n**\ubd80\uac00\uc801\uc778 \ubd80\ubd84**\\n\\n\ub9ac\ubdf0\uc5b4\uc778 \ucc30\ub9ac\ud83c\udf6b\uac00 \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uac8c\uc784\uc774 \uc9c4\ud589\ub41c\ub2e4\uba74 \uc5b4\ub5a8\uc9c0? \uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\ub97c \ub0a8\uaca8\uc8fc\uc154\uc11c \ub2e4\uc591\ud55c \uc2dc\ub3c4\ub97c \ud574\ubd24\ub2e4. \\n- \ub204\ub204\uc758 \ub3c4\uc6c0\uc73c\ub85c ConnectionPool \uad6c\ud604 \\n- ThreadLocal \uc0ac\uc6a9\ud574\uc11c \uc4f0\ub808\ub4dc \ubcc4 \uc138\uc158 \uad00\ub9ac \\n- \uc2e4\uc81c\ub85c \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ub0b4\uc5d0\uc11c \uccb4\uc2a4 \uac8c\uc784\uc774 \uc9c4\ud589\ub418\ub294 Board\ub97c ConcurrentHashMap\uc73c\ub85c \uc800\uc7a5(\uc0ac\uc2e4 \uc774 \ubd80\ubd84\uc740 \ud604\uc7ac \uad6c\uc870\uc5d0\uc11c \ud544\uc694\uc5c6\uc9c0\ub9cc 2\uba85\uc774 \uc11c\ub85c \uac8c\uc784\ud558\ub294 \uacbd\uc6b0\ub97c \uc0dd\uac01\ud574\uc11c \ub123\uc5b4\ubcf4\uc558\ub2e4.) \\n\\n\ub450 \uba85\uc774 \uc11c\ub85c \uac19\uc740 \ubc29\uc5d0 \uc785\uc7a5\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4\uba74 \ucd9c\ub825\ud558\ub294 \ubd80\ubd84\uc774 \uae4c\ub2e4\ub85c\uc6cc\uc9c8 \uac83 \uac19\ub2e4\uace0 \uc608\uc0c1\ub418\uc5b4(Board\uc5d0 \uc635\uc800\ubc84 \ud328\ud134\uc744 \uc0ac\uc6a9\ud574\uc57c\ub418\ub098?) \ud574\ubcfc \uc5c4\ub450\uac00 \ub098\uc9c0 \uc54a\uc558\ub2e4. \\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uaf3c\uaf3c\ud558\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\uc9c0 \ubabb\ud55c \ubd80\ubd84** \\nDB \uad00\ub828 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucf54\ub529\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub3c4\uba54\uc778 \ub85c\uc9c1\uc5d0\ub9cc \uc9d1\uc911\ud558\ub2e4\ubcf4\ub2c8 \uc815\uc801 \uc911\uc694\ud55c DB\uc758 \ucf54\ub4dc\uc758 \uc608\uc678\ucc98\ub9ac, \ube48 \uac12\uc744 \ubc18\ud658 \ud558\ub294 \ubd80\ubd84\uc744 \uaf3c\uaf3c\ud558\uac8c \ucc98\ub9ac\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ud558\uc9c0\ub9cc \ucc30\ub9ac\uc758 \uaf3c\uaf3c\ud55c \ub9ac\ubdf0\ub85c DB\ubd80\ubd84\uacfc \ub098\ub9cc\uc758 JdbcTemplate\uc744 \uae54\ub054\ud558\uac8c \uad6c\ud604\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n**\uc2dc\uac04\uc5d0 \ub300\ud55c \ubd80\ub2f4\uac10** \\n\ucd08\ubc18\uc5d0\ub294 \uc5ec\uc720\ub86d\uc9c0\ub9cc \uc81c\ucd9c \ub9c8\uac10\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \uc218\ub85d \uc0ac\ub78c\uc774 \uae09\ud574\uc9c0\ub294 \uac83 \uac19\ub2e4. \\n\ub2e4\uc74c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\ud560 \ub550 \uc18d\ub3c4\ub97c \uc870\uc808\ud558\uace0, \ub9c8\uc74c\uc5d0 \uc5ec\uc720\ub97c \uac00\uc838\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**DAO \uc911\ubcf5 \uc81c\uac70**\\n\\n\ud504\ub864\ub85c\uadf8\uc5d0 [\uae00](https://prolog.techcourse.co.kr/studylogs/2947)\uc744 \uc791\uc131\ud588\ub2e4. \\nDAO\ub97c \uc791\uc131\ud558\ub294\ub370 try-catch-resources\uc640 \uc5ec\ub7ec \ucf54\ub4dc\uac00 \uc911\ubcf5\ub418\uc11c \uc81c\uac70\ud558\uace0\uc2f6\uc5c8\ub2e4. \\n\ud15c\ud50c\ub9bf \ucf5c\ubc31 \ud328\ud134\uc73c\ub85c \uae54\ub054\ud558\uac8c \uc911\ubcf5\uc744 \uc81c\uac70\ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\udc4d\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc0dd\uac01\ud558\uae30** \\n\uac00\ube44\ub294 \ub204\uad6c\ubcf4\ub2e4 \ud398\uc5b4\ub97c \uc0dd\uac01\ud558\uace0, \ubc30\ub824\ud574\uc8fc\ub294 \ud398\uc5b4\uc600\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ub2f9 \ub5a8\uc5b4\uc9c8\uae4c\ubd10 \uac71\uc815\ub3c4 \ud574\uc8fc\uace0, \ub098\uc758 \ucee8\ub514\uc158\ub3c4 \ud655\uc778\ud574\uc92c\ub2e4! \\n\\n**\ubbf8\uc158 \ubab0\uc785\ud558\uae30** \\n\ucd5c\uadfc\uc5d0 \ubbf8\uc158\uc5d0 \uc798 \ubab0\uc785\ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\uac00\ube44\ub294 \ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \ubbf8\uc158\uc5d0 \ub300\ud55c \ubab0\uc785\ub3c4\uac00 \ub9e4\uc6b0 \uc88b\uc558\ub2e4. \\n\uc9d1\uc5d0\uac00\uc11c\ub3c4 \uccb4\uc2a4 \uc774\ub3d9\uc5d0 \ub300\ud55c \ub85c\uc9c1\uc744 \uc5b4\ub5bb\uac8c \uad6c\ud604\ud560 \uc9c0 \uc0dd\uac01\ud55c \ub4a4 \uaf3c\uaf3c\ud574\uc11c \uc815\ub9ac\ud574\uc11c \ub098\uc5d0\uac8c \ubcf4\ub0b4\uc8fc\uc5c8\ub2e4. \\n\ub355\ubd84\uc5d0 \ub098\ub3c4 \uac00\ube44\uc758 \uc0dd\uac01\uc744 \uc54c \uc218 \uc788\uc5b4\uc11c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294\ub370 \uac00\uc18d\ub3c4\uac00 \ubd99\uc740 \uac83 \uac19\ub2e4. \\n\ub610\ud55c \ubbf8\uc158\uc744 \uc798 \ub9c8\ubb34\ub9ac\ud558\uace0 \uc2f6\uc740 \ub9c8\uc74c\uc774 \uc804\ub2ec\ub418\uc11c \uadf8\ub7f0\uc9c0 \ub098\ub3c4 \ub369\ub2ec\uc544 \uc5f4\uc2ec\ud788 \ubbf8\uc158\uc744 \ud560 \uc218 \uc788\uc5c8\ub2e4.\ud83d\ude04 \\n\\n**\uc194\uc9c1\ud568** \\n\uba3c\uc800 \ud68c\uace0\ud558\uc790\uace0 \ub9d0 \uac78\uc5b4\uc918\uc11c \uc815\ub9d0 \uace0\ub9c8\uc6e0\ub2e4\uace0 \ud45c\ud604\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ubaa8\ub974\ub294\uac8c \uc788\uc73c\uba74 \uc194\uc9c1\ud558\uac8c \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\ub098\uc758 \uc758\uacac\uc744 \uc815\ub9ac\ud558\uc9c0 \ubabb\ud55c \uc0c1\ud0dc\ub85c \uc804\ub2ec\ud560 \ub54c \uc774\ud574\uac00 \uc548\ub418\uc5c8\ub2e4\uace0 \uc815\ud655\ud788 \uc804\ub2ec\ud574\uc8fc\ub294 \ubd80\ubd84 \\n\uc194\uc9c1\ud568\uc740 \ud398\uc5b4\ud560 \ub54c \uc911\uc694\ud55c \ubd80\ubd84\uc778 \uac83 \uac19\ub2e4. \\n\\n\ub9c8\uc9c0\ub9c9\uc73c\ub85c \ucc30\ub9ac\ud83c\udf6b \uccb4\uc2a4 \ubbf8\uc158\ub54c \uaf3c\uaf3c\ud558\uac8c \ub9ac\ubdf0 \ub0a8\uaca8\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4!"},{"id":"grasp","metadata":{"permalink":"/grasp","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-30-GRASP.mdx","source":"@site/blog/2023-1/2023-03-30-GRASP.mdx","title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","description":"GRASP(General Responsibility Assignment Software Pattern)","date":"2023-03-30T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 30\uc77c","tags":[{"label":"GRASP","permalink":"/tags/grasp"},{"label":"OOP","permalink":"/tags/oop"}],"readingTime":8.085,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","slug":"grasp","tags":["GRASP","OOP"]},"prevItem":{"title":"\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0","permalink":"/chess-retrospective"},"nextItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"}},"content":"### GRASP(General Responsibility Assignment Software Pattern)\\n\\n\ud06c\ub808\uc774\uadf8 \ub77c\ub9cc\uc758 Applying UML and Patterns\uc774\ub77c\ub294 \ucc45\uc5d0\uc11c \ub098\uc628 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134\\n\\n\uac01 \ud328\ud134\ub9c8\ub2e4 Solution\uacfc Problem\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\ub2e4.\\n\\n### \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134(Information Expert)\\n\\nQ: \uac1d\uccb4\uc5d0 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uae30\ubcf8 \uc6d0\uce59\uc740 \ubb34\uc5c7\uc778\uac00?\\n\\nA: \ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub370 \ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \ud074\ub798\uc2a4(\uc815\ubcf4 \uc804\ubb38\uac00)\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uc815\ubcf4\uc640 \ud589\ub3d9\uc744 \uac00\uae4c\uc6b4 \uacf3\uc5d0 \uc704\uce58\uc2dc\ud0a4\uae30 \ub54c\ubb38\uc5d0 \ucea1\uc290\ud654\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud544\uc694\ud55c \uc815\ubcf4\ub97c \uac00\uc9c4 \uac1d\uccb4\ub4e4\ub85c \ucc45\uc784\uc774 \ubd84\uc0b0\ub41c\ub2e4.\\n\\n### \ucc3d\uc870\uc790 \ud328\ud134(Creator)\\n\\nQ: \ub204\uac00 \uac1d\uccb4 A\ub97c \uc0dd\uc131\ud558\ub294\uac00?\\n\\nA: \ub2e4\uc74c\uc758 \uc870\uac74\uc744 \ucd5c\ub300\ud55c \ub9ce\uc774 \ub9cc\uc871\ud558\ub294 \uac1d\uccb4\uc5d0\uac8c \uac1d\uccb4 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\uc758 \ucd08\uae30\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4.\\n\\n\uc0dd\uc131 \uc608\uc815\uc778 \uac1d\uccb4\uc640 \uc5f0\uad00\ub418\uc5b4 \uc788\ub294 \uac1d\uccb4\uac00 \uc0dd\uc131 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uac8c \ub41c\ub2e4\uba74, \uc774\ubbf8 \ud574\ub2f9 \uac1d\uccb4\uc640 \uacb0\ud569\ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c \uc804\uccb4\uc801\uc778 \uacb0\ud569\ub3c4\ub97c \ub0ae\uac8c \uc720\uc9c0\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ub0ae\uc740 \uacb0\ud569\ub3c4 \ud328\ud134(Low Coupling)\\n\\nQ: \uc758\uc874\uc131\uc744 \ub0ae\ucd94\uace0 \ubcc0\ud654\uc758 \uc601\ud5a5\uc744 \uc904\uc774\uba70 \uc7ac\uc0ac\uc6a9\uc131\uc744 \uc99d\uac00\uc2dc\ud0a4\ub294 \ubc29\ubc95\uc740?\\n\\nA: \uc804\uccb4\uc801\uc778 \uacb0\ud569\uc774 \ub0ae\uac8c \uc720\uc9c0\ub418\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uacb0\ud569\ub3c4(Coupling)\\n\uac1d\uccb4 \uc0ac\uc774\uc758 \uc758\uc874\uc131\uc774 \uacfc\ud55c \uacbd\uc6b0 \uacb0\ud569\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.17\\n> \\n\\n\uacb0\ud569\ub3c4\ub97c \ub0ae\ucd98\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ub2e4\ub978 \uad6c\uc131 \uc694\uc18c\uc758 \ubcc0\ud654\uc5d0 \uc601\ud5a5\uc744 \ubc1b\uc9c0 \uc54a\ub294\ub2e4.\\n- \uc7ac\uc0ac\uc6a9\uc774 \ud3b8\ub9ac\ud574\uc9c4\ub2e4.\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\uc758\uc874\ud558\ub294 \ud074\ub798\uc2a4\uac00 \uc801\uae30 \ub54c\ubb38\uc5d0)\\n\\n### \ub192\uc740 \uc751\uc9d1\ub3c4 \ud328\ud134(High Cohesion)\\n\\nQ. \uac1d\uccb4\ub97c \uad00\ub9ac\ud558\uae30 \uc27d\uac8c \ud558\ub824\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub192\uc740 \uc751\uc9d1\ub3c4\ub97c \uc720\uc9c0\ud560 \uc218 \uc788\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n> \uc751\uc9d1\ub3c4(Cohesion)\\n\uc5f0\uad00\ub41c \uc791\uc5c5\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc5f0\uad00\uc131 \uc5c6\ub294 \uc791\uc5c5\uc740 \ub2e4\ub978 \uac1d\uccb4\uc5d0\uac8c \uc704\uc784\ud558\ub294 \uac1d\uccb4\ub97c \uac00\ub9ac\ucf1c \uc751\uc9d1\ub3c4\uac00 \ub192\ub2e4\uace0 \ub9d0\ud55c\ub2e4.\\n- \uc624\ube0c\uc81d\ud2b8 p.26\\n> \\n\\n\ubcc0\uacbd\uc758 \uc774\uc720\uc5d0 \ub530\ub77c \ud074\ub798\uc2a4\ub97c \ubd84\ub9ac\ud55c\ub2e4\uba74 \uc751\uc9d1\ub3c4\ub97c \ub192\uc77c \uc218 \uc788\uace0, \uc751\uc9d1\ub3c4\uac00 \ub192\uc544\uc9c4\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc774\uc810\uc774 \uc788\ub2e4.\\n\\n- \ud574\ub2f9 \ud074\ub798\uc2a4\uc5d0 \ub300\ud55c \uc774\ud574\uac00 \uc26c\uc6cc\uc9c4\ub2e4. (\ud560\ub2f9\ub41c \ucc45\uc784\ub9cc\uc744 \uc218\ud589\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0)\\n- \uc720\uc9c0\ubcf4\uc218\uac00 \uc26c\uc6cc\uc9c4\ub2e4.\\n- \ub0ae\uc740 \uacb0\ud569\ub3c4 \ub610\ud55c \uc9c0\uc6d0\ud55c\ub2e4.\\n- \uc751\uc9d1\ub3c4\uac00 \ub192\uc740 \ud074\ub798\uc2a4\ub294 \ud2b9\uc815\ud55c \ubaa9\uc801\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc7ac\uc0ac\uc6a9\ud558\uae30 \uc88b\ub2e4.\\n\\n### \ucee8\ud2b8\ub864\ub7ec \ud328\ud134(Controller)\\n\\nQ. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 \uac83\uc740 \ub204\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294\uac00?\\n\\nA. \uc0ac\uc6a9\uc790\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294 Controller \uac1d\uccb4\ub97c \ub9cc\ub4e4\uc5b4\uc11c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.\\n\\n\uc5b4\ub5a4 \uc11c\ube0c\uc2dc\uc2a4\ud15c\uc774 \uc874\uc7ac\ud55c\ub2e4\uace0 \uac00\uc815\ud560 \ub54c\\n\\n- \uc9c1\uc811\uc801\uc73c\ub85c \uac1d\uccb4\uc5d0 \uc811\uadfc\ud558\uc5ec \ud504\ub85c\uadf8\ub7a8\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uacb0\ud569\ub3c4\uac00 \uc0c1\uc2b9\ud55c\ub2e4.\\n- \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc5d0 \ub4e4\uc5b4\uc624\ub294 \uc694\uccad\uc744 \ucc98\ub9ac\ud574\uc8fc\ub294 \ucee8\ud2b8\ub864\ub7ec\uac00 \uc788\ub2e4\uba74 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 \ud574\ub2f9 \ucee8\ud2b8\ub864\ub7ec\ub9cc \uc54c\uba74 \ub41c\ub2e4.\\n- \ub9cc\uc57d \uc11c\ube0c \uc2dc\uc2a4\ud15c\uc758 \ubcc0\uacbd\uc774 \uc0dd\uacbc\uc744 \ub54c \uc678\ubd80\uc5d0 \ubbf8\uce58\ub294 \uc601\ud5a5\ub3c4 \uc904\uc5b4\ub4e0\ub2e4.\\n\\n### \ub2e4\ud615\uc131 \ud328\ud134(Polymorphism)\\n\\nQ. \uac1d\uccb4\uc758 \ud0c0\uc785\uc5d0 \ub530\ub77c \ud589\ub3d9\uc774 \ubc14\ub010\ub2e4\uba74 \ucc45\uc784\uc744 \uc5b4\ub5bb\uac8c \ud560\ub2f9\ud574\uc57c \ud560\uae4c?\\n\\nA. OOP\uac00 \uc9c0\uc6d0\ud558\ub294 \ub2e4\ud615\uc131\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ud65c\uc6a9\ud55c\ub2e4. (\uc778\ud130\ud398\uc774\uc2a4\ub97c \ub450\uace0 \ud589\ub3d9\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uad6c\ud604)\\n\\n\uac1d\uccb4\uc758 \uc885\ub958\uc5d0 \ub530\ub77c \ubd84\uae30\ud558\ub294 \uc870\uac74\ubb38\uc774 \uc544\ub2cc \ub2e4\ud615\uc131\uc744 \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4.\\n\\n\uc0c8\ub85c\uc6b4 \ud0c0\uc785\uc774 \ucd94\uac00\ub418\uc5c8\uc744 \ub54c \uc870\uac74\ubb38\uc744 \uc0ac\uc6a9\ud55c\ub2e4\uba74 \uae30\uc874\uc758 \uc870\uac74\ubb38\uc744 \uc218\uc815\ud574\uc57c \ud558\uc9c0\ub9cc \ub2e4\ud615\uc131\uc744 \ud65c\uc6a9\ud558\uba74 \uc27d\uac8c \ud655\uc7a5\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\\n\\nQ. \uc5b4\ub5bb\uac8c \ud558\uba74 \ubcc0\uacbd\uc774 \ub2e4\ub978 \uc694\uc18c\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub3c4\ub85d \ubc29\uc9c0\ud560 \uc218 \uc788\uc744\uae4c?\\n\\nA. \ubcc0\ud654\uac00 \uc608\uc0c1\ub418\ub294 \uc9c0\uc810\uc744 \uc2dd\ubcc4\ud558\uace0, \uc8fc\uc704\uc5d0 \uc548\uc815\ub41c \uc778\ud130\ud398\uc774\uc2a4\ub97c \ud615\uc131\ud558\ub3c4\ub85d \ucc45\uc784\uc744 \ud560\ub2f9\ud574\uc57c \ud55c\ub2e4.\\n\\n### \uac04\uc811 \ucc38\uc870 \ud328\ud134(Indirection)\\n\\nQ. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud558\uace0 \uc2f6\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ub2e4\ub978 \uac1d\uccb4\ub97c \ub450\uc5b4 \uc9c1\uc811\uc801\uc778 \uc5f0\uacb0\uc744 \ud53c\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uc7ac\uc790 \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub450 \uac1d\uccb4 \uc0ac\uc774\uc5d0 \ub610 \ud558\ub098\uc758 \uac1d\uccb4\ub97c \ucd94\uac00\ud558\uc5ec \ubcf5\uc7a1\ud55c \uad00\uacc4\ub97c \ub2e8\uc21c\ud654\ud560 \uc218 \uc788\ub2e4.\\n\\n\uc911\uac04\uc5d0 \uc778\ud130\ud398\uc774\uc2a4\ub97c \ub454\ub2e4\uba74 \ubcc0\uacbd \ubcf4\ud638 \ud328\ud134(Protected Variations)\uc5d0 \ud574\ub2f9\ub41c\ub2e4.\\n\\n### \uc21c\uc218\ud55c \uac00\uacf5\ubb3c \ud328\ud134(Pure Fabrication)\\n\\nQ. \ucc45\uc784\uc744 \ud560\ub2f9\ud55c \ub3c4\uba54\uc778 \uac1d\uccb4\uac00 Low Coupling, High Cohesion, \uc7ac\uc0ac\uc6a9\uc131 \ub4f1\uc758 \ubaa9\uc801\uc744 \uc704\ubc18\ud55c\ub2e4\uba74 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c?\\n\\nA. \ub3c4\uba54\uc778 \uac1c\ub150\uc744 \ud3ec\ud568\ud558\uc9c0 \uc54a\ub294 \ud074\ub798\uc2a4\ub97c \ud558\ub098 \ub9cc\ub4e4\uace0 \ub9e4\uc6b0 \uc751\uc9d1\ub41c \ucc45\uc784\uc744 \ud560\ub2f9\ud560 \uc218 \uc788\ub2e4.\\n\\n\ud589\ub3d9\uc744 \ucd94\uac00\ud560 \ub54c, \ud574\ub2f9 \ucc45\uc784\uc744 \uc218\ud589\ud560 \ub3c4\uba54\uc778 \uac1c\ub150\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74 \ub3c4\uba54\uc778\uacfc \ubb34\uad00\ud55c \uc778\uacf5\uc801\uc778 \uac1d\uccb4\ub97c \ub9cc\ub4e0\ub2e4\uc74c \ud574\ub2f9 \uac1d\uccb4\uc5d0\uac8c \ucc45\uc784\uc744 \ud560\ub2f9\ud55c\ub2e4.\\n\\n\uac1d\uccb4\uac00 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud574\uc57c \ud560 \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4\uace0, \uc815\ubcf4 \uc804\ubb38\uac00 \ud328\ud134\uc744 \uc801\uc6a9\ud558\uc5ec \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc800\uc7a5\ud558\ub77c\ub294 \ucc45\uc784\uc744 \uac00\uc9c0\ub77c\uace0 \ud558\uc9c0 \uc54a\ub294\ub2e4.\\n\\n\uc608) \uc0c1\uc810\uacfc \uace0\uac1d \ud074\ub798\uc2a4\uac00 \uc788\uace0 \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4\uace0 \uac00\uc815\\n\\n- \uc11c\ub85c \ub2e4\ub978 \ud1b5\ud654\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uae30 \ub54c\ubb38\uc5d0 \uac70\ub798\ub97c \ud558\ub824\uba74 \ud658\uc804\uc744 \ud574\uc57c\ud55c\ub2e4.\\n- \ub450 \ud074\ub798\uc2a4 \ub2e4 \ud658\uc804\uc5d0 \ub300\ud55c \ucc45\uc784\uc744 \ubd80\uc5ec\ud558\uae30 \uc560\ub9e4\ud558\ub2e4\uba74 \ud658\uc804\uc744 \ucc45\uc784\ud558\ub294 \ud074\ub798\uc2a4\ub97c \ucd94\uac00\ud558\uace0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n\uc624\ube0c\uc81d\ud2b8 5\uc7a5. \ucc45\uc784 \ud560\ub2f9\ud558\uae30, [\uc870\uc601\ud638](http://aeternum.egloos.com/)\\n\\nApplying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman\\n\\n[GRASP, \ud55c\ube5b \ub124\ud2b8\uc6cc\ud06c](https://www.hanbit.co.kr/network/category/category_view.html?cms_code=CMS8586826397)"},{"id":"blackjack-retrospective","metadata":{"permalink":"/blackjack-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx","title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","description":"\ube14\ub799\uc7ad","date":"2023-03-14T00:00:00.000Z","formattedDate":"2023\ub144 3\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":5.105,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","slug":"blackjack-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc77c\ubc18\uc801\uc778 \ucc45\uc784 \ud560\ub2f9\uc744 \uc704\ud55c \ud328\ud134","permalink":"/grasp"},"nextItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"}},"content":"### \ube14\ub799\uc7ad\\n\\n\ube14\ub799\uc7ad \ubbf8\uc158\uc5d0\uc11c\ub294 \ud6c4\ucd94\uc640 \ud398\uc5b4(\uc870\ubbf8\ub8cc \ub4c0\uc624?)\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\ubc88\uc5d0\ub294 \uc2e4\uc218\ud558\uc9c0 \uc54a\uace0, \ubc14\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uc9c0 \uc54a\uace0 \uce5c\ud574\uc9c0\uae30 \ubd80\ud130 \uc2dc\uc791\ud588\ub2e4. \\n\\n\ube14\ub799\uc7ad\uc740 \uad6c\ud604\ud574\uc57c \ub420 \ub0b4\uc6a9\uc774 \ub9ce\uc544 \uc2dc\uac04\uc774 \ub9ce\uc774 \ubd80\uc871\ud560 \uac83 \uac19\uc558\uc9c0\ub9cc \\n\ud6c4\ucd94\uc640 \ud568\uaed8 \uc804\ub7b5\uc801(\uc0bc\uc77c\uc808\uc5d0 \ubbf8\uc158 \uc774\uc57c\uae30 \ub098\ub204\uae30)\uc73c\ub85c \ubbf8\uc158\uc744 \uc9c4\ud589\ud574 \uc2dc\uac04 \ub0b4\uc5d0 \uc81c\ucd9c\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\ubbf8\uc158\uc744 \ub05d\ub098\uace0 \ud68c\uace0\ub97c \ud588\uc744 \ub54c \ud6c4\ucd94\uac00 \uace0\ubbfc\uac70\ub9ac\ub97c \ud558\ub098 \ub0b4\uc92c\ub2e4. \\n\\"\ud398\uc5b4\ub97c \uc9c4\ud589\ud560 \ub54c \uc555\ubc15\uac10\uc744 \ub290\ub07c\ub294 \ud398\uc5b4\uac00 \uc788\ub2e4\uba74 \ud5c8\ube0c\uac00 \ud574\uc904 \uc218 \uc788\ub294\uac8c \ubb50\uac00 \uc788\uc744\uae4c?\\" \\n\\n\uacf0\uacf0\ud788 \uc0dd\uac01\ud574\ubd24\uc9c0\ub9cc \uc27d\uac8c \ub2f5\uc744 \ub0b4\ub9b4 \uc218 \uc5c6\uc5c8\ub2e4. \\n\uc911\uac04 \uc911\uac04 \ud68c\uace0\ub97c \ud558\uace0, \ub098\uc758 \uc18c\ud504\ud2b8\uc2a4\ud0ac\uc744 \ub192\ud788\ub294\uac8c \ub2f5\uc77c\uae4c? \\n\ubd80\ub2f4\uac10\uc744 \ub290\ub07c\uc9c0 \uc54a\uace0 \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub420 \uc218 \uc788\ub3c4\ub85d \uacc4\uc18d \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4. \\n\\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574 \uc0dd\uac01\uc774 \ub9ce\uc544\uc838\uc11c \uc804 \ub9ac\ubdf0\uc5b4\uc778 \ud130\ud2c0\ud83d\udc22\uacfc\ub3c4 \ub300\ud654\ub97c \ub098\ub204\uc5c8\ub2e4. \\n\ud130\ud2c0\uc740 \uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\ubcf4\ub2e4 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84(\uad81\uadf9\uc801\uc778 \ubaa9\ud45c\uc778 \uc88b\uc740 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \uac83)\uc5d0 \uc9d1\uc911\ud574\ubcf4\ub77c\uace0 \ud558\uc168\ub2e4. \\n\\n\uc88b\uc740 \ucf54\ub4dc, \uc88b\uc740 \ud398\uc5b4\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \uc77c\ub2e8 \uc9c0\uc18d\uc801\uc73c\ub85c \uc0dd\uac01\ud574\ubd10\uc57c\uaca0\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\ud398\uc5b4 \uc2e0\uacbd\uc4f0\uae30** \\n\uc774\ubc88 \ud398\uc5b4\ud560 \ub54c \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub0b4\ubcf4\ub3c4\ub85d \ud588\ub2e4. \uadf8\ub807\uae30\uc5d0 \ub108\ubb34 \uc758\uacac\uc744 \uac15\ud558\uac8c \ubc00\uc5b4\ubd99\uc778 \ub290\ub08c\uc774 \ub4e4\uc5b4\uc11c \ubbf8\uc548\ud588\ub2e4. \\n\ud6c4\ucd94\uac00 \uc555\ubc15\uc744 \ub290\uaf08\uc744 \uc218\ub3c4 \uc788\uc744 \uac83 \uac19\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\uc911\uac04 \uc911\uac04 \uc791\uc740 \ud68c\uace0\ub97c \uc9c4\ud589\ud574\ubcf4\ub294 \uac83\uc774 \uc88b\uc744\uae4c?\\n\\n**\uccb4\ub825 \uad00\ub9ac** \\n\uc694\uc998 \uc798 \ubabb\uba39\ub294 \uac83 \uac19\ub2e4. \\n\uc55e\uc73c\ub85c \uc0b4 \ub0a0\uc774 \ub9ce\uc740\ub370 \uc798 \ucc59\uaca8\uba39\uace0, \ud798\ub0b4\uc57c\uaca0\ub2e4.\\n\\n**\uc911\uac04 \uc911\uac04 \ub3cc\uc544\ubcf4\uae30** \\n\uc774\ubc88 \ubbf8\uc158\uacfc \uad00\ub828\ub41c \ub0b4\uc6a9\uc740 \uc544\ub2c8\uc9c0\ub9cc \uc6b0\ud14c\ucf54\ub97c \uc798 \ud65c\uc6a9 \ud558\uace0 \uc788\ub294\uc9c0 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4. \\n\ub0b4\uac00 \uc6b0\ud14c\ucf54\uc5d0 \uc9c0\uc6d0\ud55c \uc774\uc720\ub97c \ud56d\uc0c1 \uc78a\uc9c0 \uc54a\uc544\uc57c\uaca0\ub2e4. \\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uc0c1\ud0dc \ud328\ud134** \\n\uac1d\uccb4\uc758 \ub0b4\ubd80 \uc0c1\ud0dc\uc5d0 \ub530\ub77c \uc2a4\uc2a4\ub85c \ud589\ub3d9\uc744 \ubcc0\uacbd\ud558\ub3c4\ub85d \ud558\ub294 \ud328\ud134\uc73c\ub85c if/else/switch\uc640 \uac19\uc740 \uc870\uac74\ubb38\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \uc81c\uac70\ud560 \uc218 \uc788\ub2e4. \\n\ube14\ub799\uc7ad \ubbf8\uc158\uc744 \uc9c4\ud589\ud558\uba74\uc11c \uc0c1\ud0dc \ud328\ud134\uc5d0 \ub300\ud55c \ubd80\ubd84\uc744 \ucc98\uc74c \uc801\uc6a9\ud574\ubcf4\uc558\ub2e4. \\n\ucc98\uc74c \uc801\uc6a9\ud558\uae30 \uc804\uc5d0\ub294 \ubcc4\ub85c\ub77c\uace0 \uc0dd\uac01\ud588\ub294\ub370, \uc0dd\uac01\ubcf4\ub2e4 \uad1c\ucc2e\uc740 \uac83 \uac19\ub2e4. \\n\\n**\uc77c\uad00\uc131, \uac00\ub3c5\uc131, \ucd94\uc0c1\ud654** \\n\uc774\ubc88 \ub9ac\ubdf0\uc5b4\ub294 \uac80\ud504\ud83c\udf6b \uc600\ub2e4! \\n\uac80\ud504\uc758 \ub9ac\ubdf0\ub294 \uac04\uacb0\ud568\uc5d0 \uad00\ub828\ub41c \ub0b4\uc6a9\uc774 \ub9ce\uc558\ub2e4. \\n\uc77c\uad00\uc131\uc774 \uc788\ub294 \ucf54\ub4dc, \uac00\ub3c5\uc131\uc774 \uc88b\uc740 \ucf54\ub4dc, \ucd94\uc0c1\ud654\uac00 \uc798 \ub418\uc5b4\uc788\ub294 \ucf54\ub4dc \\n\uc77d\uae30 \uc88b\uace0, \uac04\uacb0\ud55c \ubc29\ud5a5\uc73c\ub85c \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub294 \ubc29\ubc95\uc744 \ubc30\uc6b4 \uac83 \uac19\ub2e4. \\n\ucf54\ub4dc\ub97c \ubc14\ub77c\ubcf4\ub294 \uc2dc\uc810\uc774 \ud558\ub098 \ub298\uc5b4\ub09c \uae30\ubd84\uc774\ub2e4!(\uc55e\uc73c\ub85c \uc801\uc6a9\ud558\ub294 \uac83\uc740 \ub098\uc758 \ubaab\uc774\uc9c0\ub9cc) \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n**\uc0dd\uac01 \uc815\ub9ac** \\n\uc911\uac04 \uc911\uac04 \ud604\uc7ac \uc0c1\ud669\uc5d0 \ub300\ud574 \uadf8\ub9bc\uc744 \uadf8\ub9ac\uac70\ub098, \uae00\uc744 \uc801\uc73c\uba74\uc11c \uc815\ub9ac\ud55c\ub2e4. \\n\ud398\uc5b4\uc640 \ub3d9\uc77c\ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \\n\uc9c4\ud589\ud558\ub294\ub370 \ub9e4\uc6b0 \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ub098\ub3c4 \ub2e4\uc74c \ud398\uc5b4\ub54c\ubd80\ud130 \ud39c\uc774\ub791 \uc885\uc774\ub97c \uc900\ube44\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uac00\uac10\uc5c6\uc774 \uc758\uacac\uc744 \ub9d0\ud574\uc8fc\ub294 \ubd80\ubd84** \\n\uc9c4\ud589 \uc0c1\ud669\uc5d0 \ub300\ud55c \ubd80\ubd84, \uc9c4\ud589 \uc18d\ub3c4, \uc9c0\uae08 \uc790\uc2e0\uc774 \uc774\ud574\ud558\uace0 \uc788\ub294 \ubd80\ubd84\uc744 \ub9d0\ud574\uc918\uc11c \ud3b8\ud588\ub2e4. \\n\ud68c\uace0\ub54c\ub3c4 \uc11c\ub85c \uc194\uc9c1\ud558\uac8c \uc758\uacac\uc744 \uc8fc\uace0 \ubc1b\uc544\uc11c \uc88b\uc558\ub2e4. \\n\\n**\ub3c4\uba54\uc778 \uc5b8\uc5b4\uc5d0 \uc2e0\uacbd\uc4f0\ub294 \ubd80\ubd84** \\n\ud074\ub798\uc2a4\uba85, \ubcc0\uc218\uba85\uacfc \uac19\uc740 \uc5b8\uc5b4\ub97c \uc138\uc2ec\ud558\uac8c \uc2e0\uacbd\uc4f4\ub2e4. \\n\uc694\uad6c\uc0ac\ud56d \uc815\ub9ac\ub3c4 \uae54\ub054\ud558\uac8c \uc798\ud558\ub294 \uac83 \uac19\ub2e4. \\n\\n\ud6c4\ucd94 \ucd5c\uace0 \ud83d\udc4d"},{"id":"ladder-retrospective","metadata":{"permalink":"/ladder-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","description":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30","date":"2023-02-26T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 26\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":10.22,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","slug":"ladder-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0","permalink":"/blackjack-retrospective"},"nextItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"}},"content":"### \uc0ac\ub2e4\ub9ac \ud0c0\uae30\\n\\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158\uc5d0\uc11c\ub294 \uc6b0\uac00\uc640 \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub2ec\ub9ac TDD\ub85c \uc9c4\ud589\ud558\ub294 \uac83\uc774 \ud544\uc218\uc600\uae30 \ub54c\ubb38\uc5d0 \uc775\uc219\ud558\uc9c0 \uc54a\uc558\uc9c0\ub9cc, \uc6b0\uac00\uc640 \ubbf8\uc158\uc5d0 \uad00\ud55c \uc18c\ud1b5\uc774 \uc798 \ub418\uc5b4\uc11c \ud070 \ubb38\uc81c \uc5c6\uc774 \ubbf8\uc158\uc744 \ub9c8\ubb34\ub9ac\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\\n\uc6b0\uac00\uc640 \uc774\uc57c\uae30\uac00 \uc798 \ud1b5\ud574\uc11c \uadf8\ub7f0\uc9c0 1\ub2e8\uacc4\ub294 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uac8c \uc9c4\ud589\ud560 \uc218 \uc788\uc5c8\ub294\ub370, 2\ub2e8\uacc4\uc5d0\uc11c \ub9ce\uc774 \uace0\uc804\ud55c \uac83 \uac19\ub2e4.\\n\\n2\ub2e8\uacc4\uc5d0\uc11c\ub294 2\uac00\uc9c0 \ubc29\ubc95\uc73c\ub85c \uad6c\ud604\ud574\ubd24\ub2e4.\\n\\n1. LadderGame\uc5d0\uc11c Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n2. Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c Ladder\uc5d0\uac8c Position\uc744 \ub118\uaca8\uc8fc\uba70 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \ubc29\ubc95\\n\\n### Position \uae30\uc900\uc73c\ub85c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\n\uc0ac\uc2e4\uc0c1 index\ub97c Ladder\uc5d0\uac8c \ub118\uaca8\uc8fc\uace0, \ud574\ub2f9 index\uc5d0 \ub300\ud55c \uacb0\uacfc\ub97c \ubc1b\ub294 \ubc29\ubc95\uacfc \uc720\uc0ac\ud588\ub2e4. \\n\uad6c\ud604\ud558\uace0 \ub098\ub2c8 \ub2e4\ub978 \ud074\ub798\uc2a4\ub4e4\uc774 Position\uc5d0 \ub300\ud55c \uc758\uc874\ub3c4\uac00 \ub108\ubb34 \ub192\uc740 \uac83 \uac19\uc558\ub2e4. \\n\ub610\ud55c Players\uac00 \ubcc4\ub2e4\ub978 \ucc45\uc784\uc744 \uac00\uc9c0\uace0 \uc788\uc9c0 \uc54a\ub2e4\uace0 \ub290\uaf08\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n\\n LadderGame --\x3e Position\\n Ladder --\x3e Position\\n Items --\x3e Position\\n Line --\x3e Position\\n Players --\x3e Position\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item\\n Players --\x3e Player\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n final Map result = new LinkedHashMap<>();\\n // \uc0ac\uc6a9\uc790 \uc218\ub9cc\ud07c Position\uc744 \uac00\uc838\uc640\uc11c \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc9c4\ud589\ud55c\ub2e4.\\n for (Position position : Position.range(players.count())) {\\n final Position resultPosition = ladder.play(position);\\n result.put(players.get(position), items.get(resultPosition));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### Player\uc5d0\uac8c Ladder\ub97c \uc804\ub2ec\ud558\uc5ec \uac8c\uc784\uc744 \uc9c4\ud589\ud558\ub294 \ubc29\ubc95\\n\\nPosition\uc5d0 \ub300\ud55c \uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub294 Player\uc5d0\uac8c Ladder\ub97c \ub118\uaca8\uc11c, Player\uac00 Ladder\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \uad6c\ud604\ud558\uc600\ub2e4. \\n\uc774 \ubc29\ubc95\uc774 \uc0ac\ub2e4\ub9ac \uac8c\uc784\uc744 \uc704\ud574\uc11c \uac1d\uccb4\ub4e4\uc774 \uae34\ubc00\ud558\uac8c \ud611\ub825\ud558\uace0, \uc870\uae08 \ub354 \ucc45\uc784\uc758 \ubd84\ubc30\uac00 \uc798 \ub418\uc5b4\uc788\ub2e4\uace0 \uc0dd\uac01\uc774 \ub418\uc5c8\ub2e4. \\n\\n```mermaid\\ngraph TD\\n\\n LadderGameController --\x3e LadderGame\\n LadderGame --\x3e Ladder\\n LadderGame --\x3e Players\\n LadderGame --\x3e Items\\n\\n Ladder --\x3e Line\\n Line --\x3e LineStatus\\n Line --\x3e Position\\n\\n Players --\x3e Ladder\\n Player --\x3e Ladder\\n\\n Item --\x3e Position\\n Player --\x3e Position\\n\\n\\n LadderGame --\x3e LadderGameResult\\n\\n Items --\x3e Item --\x3e ItemName\\n Players --\x3e Player --\x3e PlayerName\\n\\n LadderGameController --\x3e InputView\\n LadderGameController --\x3e OutputView\\n\\n OutputView --\x3e LadderMessageGenerator\\n```\\n\\n```java\\npublic LadderGameResult play() {\\n // \ucc38\uac00\uc790\ub4e4\uc5d0\uac8c \uc0ac\ub2e4\ub9ac\ub97c \uc804\ub2ec\ud574\uc11c \uc0ac\ub2e4\ub9ac\uc5d0\uac8c \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub3c4\ub85d \ud55c\ub2e4.\\n final Map playResult = players.play(ladder);\\n\\n final Map result = new LinkedHashMap<>();\\n for (Player player : playResult.keySet()) {\\n result.put(player, toItem(playResult.get(player)));\\n }\\n return new LadderGameResult(result);\\n}\\n```\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n**\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\uc5d0 \uc2dc\uac04\uc744 \ub4e4\uc774\uae30** \\n\uc720\ube44\ucffc\ud130\uc2a4 \uc5b8\uc5b4\ub97c \uc815\ud558\ub294\ub370 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \ub4e4\uc5ec\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc0ac\ub2e4\ub9ac \ud0c0\uae30\uc758 \uc2e4\ud589 \uacb0\uacfc\ub97c Item\uc73c\ub85c \uc9d3\ub2e4\ub2c8.. \ubb54\uac00 \ub9cc\uc871\uc2a4\ub7fd\uc9c0 \uc54a\ub2e4. \\n\uc774\uc804 \ubbf8\uc158\uacfc \ub9c8\ucc2c\uac00\uc9c0\ub85c, \uba85\uba85\ud558\ub294 \ubd80\ubd84\uc5d0\uc11c \ubd80\uc871\ud568\uc744 \ub9ce\uc774 \ub290\uaf08\ub2e4. \\n\\n**\ud398\uc5b4\uc640 \uc870\uae08 \ub354 \uce5c\ud574\uc9c0\uae30** \\n\uccab\ub0a0\uc740 \ud398\uc5b4\uc640 \uce5c\ud574\uc9c0\ub294 \uc2dc\uac04\uc744 \uc870\uae08 \ub354 \uac00\uc838\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6b0\uac00\ub791 \ud68c\uace0\ud560 \ub54c \ub0b4\uac00 \uc2dc\uc791\ud558\uc790\ub9c8\uc790 \ucee8\ubca4\uc158 \uc815\ud558\uc790\uace0 \ud574\uc11c \ub9ce\uc774 \ub2f9\ud669\uc2a4\ub7ec\uc6e0\ub2e4\uace0 \ud55c\ub2e4. \uc6b0\uac00 \ubbf8\uc548.. \ud83e\udd72\\n\\n**README\ub97c \uc870\uae08 \ub354 \uaf3c\uaf3c\ud558\uac8c** \\n\uc774\uc0c1\ud558\uac8c \ucf54\ub529\uc5d0 \uc9d1\uc911\ud558\uba74 README\ub97c \uc5c5\ub370\uc774\ud2b8\ud558\uba74\uc11c \uac19\uc774 \ucee4\ubc0b \ud558\ub294 \uac78 \ud56d\uc0c1 \uae4c\uba39\ub294\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\uc5d0\ub294 \uc870\uae08 \ub354 \uc2e0\uacbd \uc368\uc57c\uaca0\ub2e4.\\n\\n**\uc88b\uc740 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud558\uae30** \\n\uccab PR\ub54c \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \uc9c8\ubb38\uc744 \ub0a8\uae30\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9ac\ubdf0\uc5b4\uc640\uc758 \uc2dc\uac04\uc774 \uc18c\uc911\ud55c \uc2dc\uac04\uc774\ub77c\ub294 \uac83\uc744 \uae4c\uba39\uc9c0 \ub9d0\uace0, \ub098\uc758 \uc131\uc7a5\uc5d0 \ub3c4\uc6c0\uc774 \ub420 \uc218 \uc788\ub294 \uc9c8\ubb38\uc744 \uc0dd\uac01\ud574\uc57c\uaca0\ub2e4. \\n\\n**PR \ud6c4\uc5d0\ub3c4 \uaf3c\uaf3c\ud558\uac8c \ud655\uc778\ud558\uae30** \\n\ubd84\uba85 \uc54c\uace0 \uc788\ub294 \ubd80\ubd84\uc774\uc9c0\ub9cc, \ub193\uce5c \ubd80\ubd84\uc774 \ub9ce\uc740 \uac83 \uac19\uc558\ub2e4. \\nPR \ud558\uae30 \uc804\uc5d0\ub3c4 \uacc4\uc18d \ud655\uc778\uc744 \ud588\uc9c0\ub9cc, \uc544\ubb34\ub798\ub3c4 IntelliJ\uc5d0\uc11c \ubcf4\ub2c8 \ucf54\ub4dc\uc5d0 \uc775\uc219\ud574\uc838\uc11c \uadf8\ub7f0\uc9c0 \ubcc0\uacbd\ud574\uc57c \ud560 \ubd80\ubd84\uc774 \uc798 \uc548\ubcf4\uc600\ub2e4. \\ngithub pr\uc5d0\uc11c\ub294 \uc804\uccb4 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc73c\ub2c8 PR \ud6c4\uc5d0\ub3c4 \uaf2d \ud655\uc778\ud574\uc57c\uaca0\ub2e4.\\n\\n**\uc801\uadf9\uc801\uc73c\ub85c \ub098\uc758 \uc758\uacac\uc744 \ub9d0\ud558\uae30** \\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\ub294 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ud398\uc5b4\uc758 \uc758\uacac\uc774 \uad1c\ucc2e\ub2e4\uace0 \uc0dd\uac01\ud558\uba74 \uc218\uc6a9 \ud6c4 \uac1c\uc120\uc744 \ud558\ub294 \ubc29\ud5a5\uc73c\ub85c \uc9c4\ud589\uc744 \ud588\uc5c8\ub294\ub370, \uc870\uae08 \ub354 \uac1c\uc120\ud560 \uc218 \uc788\ub294 \ubc29\ud5a5\uc774 \uc788\ub2e4\uba74 \ub098\ub3c4 \uc801\uadf9\uc801\uc73c\ub85c \uc758\uacac\uc744 \ub9d0\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\uc774 \ub4e0\ub2e4. \\n\ub098\ub3c4 \uc124\ub4dd\ud558\ub294 \ud798\uc744 \uae30\ub974\uace0, \ud398\uc5b4\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc744 \uc54c \uc218 \uc788\uace0, \uacb0\uacfc\ubb3c\ub3c4 \uc88b\uc740 \ubc29\ud5a5\uc73c\ub85c \ub098\uc624\uc9c0 \uc54a\uc744\uae4c? (\uace0\ubbfc \ub4e4\uc5b4\uc8fc\uc2e0 \ub9ac\ubdf0\uc5b4 \ud130\ud2c0\ud83d\udc22 \uac10\uc0ac\ud569\ub2c8\ub2e4.)\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**\uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784** \\nPlayers\uac00 Position\uc744 \uc0dd\uc131\ud558\uace0 Player\uc758 \uc0dd\uc131\uc790\uc5d0 \ub123\uc5b4\uc8fc\uc5c8\ub2e4. \ud558\uc9c0\ub9cc \uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ub828\ub41c \ucf54\uba58\ud2b8\uac00 \ub2ec\ub838\ub2e4.\\n\uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uc0dd\uac01\ud574 \ubcf4\ub2c8 Position\uc744 \uac00\uc9c0\uace0 \uc788\ub294 \uac74 Player\uae30 \ub54c\ubb38\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 Player\uac00 \ub2f4\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4\uace0 \uc0dd\uac01\ub418\uc5c8\ub2e4. \\n\\n\uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud55c \ud328\ud134\uc73c\ub85c GRASP\uc758 Creator \ud328\ud134\uc774 \uc788\ub294\ub370 \ub2e4\uc74c\uc758 \uc694\uc18c\ub97c \ucd5c\ub300\ud55c \ub9cc\uc871\ud558\ub294 \ud074\ub798\uc2a4\uc5d0 \uc0dd\uc131 \ucc45\uc784\uc744 \ud560\ub2f9\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n- B\uac00 A \uac1d\uccb4\ub97c \ud3ec\ud568 \ub610\ub294 \ucc38\uc870\ud55c\ub2e4.\\n- B\uac00 A \uac1d\uccb4\ub97c \uae30\ub85d\ud55c\ub2e4.\\n- B\uac00 A\ub97c \uae34\ubc00\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4.\\n- B\uac00 A\uc758 \ucd08\uae43\uac12\uc744 \uac00\uc9c0\uace0 \uc788\ub2e4. \\n\\n\uc2e4\uc81c\ub85c \uac1d\uccb4\uc758 \uc0dd\uc131 \ucc45\uc784\uc5d0 \uad00\ud574\uc11c \uae4a\uc774 \uc0dd\uac01\ud558\uba74\uc11c \ucf54\ub529\uc744 \ud558\uc9c0 \uc54a\uc558\ub294\ub370, \uc774\ubc88 \ubbf8\uc158\uc744 \ud1b5\ud574 \uc2dc\uc57c\uac00 \ub113\uc5b4\uc9c4 \uac83 \uac19\ub2e4.\\n\\n**\ud328\ud0a4\uc9c0 \ubd84\ub9ac \uae30\uc900** \\n\ud328\ud0a4\uc9c0 \ubd84\ub9ac\uc5d0 \ub300\ud55c \ub098\ub9cc\uc758 \uae30\uc900\uc774 \uc544\uc9c1 \uba85\ud655\ud558\uc9c0 \uc54a\uc544 \uc9c8\ubb38\uc774 \ub4e4\uc5b4\uc640\ub3c4 \uba85\ud655\ud558\uac8c \ub2f5\ubcc0\uc744 \ud558\uc9c0 \ubabb\ud588\ub2e4. \\n\ub9c8\uc9c0\ub9c9 \uc81c\ucd9c \uc804\uc5d0 \ub3c4\uba54\uc778 \ud328\ud0a4\uc9c0 \ub0b4\ubd80\ub97c \ubd84\ub9ac\ud574 \ubd24\ub294\ub370, \uae30\uc900\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \uc88b\uc9c0 \uc54a\uc740 \uc120\ud0dd\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\ud604\uc7ac \uc9c4\ud589\ud558\ub294 \ubbf8\uc158\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ud06c\uae30\uac00 \uadf8\ub807\uac8c \ud06c\uc9c0 \uc54a\uc73c\ub2c8, domain \ud328\ud0a4\uc9c0\uc5d0\uc11c \uc138\ubd80 \ud328\ud0a4\uc9c0\ub85c \ubd84\ub9ac\ud558\uc9c0 \uc54a\uc544\ub3c4 \ub420 \uac83 \uac19\ub2e4. \\n\\n**\uc0ac\uc6a9\ud558\ub294 \ucabd\uc5d0\uc11c \uc0dd\uac01\ud558\uae30 & \uc608\uce21\uac00\ub2a5\ud55c \ucf54\ub4dc \uc791\uc131\ud558\uae30** \\nPosition\uc5d0\uc11c \ub2e4\uc74c \uc704\uce58\ub098 \uc774\uc804 \uc704\uce58\ub97c \ubc18\ud658\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ud5c8\uc6a9 \ubc94\uc704(0~19)\uac00 \ubc97\uc5b4\ub09c\ub2e4\uba74, \uc758\ubbf8 \uc5c6\ub294 \uac12\uc774 \ub4e4\uc5b4\uac04 Position\uc744 \ubc18\ud658\ud558\ub3c4\ub85d \ud588\ub2e4. \\n\uc774\uac74 Position\uc744 \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc744 \uace0\ub824\ud558\uc9c0 \ubabb\ud55c \ucf54\ub529\uc774\uc5c8\ub294\ub370, \uc0ac\uc6a9\ud558\ub294 \uc785\uc7a5\uc5d0\uc11c\ub294 0~19\uc758 \uac12\uc774 \ubcf4\uc7a5\ub418\uc5b4 \uc788\ub2e4\uace0 \uc0dd\uac01\ud560 \uac83\uc774\uae30 \ub54c\ubb38\uc774\ub2e4. \\n\ub530\ub77c\uc11c hasNext, hasPrevious\ub77c\ub294 \uc774\uc804 \uac12, \uc774\ud6c4 \uac12\uc774 \ubc94\uc704 \ub0b4\uc5d0 \uc788\ub294\uc9c0 \ud655\uc778\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \ucd94\uac00\ud558\uace0, \uae30\uc874\uc758 \uac12\uc744 \uac00\uc838\uc624\ub294 \uba54\uc11c\ub4dc\ub294 \ubc94\uc704\uac00 \ubc97\uc5b4\ub098\uba74 \uc608\uc678\ub97c \ub358\uc9c0\ub294 \ubc29\ud5a5\uc73c\ub85c \ud574\uacb0\ud558\uc600\ub2e4. \\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\ubc1d\uc740 \uae30\uc6b4\uc744 \uac00\uc9c0\uace0 \uc788\uace0 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \uce5c\ud654\ub825\uc774 \uc88b\uc740 \uac83 \uac19\uc558\ub2e4. \\n\uc774\ubc88\uc5d0 \ud398\uc5b4 \ud560 \ub54c \ucee8\ub514\uc158 \uad00\ub9ac\ub97c \uc81c\ub300\ub85c \ubabb\ud574\uc11c \ub9ce\uc774 \ubbf8\uc548\ud588\ub2e4. \ub2e4\uc74c\uc5d0\ub294 \ucd5c\uc0c1\uc758 \ucee8\ub514\uc158\uc73c\ub85c \ud398\uc5b4\ub97c \uc900\ube44\ud574 \ubd10\uc57c\uaca0\ub2e4. \\n\uadf8\ub9ac\uace0 \uc6b0\uac00\ub791 \ud398\uc5b4\ub97c \ud558\uace0 \ub098\uc11c, \ub098\ub3c4 \ub2e4\ub978 \uc0ac\ub78c\ub4e4\uacfc \ub354 \uc798 \uc9c0\ub0b4\ubd10\uc57c\uaca0\ub2e4\ub294 \uc0dd\uac01\uc774 \ub4e4\uc5b4 \uc870\uae08 \ub354 \uc6a9\uae30\ub97c \ub0b4 \uc7a1\ub2f4 \uc911\uc774\ub2e4! \\n\\n\uc758\uacac\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ub0b4\uc918\uc11c \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589\uc774 \uc798 \ub418\uc5c8\ub2e4. \\n\ub610\ud55c \ud398\uc5b4 \uc9c4\ud589\uc774 \ub290\ub9b0 \uac83 \uac19\ub2e4\uace0 \ub9d0\ud574\uc918\uc11c \uc548\uc815\uc801\uc73c\ub85c \uc2dc\uac04 \uc548\uc5d0 \ubbf8\uc158\uc744 \uc644\ub8cc\ud560 \uc218 \uc788\uc5c8\ub2e4. \\n\ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d \uc9c4\ud589 \uc18d\ub3c4\uc5d0 \ub300\ud574 \uc870\uae08 \ub354 \uc0dd\uac01\uc744 \ud574\ubd10\uc57c\uaca0\ub2e4!\\n\\n\ud56d\uc0c1 \uc9c0\ub098\uac08 \ub54c\ub9c8\ub2e4 \uc6c3\uc5b4\uc8fc\ub294\ub370, \ub098\ub3c4 \uc790\uc8fc \uc6c3\uc5b4\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\uc6c3\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uc0ac\ub78c\uc774 \ubc1d\uc544 \ubcf4\uc5ec\uc11c \ub108\ubb34 \uc88b\uc740 \uac83 \uac19\ub2e4!"},{"id":"racing-car-retrospective","metadata":{"permalink":"/racing-car-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx","title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","description":"\uc790\ub3d9\ucc28 \uacbd\uc8fc","date":"2023-02-14T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 14\uc77c","tags":[{"label":"Woowahan Techcourse","permalink":"/tags/woowahan-techcourse"},{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":7.56,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","slug":"racing-car-retrospective","tags":["Woowahan Techcourse","Retrospective"]},"prevItem":{"title":"\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0","permalink":"/ladder-retrospective"},"nextItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"}},"content":"### \uc790\ub3d9\ucc28 \uacbd\uc8fc\\n\\n\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158\uc5d0\uc11c\ub294 \ub2e4\uc990\uacfc \ud398\uc5b4\uac00 \ub9e4\uce6d\ub418\uc5c8\ub2e4. \\n\uc6b0\ud14c\ucf54 \ub4e4\uc5b4\uc640\uc11c \uccab \ud398\uc5b4\ud504\ub85c\uadf8\ub798\ubc0d\uc774\ub77c \ub9ce\uc774 \ub5a8\ub838\uc9c0\ub9cc, \ub2e4\uc990\uc774 \ub300\ud654\ub97c \uc798 \uc774\ub04c\uc5b4\uc918 \ub108\ubb34 \uc990\uac70\uc6e0\ub2e4. \\n\\n\uccab\ub0a0\uc740 \uac04\ub2e8\ud788 \ucee8\ubca4\uc158\uacfc \ud658\uacbd\uc744 \uc124\uc815\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc84c\uace0 \ub2e4\uc74c \ub0a0\ubd80\ud130 \uc790\ub3d9\ucc28 \uacbd\uc8fc\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc2dc\uc791\uc740 \uac04\ub2e8\ud558\uac8c \uc694\uad6c\uc0ac\ud56d\uc744 \uc815\ub9ac\ud558\uace0, \uc5b4\ub5bb\uac8c \ucf54\ub4dc\ub97c \uc791\uc131\ud560\uc9c0 \uac19\uc774 \uace0\ubbfc\ud588\ub2e4. \\n\\n\uc2dc\uc791\ud558\uae30 \uc804 \uc544\ub798\uc640 \uac19\uc774 mermaid\ub97c \uc774\uc6a9\ud558\uc5ec \uc758\uc874\uc131 \ubc29\ud5a5\uc5d0 \ub300\ud574\uc11c \uac04\ub2e8\ud55c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \ub9cc\ub4e4\uace0 \uc2dc\uc791\ud588\ub2e4. \\nmermaid\ub294 \ucf54\ub4dc\ub85c \ub2e4\uc774\uc5b4\uadf8\ub7a8\uc744 \uc0dd\uc131 \ud574\uc8fc\ub294 \ub3c4\uad6c\ub85c \ub2e4\uc74c\uacfc \uac19\uc740 \uc7a5\uc810\uc774 \uc788\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n- \ucf54\ub4dc \uae30\ubc18\uc774\ub77c \ube60\ub978 \uc2dc\uac04 \uc548\uc5d0 \uc0dd\uac01\ud55c \uac83\uc744 \uc2dc\uac01\ud654\ud560 \uc218 \uc788\ub2e4. \\n- github\uc5d0\uc11c mermaid\ub97c \uc9c0\uc6d0\ud558\uae30 \ub54c\ubb38\uc5d0 \ub9ac\ubdf0\uc5b4\uc5d0\uac8c \ucf54\ub4dc\ub97c \uc774\ud574\ud560 \uc218 \uc788\ub294 \ubd80\uac00\uc801\uc778 \uc815\ubcf4\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```mermaid\\n---\\ntitle: \uc790\ub3d9\ucc28 \uacbd\uc8fc \uccab \ub9ac\ubdf0 \uc694\uccad\uc2dc \uad6c\uc870\\n---\\ngraph TD\\n Cars --\x3e Car\\n Car --\x3e Name\\n Car --\x3e Position\\n RacingGame --\x3e Count\\n RacingGame --\x3e NumberGenerator\\n RacingGame --\x3e Cars\\n RacingCarController --\x3e RacingGame\\n RandomNumberGenerator -.-> NumberGenerator\\n RacingCarController --\x3e InputView\\n InputView --\x3e InputValidator\\n RacingCarController --\x3e OutputView\\n```\\n\\n\ubbf8\uc158\uc744 \uc9c4\ud589\ud558\ub294 \ub370 \ud070 \uc5b4\ub824\uc6c0\uc774 \uc788\uc9c0\ub294 \uc54a\uc558\uace0, \ud398\uc5b4\ub97c \ub9c8\uce58\uae30 \uc804 \uc11c\ub85c \uace0\ubbfc\ub418\ub294 \ubd80\ubd84\uc744 \uc815\ub9ac\ud588\uc744 \ub54c \uc88b\uc558\ub2e4.\\n\\n\ud398\uc5b4\ud558\uba74\uc11c \uc798\ud588\ub2e4\uace0 \uc0dd\uac01\ud588\ub358 \uc810\uc740 \uc11c\ub85c\uc758 \uc0dd\uac01\uacfc \ub9ac\ubdf0 \ubc1b\uc740 \uac83\uc744 \uacf5\uc720\ud55c \uac83\uc774\ub2e4. \\n\ub9ac\ud329\ud130\ub9c1\uc744 \uc5b4\ub5bb\uac8c \ud588\ub294\uc9c0? \uc774\ub7f0 \ub9ac\ubdf0\uc5d0 \ub300\ud574 \uc5b4\ub5bb\uac8c \uc0dd\uac01\ud558\ub294\uc9c0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c8 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \ubd80\uc871\ud588\ub358 \ubd80\ubd84\\n\\n\ub9ac\ud329\ud130\ub9c1\uc774 \ub05d\ub09c \ud6c4 \uba54\uc11c\ub4dc\uba85, \ud14c\uc2a4\ud2b8\uc2dc \ucd9c\ub825\ud558\ub294 \uba54\uc2dc\uc9c0\uc5d0 \ub300\ud55c \ucf54\uba58\ud2b8\uac00 \ub9ce\uc774 \ub2ec\ub838\ub2e4. \\n\uac1d\uccb4\uac00 \uc5b4\ub5a4 \ucc45\uc784\uacfc \uc5ed\ud560\uc744 \uac00\uc9c0\ub294\uc9c0 \uc0dd\uac01\ud558\ub294 \uc2dc\uac04\uc744 \uac00\uc9c0\uace0 \uba85\ud655\ud55c \uba54\uc11c\ub4dc\uba85\uc744 \uc791\uc131\ud574\uc57c\uaca0\ub2e4\uace0 \uc0dd\uac01\ud588\ub2e4. \\n\\n\ud3c9\uc18c\uc5d0 \ud504\ub85c\uadf8\ub798\ubc0d \uc774\uc57c\uae30\uac00 \uc544\ub2cc \ub2e4\ub978 \uc8fc\uc81c\ub85c \uc774\uc57c\uae30\ud558\uba74 \uc798 \ub4e4\uc73c\ub824\uace0 \ud558\ub294 \ud3b8\uc774\uc9c0\ub9cc \\n\ub0b4\uac00 \uc88b\uc544\ud558\ub294 \uc8fc\uc81c, \uad00\uc2ec\uac00\ub294 \uc8fc\uc81c\uc778 \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0 \ub300\ud55c \uc774\uc57c\uae30\ub97c \ud560 \ub550 \ub9d0\uc774 \ub9ce\uc544\uc9c4\ub2e4. \\n\ub2e4\uc74c \ubbf8\uc158\ubd80\ud130\ub294 \ub354 \ub9ce\uc740 \uc2dc\uac04\uc744 \ud398\uc5b4\uc758 \uc758\uacac\uacfc \uc774\uc57c\uae30\ub97c \ub4e3\ub294 \uacf3\uc5d0 \uc0ac\uc6a9\ud574\uc57c\uaca0\ub2e4.\\n\\n### \uc0c8\ub85c \ud559\uc2b5\ud55c \ubd80\ubd84\\n\\n**Assertions extracting**\\n\\n\uacb0\uacfc \ub0b4\ubd80\uc5d0 \uc788\ub294 \uac12\uc744 \ud655\uc778\ud558\uace0 \uc2f6\uc744 \ub54c extracting \ud0a4\uc6cc\ub4dc\ub97c \uc774\uc6a9\ud574\uc11c \ub0b4\ubd80\uc758 \uac12\uc744 \uac80\uc99d\ud560 \uc218 \uc788\ub2e4. \\n\uc774\uc804\uc5d0\ub294 \ud544\uc694\uc5d0 \ub530\ub77c stream\uc744 \uc774\uc6a9\ud558\uc5ec \uac80\uc99d\ud560 \uac12\uc744 \uc0dd\uc131\ud588\uc9c0\ub9cc, \ud574\ub2f9 \ubc29\ubc95\uc744 \uc774\uc6a9\ud574\uc11c \uc808\ucc28\ub97c \uc904\uc77c \uc218 \uc788\uc5c8\ub2e4.\\n\\n```java\\n@Test\\nvoid extracting() {\\n final Cars cars = new Cars(List.of(\\"car1\\", \\"car2\\"));\\n\\n assertThat(cars.getCars())\\n .extracting(Car::getName)\\n .containsExactly(\\"car1\\", \\"car2\\");\\n}\\n```\\n\\n---\\n\\n\uc544\ub798\ub294 \ub9ac\ubdf0\uc5b4\ub2d8\uacfc \ub300\ud654\ub97c \ub098\ub204\uba74\uc11c \uc5bb\uc740 \ub2f5\ubcc0 + \ub098\uc758 \uc758\uacac\uc774\ub2e4.\\n\\n**\uc81c\uc5b4\ud560 \uc218 \uc5c6\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\ud14c\uc2a4\ud2b8 \ub300\uc0c1\uc774 \uac80\uc99d\ub41c \uac83\uc774\ub77c\uba74 \uc791\uc131\ud558\uc9c0 \uc54a\uac70\ub098, \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ubd80\ubd84\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uc791\uc131\ud55c\ub2e4. \\n\uc774\uac74 \uac1c\uc778\uc801\uc778 \uc0dd\uac01\uc774\uc9c0\ub9cc \ub0b4\uac00 \uc548\uc815\uac10\uc774 \ub4e4 \uc218 \uc788\uc744 \uc815\ub3c4\ub85c \ucd9c\ub825 \ubc94\uc704 \ub0b4\uc758 \uacb0\uacfc\ub97c \ubc18\ud658\ud558\ub294\uc9c0 \uc815\ub3c4 \ud14c\uc2a4\ud2b8\ud560 \uc218 \uc788\uc9c0 \uc54a\uc744\uae4c?\\n\\n**\ub2e8\uc21c \uc704\uc784\uc744 \ud558\ub294 \uba54\uc11c\ub4dc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8**\\n\\n\uc704\uc784\uc774\ub77c\ub294 \uac83\uc740 \uc5ed\ud560\uacfc \ucc45\uc784\uc744 \ub118\uaca8\uc900\ub2e4\ub294 \uac83\uc774\ub2e4. \\n\ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc99d\ud558\ub294 \uac83\ubcf4\ub2e4 \uacb0\uacfc\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8\ud558\ub294 \uac83\uc774 \uc88b\ub2e4. \\n\ub2e8\uc21c\ud788 \uc704\uc784\ub9cc \ud558\ub294 \ud14c\uc2a4\ud2b8\uc758 \uacbd\uc6b0 \uacb0\uacfc\ub97c \uac80\uc99d\ud55c\ub2e4\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc911\ubcf5\ub418\uc9c0 \uc54a\uc744\uae4c \uc0dd\uac01\ud588\uc5c8\ub2e4. \\n\ub530\ub77c\uc11c \uc911\ubcf5\ub41c \ud14c\uc2a4\ud2b8\ub97c \uc904\uc774\uae30 \uc704\ud574 \ub0b4\ubd80\uc758 \uba54\uc11c\ub4dc\ub97c \ud638\ucd9c\ud558\ub294\uc9c0 \uac80\uc99d\ud558\ub294 \ubc29\ubc95\ub3c4 \uc788\ub2e4\ub294 \uac83\uc744 \uc54c\uac8c \ub418\uc5c8\uc9c0\ub9cc \\n\uc548\uc815\uc801\uc73c\ub85c \uacb0\uacfc\ub97c \ud14c\uc2a4\ud2b8 \ud558\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc778 \uac83 \uac19\ub2e4.\\n\\n**\ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c getter \uc0ac\uc6a9**\\n\\n\ud14c\uc2a4\ud2b8 \uc6a9\ub3c4\ub85c \ub3c4\uba54\uc778\uc5d0 \uc0c8\ub85c\uc6b4 \uba54\uc11c\ub4dc\uac00 \uc0dd\uc131\ub418\ub294 \uac83\uc740 \uc88b\uc9c0 \ubabb\ud558\ub2e4. \\n\ud544\uc694\uc758 \uacbd\uc6b0 \uc0dd\uc131\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc9c0\ub9cc, \uae30\uc874\uc5d0 \uc788\ub294 \uba54\uc11c\ub4dc\ub4e4\uc744 \ud65c\uc6a9\ud574\ubcf4\ub294 \uac83\uc774 \ub354 \uc88b\uc740 \ubc29\ubc95\uc774\ub2e4. \\n\uc774 \ubd80\ubd84\uc5d0 \ub300\ud574\uc11c \ub9e4\uc6b0 \ub3d9\uc758\ud558\uace0, \uc55e\uc73c\ub85c\ub3c4 \ucd5c\ub300\ud55c \ud14c\uc2a4\ud2b8\ub97c \uc704\ud55c \ucf54\ub4dc\ub97c \ub3c4\uba54\uc778\uc5d0 \uc791\uc131\ud558\uc9c0 \uc54a\uc744 \uac83 \uac19\ub2e4.\\n\\n### \ud398\uc5b4\uc5d0\uac8c \ubc30\uc6b8 \ubd80\ubd84\\n\\n\uc9c8\ubb38\uc774\ub098 \uc0dd\uac01\ud560 \uc810\uc774 \uc788\uc744 \ub54c \ub9e4\uc6b0 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uac83 \uac19\uc558\ub2e4. \\n\uc0dd\uac01\uc744 \uc815\ub9ac\ud55c \ud6c4 \uc790\uc2e0\uc758 \uc758\uacac\uc744 \uba85\ub8cc\ud558\uac8c \uc804\ub2ec\ud574\uc8fc\uc5c8\ub2e4. \\n\uadf8\ub807\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc2dd\uc744 \ud6a8\uc728\uc801\uc73c\ub85c \uc2b5\ub4dd\ud55c\ub2e4. \\n\ub09c \uc0dd\uac01\uc744 \uc798 \uc815\ub9ac\ud558\uc9c0 \uc54a\uc740 \ucc44\ub85c \ub0b4\ubc84\ub824 \ub454 \uc595\uc740 \uc9c0\uc2dd\uc774 \ub9ce\uc740 \uac83 \uac19\ub2e4. (\uc774\ub7f0 \uac83\ub3c4 \uc544\ub294 \uac83\uc774\ub77c\uace0 \ud560 \uc218 \uc788\uc744\uae4c?) \\n\uc55e\uc73c\ub85c \uc870\uae08 \ub354 \uba38\ub9bf\uc18d\uc5d0\uc11c \uc815\ub9ac\ud558\uace0, \ubb38\uc81c\uc5d0 \ub300\ud574 \uae4a\uac8c \uace0\ubbfc\ud558\ub294 \uc2dc\uac04\uc744 \ub298\ub824\uc57c\uaca0\ub2e4.\\n\\n\uac1c\ubc1c\uc5d0 \uc5f4\uc815\uc744 \uac00\uc9c4 \uac8c \ub290\uaef4\uc9c4\ub2e4. \\n\ub098\ub3c4 \uac1c\ubc1c\uc744 \uc88b\uc544\ud558\uc9c0\ub9cc, \ucd5c\uadfc\uc5d0\ub294 \uc758\uc9c0\uac00 \uc57d\ud574\uc84c\uc5c8\ub2e4. \\n\uc5f4\uc815\uc774 \uac00\ub4dd\ud55c \uc0ac\ub78c\uc744 \ub9cc\ub098\ub2c8 \ub098\ub3c4 \uc5f4\uc815\uc801\uc778 \uc0ac\ub78c\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n\uce6d\ucc2c\uc744 \ub9ce\uc774 \ud574\uc900\ub2e4. \ub2e8\uc21c\ud788 \ub9ce\uc774 \ud574\uc8fc\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc9c4\uc2ec\uc744 \ub2f4\uae34 \uce6d\ucc2c\uc744 \ud574\uc92c\ub2e4. \\n\uce6d\ucc2c\uc740 \uace0\ub798\ub3c4 \ucda4\ucd94\uac8c \ud558\ub358\uac00? \\n\uadf8\ub798\uc11c \uc990\uac70\uc6b4 \ub9c8\uc74c\uc73c\ub85c \ud398\uc5b4 \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud588\uc5c8\ub358 \uac83 \uac19\ub2e4.\\n\\n\uc5b4\ub5a4 \uc774\uc720 \ub54c\ubb38\uc778\uc9c0 \ubaa8\ub974\uaca0\uc9c0\ub9cc \uac19\uc774 \ud398\uc5b4\ud558\ub294\ub370 \ud3b8\ud55c \ub9c8\uc74c\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc774\uac74 \ubc14\ub85c \ubc30\uc6b8 \uc218 \uc5c6\uc9c0\ub9cc. \\n\ub098\ub3c4 \uac19\uc774 \uc77c\ud560 \ub54c \ud3b8\ud55c \uc0ac\ub78c, \uac19\uc774 \uc77c\ud558\uace0 \uc2f6\uc740 \uc0ac\ub78c\uc774 \ub418\uae30 \uc704\ud574 \uae4a\uc774 \uace0\ubbfc\ud574\ubd10\uc57c\uaca0\ub2e4."},{"id":"parameterized-tests","metadata":{"permalink":"/parameterized-tests","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-02-12-Parameterized Tests.mdx","source":"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx","title":"Parameterized Tests","description":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4.","date":"2023-02-12T00:00:00.000Z","formattedDate":"2023\ub144 2\uc6d4 12\uc77c","tags":[{"label":"Java","permalink":"/tags/java"}],"readingTime":3.17,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Parameterized Tests","slug":"parameterized-tests","tags":["Java"]},"prevItem":{"title":"\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0","permalink":"/racing-car-retrospective"},"nextItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"}},"content":"\ud14c\uc2a4\ud2b8\ub97c \uc791\uc131\ud558\ub2e4\ubcf4\uba74 \ub9e4\uac1c\ubcc0\uc218\uc5d0 \ub530\ub77c \ubc18\ubcf5\uc774 \ub418\ub294 \ud14c\uc2a4\ud2b8\ub4e4\uc774 \uc0dd\uae34\ub2e4. \\n\uc774 \ub54c `@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\uba74 \ub2e8\uc77c \ud14c\uc2a4\ud2b8\ub97c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc5ec\ub7ec \ubc88 \ubc18\ubcf5\ud560 \uc218 \uc788\ub2e4.\\n\\n## Argument Sources\\n\\n`@ParameterizedTest`\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 \ucd5c\uc18c \ud558\ub098 \uc774\uc0c1\uc758 Source \uc560\ub178\ud14c\uc774\uc158\uc774 \ud544\uc694\ud558\ub2e4. \\nJUnit\uc774 \uc81c\uacf5\ud558\ub294 \ub2e4\uc591\ud55c Source\uac00 \uc788\uae30 \ub54c\ubb38\uc5d0, \ud14c\uc2a4\ud2b8\uc5d0 \ub9de\ucdb0 \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n### Value Source\\n\\n\uac12\uc744 \uc774\uc6a9\ud558\uc5ec \uc81c\uacf5\ud558\ub294 \ud615\ud0dc\ub85c, \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4. \\n- short, int, long, float, double\\n- byte, char, boolean, String, Class \\n\\n```java\\n@ParameterizedTest\\n@ValueSource(ints = {1, 100, Integer.MAX_VALUE})\\nvoid valueTest(final int value) {\\n Assertions.assertThat(value).isPositive();\\n}\\n```\\n\\n### Null & Empty Source\\n\\nnull \uac12, \ube48 \uac12\uc744 \uc81c\uacf5\ud55c\ub2e4. \\nEmpty Source\uc758 \uacbd\uc6b0 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0c0\uc785\uc5d0 \ud55c\ud574 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n- String\\n- java.util.List, java.util.Set, java.util.Map\\n- primitive arrays \u2014 ex) int[]\\n- object arrays \u2014 ex) String[]\\n\\n```java\\n@ParameterizedTest\\n@NullAndEmptySource\\nvoid nullAndEmptyTest(final String value) {\\n Assertions.assertThat(value).isNullOrEmpty();\\n}\\n```\\n\\n### Enum Source\\n\\nEnumSource\ub97c \uc774\uc6a9\ud558\uc5ec Enum \ub610\ud55c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n```java\\nenum Day {\\n MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\\n}\\n\\n@ParameterizedTest\\n@EnumSource(Day.class)\\nvoid enumTest(final Day day) {\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n\ub2e4\uc74c\uacfc \uac19\uc774 mode \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ud2b9\uc9d5 Enum\uc744 \uc81c\uc678\ud558\uac70\ub098, \ud3ec\ud568\uc2dc\ud0ac \uc218 \uc788\ub2e4. (default: Mode.Include)\\n\\n```java\\n@ParameterizedTest\\n@EnumSource(value = Day.class, names = {\\"SATURDAY\\", \\"SUNDAY\\"}, mode = Mode.EXCLUDE)\\nvoid enumTest(final Day day) {\\n // MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY\\n assertThat(day).isInstanceOf(Day.class);\\n}\\n```\\n\\n### CSV Source\\n\\ncsv \ud615\uc2dd\uc758 \uac12\uc744 \uc774\uc6a9\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud55c\ub2e4. \\n\uad6c\ubd84\uc790\uc758 \uae30\ubcf8\uac12\uc740 \uc27c\ud45c(,)\ub85c \uad6c\ubd84\uc790\ub97c \ubcc0\uacbd\ud558\uace0 \uc2f6\uc744 \ub550 delimeter \uac12\uc744 \ub530\ub85c \uc804\ub2ec\ud558\uc5ec \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\uac1c\uc778\uc801\uc73c\ub85c 2\uac1c \uc815\ub3c4\uc758 \uac12\uc744 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ud558\ub294 \uacbd\uc6b0 CsvSource\ub97c \uc0ac\uc6a9\ud55c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@CsvSource({\\"1,1\\", \\"2,4\\", \\"3,9\\", \\"4,16\\"})\\nvoid csvTest(final int number, final int result) {\\n assertThat(number * number).isEqualTo(result);\\n}\\n```\\n\\n### Method Source\\n\\n\ubcf5\uc7a1\ud55c \ud0c0\uc785\uc758 \uac12\uc744 \uc804\ub2ec\ud560 \ub54c \uc0ac\uc6a9\ud55c\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \uc785\ub825\ud558\uc5ec \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud558\ub294 \uba54\uc11c\ub4dc\ub97c \uc9c0\uc815\ud560 \uc218 \uc788\ub2e4. \\n\uba54\uc11c\ub4dc\uba85\uc744 \ub530\ub85c \uc785\ub825\ud558\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uba85\uacfc \ub3d9\uc77c\ud55c static \uba54\uc11c\ub4dc\uac00 \uc9c0\uc815\ub41c\ub2e4.\\n\\n```java\\n@ParameterizedTest\\n@MethodSource\\nvoid methodTest(final List numbers, final int count) {\\n assertThat(numbers).hasSize(count);\\n}\\n\\nprivate static Stream methodTest() {\\n return Stream.of(\\n Arguments.of(List.of(1), 1),\\n Arguments.of(List.of(1, 2), 2),\\n Arguments.of(List.of(1, 2, 3), 3)\\n );\\n}\\n```\\n\\n### ETC.\\n\\n\uc704\uc5d0\uc11c \uc5b8\uae09\ud55c \ubc29\ubc95 \uc774\uc678\uc5d0\ub3c4 \ub2e4\uc591\ud55c \ubc29\ubc95\uc73c\ub85c \ub9e4\uac1c\ubcc0\uc218\ub97c \uc81c\uacf5\ud560 \uc218 \uc788\ub2e4.\\n\\n- CSV \ud30c\uc77c\uc744 \uc774\uc6a9\ud55c CsvFileSource\\n- ArgumentsProvider \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \uc774\uc6a9\ud558\ub294 ArgumentsSource\\n\\n## \ucc38\uace0 \uc790\ub8cc\\n\\n- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)"},{"id":"intellij-settings","metadata":{"permalink":"/intellij-settings","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","source":"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx","title":"IntelliJ \uc124\uc815","description":"Import \uc790\ub3d9 \uc801\uc6a9","date":"2023-01-30T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 30\uc77c","tags":[{"label":"IntelliJ","permalink":"/tags/intelli-j"}],"readingTime":0.465,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"IntelliJ \uc124\uc815","slug":"intellij-settings","tags":["IntelliJ"]},"prevItem":{"title":"Parameterized Tests","permalink":"/parameterized-tests"},"nextItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"}},"content":"### Import \uc790\ub3d9 \uc801\uc6a9\\n\\nPrefrences > Editor > General > Auto Import > Add unambiguous imports on the fly\\n\\n![auto-import](./auto-import.png)\\n\\n### \uc800\uc7a5\uc2dc \ub3d9\uc791\\n\\nPrefrences > Tools > Actions on Save\\n\\n![actions-on-save](./actions-on-save.png)\\n\\nReformat Code: Code Reformmating\\n\\nOptimize imports: \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 Import \uc81c\uac70\\n\\nRearrange: Code Style > Arrangement \uc124\uc815 \uae30\ubc18 \ucf54\ub4dc \uc7ac\uc815\ub82c\\n\\n### \uba54\uc18c\ub4dc \ucd94\ucd9c, \ubcc0\uc218 \ucd94\ucd9c\uc2dc final \uc801\uc6a9\\n\\nPrefrences > Editor > Code Style > Java > Code Generation > Final Modifier\\n\\n![final-modifier](./final-modifier.png)"},{"id":"kotlin-null","metadata":{"permalink":"/kotlin-null","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","source":"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx","title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","description":"nullable \ud0c0\uc785","date":"2023-01-16T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 16\uc77c","tags":[{"label":"Kotlin","permalink":"/tags/kotlin"}],"readingTime":4.225,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","slug":"kotlin-null","tags":["Kotlin"]},"prevItem":{"title":"IntelliJ \uc124\uc815","permalink":"/intellij-settings"},"nextItem":{"title":"JSR-310","permalink":"/jsr-310"}},"content":"import Tabs from \\"@theme/Tabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\n\\n### nullable \ud0c0\uc785\\n\\n\ucf54\ud2c0\ub9b0\uc740 `NullPointerException` \uc608\uc678\ub97c \ucd5c\ub300\ud55c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 \ud0c0\uc785 \uc2dc\uc2a4\ud15c\uc774 \uc124\uacc4\ub418\uc5b4 \uc788\ub2e4. \\n\uc774\ub294 \uc2e4\ud589 \uc2dc\uc810\uc774 \uc544\ub2cc \ucef4\ud30c\uc77c \uc2dc \ubbf8\ub9ac \uc624\ub958\uac00 \ubc1c\uc0dd\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub294 \ubd80\ubd84\uc744 \ubbf8\ub9ac \uac10\uc9c0\ud558\uc5ec NPE \ubc1c\uc0dd\uc758 \uac00\ub2a5\uc131\uc744 \uc904\uc5ec\uc900\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc758 \uacbd\uc6b0 nullable \ud0c0\uc785\uc744 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4.\\n\\n```kotlin\\nval number: Int?\\n```\\n\\n\ud0c0\uc785 \ub4a4\uc5d0 `?`\ub97c \ubd99\uc5ec \ud574\ub2f9 \uac12\uc774 null\uc774 \ub420 \uc218 \uc788\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4. \\n\ub9cc\uc57d `?`\ub97c \ubd99\uc774\uc9c0 \uc54a\uc744 \ub54c null\uc744 \ubc1b\ub294 \uacbd\uc6b0 \ucef4\ud30c\uc77c \uc2dc \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4.\\n\\n### `?.` Safe Calls \uc5f0\uc0b0\uc790\\n\\n\uc790\ubc14\uc5d0\uc11c NPE\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uae30 \uc704\ud574 null\uc744 \ucc98\ub9ac\ud558\ub294 \uac00\uc7a5 \uac04\ub2e8\ud55c \ubc29\ubc95\uc73c\ub85c\ub294 \ubd84\uae30\ub97c \uc0ac\uc6a9\ud558\ub294 \ubc29\ubc95\uc774 \uc788\ub2e4.\\n\\n\ucf54\ud2c0\ub9b0\uc740 \uc548\uc804\ud55c \ud638\ucd9c \uc5f0\uc0b0\uc790\uc778 `?.` \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4. \\n\ub530\ub77c\uc11c \ucc38\uc870 \uac12\uc774 null\uc774 \uc544\ub2d0 \uacbd\uc6b0\uc5d0\ub9cc \uba54\uc11c\ub4dc \ud638\ucd9c\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ucc38\uc870 \uac12\uc774 null\uc778 \uacbd\uc6b0 \uba54\uc11c\ub4dc \ud638\ucd9c\uc774 \ubb34\uc2dc\ub418\uace0, null\uc744 \ubc18\ud658\ud55c\ub2e4. \\n\\n\\n\\n\\n```java\\npublic String repeat(String word) {\\n if (word == null) {\\n return null;\\n }\\n return word.repeat(2);\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun repeat(word: String?): String? {\\n return word?.repeat(2)\\n}\\n```\\n\\n\\n\\n\\n### `?:` \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\\n\\n\ucc38\uc870\ud558\ub824\ub294 \uac12\uc774 null\uc77c \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \ubc18\ud658\ud558\uace0 \uc2f6\uc744 \ub54c\ub294 \uc5b4\ub5bb\uac8c \ud574\uc57c \ud560\uae4c? \\n\ucf54\ud2c0\ub9b0\uc740 null\uc774 \uc544\ub2cc \uacbd\uc6b0 \uae30\ubcf8 \uac12\uc744 \uc9c0\uc815\ud560 \ub54c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc9c0\uc6d0\ud55c\ub2e4.\\n\\n\\n\\n\\n```java\\npublic String stringSafe(String word) {\\n if (word == null) {\\n return \\"\\";\\n }\\n return word;\\n}\\n```\\n\\n\\n\\n\\n```kotlin\\nfun stringSafe(word: String?): String {\\n return word ?: \\"\\"\\n}\\n```\\n\\n\\n\\n\\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 throw\ub3c4 \uc2dd\uc774\uae30 \ub54c\ubb38\uc5d0 \uc5d8\ube44\uc2a4 \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud558\uc5ec \uc608\uc678\ub97c \ub358\uc9c8 \uc218 \uc788\ub2e4. \\n\uc608\ub97c \ub4e4\uc5b4 \uc0ac\uc6a9\uc790 \uc815\ubcf4\uac00 \uc788\ub294 \uc800\uc7a5\uc18c\uc5d0 \ucc3e\ub294 \uc0ac\uc6a9\uc790\uac00 \uc5c6\ub294 \uacbd\uc6b0 \uc544\ub798\uc640 \uac19\uc774 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.\\n\\n```kotlin\\nuserRepository.findByName(name) ?: throw IllegalArgumentException()\\n```\\n\\n### `!!` \ub110 \uc544\ub2d8 \ub2e8\uc5b8 \uc5f0\uc0b0\uc790\\n\\n!! \uc5f0\uc0b0\uc790\ub97c \uc774\uc6a9\ud55c\ub2e4\uba74 \uac15\uc81c\ub85c \uc5b4\ub5a4 \uac12\uc774\ub4e0 non-nullable \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. \\n\ud558\uc9c0\ub9cc null\uc778 \uac12\uc5d0 \uc0ac\uc6a9\ud55c\ub2e4\uba74 NPE\uac00 \ubc1c\uc0dd\ud558\uac8c \ub41c\ub2e4. \\n\uc77c\ubc18\uc801\uc778 \uacbd\uc6b0\uc5d0\ub294 !! \uc5f0\uc0b0\uc790\ub97c \uc0ac\uc6a9\ud558\ub294 \uac83\uc740 \uc704\ud5d8\ud558\ub2e4. \\n\uc0ac\uc6a9\ud558\uae30 \uc27d\uc9c0\ub9cc, \ub9ac\uc2a4\ud06c\uac00 \ud06c\uace0 \ud639\uc2dc\ub098 \ud574\ub2f9 \uac12\uc774 \ucd94\ud6c4\uc5d0\ub294 null\uc774 \ub420 \uc218 \uc788\uae30 \ub54c\ubb38\uc5d0 \uc9c0\uc591\ud574\uc57c \ub41c\ub2e4\uace0 \uc0dd\uac01\ud55c\ub2e4.\\n\\n```kotlin\\nval length: Int = word!!.length\\n```\\n\\n### `as?` \uc548\uc804\ud55c \uce90\uc2a4\ud305\\n\\n\ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \ub54c \uc9c0\uc815\ud55c \ud0c0\uc785\uc73c\ub85c \ubcc0\uacbd\ud560 \uc218 \uc5c6\ub2e4\uba74 `ClassCastException`\uc774 \ubc1c\uc0dd\ud55c\ub2e4. \\n\ucf54\ud2c0\ub9b0\uc5d0\uc11c\ub294 as \ub4a4\uc5d0 ?\ub97c \ubd99\uc5ec \uc548\uc804\ud558\uac8c \ud0c0\uc785 \ubcc0\ud658\uc744 \ud560 \uc218 \uc788\ub2e4. \\n\ub530\ub77c\uc11c \ubbf8\ub9ac \ubcc0\ud658 \uac00\ub2a5\ud55c \ud0c0\uc785\uc778\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uace0, \uc548\uc804\ud558\uac8c \ud0c0\uc785\uc744 \ubcc0\ud658 \ud560 \uc218 \uc788\ub2e4. \\n\\n\ud0c0\uc785 \ubcc0\ud658\uc774 \ubd88\uac00\ub2a5 \ud560 \uacbd\uc6b0 \uc608\uc678\ub97c \ubc1c\uc0dd\uc2dc\ud0a4\uc9c0 \uc54a\uace0 null\uc744 \ubc18\ud658\ud55c\ub2e4.\\n\\n```kotlin\\nval value: Int? = something as? Int\\n```\\n\\n### List\uc5d0\uc11c\uc758 null \ucc98\ub9ac\\n\\nList\uc5d0\ub294 null\uc774 \uc544\ub2cc \uac12\ub9cc \ubc18\ud658\ud558\ub294 `filterNotNull` \uc720\ud2f8\ub9ac\ud2f0 \uba54\uc11c\ub4dc\ub97c \uc81c\uacf5\ud55c\ub2e4.\\n\\n```kotlin\\nval foodsWithNull: List = listOf(\\"Pizza\\", \\"Cheese\\", null, \\"Potato\\")\\nval foods = foodsWithNull.filterNotNull()\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [Kotlin in Action](https://product.kyobobook.co.kr/detail/S000001804588)\\n- [Effective Kotlin Item 8](https://product.kyobobook.co.kr/detail/S000001033129)\\n- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin/null-safety)\\n- [Kotlin NullSafety](https://kotlinlang.org/docs/null-safety.html)"},{"id":"jsr-310","metadata":{"permalink":"/jsr-310","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-08-JSR-310.mdx","source":"@site/blog/2023-1/2023-01-08-JSR-310.mdx","title":"JSR-310","description":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API","date":"2023-01-08T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 8\uc77c","tags":[{"label":"Java","permalink":"/tags/java"},{"label":"Time","permalink":"/tags/time"}],"readingTime":1.685,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"JSR-310","slug":"jsr-310","tags":["Java","Time"]},"prevItem":{"title":"Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95","permalink":"/kotlin-null"},"nextItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"}},"content":"\uc774\uc804\uc5d0 \ub9ce\uc740 \ubb38\uc81c\uac00 \uc788\ub358 \uc790\ubc14\uc758 \ud074\ub798\uc2a4(Calendar, Date)\ub97c \ub300\uccb4\ud558\ub294 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API \\nISO-8601\uc744 \uae30\ubc18\uc73c\ub85c \uc791\uc131 \\n\uc124\uacc4 \ubaa9\ud45c \u2192 \ubd88\ubcc0, Fluent API, \uba85\ud655\ud558\uace0 \uba85\uc2dc\uc801, \ud655\uc7a5 \uac00\ub2a5\uc131\\n\\n:::note ISO-8601\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc5d0 \uad00\ub828\ub41c \ub370\uc774\ud130\ub97c \ub2e4\ub8e8\ub294 \uad6d\uc81c \ud45c\uc900\\n\\n:::\\n\\n### LocalDate, LocalTime, LocalDateTime\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### Instant\\n\\n\uc720\ub2c9\uc2a4 \uc2dc\uac04(1970-01-01, 00:00:00 UTC) \uae30\uc900\uc73c\ub85c \ud2b9\uc815 \uc9c0\uc810\uae4c\uc9c0\uc758 \uc2dc\uac04\uc744 \ucd08\ub85c \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4 \\n\uae30\uacc4\uc758 \uad00\uc810\uc5d0\uc11c \uc2dc\uac04 \ud45c\ud604\\n\\n### Duration, Period\\n\\n\uac04\uaca9\uc744 \ud45c\ud604\ud558\ub294 \ud074\ub798\uc2a4\\n\\n### TemporalAdjusters\\n\\n\ubcf5\uc7a1\ud55c \ub0a0\uc9dc \uc870\uc815\uc774 \ud544\uc694\ud560 \ub54c \uc0ac\uc6a9 \\n\ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud558\uc5ec \ucee4\uc2a4\ud140 TemporalAdjuster\ub97c \uad6c\ud604 \uac00\ub2a5\\n\\n```java\\n@FunctionalInterface\\npublic interface TemporalAdjuster {\\n Temporal adjustInto(Temporal temporal);\\n}\\n```\\n\\n### DateTimeFormatter\\n\\n\ub0a0\uc9dc\uc640 \uc2dc\uac04 \ud3ec\ub9f7 \ud074\ub798\uc2a4 \\n\ud2b9\uc815 \ub0a0\uc9dc \ud328\ud134\uc774\ub098, DateTimeFormatterBuilder\ub97c \uc774\uc6a9\ud574\uc11c \ucee4\uc2a4\ud140\ud55c \ud3ec\ub9f7\uc744 \uc0dd\uc131 \uac00\ub2a5\\n\\n### ZoneId, ZoneOffset\\n\\nZoneId\ub294 \uc9c0\uc5ed ID\ub294 `\u2018\uc9c0\uc5ed/\ub3c4\uc2dc\u2019` \ud615\uc2dd, ZoneOffset\uc740 \uc2dc\ucc28 UTC \uae30\uc900 \uace0\uc815\ub41c \uc2dc\uac04 \ucc28\uc774 \uc774\uc6a9 \\nZoneId\uc758 \uacbd\uc6b0 IANA Time Zone Database\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc9c0\uc5ed \uc9d1\ud569 \uc815\ubcf4 \uc0ac\uc6a9\\n\\n```java\\nInstant instant = Instant.now();\\nLocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);\\n```\\n\\n### \ucc38\uace0 \uc790\ub8cc\\n\\n- [\ubaa8\ub358 \uc790\ubc14 \uc778 \uc561\uc158](https://product.kyobobook.co.kr/detail/S000001810171)\\n- [Java\uc758 \ub0a0\uc9dc\uc640 \uc2dc\uac04 API](https://d2.naver.com/helloworld/645609)\\n- [ISO-8601](https://www.w3.org/TR/NOTE-datetime)\\n- [JSR-310 Spec](https://download.oracle.com/otn-pub/jcp/date_time-0.2-edr-oth-JSpec/date_time-0_2-edr-spec.pdf?AuthParam=1673171124_74a718be92efe4911c6977c02965aff4)\\n- [Temporal Adjuster](https://www.baeldung.com/java-temporal-adjuster)\\n- [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)"},{"id":"the-essence-of-object-orientation","metadata":{"permalink":"/the-essence-of-object-orientation","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","source":"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx","title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","description":"\ucc45 \uc815\ubcf4","date":"2023-01-07T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 7\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":5.415,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","slug":"the-essence-of-object-orientation","tags":["Book"]},"prevItem":{"title":"JSR-310","permalink":"/jsr-310"},"nextItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574 \\n> \uc870\uc601\ud638\\n> \\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc870\uc601\ud638\ub2d8\uc758 \uc624\ube0c\uc81d\ud2b8\ub97c \uc77d\uace0 \ub098\uc11c \ub2e4\uc2dc \ud55c \ubc88 \uc77d\uc5b4\ubcf4\uc558\ub2e4. \\n\uc544\uc9c1 \uc774\ud574\uac00 \uc548\ub418\ub294 \ubd80\ubd84\uc774 \ub9ce\uc9c0\ub9cc, \uadf8\ub798\ub3c4 \ud56d\uc0c1 \uc0c8\ub85c\uc6c0\uc744 \ub290\ub080\ub2e4. \\n\ub354\ud560 \ub098\uc704 \uc5c6\uc774 \ud73c\ub96d\ud55c \uac1d\uccb4\uc9c0\ud5a5 \ucc45\uc774\uace0, \uc870\uae08 \ub354 \uacf5\ubd80\ud558\uace0 \ub2e4\uc2dc \uc77d\uc5b4\ubd10\uc57c\ub420 \uac83 \uac19\ub2e4. \\n\\n\ucee4\ud53c \uc804\ubb38\uc810, \uc9c0\ud558\ucca0 \ub178\uc120\ub3c4, \uc774\uc0c1\ud55c \ub098\ub77c\uc758 \uc5d8\ub9ac\uc2a4\ub97c \uc608\uc2dc\ub85c \ub4e0 \uc124\uba85\uc774 \ub108\ubb34 \uc88b\uc558\uace0 \\n\uc88b\uc740 \ub0b4\uc6a9\uc744 \ub2f4\uace0 \uc788\uc9c0\ub9cc \uadf8\ub807\ub2e4\uace0 \ub108\ubb34 \ubb34\uac81\uc9c0 \uc54a\uc544 \uac00\ubccd\uac8c \uc77d\uae30\ub3c4 \uc88b\uc740 \uac83 \uac19\ub2e4.\\n\\n### \ucc45\uc784\uc758 \uc790\uc728\uc131\uc744 \uac15\uc870\ud558\ub294 \uc774\uc720 p.173\\n\\n\ud611\ub825\uc744 \ub2e8\uc21c\ud558\uac8c \ub9cc\ub4e0\ub2e4.\\n\\n- \uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604 \u2192 \ud611\ub825\uc758 \ubcf5\uc7a1\ud568 \uc800\ud558\\n- \ucc45\uc784\uc758 \ucd94\uc0c1\ud654\\n\\n\uc678\ubd80\uc640 \ub0b4\ubd80\ub97c \uba85\ud655\ud558\uac8c \ubd84\ub9ac\ud55c\ub2e4.\\n\\n- \uc694\uccad\ud558\ub294 \uac1d\uccb4\uac00 \ubab0\ub77c\ub3c4 \ub418\ub294 \ubd80\ubd84\uc774 \ucea1\uc290\ud654\ub428\uc73c\ub85c \uc778\ud130\ud398\uc774\uc2a4\uc640 \uad6c\ud604\uc758 \ubd84\ub9ac\\n\\n\ucc45\uc784\uc744 \uc218\ud589\ud558\ub294 \ub0b4\ubd80\uc801\uc778 \ubc29\ubc95\uc744 \ubcc0\uacbd\ud558\ub354\ub77c\ub3c4 \uc678\ubd80\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\uc9c0 \uc54a\ub294\ub2e4.\\n\\n- \ubcc0\uacbd\uc758 \ud30c\uae09\ud6a8\uacfc\ub97c \uac1d\uccb4 \ub0b4\ubd80\ub85c \ucea1\uc290\ud654 \u2192 \uba54\uc2dc\uc9c0\ub97c \ubcf4\ub0b4\ub294 \uac1d\uccb4\uc640\uc758 \uacb0\ud569\ub3c4 \uc800\ud558\\n\\n\ud611\ub825\uc758 \ub300\uc0c1\uc744 \ub2e4\uc591\ud558\uac8c \uc120\ud0dd\ud560 \uc218 \uc788\ub294 \uc720\uc5f0\uc131\uc744 \uc81c\uacf5\ud55c\ub2e4.\\n\\n- \uc720\uc5f0\ud55c \uc124\uacc4 \u2192 \uc7ac\uc0ac\uc6a9\uc131 \uc99d\uac00\\n\\n\uac1d\uccb4\uc758 \uc5ed\ud560\uc744 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc9c4\ub2e4.\\n\\n- \uc751\uc9d1\ub3c4\ub97c \ub192\uc740 \uc0c1\ud0dc\ub85c \uc720\uc9c0\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc758 \ubaa9\ud45c\ub294 \uc2e4\uc138\uacc4\ub97c \ubaa8\ubc29\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\n\uc624\ud788\ub824 \uc0c8\ub85c\uc6b4 \uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc18c\ud504\ud2b8\uc6e8\uc5b4 \uac1c\ubc1c\uc790\uc758 \uc5ed\ud560\uc740 \ub2e8\uc21c\ud788 \uc2e4\uc138\uacc4\ub97c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc548\uc73c\ub85c \uc62e\uaca8 \ub2f4\ub294 \uac83\uc774 \uc544\ub2c8\ub77c \uace0\uac1d\uacfc \uc0ac\uc6a9\uc790\ub97c \ub9cc\uc871\uc2dc\ud0ac \uc218 \uc788\ub294 \uc2e0\uc138\uacc4\ub97c \ucc3d\uc870\ud558\ub294 \uac83\uc774\ub2e4.\\np.21\\n> \\n\\n> \uacfc\uac70\uc758 \uc804\ud1b5\uc801\uc778 \uac1c\ubc1c \ubc29\ubc95\uc740 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uc5c4\uaca9\ud558\uac8c \uad6c\ubd84\ud55c\ub2e4.\\n\uc774\uc5d0 \ubc18\ud574 \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c\ub294 \ub370\uc774\ud130\uc640 \ud504\ub85c\uc138\uc2a4\ub97c \uac1d\uccb4\ub77c\ub294 \ud558\ub098\uc758 \ud2c0 \uc548\uc5d0 \ud568\uaed8 \ubb36\uc5b4 \ub193\uc74c\uc73c\ub85c\uc368 \uac1d\uccb4\uc758 \uc790\uc728\uc131\uc744 \ubcf4\uc7a5\ud55c\ub2e4.\\n\uc790\uc728\uc801\uc778 \uac1d\uccb4\ub85c \uad6c\uc131\ub41c \uacf5\ub3d9\uccb4\ub294 \uc720\uc9c0 \ubcf4\uc218\uac00 \uc27d\uace0 \uc7ac\uc0ac\uc6a9\uc774 \uc6a9\uc774\ud55c \uc2dc\uc2a4\ud15c\uc744 \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uac00\ub2a5\uc131\uc744 \uc81c\uc2dc\ud55c\ub2e4.\\np.33\\n> \\n\\n> **\uac1d\uccb4\uc9c0\ud5a5\uc758 \ubcf8\uc9c8**\\n> \\n> \\n> \uc2dc\uc2a4\ud15c\uc744 \uc0c1\ud638\uc791\uc6a9\ud558\ub294 \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub4e4\uc758 \uacf5\ub3d9\uccb4\ub85c \ubc14\ub77c\ubcf4\uace0 \uac1d\uccb4\ub97c \uc774\uc6a9\ud574 \uc2dc\uc2a4\ud15c\uc744 \ubd84\ud560\ud558\ub294 \ubc29\ubc95\\n> \\n> \uc790\uc728\uc801\uc778 \uac1d\uccb4\ub780 \uc0c1\ud0dc\uc640 \ud589\uc704\ub97c \ud568\uaed8 \uc9c0\ub2c8\uba70 \uc2a4\uc2a4\ub85c \uc790\uae30 \uc790\uc2e0\uc744 \ucc45\uc784\uc9c0\ub294 \uac1d\uccb4\ub97c \uc758\ubbf8\ud55c\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \uc2dc\uc2a4\ud15c\uc758 \ud589\uc704\ub97c \uad6c\ud604\ud558\uae30 \uc704\ud574 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud55c\ub2e4. \uac01 \uac1d\uccb4\ub294 \ud611\ub825 \ub0b4\uc5d0\uc11c \uc815\ud574\uc9c4 \uc5ed\ud560\uc744 \uc218\ud589\ud558\uba70 \uc5ed\ud560\uc740 \uad00\ub828\ub41c \ucc45\uc784\uc758 \uc9d1\ud569\uc774\ub2e4.\\n> \\n> \uac1d\uccb4\ub294 \ub2e4\ub978 \uac1d\uccb4\uc640 \ud611\ub825\ud558\uae30 \uc704\ud574 \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\ud558\uace0, \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c \uac1d\uccb4\ub294 \uba54\uc2dc\uc9c0\ub97c \ucc98\ub9ac\ud558\ub294 \ub370 \uc801\ud569\ud55c \uba54\uc11c\ub4dc\ub97c \uc790\uc728\uc801\uc73c\ub85c \uc120\ud0dd\ud55c\ub2e4.\\n> p.35\\n> \\n\\n> \ud074\ub798\uc2a4\uc758 \uad6c\uc870\uc640 \uba54\uc11c\ub4dc\uac00 \uc544\ub2c8\ub77c \uac1d\uccb4\uc758 \uc5ed\ud560, \ucc45\uc784, \ud611\ub825\uc5d0 \uc9d1\uc911\ud558\ub77c.\\n\uac1d\uccb4\uc9c0\ud5a5\uc740 \uac1d\uccb4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774\uc9c0 \ud074\ub798\uc2a4\ub97c \uc9c0\ud5a5\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub2e4.\\np.38\\n> \\n\\n> \uac1d\uccb4\uc9c0\ud5a5\uc5d0\uc11c \uc911\uc694\ud55c \uac83\uc740 \ub3d9\uc801\uc73c\ub85c \ubcc0\ud558\ub294 \uac1d\uccb4\uc758 \u2018\uc0c1\ud0dc\u2019\uc640 \uc0c1\ud0dc\ub97c \ubcc0\uacbd\ud558\ub294 \u2018\ud589\uc704\u2019\ub2e4.\\n\ud074\ub798\uc2a4\ub294 \ud0c0\uc785\uc744 \uad6c\ud604\ud558\uae30 \uc704\ud574 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uad6c\ud604 \uba54\ucee4\ub2c8\uc998\uc774\ub77c\ub294 \uc0ac\uc2e4\uc744 \uae30\uc5b5\ud558\ub77c.\\np.105\\n> \\n\\n> \ucc45\uc784 \uc8fc\ub3c4 \uc124\uacc4\uc758 \ud575\uc2ec\uc740 \uc5b4\ub5a4 \ud589\uc704\uac00 \ud544\uc694\ud55c\uc9c0\ub97c \uba3c\uc800 \uacb0\uc815\ud55c \ud6c4\uc5d0 \uc774 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac1d\uccb4\ub97c \uacb0\uc815\ud558\ub294 \uac83\uc774\ub2e4.\\n\uc774 \uacfc\uc815\uc744 \ud754\ud788 What/Who \uc0ac\uc774\ud074\uc774\ub77c\uace0 \ud55c\ub2e4.\\n\u2019\uc5b4\ub5a4 \ud589\uc704(What)\u2019\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud55c \ud6c4 \u2018\ub204\uac00(who)\u2019 \uadf8 \ud589\uc704\ub97c \uc218\ud589\ud560 \uac83\uc778\uc9c0 \uacb0\uc815\ud574\uc57c \ud55c\ub2e4.\\n\uc5ec\uae30\uc11c \u2018\uc5b4\ub5a4 \ud589\uc704\u2019\uac00 \ubc14\ub85c \uba54\uc2dc\uc9c0\ub2e4.\\np.158\\n>"},{"id":"2022-retrospective","metadata":{"permalink":"/2022-retrospective","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","source":"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx","title":"2022\ub144 \ud68c\uace0","description":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70","date":"2023-01-02T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 2\uc77c","tags":[{"label":"Retrospective","permalink":"/tags/retrospective"}],"readingTime":3.705,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"2022\ub144 \ud68c\uace0","slug":"2022-retrospective","tags":["Retrospective"]},"prevItem":{"title":"[\ucc45] \uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574","permalink":"/the-essence-of-object-orientation"},"nextItem":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","permalink":"/book-writer"}},"content":"\uc801\ub2f9\ud55c \uc804\ud658\uc810, 2022\ub144\uc744 \ub3cc\uc544\ubcf4\uba70 \\n\\n### \uc804\uc5ed\\n\\n\uc57d 1\ub144 6\uac1c\uc6d4\uac04\uc758 \uacf5\uad70 \uc815\ubcf4\ubcf4\ud638\ubcd1 \uc0dd\ud65c\uc744 \ub9c8\uce58\uace0 \uc804\uc5ed\uc744 \ud588\ub2e4. \\n\uc870\uae30 \uc804\uc5ed \ub54c\ubb38\uc5d0 2021\ub144 12\uc6d4\uc5d0 \ub098\uc654\uc9c0\ub9cc, \uc2e4\uc81c \uc804\uc5ed \ub0a0\uc9dc\ub294 2022\ub144\uc774\ub2c8 \ud68c\uace0\uc5d0 \uc801\uc5b4\ub3c4 \uc0c1\uad00\uc5c6\uaca0\uc9c0. \\n\\n\uc870\uae08 \ub354 \ubbf8\ub798\uc5d0 \ub300\ud55c \uc0dd\uac01\uc744 \ud574\ubcfc\uac78 \uadf8\ub7ac\ub2e4. \\n\uc804\uc5ed\uc744 \ud588\uc9c0\ub9cc \ubb50 \ud558\ub098 \uc81c\ub300\ub85c \ud560 \uc904 \uc544\ub294 \uac83\ub3c4 \uc5c6\uc73c\ub2c8 \ub113\uc740 \ubc14\ub2f7\uc18d\uc5d0 \ub369\uadf8\ub7ec\ub2c8 \ub193\uc544\uc9c4 \uae30\ubd84\uc774 \uad1c\ud788 \ub4e4\uc5c8\uc5c8\ub2e4. \\n\uc77c\ucc0d \uc0dd\uac01\uc744 \uc815\ub9ac\ud558\uc5ec \ubc29\ud5a5\uc744 \uc7a1\uc9c0 \ubabb\ud588\uae30\uc5d0 \uc544\uc26c\uc6c0\uc774 \ub9ce\uc774 \ub0a8\uc558\ub2e4. \\n\\n### \uc790\ubc14\\n\\n\uc804\uc5ed\uc744 \ud558\uace0 \uc9c4\ub85c\ub97c \uace0\ubbfc\ud558\ub2e4 \ud5a5\ub85c\ub2d8\uc758 [\uc790\ubc14 \uacf5\ud654\uad6d](https://jojoldu.tistory.com/609) \ud3ec\uc2a4\ud305\uc744 \uc77d\uace0 \ub098\uc11c \uc790\ubc14 \uacf5\ubd80\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\uc720\uba85\ud55c \uc778\ud504\ub7f0\uc758 \uae40\uc601\ud55c\ub2d8\uc758 \uc2a4\ud504\ub9c1 \uac15\uc758\ub3c4 \uc788\uace0, \uc88b\uc740 \uc790\ubc14 \uac1c\ubc1c \uc11c\uc801\uc774 \ub9ce\uc544\uc11c \ub3c5\ud559\ud558\uae30\ub85c \uacb0\uc815\ud588\ub2e4. \\n\ud558\ub2e4 \ubcf4\ub2c8 \uc790\ubc14\uc640 \uc2a4\ud504\ub9c1\uc744 \uacf5\ubd80\ud558\uba74\uc11c \u201c\uc65c \uc9c4\uc791\ud558\uc9c0 \uc54a\uc558\uc9c0\u201d\ub77c\ub294 \uc0dd\uac01\ub3c4 \ub9ce\uc774 \ub4e4\uc5c8\ub2e4. \\n\uc591\uc9c8\uc758 \uc790\ub8cc\ub3c4 \ub9ce\uc558\uae30 \ub54c\ubb38\uc5d0, \uc608\uc804\uc5d0 \ub178\ub4dc\ub85c \uac1c\ubc1c\ud588\uc744 \ub54c \ud480\uc9c0 \ubabb\ud588\ub358 \ub2f5\ub2f5\ud568\uc744 \ub9ce\uc774 \ud574\uc18c\ud588\ub358 \uac83 \uac19\ub2e4.\\n\\n23\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae4a\uac8c \uc790\ubc14\ub97c \uacf5\ubd80\ud574\ubcfc \uc0dd\uac01\uc774\ub2e4. \\n\uc5b8\uc5b4\ub97c \ud558\ub098 \uae4a\uac8c \uacf5\ubd80\ud558\ub294 \uac74 \ub9ce\uc740 \ub3c4\uc6c0\uc774 \ub418\ub294 \uac83 \uac19\ub2e4.\\n\\n### \uc2a4\ud130\ub514\\n\\n\uae40\uc601\ud55c\ub2d8\uc758 \uac15\uc758\ub97c \uac70\uc758 \ub2e4 \ub4e4\uc5c8\uc744 \ub54c\ucbe4, \ud56d\uc0c1 \uac15\uc758\uc5d0\uc11c \uc5b8\uae09\ub418\ub294 \ud1a0\ube44\uc758 \uc2a4\ud504\ub9c1\uc744 \uc77d\uc5b4\ubcf4\uace0 \uc2f6\uc5b4\uc84c\uace0 \\n\ud63c\uc790 \uacf5\ubd80\ud558\uae30\uc5d0\ub294 \ub3d9\uae30\ubd80\uc5ec\ub3c4 \ubd80\uc871\ud588\uae30 \ub54c\ubb38\uc5d0 \uc2a4\ud130\ub514\ub97c \uc2dc\uc791\ud588\ub2e4. \\n\ub2e4\ub978 \uc0ac\ub78c\uc5d0\uac8c \uc124\uba85\uc744 \ud574\uc57c \ud588\uae30 \ub54c\ubb38\uc5d0 \ub354\uc6b1 \uaf3c\uaf3c\ud558\uac8c \uacf5\ubd80\ub97c \ud560 \uc218 \uc788\uc5b4\uc11c \uc88b\uc558\uc9c0\ub9cc \ub098\uc5d0\uac8c\ub294 \ub0b4\uc6a9\uc774 \uaf64\ub098 \uc5b4\ub824\uc6cc\uc11c \uc2dc\uac04\uc744 \ub9ce\uc774 \uc18c\ube44\ud588\ub2e4. \\n\uac19\uc774 \uc2a4\ud130\ub514\ud558\uc2dc\ub294 \ubd84\uacfc 7\uac1c\uc6d4 \ub3d9\uc548 \uc2a4\ud130\ub514\ub97c \uafb8\uc900\ud788 \uc774\uc5b4\ub098\uac00 \ucd1d 3\uad8c\uc758 \ucc45\uc744 \uc77d\uc744 \uc218 \uc788\uc5c8\ub2e4.\\n\\n### \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\\n\\n\uad70 \ubcf5\ubb34 \uc911\uc77c \ub54c \uc9c0\uc6d0\ud588\ub2e4 \ub5a8\uc5b4\uc9c4 \uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ub2e4\uc2dc \uc9c0\uc6d0\ud588\ub2e4. \\n\uc774\ubc88 \uc5f0\ub3c4\uc5d0 \ucde8\uc5c5\uc744 \ud558\ub294 \uac8c \ubaa9\ud45c\uc600\uc9c0\ub9cc \ub0b4\uac00 \uac00\uc9c0\uace0 \uc788\ub294 \ud2b9\ubcc4\ud55c \ubb34\uae30\uac00 \uc5c6\ub2e4\ub294 \uac78 \uae68\ub2ec\uc558\ub2e4. \\n\uc801\uc9c0 \uc54a\uc740 \uc2dc\uac04\uc744 \ud22c\uc790\ud574 \uc900\ube44\ub97c \ud588\uace0, \uac10\uc0ac\ud558\uac8c\ub3c4 \uc774\ubc88\uc5d0\ub294 \ucd5c\uc885 \ud569\uaca9\uc744 \ud588\ub2e4. \\n\\n\ub09c \uc0ac\ub78c\ub4e4\uacfc \uc18c\ud1b5\ud558\uace0, \ud611\uc5c5\ud558\ub294 \ub2a5\ub825\uc774 \ubd80\uc871\ud558\ub2e4\uace0 \uc0dd\uac01\uc744 \ub9ce\uc774 \ud588\ub2e4. \\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\ub97c \ud1b5\ud574 \uadf8 \ube48 \ubd80\ubd84\uc744 \ucc44\uc6b0\ub3c4\ub85d \ub178\ub825\ud574\uc57c\uaca0\ub2e4. \\n\\n### 2023\ub144\uc5d0\ub294\\n\\n\ub9c8\uc74c\uc758 \uc5ec\uc720\uac00 \uc5c6\uc5c8\ub358 2022\ub144\uc774\uc5c8\ub358 \uac83 \uac19\ub2e4. \\n\ud558\uace0 \uc2f6\uc740 \uac74 \ub9ce\uc9c0\ub9cc, \uc774\ubc88\uc5d0\ub294 \uc5ec\uc720\ub97c \uac00\uc9c0\uace0 \ud560 \uc218 \uc788\ub294 \uac83\uc5d0 \ucd5c\uc120\uc744 \ub2e4\ud574\uc57c\uaca0\ub2e4."},{"id":"book-writer","metadata":{"permalink":"/book-writer","editUrl":"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","source":"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx","title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","description":"\ucc45 \uc815\ubcf4","date":"2023-01-01T00:00:00.000Z","formattedDate":"2023\ub144 1\uc6d4 1\uc77c","tags":[{"label":"Book","permalink":"/tags/book"}],"readingTime":4.425,"hasTruncateMarker":false,"authors":[],"frontMatter":{"title":"[\ucc45] \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.","slug":"book-writer","tags":["Book"]},"prevItem":{"title":"2022\ub144 \ud68c\uace0","permalink":"/2022-retrospective"}},"content":"### \ucc45 \uc815\ubcf4\\n\\n> \uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \\n> \ubc15\uc194\ubbf8 \\n>\\n\\n### \uc77d\uace0 \ub098\uc11c\\n\\n\uc800\uc790\uc758 \uacbd\ud5d8\uacfc \ud568\uaed8 \uae00\uc4f0\uae30\uc5d0 \ub300\ud55c \uac00\ubcbc\uc6b4 \uc870\uc5b8\uc774 \ub2f4\uaca8\uc788\uc5b4 \uac00\ubccd\uac8c \uc77d\uae30 \uc88b\uc558\ub2e4. \\n\uae00\uc744 \uc798 \uc791\uc131\ud574 \ubcf4\uace0 \uc2f6\uc744 \ub54c \uc801\uc6a9\ud574 \ubcfc \uc218 \uc788\ub294 \uc815\ubcf4\uac00 \ub9ce\uc544\uc11c \ub3c4\uc6c0\uc774 \ub418\uc5c8\ub2e4. \\n\\n\uc6b0\uc544\ud55c \ud14c\ud06c\ucf54\uc2a4\uc758 \ud504\ub9ac\ucf54\uc2a4\ub97c \uc9c4\ud589\ud560 \ub54c \ud6c4\uae30\ub97c \uc791\uc131\ud558\uace0 \ub098\uba74 \ud56d\uc0c1 \uae00\uc774 \ub531\ub531\ud558\ub2e4\ub294 \ub290\ub08c\uc744 \ubc1b\uc558\ub2e4. \\n\ub2e4\ub978 \uc9c0\uc6d0\uc790\ub4e4\uc758 \uc77d\uae30 \ud3b8\ud558\uace0, \ubc1d\uc740 \ub290\ub08c\uc744 \uc8fc\ub294 \uae00\uc744 \ubcf4\uba74 \ubd80\ub7ec\uc6b4 \ub9c8\uc74c\uc744 \uac00\uc9c0\uae30\ub3c4 \ud588\ub2e4. \\n\uc774 \ucc45\uc744 \uc77d\uc5c8\uc73c\ub2c8 2023\ub144\uc5d0\ub294 \uc870\uae08 \ub354 \uae00\uc744 \uc798 \uc801\uc5b4\ubcf4\ub824\uace0 \ud55c\ub2e4.\\n\\n### \ubc11\uc904 \uce5c \ubb38\uc7a5\ub4e4\\n\\n> \ubb38\uc7a5\uc774 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74\\n\ub0b4\uc6a9\uc744 \uc77c\ubaa9\uc694\uc5f0\ud558\uac8c \uc815\ub9ac\ud588\uace0, \uae00\uc758 \uc758\ub3c4\ub3c4 \uc090\ub6a4\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub3c4 \uc801\uc808\ud55c \uac83\uc73c\ub85c \uace8\ub790\ub294\ub370\u2026 \uadf8\ub7f0\ub370\ub3c4 \uc5b4\ub518\uac00\uac00 \uc2ec\uc2ec\ud558\uace0 \uc9c0\ub8e8\ud558\ub2e4\uba74? \ucd95\ucd95 \ucc98\uc9c0\uace0 \ub530\ubd84\ud558\ub2e4\uba74? \ub9d0\uaf2c\ub9ac\ub97c \ubaa8\uc870\ub9ac \u2018~\ub2e4\u2019\ub85c \ud1b5\uc77c\ud55c \uac74 \uc544\ub2cc\uc9c0 \uc810\uac80\ud574 \ubcf4\uc138\uc694.\\n> \\n\\n> \ub9d0\uaf2c\ub9ac\ub97c \uc798 \uac16\uace0 \ub180\uc544\uc57c \ud569\ub2c8\ub2e4. \ubb38\uc7a5\uc758 \ub9c8\uc9c0\ub9c9 \uae00\uc790\ub97c \ub9e4\ubc88 \ub2e4\ub974\uac8c \uace0\uccd0\uc4f0\ub294 \uac83\ub9cc\uc73c\ub85c\ub3c4 \uae00\uc5d0 \ud65c\uae30\ub97c \ub354\ud560 \uc218 \uc788\uc8e0. \ub54c\ub860 \ubb38\uc7a5\uc744 \ub2e4 \ub9c8\uce58\uc9c0 \uc54a\uace0, \ub2e8\uc5b4\ub85c\ub9cc \ub05d\ub9fa\ub294 \uac83\ub3c4 \ubc29\ubc95. \ubb38\uc7a5\uacfc \ubb38\uc7a5 \uc0ac\uc774\uc5d0 \uc27c\ud45c\uac00 \ub4e4\uc5b4\uc11c\uba70 \uae00 \uc804\uccb4\uc5d0 \ud65c\uae30\uac00 \ub3cc\uac8c \ub3fc\uc694. \ubb38\uc7a5\uc758 \uae38\uc774\ub3c4 \ub2e4\ucc44\ub85c\uc6cc\uc9c0\ub294 \ub355\ubd84\uc5d0 \ub364\uc73c\ub85c \uc5bb\uac8c \ub418\ub294 \uac83\ub3c4 \uc788\uc2b5\ub2c8\ub2e4. \ubc14\ub85c, \uae00\uc758 \ub9ac\ub4ec.\\n> \\n\\n> \uc774\uc804 \ubb38\uc7a5\uc5d0\uc11c \ub05d\ub09c \uae00\uc790\ub85c, \ub2e4\uc74c \ubb38\uc7a5\uc744 \ub05d\ub9fa\uc9c0 \uc54a\uae30. \ud55c\ub450 \ubb38\ub2e8\ub9c8\ub2e4 \ub2e8\uc5b4 \uc218\uc900\uc758 \uc544\uc8fc \uc9e7\uc740 \ubb38\uc7a5 \ubc30\uce58\ud558\uae30.\\n> \\n\\n> \uae00\uc758 \uc9c4\uc9dc \uc774\uc720, \uae00\uc758 \uc9c4\uc9dc \ubaa9\uc801, \uae00\uc758 \uc9c4\uc9dc \ub300\uc0c1\uc744 \ucc3e\uc73c\ub824\uace0 \uc560\uc37c\uc2b5\ub2c8\ub2e4. \uc9c0\uae08\ucc98\ub7fc \ud2c0\uc744 \ub5a0\uc62c\ub9b0\ub2e4\uac70\ub098, \ub208\uce58\ub97c \ubcf8\ub2e4\uac70\ub098, \uc815\uce58\uc801\uc778 \uc148\ub3c4 \ud558\uc9c0 \uc54a\uc558\uc5b4\uc694.\\n> \\n\\n> \uc81c\ubaa9\uc740 \uc9e7\uac8c, \ubcf4\uae30 \uc27d\uac8c, \uc77d\uae30 \uc27d\uac8c, \ubc1c\uc74c\uc774 \ube44\uc2b7\ud558\uac8c, \uc21c\uc11c\ub97c \ubc14\uafd4\uc11c\\n> \\n\\n> \uae00\uc744 \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ub2e4\ub4ec\uc744 \ub54c, \ub178\ub798\uc5d0 \uac00\uae4c\uc6cc\uc9c8 \ubc29\ubc95\uc740 \uc5c6\uc744\uc9c0 \uace0\ubbfc\ud574\ubd05\ub2c8\ub2e4. \uac10\ud788 \uac00 \ub2ff\uc744 \uc218 \uc5c6\ub294 \ubaa9\ud45c\uc774\uaca0\uc9c0\ub9cc, \ud560 \uc218 \uc788\ub294 \ucd5c\uc18c\ud55c\uc758 \ub9ac\ub4ec\uc774\ub77c\ub3c4 \ubd99\uc5ec\uc8fc\uace0 \uc2f6\uc5b4\uc694.\\n> \\n\\n> \uc5ec\ub294 \ub9d0\uacfc \ub9c8\uc9c0\ub9c9 \ub9d0\uc5d0 \uc791\uc815\ud558\uace0 \ub9c8\uc74c\uc744 \ub2f4\ub294 \uc5f0\uc2b5\uc744 \ud574\ubd05\uc2dc\ub2e4. \uae00\uc758 \uc5b4\ub290 \uad6c\uc11d\uc774\ub77c\ub3c4 \ubed4\ud55c \uae00\uc790\ub294 \ub0a8\uae30\uc9c0 \uc54a\uaca0\ub178\ub77c \ub2e4\uc9d0\ud558\uba70 \uc368\ubcf4\ub294 \uac81\ub2c8\ub2e4. \ub098\ub9cc\uc774 \uac00\uc9c4 \uc720\uc77c\ud55c \uba54\uc2dc\uc9c0\uc5d0 \uc9d1\uc911\ud558\uba74\uc11c\uc694. \uadf8\ub7fc \uc0dd\uac01\uc774 \ub2ec\ub77c\uc9c0\uace0, \uace0\ub974\ub294 \ub2e8\uc5b4\ub3c4 \ub2ec\ub77c\uc9c0\uace0, \ub0a8\uae34 \ubb38\uc7a5\ub3c4 \ub2ec\ub77c\uc838\uc694. \uacb0\uad6d\uc5d0\ub294 \uae00\uc744 \uc4f4 \uc0ac\ub78c\uc778 \ub098 \uc790\uc2e0\ub3c4 \ub0a8\ub2ec\ub77c\uc9c8 \uac81\ub2c8\ub2e4.\\n> \\n\\n> \ub9de\ucda4\ubc95\uc740 \uc911\uc694\ud569\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub9de\ucda4\ubc95\ubcf4\ub2e4 \ub354 \uc911\uc694\ud55c \uac74 \uac70\uae30\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc785\ub2c8\ub2e4. \ub0b4 \ub9c8\uc74c\uc744 \uae00\uc5d0 \ub2f4\uc544 \uc2e4\uc5b4 \ubcf4\ub0b4\uae30 \uc804, \ub9de\ucda4\ubc95\uc744 \uc810\uac80\ud558\ub294 \uc774\uc720 \uc5ed\uc2dc \uadf8\uac81\ub2c8\ub2e4. \uc624\uc9c1 \ub0b4 \ub9c8\uc74c\uc774 \ub0a8\uc5d0\uac8c \uc77d\ud788\ub294 \ub3d9\uc548 \ubc29\ud574\uac00 \ub418\uc9c0 \uc54a\uae30\ub97c \ubc14\ub77c\uae30 \ub54c\ubb38\uc774\uc8e0. \ub0b4\uac00 \uc4f4 \uae00\ub3c4, \ub0a8\uc774 \uc4f4 \uae00\ub3c4. \uc5b8\uc81c\ub098 \uadf8 \uc548\uc5d0 \ub2f4\uae34 \ub9c8\uc74c\uc774 \uba3c\uc800\uc785\ub2c8\ub2e4.\\n> \\n\\n> \uae00\uc744 \uc4f4\ub2e4\uace0 \uae00\uc774 \uc644\uc131\ub418\ub294 \uac8c \uc544\ub2c8\uc5d0\uc694. \uae00\uacfc \ub2ee\uc740 \ubaa8\uc2b5\uc73c\ub85c \uc0b4 \ub54c, \uae00\uc740 \ube44\ub85c\uc18c \uc644\uc131\ub429\ub2c8\ub2e4.\\n>"}]}')}}]); \ No newline at end of file diff --git a/assets/js/b421ebb7.867062fd.js b/assets/js/b421ebb7.dc3db9c5.js similarity index 98% rename from assets/js/b421ebb7.867062fd.js rename to assets/js/b421ebb7.dc3db9c5.js index b354ace59..42e571383 100644 --- a/assets/js/b421ebb7.867062fd.js +++ b/assets/js/b421ebb7.dc3db9c5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8518],{3905:(e,t,r)=>{r.d(t,{Zo:()=>i,kt:()=>h});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var u=n.createContext({}),c=function(e){var t=n.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},i=function(e){var t=c(e.components);return n.createElement(u.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,u=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),m=c(r),h=a,d=m["".concat(u,".").concat(h)]||m[h]||s[h]||o;return r?n.createElement(d,p(p({ref:t},i),{},{components:r})):n.createElement(d,p({ref:t},i))}));function h(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,p=new Array(o);p[0]=m;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,p[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>u,contentTitle:()=>p,default:()=>s,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",slug:"/performance/throughput-latency",tags:["throughput","latency"]},p=void 0,l={unversionedId:"\uc131\ub2a5/Throughput\uacfc Latency",id:"\uc131\ub2a5/Throughput\uacfc Latency",title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",description:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",source:"@site/docs/\uc131\ub2a5/Throughput\uacfc Latency.mdx",sourceDirName:"\uc131\ub2a5",slug:"/performance/throughput-latency",permalink:"/docs/performance/throughput-latency",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc131\ub2a5/Throughput\uacfc Latency.mdx",tags:[{label:"throughput",permalink:"/docs/tags/throughput"},{label:"latency",permalink:"/docs/tags/latency"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",slug:"/performance/throughput-latency",tags:["throughput","latency"]},sidebar:"tutorialSidebar",previous:{title:"Throughput \ubaa9\ud46f\uac12",permalink:"/docs/performance/throughput"},next:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",permalink:"/docs/performance/types"}},u={},c=[{value:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",id:"\uc2dc\uc2a4\ud15c-\uc131\ub2a5-\uc9c0\ud45c",level:3},{value:"Throughput",id:"throughput",level:3},{value:"Latency",id:"latency",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],i={toc:c};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},i,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uc2dc\uc2a4\ud15c-\uc131\ub2a5-\uc9c0\ud45c"},"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c"),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c \uc131\ub2a5\uc740 \uc5b4\ub5bb\uac8c \uce21\uc815\ud560\uae4c?",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"\uc131\ub2a5\uc774 \ube68\ub77c\uc84c\ub2e4.")," \ub77c\ub294 \uac83\uc744 \uc5b4\ub5bb\uac8c \uc218\uce58\ud654\ud560 \uc218 \uc788\uc744\uae4c?",(0,a.kt)("br",{parentName:"p"}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \uc2dc\uc2a4\ud15c \uc131\ub2a5\uc740 Throughput\uacfc Latency\ub77c\ub294 \uc131\ub2a5 \uc9c0\ud45c\ub85c \uce21\uc815\uc744 \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"throughput"},"Throughput"),(0,a.kt)("p",null,"\ucd08\ub2f9 \ucc98\ub9ac\ud558\ub294 \uc791\uc5c5\uc758 \uc218, \uc989 \ucc98\ub9ac\ub7c9\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \ucd08\ub2f9 \uba87 \uac1c\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0(RPS, Request Per Second)\ub97c \uae30\uc900\uc73c\ub85c \uce21\uc815\uc744 \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\uc74c\uacfc \uac19\uc740 \uc2dc\uc2a4\ud15c\uc774 \uc788\ub2e4\uace0 \uac00\uc815\ud574\ubcf4\uc790."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c A: \ucd08\ub2f9 \uc57d 100\uac1c\uc758 \uc694\uccad \ucc98\ub9ac"),(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c B: \ucd08\ub2f9 \uc57d 200\uac1c\uc758 \uc694\uccad \ucc98\ub9ac")),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c B\uac00 \ub3d9\uc2dc\uac04 \ub300\ube44 \ub354 \ub192\uc740 \ucc98\ub9ac\ub7c9\uc744 \ubcf4\uc5ec\uc8fc\uace0 \uc788\uc73c\ub2c8, \uc2dc\uc2a4\ud15c B\uc758 \uc131\ub2a5\uc774 \ub354 \uc88b\ub2e4\uace0 \ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"latency"},"Latency"),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c\uc758 \ud3c9\uade0 \uc751\ub2f5 \uc2dc\uac04, \uc989 \ucc98\ub9ac \uc2dc\uac04\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","Latency\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \ub450 \uac00\uc9c0\ub85c \uad6c\ubd84\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"\uc0ac\uc6a9\uc790\uac00 \ubcf8 \ucc98\ub9ac \uc2dc\uac04"),": \uc0ac\uc6a9\uc790\uac00 \uc694\uccad\uc744 \ubcf4\ub0b4\uace0 \uc751\ub2f5\uc744 \ubc1b\uc744 \ub54c\uae4c\uc9c0\uc758 \uc2dc\uac04",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"\uc2dc\uc2a4\ud15c\uc5d0\uc11c \ubcf8 \ucc98\ub9ac \uc2dc\uac04"),": \uc2dc\uc2a4\ud15c\uc774 \uc694\uccad\uc744 \ubc1b\uace0 \uc751\ub2f5\uc744 \ubcf4\ub0bc \ub54c\uae4c\uc9c0\uc758 \uc2dc\uac04 "),(0,a.kt)("p",null,"\uc0ac\uc6a9\uc790\uac00 \ubcf8 \ucc98\ub9ac \uc2dc\uac04\uc758 \uacbd\uc6b0 \ub124\ud2b8\uc6cc\ud06c\uc5d0 \ub300\ud55c \uc2dc\uac04\uc774 \ud3ec\ud568\ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub530\ub77c\uc11c \uc131\ub2a5 \uce21\uc815\uacfc \uac1c\uc120\uc740 \uc2dc\uc2a4\ud15c\uc5d0\uc11c \ubcf8 \ucc98\ub9ac \uc2dc\uac04\uc73c\ub85c \uce21\uc815\ud558\uace0 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc815\ud655\ud574 \ubcf4\uc778\ub2e4. "),(0,a.kt)("p",null,"\ub2e4\uc74c\uacfc \uac19\uc740 \uc2dc\uc2a4\ud15c\uc774 \uc788\ub2e4\uace0 \uac00\uc815\ud574\ubcf4\uc790. "),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c A: \uc694\uccad\uc2dc \ud3c9\uade0 200ms \ub0b4 \uc751\ub2f5 "),(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c B: \uc694\uccad\uc2dc \ud3c9\uade0 100ms \ub0b4 \uc751\ub2f5 ")),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c B\uac00 \uc694\uccad\uc5d0 \ub300\ud55c \uc751\ub2f5\uc774 \ub354 \ube60\ub974\ub2c8, \uc2dc\uc2a4\ud15c B\uc758 \uc131\ub2a5\uc774 \ub354 \uc88b\ub2e4\uace0 \ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://aws.amazon.com/ko/compare/the-difference-between-throughput-and-latency/"},"difference between throughput and latency, AWS")," - \ud574\ub2f9 \ub0b4\uc6a9\uc740 \ub124\ud2b8\uc6cc\ud06c \uae30\uc900\uc774\ub2e4."))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8518],{3905:(e,t,r)=>{r.d(t,{Zo:()=>i,kt:()=>h});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function p(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var u=n.createContext({}),c=function(e){var t=n.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},i=function(e){var t=c(e.components);return n.createElement(u.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,u=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),m=c(r),h=a,d=m["".concat(u,".").concat(h)]||m[h]||s[h]||o;return r?n.createElement(d,p(p({ref:t},i),{},{components:r})):n.createElement(d,p({ref:t},i))}));function h(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,p=new Array(o);p[0]=m;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:a,p[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>u,contentTitle:()=>p,default:()=>s,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",slug:"/performance/throughput-latency",tags:["throughput","latency"]},p=void 0,l={unversionedId:"\uc131\ub2a5/Throughput\uacfc Latency",id:"\uc131\ub2a5/Throughput\uacfc Latency",title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",description:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",source:"@site/docs/\uc131\ub2a5/Throughput\uacfc Latency.mdx",sourceDirName:"\uc131\ub2a5",slug:"/performance/throughput-latency",permalink:"/docs/performance/throughput-latency",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc131\ub2a5/Throughput\uacfc Latency.mdx",tags:[{label:"throughput",permalink:"/docs/tags/throughput"},{label:"latency",permalink:"/docs/tags/latency"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",slug:"/performance/throughput-latency",tags:["throughput","latency"]},sidebar:"tutorialSidebar",previous:{title:"Throughput \ubaa9\ud46f\uac12",permalink:"/docs/performance/throughput"},next:{title:"\uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc720\ud615",permalink:"/docs/performance/types"}},u={},c=[{value:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",id:"\uc2dc\uc2a4\ud15c-\uc131\ub2a5-\uc9c0\ud45c",level:3},{value:"Throughput",id:"throughput",level:3},{value:"Latency",id:"latency",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],i={toc:c};function s(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},i,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uc2dc\uc2a4\ud15c-\uc131\ub2a5-\uc9c0\ud45c"},"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c"),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c \uc131\ub2a5\uc740 \uc5b4\ub5bb\uac8c \uce21\uc815\ud560\uae4c?",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"\uc131\ub2a5\uc774 \ube68\ub77c\uc84c\ub2e4.")," \ub77c\ub294 \uac83\uc744 \uc5b4\ub5bb\uac8c \uc218\uce58\ud654\ud560 \uc218 \uc788\uc744\uae4c?",(0,a.kt)("br",{parentName:"p"}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \uc2dc\uc2a4\ud15c \uc131\ub2a5\uc740 Throughput\uacfc Latency\ub77c\ub294 \uc131\ub2a5 \uc9c0\ud45c\ub85c \uce21\uc815\uc744 \ud55c\ub2e4. "),(0,a.kt)("h3",{id:"throughput"},"Throughput"),(0,a.kt)("p",null,"\ucd08\ub2f9 \ucc98\ub9ac\ud558\ub294 \uc791\uc5c5\uc758 \uc218, \uc989 \ucc98\ub9ac\ub7c9\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc77c\ubc18\uc801\uc73c\ub85c \ucd08\ub2f9 \uba87 \uac1c\uc758 \uc694\uccad\uc744 \ucc98\ub9ac\ud558\ub294\uc9c0(RPS, Request Per Second)\ub97c \uae30\uc900\uc73c\ub85c \uce21\uc815\uc744 \ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2e4\uc74c\uacfc \uac19\uc740 \uc2dc\uc2a4\ud15c\uc774 \uc788\ub2e4\uace0 \uac00\uc815\ud574\ubcf4\uc790."),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c A: \ucd08\ub2f9 \uc57d 100\uac1c\uc758 \uc694\uccad \ucc98\ub9ac"),(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c B: \ucd08\ub2f9 \uc57d 200\uac1c\uc758 \uc694\uccad \ucc98\ub9ac")),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c B\uac00 \ub3d9\uc2dc\uac04 \ub300\ube44 \ub354 \ub192\uc740 \ucc98\ub9ac\ub7c9\uc744 \ubcf4\uc5ec\uc8fc\uace0 \uc788\uc73c\ub2c8, \uc2dc\uc2a4\ud15c B\uc758 \uc131\ub2a5\uc774 \ub354 \uc88b\ub2e4\uace0 \ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"latency"},"Latency"),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c\uc758 \ud3c9\uade0 \uc751\ub2f5 \uc2dc\uac04, \uc989 \ucc98\ub9ac \uc2dc\uac04\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","Latency\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \ub450 \uac00\uc9c0\ub85c \uad6c\ubd84\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("inlineCode",{parentName:"p"},"\uc0ac\uc6a9\uc790\uac00 \ubcf8 \ucc98\ub9ac \uc2dc\uac04"),": \uc0ac\uc6a9\uc790\uac00 \uc694\uccad\uc744 \ubcf4\ub0b4\uace0 \uc751\ub2f5\uc744 \ubc1b\uc744 \ub54c\uae4c\uc9c0\uc758 \uc2dc\uac04",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("inlineCode",{parentName:"p"},"\uc2dc\uc2a4\ud15c\uc5d0\uc11c \ubcf8 \ucc98\ub9ac \uc2dc\uac04"),": \uc2dc\uc2a4\ud15c\uc774 \uc694\uccad\uc744 \ubc1b\uace0 \uc751\ub2f5\uc744 \ubcf4\ub0bc \ub54c\uae4c\uc9c0\uc758 \uc2dc\uac04 "),(0,a.kt)("p",null,"\uc0ac\uc6a9\uc790\uac00 \ubcf8 \ucc98\ub9ac \uc2dc\uac04\uc758 \uacbd\uc6b0 \ub124\ud2b8\uc6cc\ud06c\uc5d0 \ub300\ud55c \uc2dc\uac04\uc774 \ud3ec\ud568\ub41c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub530\ub77c\uc11c \uc131\ub2a5 \uce21\uc815\uacfc \uac1c\uc120\uc740 \uc2dc\uc2a4\ud15c\uc5d0\uc11c \ubcf8 \ucc98\ub9ac \uc2dc\uac04\uc73c\ub85c \uce21\uc815\ud558\uace0 \uac1c\uc120\ud558\ub294 \uac83\uc774 \ub354 \uc815\ud655\ud574 \ubcf4\uc778\ub2e4. "),(0,a.kt)("p",null,"\ub2e4\uc74c\uacfc \uac19\uc740 \uc2dc\uc2a4\ud15c\uc774 \uc788\ub2e4\uace0 \uac00\uc815\ud574\ubcf4\uc790. "),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c A: \uc694\uccad\uc2dc \ud3c9\uade0 200ms \ub0b4 \uc751\ub2f5 "),(0,a.kt)("li",{parentName:"ul"},"\uc2dc\uc2a4\ud15c B: \uc694\uccad\uc2dc \ud3c9\uade0 100ms \ub0b4 \uc751\ub2f5 ")),(0,a.kt)("p",null,"\uc2dc\uc2a4\ud15c B\uac00 \uc694\uccad\uc5d0 \ub300\ud55c \uc751\ub2f5\uc774 \ub354 \ube60\ub974\ub2c8, \uc2dc\uc2a4\ud15c B\uc758 \uc131\ub2a5\uc774 \ub354 \uc88b\ub2e4\uace0 \ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,"\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04",(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://aws.amazon.com/ko/compare/the-difference-between-throughput-and-latency/"},"difference between throughput and latency, AWS")," - \ud574\ub2f9 \ub0b4\uc6a9\uc740 \ub124\ud2b8\uc6cc\ud06c \uae30\uc900\uc774\ub2e4."))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b88cb85b.d779ea6a.js b/assets/js/b88cb85b.fbb07e48.js similarity index 98% rename from assets/js/b88cb85b.d779ea6a.js rename to assets/js/b88cb85b.fbb07e48.js index 4d6625780..c861c5a84 100644 --- a/assets/js/b88cb85b.d779ea6a.js +++ b/assets/js/b88cb85b.fbb07e48.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2293],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var d=r.createContext({}),c=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(d.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,d=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=c(n),m=a,h=u["".concat(d,".").concat(m)]||u[m]||s[m]||o;return n?r.createElement(h,l(l({ref:t},p),{},{components:n})):r.createElement(h,l({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=u;var i={};for(var d in t)hasOwnProperty.call(t,d)&&(i[d]=t[d]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>s,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var r=n(87462),a=(n(67294),n(3905));const o={title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",slug:"/network/load-balancing-algorithm",tags:["network","load balancing"]},l=void 0,i={unversionedId:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",id:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",description:"\ub77c\uc6b4\ub4dc\ub85c\ube48 \ubc29\uc2dd(Round Robin Method)",source:"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998.mdx",sourceDirName:"\ub124\ud2b8\uc6cc\ud06c",slug:"/network/load-balancing-algorithm",permalink:"/docs/network/load-balancing-algorithm",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998.mdx",tags:[{label:"network",permalink:"/docs/tags/network"},{label:"load balancing",permalink:"/docs/tags/load-balancing"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",slug:"/network/load-balancing-algorithm",tags:["network","load balancing"]},sidebar:"tutorialSidebar",previous:{title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",permalink:"/docs/etc/communication"},next:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",permalink:"/docs/network/load-balancing"}},d={},c=[{value:"\ub77c\uc6b4\ub4dc\ub85c\ube48 \ubc29\uc2dd(Round Robin Method)",id:"\ub77c\uc6b4\ub4dc\ub85c\ube48-\ubc29\uc2ddround-robin-method",level:3},{value:"\uac00\uc911 \uae30\ubc18 \ub77c\uc6b4\ub4dc \ub85c\ube48 \ubc29\uc2dd(Weighted Round Robin Method)",id:"\uac00\uc911-\uae30\ubc18-\ub77c\uc6b4\ub4dc-\ub85c\ube48-\ubc29\uc2ddweighted-round-robin-method",level:3},{value:"\ucd5c\uc18c \uc5f0\uacb0 \uae30\ubc18 \ubc29\uc2dd(Least Connection Method)",id:"\ucd5c\uc18c-\uc5f0\uacb0-\uae30\ubc18-\ubc29\uc2ddleast-connection-method",level:3},{value:"IP \ud574\uc2dc \ubc29\uc2dd(IP Hash Method)",id:"ip-\ud574\uc2dc-\ubc29\uc2ddip-hash-method",level:3},{value:"\ucd5c\uc18c \uc751\ub2f5 \uc2dc\uac04 \ubc29\uc2dd(Least Response Time Method)",id:"\ucd5c\uc18c-\uc751\ub2f5-\uc2dc\uac04-\ubc29\uc2ddleast-response-time-method",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],p={toc:c};function s(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ub77c\uc6b4\ub4dc\ub85c\ube48-\ubc29\uc2ddround-robin-method"},"\ub77c\uc6b4\ub4dc\ub85c\ube48 \ubc29\uc2dd(Round Robin Method)"),(0,a.kt)("p",null,"\ud074\ub77c\uc774\uc5b8\ud2b8\ub85c\ubd80\ud130 \ubc1b\uc740 \uc694\uccad\uc744 \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub300\uc0c1 \uc11c\ubc84\uc5d0 \uc21c\uc11c\ub300\ub85c \ud560\ub2f9\ubc1b\ub294 \ubc29\uc2dd"),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- 33% --\x3e A\n LB -- 33% --\x3e B\n LB -- 33% --\x3e C"}),(0,a.kt)("h3",{id:"\uac00\uc911-\uae30\ubc18-\ub77c\uc6b4\ub4dc-\ub85c\ube48-\ubc29\uc2ddweighted-round-robin-method"},"\uac00\uc911 \uae30\ubc18 \ub77c\uc6b4\ub4dc \ub85c\ube48 \ubc29\uc2dd(Weighted Round Robin Method)"),(0,a.kt)("p",null,"\uc2e4\uc81c \uc11c\ubc84\uc5d0 \uc11c\ub85c \ub2e4\ub978 \ucc98\ub9ac \uc6a9\ub7c9\uc744 \uc9c0\uc815\ud558\ub294 \ubc29\uc2dd"),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- 80% --\x3e A[A \uc11c\ubc84 4]\n LB -- 20% --\x3e B[B \uc11c\ubc84 1]"}),(0,a.kt)("h3",{id:"\ucd5c\uc18c-\uc5f0\uacb0-\uae30\ubc18-\ubc29\uc2ddleast-connection-method"},"\ucd5c\uc18c \uc5f0\uacb0 \uae30\ubc18 \ubc29\uc2dd(Least Connection Method)"),(0,a.kt)("p",null,"\ub85c\ub4dc \ubc38\ub7f0\uc11c\ub294 \ud65c\uc131 \uc5f0\uacb0\uc774 \uac00\uc7a5 \uc801\uc740 \uc11c\ubc84\ub97c \ud655\uc778\ud558\uace0 \ud574\ub2f9 \uc11c\ubc84\ub85c \ud2b8\ub798\ud53d\uc744 \uc804\uc1a1"),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- X --\x3e A[A \uc11c\ubc84 \uc5f0\uacb0 \uc218 4]\n LB -- \uc5f0\uacb0\uc218\uac00 \uc801\uc740 \uc11c\ubc84\ub85c \uc120\ud0dd --\x3e B[B \uc11c\ubc84 \uc5f0\uacb0 \uc218 3]"}),(0,a.kt)("h3",{id:"ip-\ud574\uc2dc-\ubc29\uc2ddip-hash-method"},"IP \ud574\uc2dc \ubc29\uc2dd(IP Hash Method)"),(0,a.kt)("p",null,"\uac01 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \ub300\ud574 Hashing key\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c\ub97c \uc9c0\uc815",(0,a.kt)("br",{parentName:"p"}),"\n","Hashing key\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 IP + port \ud639\uc740 IP \uc8fc\uc18c\ub9cc\uc73c\ub85c \uacb0\uc815",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc6a9\uc790\uac00 \ud56d\uc0c1 \ub3d9\uc77c\ud55c \uc11c\ubc84\ub85c \uc5f0\uacb0\ub418\ub294 \uac83\uc744 \ubcf4\uc7a5"),(0,a.kt)("mermaid",{value:'graph LR\n LB[Load Balancer] -- "hash(13.32.45.56)" --\x3e A\n LB -- "hash(142.2.55.24)" --\x3e B\n LB -- "hash(142.2.55.24) \uc7ac\uc694\uccad" --\x3e B'}),(0,a.kt)("h3",{id:"\ucd5c\uc18c-\uc751\ub2f5-\uc2dc\uac04-\ubc29\uc2ddleast-response-time-method"},"\ucd5c\uc18c \uc751\ub2f5 \uc2dc\uac04 \ubc29\uc2dd(Least Response Time Method)"),(0,a.kt)("p",null,"\uc11c\ubc84\uc758 \ud604\uc7ac \uc5f0\uacb0 \uc0c1\ud0dc, \uc751\ub2f5 \uc2dc\uac04 \uace0\ub824\ud558\uc5ec \ud2b8\ub798\ud53d\uc744 \uc804\uc1a1",(0,a.kt)("br",{parentName:"p"}),"\n","\uac00\uc7a5 \uc801\uc740 \uc5f0\uacb0 \uc0c1\ud0dc\uc640 \uac00\uc7a5 \uc9e7\uc740 \uc751\ub2f5 \uc2dc\uac04\uc744 \ubcf4\uc774\ub294 \uc11c\ubc84\uc5d0 \uc6b0\uc120\uc801\uc73c\ub85c \ub85c\ub4dc\ub97c \ubc30\ubd84\ud558\ub294 \ubc29\uc2dd "),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- \uc751\ub2f5 \uc2dc\uac04\uc774 \ub354 \ube60\ub974\ub2c8 A \uc11c\ubc84\ub85c \uc804\ub2ec --\x3e A[A \uc751\ub2f5\uc2dc\uac04 100ms]\n LB -- X --\x3e B[B \uc751\ub2f5\uc2dc\uac04 150ms]"}),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://aws.amazon.com/ko/what-is/load-balancing/"},"load balancing, AWS"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://tecoble.techcourse.co.kr/post/2021-11-07-load-balancing/"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc790, \ud14c\ucf54\ube14")))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2293],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var d=r.createContext({}),c=function(e){var t=r.useContext(d),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(d.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},u=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,d=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=c(n),m=a,h=u["".concat(d,".").concat(m)]||u[m]||s[m]||o;return n?r.createElement(h,l(l({ref:t},p),{},{components:n})):r.createElement(h,l({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=u;var i={};for(var d in t)hasOwnProperty.call(t,d)&&(i[d]=t[d]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>s,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var r=n(87462),a=(n(67294),n(3905));const o={title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",slug:"/network/load-balancing-algorithm",tags:["network","load balancing"]},l=void 0,i={unversionedId:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",id:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",description:"\ub77c\uc6b4\ub4dc\ub85c\ube48 \ubc29\uc2dd(Round Robin Method)",source:"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998.mdx",sourceDirName:"\ub124\ud2b8\uc6cc\ud06c",slug:"/network/load-balancing-algorithm",permalink:"/docs/network/load-balancing-algorithm",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998.mdx",tags:[{label:"network",permalink:"/docs/tags/network"},{label:"load balancing",permalink:"/docs/tags/load-balancing"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",slug:"/network/load-balancing-algorithm",tags:["network","load balancing"]},sidebar:"tutorialSidebar",previous:{title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",permalink:"/docs/etc/communication"},next:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",permalink:"/docs/network/load-balancing"}},d={},c=[{value:"\ub77c\uc6b4\ub4dc\ub85c\ube48 \ubc29\uc2dd(Round Robin Method)",id:"\ub77c\uc6b4\ub4dc\ub85c\ube48-\ubc29\uc2ddround-robin-method",level:3},{value:"\uac00\uc911 \uae30\ubc18 \ub77c\uc6b4\ub4dc \ub85c\ube48 \ubc29\uc2dd(Weighted Round Robin Method)",id:"\uac00\uc911-\uae30\ubc18-\ub77c\uc6b4\ub4dc-\ub85c\ube48-\ubc29\uc2ddweighted-round-robin-method",level:3},{value:"\ucd5c\uc18c \uc5f0\uacb0 \uae30\ubc18 \ubc29\uc2dd(Least Connection Method)",id:"\ucd5c\uc18c-\uc5f0\uacb0-\uae30\ubc18-\ubc29\uc2ddleast-connection-method",level:3},{value:"IP \ud574\uc2dc \ubc29\uc2dd(IP Hash Method)",id:"ip-\ud574\uc2dc-\ubc29\uc2ddip-hash-method",level:3},{value:"\ucd5c\uc18c \uc751\ub2f5 \uc2dc\uac04 \ubc29\uc2dd(Least Response Time Method)",id:"\ucd5c\uc18c-\uc751\ub2f5-\uc2dc\uac04-\ubc29\uc2ddleast-response-time-method",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],p={toc:c};function s(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ub77c\uc6b4\ub4dc\ub85c\ube48-\ubc29\uc2ddround-robin-method"},"\ub77c\uc6b4\ub4dc\ub85c\ube48 \ubc29\uc2dd(Round Robin Method)"),(0,a.kt)("p",null,"\ud074\ub77c\uc774\uc5b8\ud2b8\ub85c\ubd80\ud130 \ubc1b\uc740 \uc694\uccad\uc744 \ub85c\ub4dc \ubc38\ub7f0\uc2f1 \ub300\uc0c1 \uc11c\ubc84\uc5d0 \uc21c\uc11c\ub300\ub85c \ud560\ub2f9\ubc1b\ub294 \ubc29\uc2dd"),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- 33% --\x3e A\n LB -- 33% --\x3e B\n LB -- 33% --\x3e C"}),(0,a.kt)("h3",{id:"\uac00\uc911-\uae30\ubc18-\ub77c\uc6b4\ub4dc-\ub85c\ube48-\ubc29\uc2ddweighted-round-robin-method"},"\uac00\uc911 \uae30\ubc18 \ub77c\uc6b4\ub4dc \ub85c\ube48 \ubc29\uc2dd(Weighted Round Robin Method)"),(0,a.kt)("p",null,"\uc2e4\uc81c \uc11c\ubc84\uc5d0 \uc11c\ub85c \ub2e4\ub978 \ucc98\ub9ac \uc6a9\ub7c9\uc744 \uc9c0\uc815\ud558\ub294 \ubc29\uc2dd"),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- 80% --\x3e A[A \uc11c\ubc84 4]\n LB -- 20% --\x3e B[B \uc11c\ubc84 1]"}),(0,a.kt)("h3",{id:"\ucd5c\uc18c-\uc5f0\uacb0-\uae30\ubc18-\ubc29\uc2ddleast-connection-method"},"\ucd5c\uc18c \uc5f0\uacb0 \uae30\ubc18 \ubc29\uc2dd(Least Connection Method)"),(0,a.kt)("p",null,"\ub85c\ub4dc \ubc38\ub7f0\uc11c\ub294 \ud65c\uc131 \uc5f0\uacb0\uc774 \uac00\uc7a5 \uc801\uc740 \uc11c\ubc84\ub97c \ud655\uc778\ud558\uace0 \ud574\ub2f9 \uc11c\ubc84\ub85c \ud2b8\ub798\ud53d\uc744 \uc804\uc1a1"),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- X --\x3e A[A \uc11c\ubc84 \uc5f0\uacb0 \uc218 4]\n LB -- \uc5f0\uacb0\uc218\uac00 \uc801\uc740 \uc11c\ubc84\ub85c \uc120\ud0dd --\x3e B[B \uc11c\ubc84 \uc5f0\uacb0 \uc218 3]"}),(0,a.kt)("h3",{id:"ip-\ud574\uc2dc-\ubc29\uc2ddip-hash-method"},"IP \ud574\uc2dc \ubc29\uc2dd(IP Hash Method)"),(0,a.kt)("p",null,"\uac01 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \ub300\ud574 Hashing key\ub97c \uac00\uc9c0\uace0 \uacbd\ub85c\ub97c \uc9c0\uc815",(0,a.kt)("br",{parentName:"p"}),"\n","Hashing key\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 IP + port \ud639\uc740 IP \uc8fc\uc18c\ub9cc\uc73c\ub85c \uacb0\uc815",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc6a9\uc790\uac00 \ud56d\uc0c1 \ub3d9\uc77c\ud55c \uc11c\ubc84\ub85c \uc5f0\uacb0\ub418\ub294 \uac83\uc744 \ubcf4\uc7a5"),(0,a.kt)("mermaid",{value:'graph LR\n LB[Load Balancer] -- "hash(13.32.45.56)" --\x3e A\n LB -- "hash(142.2.55.24)" --\x3e B\n LB -- "hash(142.2.55.24) \uc7ac\uc694\uccad" --\x3e B'}),(0,a.kt)("h3",{id:"\ucd5c\uc18c-\uc751\ub2f5-\uc2dc\uac04-\ubc29\uc2ddleast-response-time-method"},"\ucd5c\uc18c \uc751\ub2f5 \uc2dc\uac04 \ubc29\uc2dd(Least Response Time Method)"),(0,a.kt)("p",null,"\uc11c\ubc84\uc758 \ud604\uc7ac \uc5f0\uacb0 \uc0c1\ud0dc, \uc751\ub2f5 \uc2dc\uac04 \uace0\ub824\ud558\uc5ec \ud2b8\ub798\ud53d\uc744 \uc804\uc1a1",(0,a.kt)("br",{parentName:"p"}),"\n","\uac00\uc7a5 \uc801\uc740 \uc5f0\uacb0 \uc0c1\ud0dc\uc640 \uac00\uc7a5 \uc9e7\uc740 \uc751\ub2f5 \uc2dc\uac04\uc744 \ubcf4\uc774\ub294 \uc11c\ubc84\uc5d0 \uc6b0\uc120\uc801\uc73c\ub85c \ub85c\ub4dc\ub97c \ubc30\ubd84\ud558\ub294 \ubc29\uc2dd "),(0,a.kt)("mermaid",{value:"graph LR\n LB[Load Balancer] -- \uc751\ub2f5 \uc2dc\uac04\uc774 \ub354 \ube60\ub974\ub2c8 A \uc11c\ubc84\ub85c \uc804\ub2ec --\x3e A[A \uc751\ub2f5\uc2dc\uac04 100ms]\n LB -- X --\x3e B[B \uc751\ub2f5\uc2dc\uac04 150ms]"}),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://aws.amazon.com/ko/what-is/load-balancing/"},"load balancing, AWS"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://tecoble.techcourse.co.kr/post/2021-11-07-load-balancing/"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc790, \ud14c\ucf54\ube14")))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/c55d205b.8cce9cb6.js b/assets/js/c55d205b.f6bfe07b.js similarity index 98% rename from assets/js/c55d205b.8cce9cb6.js rename to assets/js/c55d205b.f6bfe07b.js index 2aa59a77d..978867282 100644 --- a/assets/js/c55d205b.8cce9cb6.js +++ b/assets/js/c55d205b.f6bfe07b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3438],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>d});var r=t(67294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var p=r.createContext({}),c=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u=function(e){var n=c(e.components);return r.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},s=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),s=c(t),d=i,g=s["".concat(p,".").concat(d)]||s[d]||m[d]||a;return t?r.createElement(g,l(l({ref:n},u),{},{components:t})):r.createElement(g,l({ref:n},u))}));function d(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,l=new Array(a);l[0]=s;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var c=2;c{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>l,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var r=t(87462),i=(t(67294),t(3905));const a={title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",slug:"/nginx/command",tags:["nginx"]},l=void 0,o={unversionedId:"Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4",id:"Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4",title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",description:"\ud3f4\ub354 \ubc0f \ud30c\uc77c",source:"@site/docs/Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4.mdx",sourceDirName:"Nginx",slug:"/nginx/command",permalink:"/docs/nginx/command",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4.mdx",tags:[{label:"nginx",permalink:"/docs/tags/nginx"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",slug:"/nginx/command",tags:["nginx"]},sidebar:"tutorialSidebar",previous:{title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",permalink:"/docs/jpa/key"},next:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",permalink:"/docs/nginx/static-file"}},p={},c=[{value:"\ud3f4\ub354 \ubc0f \ud30c\uc77c",id:"\ud3f4\ub354-\ubc0f-\ud30c\uc77c",level:3},{value:"\uba85\ub839\uc5b4",id:"\uba85\ub839\uc5b4",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function m(e){let{components:n,...t}=e;return(0,i.kt)("wrapper",(0,r.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h3",{id:"\ud3f4\ub354-\ubc0f-\ud30c\uc77c"},"\ud3f4\ub354 \ubc0f \ud30c\uc77c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/etc/nginx/")),(0,i.kt)("p",null,"\uae30\ubcf8 \uc124\uc815\uc774 \uc800\uc7a5\ub41c \ub8e8\ud2b8 \ub514\ub809\ud130\ub9ac"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/etc/nginx/nginx.conf")),(0,i.kt)("p",null,"\uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\ub85c \ubaa8\ub4e0 \uc124\uc815\uc5d0 \ub300\ud55c \uc9c4\uc785\uc810",(0,i.kt)("br",{parentName:"p"}),"\n","\ub514\ub809\ud130\ub9ac\uc5d0 \uc704\uce58\ud55c \ubaa8\ub4e0 \uc124\uc815 \ud30c\uc77c\uc744 \ud3ec\ud568\ud558\ub294 \ucd5c\uc0c1\uc704 Http \ube14\ub85d\uc744 \ud3ec\ud568\ud55c\ub2e4. "),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:'title="nginx\uc5d0 \ud3ec\ud568\ub41c \uc124\uc815 \ud30c\uc77c \ud3ec\ud568 include \uad6c\ubb38"',title:'"nginx\uc5d0',"\ud3ec\ud568\ub41c":!0,"\uc124\uc815":!0,"\ud30c\uc77c":!0,"\ud3ec\ud568":!0,include:!0,'\uad6c\ubb38"':!0},"http {\n ...\n include /etc/nginx/conf.d/*.conf;\n include /etc/nginx/sites-enabled/*;\n}\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/etc/nginx/conf.d/")),(0,i.kt)("p",null,"\uae30\ubcf8 HTTP \uc11c\ubc84 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \ub514\ub809\ud130\ub9ac",(0,i.kt)("br",{parentName:"p"}),"\n",(0,i.kt)("inlineCode",{parentName:"p"},".conf")," \ub85c \ub05d\ub098\ub294 \uacbd\uc6b0 \uc704\uc758 include \uc124\uc815\uc5d0 \uc758\ud574 \ucd5c\uc0c1\uc704 http \ube14\ub85d\uc5d0 \ud3ec\ud568\ub41c\ub2e4.",(0,i.kt)("br",{parentName:"p"}),"\n","conf.d \ub514\ub809\ud130\ub9ac \ub300\uc2e0 site-enabled \ub514\ub809\ud130\ub9ac\uc640 symlink\ub97c \ud1b5\ud574 \uc124\uc815 \ud30c\uc77c\uc744 \uc5f0\uacb0\ud558\ub294 \ubc29\ubc95\uc740 \ub354 \uc774\uc0c1 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4. "),(0,i.kt)("admonition",{title:"NIGNX \uc124\uc815",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"nginx \uc124\uc815\uc758 \uacbd\uc6b0 include \uad6c\ubb38\uc744 \ud65c\uc6a9\ud574 \uad6c\uc870\ud654\ud558\uc5ec \uc124\uc815 \ud30c\uc77c\uc744 \uac04\uacb0\ud558\uac8c \uc720\uc9c0\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/var/log/nginx/")),(0,i.kt)("p",null,"\uc5d4\uc9c4\uc5d1\uc2a4 \ub85c\uadf8\uac00 \uc800\uc7a5\ub418\ub294 \ub514\ub809\ud130\ub9ac\ub85c access \ub85c\uadf8\uc640 error \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,i.kt)("br",{parentName:"p"}),"\n","\ub85c\uadf8 \ud615\uc2dd\uc758 \uacbd\uc6b0 \uc124\uc815 \ud30c\uc77c\uc758 log_format \uad6c\ubb38\uc744 \uc774\uc6a9\ud574\uc11c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. "),(0,i.kt)("h3",{id:"\uba85\ub839\uc5b4"},"\uba85\ub839\uc5b4"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"nginx -t")),(0,i.kt)("p",null,"nginx \uc124\uc815\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud55c\ub2e4. "),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"nginx -T")," "),(0,i.kt)("p",null,"nginx \uc124\uc815 \ud655\uc778\uc758 \uacb0\uacfc\ub97c \uc870\uae08 \ub354 \uc790\uc138\ud558\uac8c \ucd9c\ub825\ud574\uc900\ub2e4. "),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"nginx -s ")),(0,i.kt)("p",null,"\uc5ec\uae30\uc11c SIGNAL\uc740 \ub2e4\uc74c \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud560 \uc218 \uc788\ub2e4."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"quit: \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc(SIGQUIT)"),(0,i.kt)("li",{parentName:"ul"},"reload: \uc124\uc815 \ud30c\uc77c \ub9ac\ub85c\ub4dc(SIGHUP)"),(0,i.kt)("li",{parentName:"ul"},"reopen: \ub85c\uadf8 \ud30c\uc77c\uc744 \ub2e4\uc2dc \uc5f4\ub3c4\ub85d \uc694\uccad(SIGUSR1)"),(0,i.kt)("li",{parentName:"ul"},"stop: \uc885\ub8cc \uc694\uccad(SIGTERM)")),(0,i.kt)("p",null,"\uc5ec\uae30\uc11c SIGQUIT & SIGTREM \ubaa8\ub450 graceful shutdown\uc744 \uc218\ud589\ud55c\ub2e4."),(0,i.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,i.kt)("p",null,"NGINX \ucfe1\ubd81, \ub370\ub9ad \ub514\uc6a9\uae30 p.22 ~ p.23",(0,i.kt)("br",{parentName:"p"}),"\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.nginx.com/"},"https://docs.nginx.com/"),(0,i.kt)("br",{parentName:"p"}),"\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.nginx.com/nginx/admin-guide/monitoring/logging/"},"https://docs.nginx.com/nginx/admin-guide/monitoring/logging/")))}m.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3438],{3905:(e,n,t)=>{t.d(n,{Zo:()=>u,kt:()=>d});var r=t(67294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var p=r.createContext({}),c=function(e){var n=r.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u=function(e){var n=c(e.components);return r.createElement(p.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},s=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),s=c(t),d=i,g=s["".concat(p,".").concat(d)]||s[d]||m[d]||a;return t?r.createElement(g,l(l({ref:n},u),{},{components:t})):r.createElement(g,l({ref:n},u))}));function d(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,l=new Array(a);l[0]=s;var o={};for(var p in n)hasOwnProperty.call(n,p)&&(o[p]=n[p]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var c=2;c{t.r(n),t.d(n,{assets:()=>p,contentTitle:()=>l,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var r=t(87462),i=(t(67294),t(3905));const a={title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",slug:"/nginx/command",tags:["nginx"]},l=void 0,o={unversionedId:"Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4",id:"Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4",title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",description:"\ud3f4\ub354 \ubc0f \ud30c\uc77c",source:"@site/docs/Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4.mdx",sourceDirName:"Nginx",slug:"/nginx/command",permalink:"/docs/nginx/command",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4.mdx",tags:[{label:"nginx",permalink:"/docs/tags/nginx"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",slug:"/nginx/command",tags:["nginx"]},sidebar:"tutorialSidebar",previous:{title:"\uae30\ubcf8 \ud0a4 \ub9e4\ud551",permalink:"/docs/jpa/key"},next:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",permalink:"/docs/nginx/static-file"}},p={},c=[{value:"\ud3f4\ub354 \ubc0f \ud30c\uc77c",id:"\ud3f4\ub354-\ubc0f-\ud30c\uc77c",level:3},{value:"\uba85\ub839\uc5b4",id:"\uba85\ub839\uc5b4",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function m(e){let{components:n,...t}=e;return(0,i.kt)("wrapper",(0,r.Z)({},u,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h3",{id:"\ud3f4\ub354-\ubc0f-\ud30c\uc77c"},"\ud3f4\ub354 \ubc0f \ud30c\uc77c"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/etc/nginx/")),(0,i.kt)("p",null,"\uae30\ubcf8 \uc124\uc815\uc774 \uc800\uc7a5\ub41c \ub8e8\ud2b8 \ub514\ub809\ud130\ub9ac"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/etc/nginx/nginx.conf")),(0,i.kt)("p",null,"\uae30\ubcf8 \uc124\uc815 \ud30c\uc77c\ub85c \ubaa8\ub4e0 \uc124\uc815\uc5d0 \ub300\ud55c \uc9c4\uc785\uc810",(0,i.kt)("br",{parentName:"p"}),"\n","\ub514\ub809\ud130\ub9ac\uc5d0 \uc704\uce58\ud55c \ubaa8\ub4e0 \uc124\uc815 \ud30c\uc77c\uc744 \ud3ec\ud568\ud558\ub294 \ucd5c\uc0c1\uc704 Http \ube14\ub85d\uc744 \ud3ec\ud568\ud55c\ub2e4. "),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash",metastring:'title="nginx\uc5d0 \ud3ec\ud568\ub41c \uc124\uc815 \ud30c\uc77c \ud3ec\ud568 include \uad6c\ubb38"',title:'"nginx\uc5d0',"\ud3ec\ud568\ub41c":!0,"\uc124\uc815":!0,"\ud30c\uc77c":!0,"\ud3ec\ud568":!0,include:!0,'\uad6c\ubb38"':!0},"http {\n ...\n include /etc/nginx/conf.d/*.conf;\n include /etc/nginx/sites-enabled/*;\n}\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/etc/nginx/conf.d/")),(0,i.kt)("p",null,"\uae30\ubcf8 HTTP \uc11c\ubc84 \uc124\uc815 \ud30c\uc77c\uc5d0 \ub300\ud55c \ub514\ub809\ud130\ub9ac",(0,i.kt)("br",{parentName:"p"}),"\n",(0,i.kt)("inlineCode",{parentName:"p"},".conf")," \ub85c \ub05d\ub098\ub294 \uacbd\uc6b0 \uc704\uc758 include \uc124\uc815\uc5d0 \uc758\ud574 \ucd5c\uc0c1\uc704 http \ube14\ub85d\uc5d0 \ud3ec\ud568\ub41c\ub2e4.",(0,i.kt)("br",{parentName:"p"}),"\n","conf.d \ub514\ub809\ud130\ub9ac \ub300\uc2e0 site-enabled \ub514\ub809\ud130\ub9ac\uc640 symlink\ub97c \ud1b5\ud574 \uc124\uc815 \ud30c\uc77c\uc744 \uc5f0\uacb0\ud558\ub294 \ubc29\ubc95\uc740 \ub354 \uc774\uc0c1 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294\ub2e4. "),(0,i.kt)("admonition",{title:"NIGNX \uc124\uc815",type:"note"},(0,i.kt)("p",{parentName:"admonition"},"nginx \uc124\uc815\uc758 \uacbd\uc6b0 include \uad6c\ubb38\uc744 \ud65c\uc6a9\ud574 \uad6c\uc870\ud654\ud558\uc5ec \uc124\uc815 \ud30c\uc77c\uc744 \uac04\uacb0\ud558\uac8c \uc720\uc9c0\ud558\ub294 \uac83\uc774 \uc88b\ub2e4.")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"/var/log/nginx/")),(0,i.kt)("p",null,"\uc5d4\uc9c4\uc5d1\uc2a4 \ub85c\uadf8\uac00 \uc800\uc7a5\ub418\ub294 \ub514\ub809\ud130\ub9ac\ub85c access \ub85c\uadf8\uc640 error \ub85c\uadf8\ub97c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.",(0,i.kt)("br",{parentName:"p"}),"\n","\ub85c\uadf8 \ud615\uc2dd\uc758 \uacbd\uc6b0 \uc124\uc815 \ud30c\uc77c\uc758 log_format \uad6c\ubb38\uc744 \uc774\uc6a9\ud574\uc11c \ubcc0\uacbd\ud560 \uc218 \uc788\ub2e4. "),(0,i.kt)("h3",{id:"\uba85\ub839\uc5b4"},"\uba85\ub839\uc5b4"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"nginx -t")),(0,i.kt)("p",null,"nginx \uc124\uc815\uc774 \uc815\uc0c1\uc778\uc9c0 \ud655\uc778\ud55c\ub2e4. "),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"nginx -T")," "),(0,i.kt)("p",null,"nginx \uc124\uc815 \ud655\uc778\uc758 \uacb0\uacfc\ub97c \uc870\uae08 \ub354 \uc790\uc138\ud558\uac8c \ucd9c\ub825\ud574\uc900\ub2e4. "),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"nginx -s ")),(0,i.kt)("p",null,"\uc5ec\uae30\uc11c SIGNAL\uc740 \ub2e4\uc74c \uc911 \ud558\ub098\ub97c \uc120\ud0dd\ud560 \uc218 \uc788\ub2e4."),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"quit: \uc815\uc0c1\uc801\uc73c\ub85c \uc885\ub8cc(SIGQUIT)"),(0,i.kt)("li",{parentName:"ul"},"reload: \uc124\uc815 \ud30c\uc77c \ub9ac\ub85c\ub4dc(SIGHUP)"),(0,i.kt)("li",{parentName:"ul"},"reopen: \ub85c\uadf8 \ud30c\uc77c\uc744 \ub2e4\uc2dc \uc5f4\ub3c4\ub85d \uc694\uccad(SIGUSR1)"),(0,i.kt)("li",{parentName:"ul"},"stop: \uc885\ub8cc \uc694\uccad(SIGTERM)")),(0,i.kt)("p",null,"\uc5ec\uae30\uc11c SIGQUIT & SIGTREM \ubaa8\ub450 graceful shutdown\uc744 \uc218\ud589\ud55c\ub2e4."),(0,i.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,i.kt)("p",null,"NGINX \ucfe1\ubd81, \ub370\ub9ad \ub514\uc6a9\uae30 p.22 ~ p.23",(0,i.kt)("br",{parentName:"p"}),"\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.nginx.com/"},"https://docs.nginx.com/"),(0,i.kt)("br",{parentName:"p"}),"\n",(0,i.kt)("a",{parentName:"p",href:"https://docs.nginx.com/nginx/admin-guide/monitoring/logging/"},"https://docs.nginx.com/nginx/admin-guide/monitoring/logging/")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/caf1b628.0cf6df3a.js b/assets/js/caf1b628.c5a48a49.js similarity index 98% rename from assets/js/caf1b628.0cf6df3a.js rename to assets/js/caf1b628.c5a48a49.js index 0b7b6f933..62c3818e5 100644 --- a/assets/js/caf1b628.0cf6df3a.js +++ b/assets/js/caf1b628.c5a48a49.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7230],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),c=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,p=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=c(n),m=a,b=d["".concat(p,".").concat(m)]||d[m]||s[m]||o;return n?r.createElement(b,l(l({ref:t},u),{},{components:n})):r.createElement(b,l({ref:t},u))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=d;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>s,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var r=n(87462),a=(n(67294),n(3905));const o={title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",slug:"/network/load-balancing",tags:["network","load balancing"]},l=void 0,i={unversionedId:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1",id:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1",title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",description:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc774\ub780?",source:"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1.mdx",sourceDirName:"\ub124\ud2b8\uc6cc\ud06c",slug:"/network/load-balancing",permalink:"/docs/network/load-balancing",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1.mdx",tags:[{label:"network",permalink:"/docs/tags/network"},{label:"load balancing",permalink:"/docs/tags/load-balancing"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",slug:"/network/load-balancing",tags:["network","load balancing"]},sidebar:"tutorialSidebar",previous:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",permalink:"/docs/network/load-balancing-algorithm"},next:{title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",permalink:"/docs/book/getting-out-of-the-box"}},p={},c=[{value:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc774\ub780?",id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc774\ub780",level:3},{value:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc758 \uc7a5\uc810",id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc758-\uc7a5\uc810",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function s(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc774\ub780"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc774\ub780?"),(0,a.kt)("p",null,"\uc11c\ubc84\uac00 \ucc98\ub9ac\ud574\uc57c \ud560 \uc694\uccad\uc744 \uc5ec\ub7ec \ub300\uc758 \uc11c\ubc84\ub85c \ub098\ub204\uc5b4 \ucc98\ub9ac\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc740 \ub85c\ub4dc \ubc38\ub7f0\uc11c\ub97c \ud1b5\ud574 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. "),(0,a.kt)("admonition",{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uacfc \ub85c\ub4dc \ubc38\ub7f0\uc11c",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1: \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc9c0\uc6d0\ud558\ub294 \ub9ac\uc18c\uc2a4 \ud480 \uc804\uccb4\uc5d0 \ub124\ud2b8\uc6cc\ud06c \ud2b8\ub798\ud53d\uc744 \uade0\ub4f1\ud558\uac8c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95",(0,a.kt)("br",{parentName:"p"}),"\n","\ub85c\ub4dc \ubc38\ub7f0\uc11c: \uc0ac\uc6a9\uc790\uc640 \uc11c\ubc84 \uadf8\ub8f9 \uc0ac\uc774\uc5d0 \uc704\uce58\ud558\uba70 \ubcf4\uc774\uc9c0 \uc54a\ub294 \ucd09\uc9c4\uc790 \uc5ed\ud560\uc744 \ud558\uc5ec \ubaa8\ub4e0 \ub9ac\uc18c\uc2a4 \uc11c\ubc84\uac00 \ub3d9\uc77c\ud558\uac8c \uc0ac\uc6a9\ub418\ub3c4\ub85d \ud558\ub294 \ub514\ubc14\uc774\uc2a4")),(0,a.kt)("h3",{id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc758-\uc7a5\uc810"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc758 \uc7a5\uc810"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\uac00\uc6a9\uc131")),(0,a.kt)("p",null,"\uc11c\ubc84\uc5d0 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\ub4dc\ubc38\ub7f0\uc11c\uac00 \ud574\ub2f9 \ubb38\uc81c\ub97c \uac10\uc9c0(\ud5ec\uc2a4 \uccb4\ud06c\ub97c \ud1b5\ud574)\ud558\uc5ec \ud2b8\ub798\ud53d\uc744 \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc11c\ubc84\ub85c \ubcf4\ub0c4\uc73c\ub85c\uc368 \ub0b4\uacb0\ud568\uc131\uc744 \ub192\ud78c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub85c\ub4dc\ubc38\ub7f0\uc11c\ub97c \ud65c\uc6a9\ud55c \ubb34\uc911\ub2e8 \ubc30\ud3ec "),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\ud655\uc7a5\uc131")),(0,a.kt)("p",null,"\uc218\ud3c9 \ud655\uc7a5\uc131(Horizontal Scalability) \uc6a9\uc774",(0,a.kt)("br",{parentName:"p"}),"\n","\ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 AutoScaling\uc744 \ud1b5\ud574 \uc11c\ubc84\ub97c \uc790\ub3d9\uc73c\ub85c \ud655\uc7a5(Scale-out)",(0,a.kt)("br",{parentName:"p"}),"\n","\ud2b8\ub798\ud53d\uc774 \uac10\uc18c\ud558\ub294 \uacbd\uc6b0 \ucd95\uc18c(Scale-in) "),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\ubcf4\uc548")),(0,a.kt)("p",null,"\ubd84\uc0b0 \uc11c\ube44\uc2a4 \uac70\ubd80 \uacf5\uaca9(DDoS)\uc774 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ud2b8\ub798\ud53d\uc744 \ubd80\ud558 \ubd84\uc0b0\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\uc131\ub2a5")),(0,a.kt)("p",null,"\uc11c\ubc84 \uac04 \ub85c\ub4dc\ub97c \uade0\ub4f1\ud558\uac8c \ubc30\ud3ec\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc131\ub2a5\uc744 \ud5a5\uc0c1 \uc2dc\ud0a8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc744 \uc9c0\ub9ac\uc801\uc73c\ub85c \ub354 \uac00\uae4c\uc6b4 \uc11c\ubc84\ub85c \ub9ac\ub2e4\uc774\ub809\uc158\ud558\uc5ec \uc9c0\uc5f0 \uc2dc\uac04\uc744 \ub2e8\ucd95\uc2dc\ud0a8\ub2e4. "),(0,a.kt)("admonition",{title:"\ub0b4\uacb0\ud568\uc131(Fault Tolerance)\uacfc \ud655\uc7a5\uc131(Scalability)",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\ub0b4\uacb0\ud568\uc131: \uc2dc\uc2a4\ud15c\uc758 \uc77c\ubd80 \uad6c\uc131 \uc694\uc18c\uac00 \uc791\ub3d9\ud558\uc9c0 \uc54a\ub354\ub77c\ub3c4 \uacc4\uc18d \uc791\ub3d9\ud560 \uc218 \uc788\ub294 \uae30\ub2a5",(0,a.kt)("br",{parentName:"p"}),"\n","\ud655\uc7a5\uc131: \ub300\uaddc\ubaa8\uc801\uc778 \uc7ac\uc124\uacc4/\uc7ac\uc124\uce58 \ub4f1\uc758 \ud544\uc694\uc5c6\uc774 \ud655\uc7a5\uc774 \uc5bc\ub9c8\ub098 \uc27d\uace0 \uac00\ub2a5\ud55c\uac00\uc5d0 \ub300\ud55c \uc6a9\uc774\uc131")),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://aws.amazon.com/ko/what-is/load-balancing/"},"load balancing, AWS")))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[7230],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=r.createContext({}),c=function(e){var t=r.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,p=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),d=c(n),m=a,b=d["".concat(p,".").concat(m)]||d[m]||s[m]||o;return n?r.createElement(b,l(l({ref:t},u),{},{components:n})):r.createElement(b,l({ref:t},u))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=d;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>s,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var r=n(87462),a=(n(67294),n(3905));const o={title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",slug:"/network/load-balancing",tags:["network","load balancing"]},l=void 0,i={unversionedId:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1",id:"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1",title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",description:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc774\ub780?",source:"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1.mdx",sourceDirName:"\ub124\ud2b8\uc6cc\ud06c",slug:"/network/load-balancing",permalink:"/docs/network/load-balancing",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1.mdx",tags:[{label:"network",permalink:"/docs/tags/network"},{label:"load balancing",permalink:"/docs/tags/load-balancing"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1",slug:"/network/load-balancing",tags:["network","load balancing"]},sidebar:"tutorialSidebar",previous:{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998",permalink:"/docs/network/load-balancing-algorithm"},next:{title:"\uc0c1\uc790 \ubc16\uc73c\ub85c \ud0c8\ucd9c\ud558\uae30",permalink:"/docs/book/getting-out-of-the-box"}},p={},c=[{value:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc774\ub780?",id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc774\ub780",level:3},{value:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc758 \uc7a5\uc810",id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc758-\uc7a5\uc810",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],u={toc:c};function s(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc774\ub780"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc774\ub780?"),(0,a.kt)("p",null,"\uc11c\ubc84\uac00 \ucc98\ub9ac\ud574\uc57c \ud560 \uc694\uccad\uc744 \uc5ec\ub7ec \ub300\uc758 \uc11c\ubc84\ub85c \ub098\ub204\uc5b4 \ucc98\ub9ac\ud558\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc740 \ub85c\ub4dc \ubc38\ub7f0\uc11c\ub97c \ud1b5\ud574 \uc774\ub8e8\uc5b4\uc9c4\ub2e4. "),(0,a.kt)("admonition",{title:"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uacfc \ub85c\ub4dc \ubc38\ub7f0\uc11c",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1: \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \uc9c0\uc6d0\ud558\ub294 \ub9ac\uc18c\uc2a4 \ud480 \uc804\uccb4\uc5d0 \ub124\ud2b8\uc6cc\ud06c \ud2b8\ub798\ud53d\uc744 \uade0\ub4f1\ud558\uac8c \ubc30\ud3ec\ud558\ub294 \ubc29\ubc95",(0,a.kt)("br",{parentName:"p"}),"\n","\ub85c\ub4dc \ubc38\ub7f0\uc11c: \uc0ac\uc6a9\uc790\uc640 \uc11c\ubc84 \uadf8\ub8f9 \uc0ac\uc774\uc5d0 \uc704\uce58\ud558\uba70 \ubcf4\uc774\uc9c0 \uc54a\ub294 \ucd09\uc9c4\uc790 \uc5ed\ud560\uc744 \ud558\uc5ec \ubaa8\ub4e0 \ub9ac\uc18c\uc2a4 \uc11c\ubc84\uac00 \ub3d9\uc77c\ud558\uac8c \uc0ac\uc6a9\ub418\ub3c4\ub85d \ud558\ub294 \ub514\ubc14\uc774\uc2a4")),(0,a.kt)("h3",{id:"\ub85c\ub4dc-\ubc38\ub7f0\uc2f1\uc758-\uc7a5\uc810"},"\ub85c\ub4dc \ubc38\ub7f0\uc2f1\uc758 \uc7a5\uc810"),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\uac00\uc6a9\uc131")),(0,a.kt)("p",null,"\uc11c\ubc84\uc5d0 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\ub4dc\ubc38\ub7f0\uc11c\uac00 \ud574\ub2f9 \ubb38\uc81c\ub97c \uac10\uc9c0(\ud5ec\uc2a4 \uccb4\ud06c\ub97c \ud1b5\ud574)\ud558\uc5ec \ud2b8\ub798\ud53d\uc744 \uc0ac\uc6a9 \uac00\ub2a5\ud55c \uc11c\ubc84\ub85c \ubcf4\ub0c4\uc73c\ub85c\uc368 \ub0b4\uacb0\ud568\uc131\uc744 \ub192\ud78c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ub85c\ub4dc\ubc38\ub7f0\uc11c\ub97c \ud65c\uc6a9\ud55c \ubb34\uc911\ub2e8 \ubc30\ud3ec "),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\ud655\uc7a5\uc131")),(0,a.kt)("p",null,"\uc218\ud3c9 \ud655\uc7a5\uc131(Horizontal Scalability) \uc6a9\uc774",(0,a.kt)("br",{parentName:"p"}),"\n","\ud2b8\ub798\ud53d\uc774 \uc99d\uac00\ud558\ub294 \uacbd\uc6b0 AutoScaling\uc744 \ud1b5\ud574 \uc11c\ubc84\ub97c \uc790\ub3d9\uc73c\ub85c \ud655\uc7a5(Scale-out)",(0,a.kt)("br",{parentName:"p"}),"\n","\ud2b8\ub798\ud53d\uc774 \uac10\uc18c\ud558\ub294 \uacbd\uc6b0 \ucd95\uc18c(Scale-in) "),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\ubcf4\uc548")),(0,a.kt)("p",null,"\ubd84\uc0b0 \uc11c\ube44\uc2a4 \uac70\ubd80 \uacf5\uaca9(DDoS)\uc774 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ud574\ub2f9 \ud2b8\ub798\ud53d\uc744 \ubd80\ud558 \ubd84\uc0b0\ud560 \uc218 \uc788\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("strong",{parentName:"p"},"\uc131\ub2a5")),(0,a.kt)("p",null,"\uc11c\ubc84 \uac04 \ub85c\ub4dc\ub97c \uade0\ub4f1\ud558\uac8c \ubc30\ud3ec\ud558\uc5ec \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc758 \uc131\ub2a5\uc744 \ud5a5\uc0c1 \uc2dc\ud0a8\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud074\ub77c\uc774\uc5b8\ud2b8 \uc694\uccad\uc744 \uc9c0\ub9ac\uc801\uc73c\ub85c \ub354 \uac00\uae4c\uc6b4 \uc11c\ubc84\ub85c \ub9ac\ub2e4\uc774\ub809\uc158\ud558\uc5ec \uc9c0\uc5f0 \uc2dc\uac04\uc744 \ub2e8\ucd95\uc2dc\ud0a8\ub2e4. "),(0,a.kt)("admonition",{title:"\ub0b4\uacb0\ud568\uc131(Fault Tolerance)\uacfc \ud655\uc7a5\uc131(Scalability)",type:"note"},(0,a.kt)("p",{parentName:"admonition"},"\ub0b4\uacb0\ud568\uc131: \uc2dc\uc2a4\ud15c\uc758 \uc77c\ubd80 \uad6c\uc131 \uc694\uc18c\uac00 \uc791\ub3d9\ud558\uc9c0 \uc54a\ub354\ub77c\ub3c4 \uacc4\uc18d \uc791\ub3d9\ud560 \uc218 \uc788\ub294 \uae30\ub2a5",(0,a.kt)("br",{parentName:"p"}),"\n","\ud655\uc7a5\uc131: \ub300\uaddc\ubaa8\uc801\uc778 \uc7ac\uc124\uacc4/\uc7ac\uc124\uce58 \ub4f1\uc758 \ud544\uc694\uc5c6\uc774 \ud655\uc7a5\uc774 \uc5bc\ub9c8\ub098 \uc27d\uace0 \uac00\ub2a5\ud55c\uac00\uc5d0 \ub300\ud55c \uc6a9\uc774\uc131")),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://aws.amazon.com/ko/what-is/load-balancing/"},"load balancing, AWS")))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/cd68cda1.68c11170.js b/assets/js/cd68cda1.68c11170.js deleted file mode 100644 index 8d63de95c..000000000 --- a/assets/js/cd68cda1.68c11170.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8683],{3905:(e,n,t)=>{t.d(n,{Zo:()=>s,kt:()=>g});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function c(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var i=r.createContext({}),p=function(e){var n=r.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},s=function(e){var n=p(e.components);return r.createElement(i.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(t),g=a,m=d["".concat(i,".").concat(g)]||d[g]||u[g]||o;return t?r.createElement(m,c(c({ref:n},s),{},{components:t})):r.createElement(m,c({ref:n},s))}));function g(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,c=new Array(o);c[0]=d;var l={};for(var i in n)hasOwnProperty.call(n,i)&&(l[i]=n[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var p=2;p{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=t(87462),a=(t(67294),t(3905));const o={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",slug:"async-exception",tags:["async","exception"]},c=void 0,l={permalink:"/async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",description:"\uac1c\uc694",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.15,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",slug:"async-exception",tags:["async","exception"]},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},i={authorsImageUrls:[]},p=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678\ucc98\ub9ac",id:"\ube44\ub3d9\uae30-\uc608\uc678\ucc98\ub9ac",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:p};function u(e){let{components:n,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},s,o,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uac1c\uc694"},"\uac1c\uc694"),(0,a.kt)("p",null,"\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Async"),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. "),(0,a.kt)("p",null,"\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,a.kt)("inlineCode",{parentName:"p"},"@ControllerAdvice")," + ",(0,a.kt)("inlineCode",{parentName:"p"},"@ExceptionHandler"),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\ub2e4. \ub530\ub77c\uc11c Spring\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncUncaughtExceptionHandler")," \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. "),(0,a.kt)("h3",{id:"\ube44\ub3d9\uae30-\uc608\uc678\ucc98\ub9ac"},"\ube44\ub3d9\uae30 \uc608\uc678\ucc98\ub9ac"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncExceptionHandler",title:"AsyncExceptionHandler"},'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n')),(0,a.kt)("p",null,"\ud574\ub2f9 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncExceptionHandler"),"\uc758 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncConfigurer"),"\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. ",(0,a.kt)("inlineCode",{parentName:"p"},"getAsyncUncaughtExceptionHandler")," \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \uc774\uc804\uc5d0 \uc0dd\uc131\ud574 \uc900 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncExceptionHandler"),"\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc774\ub807\uac8c \uc124\uc815\ud55c\ub2e4\uba74 \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncUncaughtExceptionHandler"),"\uc758 \uad6c\ud604\uccb4\uc778 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncExceptionHandler"),"\uac00 \uc608\uc678\ub97c \uc7a1\uc544\uc11c \ucc98\ub9ac\ub97c \ud574\uc900\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("h3",{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c"},"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-null.png",src:t(81450).Z,width:"2236",height:"426"})),(0,a.kt)("p",null,"\uae30\uc874 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\uc774\ub97c \uc801\uc808\ud558\uac8c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815\ud558\uc5ec MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud574\uc11c \ub118\uaca8\uc904 \uc218 \uc788\ub2e4. "),(0,a.kt)("p",null,"\ub2e4\uc74c\uacfc \uac19\uc774 TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=MdcTaskDecorator",title:"MdcTaskDecorator"},"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n")),(0,a.kt)("p",null,"\ud574\ub2f9 Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("p",null,"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-not-null.png",src:t(97754).Z,width:"2620",height:"440"})),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://www.baeldung.com/spring-async"},"spring async, baeldung"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception"},"@Async will not call by @ControllerAdvice for global exception"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/"},"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8")))}u.isMDXComponent=!0},97754:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file diff --git a/assets/js/cd68cda1.eeffe1e9.js b/assets/js/cd68cda1.eeffe1e9.js new file mode 100644 index 000000000..8b8cca5d5 --- /dev/null +++ b/assets/js/cd68cda1.eeffe1e9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[8683],{3905:(e,n,t)=>{t.d(n,{Zo:()=>s,kt:()=>d});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function c(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var i=r.createContext({}),p=function(e){var n=r.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},s=function(e){var n=p(e.components);return r.createElement(i.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},g=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),g=p(t),d=a,m=g["".concat(i,".").concat(d)]||g[d]||u[d]||o;return t?r.createElement(m,c(c({ref:n},s),{},{components:t})):r.createElement(m,c({ref:n},s))}));function d(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,c=new Array(o);c[0]=g;var l={};for(var i in n)hasOwnProperty.call(n,i)&&(l[i]=n[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var p=2;p{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=t(87462),a=(t(67294),t(3905));const o={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},c=void 0,l={permalink:"/log-async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",description:"\ubb38\uc81c \uc0c1\ud669",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.195,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},i={authorsImageUrls:[]},p=[{value:"\ubb38\uc81c \uc0c1\ud669",id:"\ubb38\uc81c-\uc0c1\ud669",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:p};function u(e){let{components:n,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},s,o,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ubb38\uc81c-\uc0c1\ud669"},"\ubb38\uc81c \uc0c1\ud669"),(0,a.kt)("p",null,"\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Async"),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,a.kt)("inlineCode",{parentName:"p"},"@ControllerAdvice")," + ",(0,a.kt)("inlineCode",{parentName:"p"},"@ExceptionHandler"),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4. "),(0,a.kt)("h3",{id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815"},"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815"),(0,a.kt)("p",null,"Spring\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncExceptionHandler",title:"AsyncExceptionHandler"},'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n')),(0,a.kt)("p",null,"AsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","getAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("p",null,"\uc774\uc81c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544\uc11c \ucc98\ub9ac\ub97c \ud574\uc900\ub2e4. "),(0,a.kt)("h3",{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c"},"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"),(0,a.kt)("p",null,"\ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc740 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4. \ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc5c8\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-null.png",src:t(81450).Z,width:"2236",height:"426"})),(0,a.kt)("p",null,"Spring 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html"},"TaskDecorator"),"\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=MdcTaskDecorator",title:"MdcTaskDecorator"},"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n")),(0,a.kt)("p",null,"\ud574\ub2f9 Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("p",null,"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-not-null.png",src:t(97754).Z,width:"2620",height:"440"})),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://www.baeldung.com/spring-async"},"spring async, baeldung"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception"},"@Async will not call by @ControllerAdvice for global exception"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/"},"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html"},"TaskDecorator, Spring docs")))}u.isMDXComponent=!0},97754:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file diff --git a/assets/js/d361ad2d.f08f5569.js b/assets/js/d361ad2d.86a9f24e.js similarity index 97% rename from assets/js/d361ad2d.f08f5569.js rename to assets/js/d361ad2d.86a9f24e.js index 971f29e12..c5095eb3e 100644 --- a/assets/js/d361ad2d.f08f5569.js +++ b/assets/js/d361ad2d.86a9f24e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2247],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>g});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function u(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var p=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=n.createContext({}),l=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):u(u({},t),e)),r},c=function(e){var t=l(e.components);return n.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,p=e.originalType,i=e.parentName,c=a(e,["components","mdxType","originalType","parentName"]),h=l(r),g=o,m=h["".concat(i,".").concat(g)]||h[g]||s[g]||p;return r?n.createElement(m,u(u({ref:t},c),{},{components:r})):n.createElement(m,u({ref:t},c))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var p=r.length,u=new Array(p);u[0]=h;var a={};for(var i in t)hasOwnProperty.call(t,i)&&(a[i]=t[i]);a.originalType=e,a.mdxType="string"==typeof e?e:o,u[1]=a;for(var l=2;l{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>u,default:()=>s,frontMatter:()=>p,metadata:()=>a,toc:()=>l});var n=r(87462),o=(r(67294),r(3905));const p={title:"Throughput \ubaa9\ud46f\uac12",slug:"/performance/throughput",tags:["throughput"]},u=void 0,a={unversionedId:"\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12",id:"\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12",title:"Throughput \ubaa9\ud46f\uac12",description:"Throughput",source:"@site/docs/\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12.mdx",sourceDirName:"\uc131\ub2a5",slug:"/performance/throughput",permalink:"/docs/performance/throughput",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12.mdx",tags:[{label:"throughput",permalink:"/docs/tags/throughput"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"Throughput \ubaa9\ud46f\uac12",slug:"/performance/throughput",tags:["throughput"]},sidebar:"tutorialSidebar",previous:{title:"\ud328\ud0a4\uc9c0",permalink:"/docs/design/package"},next:{title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",permalink:"/docs/performance/throughput-latency"}},i={},l=[{value:"Throughput",id:"throughput",level:3},{value:"\uacc4\uc0b0 \uc608\uc2dc",id:"\uacc4\uc0b0-\uc608\uc2dc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],c={toc:l};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"throughput"},"Throughput"),(0,o.kt)("p",null,"1\uc77c \uc0ac\uc6a9\uc790 \uc218, 1\uba85\ub2f9 1\uc77c \ud3c9\uade0 \uc811\uc18d \uc218, 1\uc77c \ud3c9\uade0 \uc811\uc18d \uc218\uc5d0 \ub300\ud55c \ud53c\ud06c \ub54c\uc758 \ubc30\uc728\uc744 \ud655\uc778\ud55c\ub2e4. "),(0,o.kt)("admonition",{title:"throughput",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"1\uc77c \ucd1d \uc811\uc18d \uc218: 1\uc77c \uc0ac\uc6a9\uc790 \uc218 x 1\uc778\ub2f9 1\uc77c \ud3c9\uade0 \uc811\uc18d \uc218",(0,o.kt)("br",{parentName:"p"}),"\n","1\uc77c \ud3c9\uade0 rps: 1\uc77c \ucd1d \uc811\uc18d \uc218 / 86400",(0,o.kt)("br",{parentName:"p"}),"\n","\ucd5c\ub300 rps: 1\uc77c \ud3c9\uade0 rps x \ucd5c\ub300 \ud53c\ud06c \ub54c\uc758 \ube44\uc728(\ud3c9\uade0 \uc811\uc18d \uc218 \ub300\ube44)")),(0,o.kt)("p",null,"\ucd5c\ub300 rps * \uc548\uc804\uacc4\uc218(2 ~ 3\ubc30)\ub97c Throughput\uc758 \ubaa9\ud45c\uce58\ub85c \ud55c\ub2e4. "),(0,o.kt)("h3",{id:"\uacc4\uc0b0-\uc608\uc2dc"},"\uacc4\uc0b0 \uc608\uc2dc"),(0,o.kt)("p",null,"DAU: 10\ub9cc\uba85",(0,o.kt)("br",{parentName:"p"}),"\n","1\uba85\ub2f9 \ud3c9\uade0 \uc811\uc18d\uc218: 10\ud68c",(0,o.kt)("br",{parentName:"p"}),"\n","\ud3c9\uade0 \uc811\uc18d \uc218 \ub300\ube44 \ucd5c\ub300 \ud53c\ud06c \ube44\uc728: 4\ubc30",(0,o.kt)("br",{parentName:"p"}),"\n","\uc548\uc804\uacc4\uc218: 3\ubc30 "),(0,o.kt)("p",null,"100000 x 10 / 86400 x 4 x 3 -> \uc57d 138rps "),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[2247],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>g});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function u(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var p=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=n.createContext({}),l=function(e){var t=n.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):u(u({},t),e)),r},c=function(e){var t=l(e.components);return n.createElement(i.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,p=e.originalType,i=e.parentName,c=a(e,["components","mdxType","originalType","parentName"]),h=l(r),g=o,m=h["".concat(i,".").concat(g)]||h[g]||s[g]||p;return r?n.createElement(m,u(u({ref:t},c),{},{components:r})):n.createElement(m,u({ref:t},c))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var p=r.length,u=new Array(p);u[0]=h;var a={};for(var i in t)hasOwnProperty.call(t,i)&&(a[i]=t[i]);a.originalType=e,a.mdxType="string"==typeof e?e:o,u[1]=a;for(var l=2;l{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>u,default:()=>s,frontMatter:()=>p,metadata:()=>a,toc:()=>l});var n=r(87462),o=(r(67294),r(3905));const p={title:"Throughput \ubaa9\ud46f\uac12",slug:"/performance/throughput",tags:["throughput"]},u=void 0,a={unversionedId:"\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12",id:"\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12",title:"Throughput \ubaa9\ud46f\uac12",description:"Throughput",source:"@site/docs/\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12.mdx",sourceDirName:"\uc131\ub2a5",slug:"/performance/throughput",permalink:"/docs/performance/throughput",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12.mdx",tags:[{label:"throughput",permalink:"/docs/tags/throughput"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"Throughput \ubaa9\ud46f\uac12",slug:"/performance/throughput",tags:["throughput"]},sidebar:"tutorialSidebar",previous:{title:"\ud328\ud0a4\uc9c0",permalink:"/docs/design/package"},next:{title:"\uc2dc\uc2a4\ud15c \uc131\ub2a5 \uc9c0\ud45c",permalink:"/docs/performance/throughput-latency"}},i={},l=[{value:"Throughput",id:"throughput",level:3},{value:"\uacc4\uc0b0 \uc608\uc2dc",id:"\uacc4\uc0b0-\uc608\uc2dc",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],c={toc:l};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h3",{id:"throughput"},"Throughput"),(0,o.kt)("p",null,"1\uc77c \uc0ac\uc6a9\uc790 \uc218, 1\uba85\ub2f9 1\uc77c \ud3c9\uade0 \uc811\uc18d \uc218, 1\uc77c \ud3c9\uade0 \uc811\uc18d \uc218\uc5d0 \ub300\ud55c \ud53c\ud06c \ub54c\uc758 \ubc30\uc728\uc744 \ud655\uc778\ud55c\ub2e4. "),(0,o.kt)("admonition",{title:"throughput",type:"note"},(0,o.kt)("p",{parentName:"admonition"},"1\uc77c \ucd1d \uc811\uc18d \uc218: 1\uc77c \uc0ac\uc6a9\uc790 \uc218 x 1\uc778\ub2f9 1\uc77c \ud3c9\uade0 \uc811\uc18d \uc218",(0,o.kt)("br",{parentName:"p"}),"\n","1\uc77c \ud3c9\uade0 rps: 1\uc77c \ucd1d \uc811\uc18d \uc218 / 86400",(0,o.kt)("br",{parentName:"p"}),"\n","\ucd5c\ub300 rps: 1\uc77c \ud3c9\uade0 rps x \ucd5c\ub300 \ud53c\ud06c \ub54c\uc758 \ube44\uc728(\ud3c9\uade0 \uc811\uc18d \uc218 \ub300\ube44)")),(0,o.kt)("p",null,"\ucd5c\ub300 rps * \uc548\uc804\uacc4\uc218(2 ~ 3\ubc30)\ub97c Throughput\uc758 \ubaa9\ud45c\uce58\ub85c \ud55c\ub2e4. "),(0,o.kt)("h3",{id:"\uacc4\uc0b0-\uc608\uc2dc"},"\uacc4\uc0b0 \uc608\uc2dc"),(0,o.kt)("p",null,"DAU: 10\ub9cc\uba85",(0,o.kt)("br",{parentName:"p"}),"\n","1\uba85\ub2f9 \ud3c9\uade0 \uc811\uc18d\uc218: 10\ud68c",(0,o.kt)("br",{parentName:"p"}),"\n","\ud3c9\uade0 \uc811\uc18d \uc218 \ub300\ube44 \ucd5c\ub300 \ud53c\ud06c \ube44\uc728: 4\ubc30",(0,o.kt)("br",{parentName:"p"}),"\n","\uc548\uc804\uacc4\uc218: 3\ubc30 "),(0,o.kt)("p",null,"100000 x 10 / 86400 x 4 x 3 -> \uc57d 138rps "),(0,o.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,o.kt)("p",null,"\uc544\ub9c8\uc874 \uc6f9 \uc11c\ube44\uc2a4 \ubd80\ud558 \ud14c\uc2a4\ud2b8 \uc785\ubb38 - \ub098\uce74\uac00\uc640 \ud0c0\ub8e8\ud558\uce58, \ubaa8\ub9ac\uc2dc\ud0c0 \ucf04"))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d86f7a37.bbe448b1.js b/assets/js/d86f7a37.098e58d0.js similarity index 97% rename from assets/js/d86f7a37.bbe448b1.js rename to assets/js/d86f7a37.098e58d0.js index 407bd6203..b7ad24c12 100644 --- a/assets/js/d86f7a37.bbe448b1.js +++ b/assets/js/d86f7a37.098e58d0.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3392],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),g=c(n),m=a,f=g["".concat(s,".").concat(m)]||g[m]||u[m]||i;return n?r.createElement(f,o(o({ref:t},p),{},{components:n})):r.createElement(f,o({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=g;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=n(87462),a=(n(67294),n(3905));const i={title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",slug:"/nginx/static-file",tags:["nginx"]},o=void 0,l={unversionedId:"Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5",id:"Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5",title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",description:"root",source:"@site/docs/Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5.mdx",sourceDirName:"Nginx",slug:"/nginx/static-file",permalink:"/docs/nginx/static-file",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5.mdx",tags:[{label:"nginx",permalink:"/docs/tags/nginx"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",slug:"/nginx/static-file",tags:["nginx"]},sidebar:"tutorialSidebar",previous:{title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",permalink:"/docs/nginx/command"},next:{title:"\ubb38\uc11c",permalink:"/docs/"}},s={},c=[{value:"root",id:"root",level:3},{value:"alias",id:"alias",level:3},{value:"try_files",id:"try_files",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],p={toc:c};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"root"},"root"),(0,a.kt)("p",null,"\ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \ud30c\uc77c\uc744 \uc81c\uacf5\ud560 \ub54c \uc0ac\uc6a9\ub418\ub294 \uacbd\ub85c\ub97c \uc9c0\uc815\ud558\ub294 \ub370 \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","root\uc758 \uacbd\uc6b0 locaiton\uc73c\ub85c \ub118\uc5b4\uc628 \uacbd\ub85c\ub97c root \uacbd\ub85c \ub4a4\uc5d0 \ucd94\uac00\ud55c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"title=root",title:"root"},"# localhost/images/1.png \ud638\ucd9c /var/www/images/images/1.png \uac80\uc0c9\nlocation /images/ {\n root /var/www/images;\n}\n")),(0,a.kt)("h3",{id:"alias"},"alias"),(0,a.kt)("p",null,"location\uc73c\ub85c \ub9e4\uce6d\ub41c \ubd80\ubd84\uc744 \uc81c\uac70\ud55c\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"title=alias",title:"alias"},"# localhost/images/1.png \ud638\ucd9c /var/www/images/1.png \uac80\uc0c9\nlocation /images/ {\n alias /var/www/images;\n}\n")),(0,a.kt)("h3",{id:"try_files"},"try_files"),(0,a.kt)("p",null,"try_files \ub514\ub809\ud2f0\ube0c\ub97c \uc774\uc6a9\ud574\uc11c \ud30c\uc77c\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc73c\uba74 \uc801\uc808\ud55c \uac12\uc744 \ubc18\ud658\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc124\uc815\ud558\uc9c0 \uc54a\uc73c\uba74 \uae30\ubcf8\uc73c\ub85c 404\ub97c \ubc18\ud658\ud55c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"location /images/ {\n alias /var/www/images;\n try_files $uri $uri/ =404;\n}\n")),(0,a.kt)("p",null,"\ub2e4\uc74c\uacfc \uac19\uc774 proxy \uc124\uc815\uc73c\ub85c\ub3c4 \uad6c\uc131\ud560 \uc218\ub3c4 \uc788\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"location /images/ {\n root /root;\n try_files $uri $uri/ default-image;\n}\n\nlocation default-image {\n proxy_pass http://localhost/images/default_image.jpg;\n}\n")),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/"},"Serving Static Content")))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3392],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>m});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),g=c(n),m=a,f=g["".concat(s,".").concat(m)]||g[m]||u[m]||i;return n?r.createElement(f,o(o({ref:t},p),{},{components:n})):r.createElement(f,o({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=g;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=n(87462),a=(n(67294),n(3905));const i={title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",slug:"/nginx/static-file",tags:["nginx"]},o=void 0,l={unversionedId:"Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5",id:"Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5",title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",description:"root",source:"@site/docs/Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5.mdx",sourceDirName:"Nginx",slug:"/nginx/static-file",permalink:"/docs/nginx/static-file",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5.mdx",tags:[{label:"nginx",permalink:"/docs/tags/nginx"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",slug:"/nginx/static-file",tags:["nginx"]},sidebar:"tutorialSidebar",previous:{title:"\uad6c\uc870 \ubc0f \uba85\ub839\uc5b4",permalink:"/docs/nginx/command"},next:{title:"\ubb38\uc11c",permalink:"/docs/"}},s={},c=[{value:"root",id:"root",level:3},{value:"alias",id:"alias",level:3},{value:"try_files",id:"try_files",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],p={toc:c};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"root"},"root"),(0,a.kt)("p",null,"\ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uac8c \ud30c\uc77c\uc744 \uc81c\uacf5\ud560 \ub54c \uc0ac\uc6a9\ub418\ub294 \uacbd\ub85c\ub97c \uc9c0\uc815\ud558\ub294 \ub370 \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","root\uc758 \uacbd\uc6b0 locaiton\uc73c\ub85c \ub118\uc5b4\uc628 \uacbd\ub85c\ub97c root \uacbd\ub85c \ub4a4\uc5d0 \ucd94\uac00\ud55c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"title=root",title:"root"},"# localhost/images/1.png \ud638\ucd9c /var/www/images/images/1.png \uac80\uc0c9\nlocation /images/ {\n root /var/www/images;\n}\n")),(0,a.kt)("h3",{id:"alias"},"alias"),(0,a.kt)("p",null,"location\uc73c\ub85c \ub9e4\uce6d\ub41c \ubd80\ubd84\uc744 \uc81c\uac70\ud55c\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash",metastring:"title=alias",title:"alias"},"# localhost/images/1.png \ud638\ucd9c /var/www/images/1.png \uac80\uc0c9\nlocation /images/ {\n alias /var/www/images;\n}\n")),(0,a.kt)("h3",{id:"try_files"},"try_files"),(0,a.kt)("p",null,"try_files \ub514\ub809\ud2f0\ube0c\ub97c \uc774\uc6a9\ud574\uc11c \ud30c\uc77c\uc774 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc73c\uba74 \uc801\uc808\ud55c \uac12\uc744 \ubc18\ud658\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc124\uc815\ud558\uc9c0 \uc54a\uc73c\uba74 \uae30\ubcf8\uc73c\ub85c 404\ub97c \ubc18\ud658\ud55c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"location /images/ {\n alias /var/www/images;\n try_files $uri $uri/ =404;\n}\n")),(0,a.kt)("p",null,"\ub2e4\uc74c\uacfc \uac19\uc774 proxy \uc124\uc815\uc73c\ub85c\ub3c4 \uad6c\uc131\ud560 \uc218\ub3c4 \uc788\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"location /images/ {\n root /root;\n try_files $uri $uri/ default-image;\n}\n\nlocation default-image {\n proxy_pass http://localhost/images/default_image.jpg;\n}\n")),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/"},"Serving Static Content")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/d8cdf5ef.4c076bff.js b/assets/js/d8cdf5ef.1caefe90.js similarity index 98% rename from assets/js/d8cdf5ef.4c076bff.js rename to assets/js/d8cdf5ef.1caefe90.js index 675398240..5ca5bafd5 100644 --- a/assets/js/d8cdf5ef.4c076bff.js +++ b/assets/js/d8cdf5ef.1caefe90.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5919],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>d});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=n.createContext({}),l=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return n.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,p=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),m=l(r),d=a,f=m["".concat(p,".").concat(d)]||m[d]||u[d]||o;return r?n.createElement(f,i(i({ref:t},s),{},{components:r})):n.createElement(f,i({ref:t},s))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=m;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c.mdxType="string"==typeof e?e:a,i[1]=c;for(var l=2;l{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",slug:"/etc/experience-and-self-question",tags:["etc"]},i=void 0,c={unversionedId:"\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8",id:"\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8",title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",description:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 10\uc6d4 6\uc77c",source:"@site/docs/\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/experience-and-self-question",permalink:"/docs/etc/experience-and-self-question",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",slug:"/etc/experience-and-self-question",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",permalink:"/docs/etc/develop-with-spring"},next:{title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",permalink:"/docs/etc/communication"}},p={},l=[{value:"\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8",id:"\uc790\uae30-\uc8fc\ub3c4\uc801\uc73c\ub85c-\ubb38\uc81c\ub97c-\ud574\uacb0\ud558\uae30-\uc704\ud55c-\ub3c4\uc804-\uacbd\ud5d8",level:3},{value:"\uc790\uc2e0\uc5d0\uac8c \ub358\uc838\ubd10\uc57c\ud560 \uc9c8\ubb38",id:"\uc790\uc2e0\uc5d0\uac8c-\ub358\uc838\ubd10\uc57c\ud560-\uc9c8\ubb38",level:3}],s={toc:l};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 10\uc6d4 6\uc77c",(0,a.kt)("br",{parentName:"p"}),"\n","\ud3ec\ube44 \ud2b9\uac15"),(0,a.kt)("h3",{id:"\uc790\uae30-\uc8fc\ub3c4\uc801\uc73c\ub85c-\ubb38\uc81c\ub97c-\ud574\uacb0\ud558\uae30-\uc704\ud55c-\ub3c4\uc804-\uacbd\ud5d8"},"\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8"),(0,a.kt)("p",null,"\ud300 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \ubc1c\uc0dd\ud55c \ud300\uc6d0 \uac04\uc758 \uac08\ub4f1\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ud300 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uc2e4 \uc0ac\uc6a9\uc790\ub97c \ubaa8\uc9d1\ud558\uae30 \uc704\ud574 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ud300\uc5d0\uc11c \uad00\uc2ec\uc744 \uac00\uc9c0\uc9c0 \uc54a\ub294 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ub05d\uae4c\uc9c0 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ub0b4\uac00 \ub04c\ub9ac\ub294 \uc8fc\uc81c\uc5d0 \ub300\ud574 \uae4a\uc774 \uc788\uac8c \ud559\uc2b5\ud558\uace0 \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc801\uc6a9\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc6a9\uc790 \uacbd\ud5d8\uc744 \ud55c \ub2e8\uacc4 \ub354 \ub192\uc774\uae30 \uc704\ud574 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2f9\uc5f0\ud558\ub2e4 \uc0dd\uac01\ud558\ub294 \ud574\uacb0\ucc45\uc5d0 \uc758\uad6c\uc2ec\uc744 \uac00\uc9c0\uace0 \uc0c8\ub85c\uc6b4 \uc811\uadfc \ubc29\uc2dd\uc73c\ub85c \ub3c4\uc804\ud55c \uacbd\ud5d8 "),(0,a.kt)("h3",{id:"\uc790\uc2e0\uc5d0\uac8c-\ub358\uc838\ubd10\uc57c\ud560-\uc9c8\ubb38"},"\uc790\uc2e0\uc5d0\uac8c \ub358\uc838\ubd10\uc57c\ud560 \uc9c8\ubb38"),(0,a.kt)("p",null,"\ub098\ub294 \ud504\ub85c\uadf8\ub798\ubc0d \uc790\uccb4\ub97c \uc990\uae30\uace0 \uc788\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \uc65c \ud504\ub85c\uadf8\ub798\uba38\uac00 \ub418\ub824\uace0 \ud558\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \ub098\ub2f5\uac8c \uc0b4\uace0 \uc788\ub098?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \uc8fc\ub3c4\uc801\uc73c\ub85c \uc0b4\uace0 \uc788\ub098?"))}u.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[5919],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>d});var n=r(67294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var p=n.createContext({}),l=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return n.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,p=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),m=l(r),d=a,f=m["".concat(p,".").concat(d)]||m[d]||u[d]||o;return r?n.createElement(f,i(i({ref:t},s),{},{components:r})):n.createElement(f,i({ref:t},s))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=m;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c.mdxType="string"==typeof e?e:a,i[1]=c;for(var l=2;l{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var n=r(87462),a=(r(67294),r(3905));const o={title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",slug:"/etc/experience-and-self-question",tags:["etc"]},i=void 0,c={unversionedId:"\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8",id:"\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8",title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",description:"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 10\uc6d4 6\uc77c",source:"@site/docs/\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8.mdx",sourceDirName:"\uae30\ud0c0",slug:"/etc/experience-and-self-question",permalink:"/docs/etc/experience-and-self-question",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8.mdx",tags:[{label:"etc",permalink:"/docs/tags/etc"}],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{title:"\uacbd\ud5d8\uacfc \uc9c8\ubb38",slug:"/etc/experience-and-self-question",tags:["etc"]},sidebar:"tutorialSidebar",previous:{title:"\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30",permalink:"/docs/etc/develop-with-spring"},next:{title:"\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00",permalink:"/docs/etc/communication"}},p={},l=[{value:"\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8",id:"\uc790\uae30-\uc8fc\ub3c4\uc801\uc73c\ub85c-\ubb38\uc81c\ub97c-\ud574\uacb0\ud558\uae30-\uc704\ud55c-\ub3c4\uc804-\uacbd\ud5d8",level:3},{value:"\uc790\uc2e0\uc5d0\uac8c \ub358\uc838\ubd10\uc57c\ud560 \uc9c8\ubb38",id:"\uc790\uc2e0\uc5d0\uac8c-\ub358\uc838\ubd10\uc57c\ud560-\uc9c8\ubb38",level:3}],s={toc:l};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 2023\ub144 10\uc6d4 6\uc77c",(0,a.kt)("br",{parentName:"p"}),"\n","\ud3ec\ube44 \ud2b9\uac15"),(0,a.kt)("h3",{id:"\uc790\uae30-\uc8fc\ub3c4\uc801\uc73c\ub85c-\ubb38\uc81c\ub97c-\ud574\uacb0\ud558\uae30-\uc704\ud55c-\ub3c4\uc804-\uacbd\ud5d8"},"\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8"),(0,a.kt)("p",null,"\ud300 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \ubc1c\uc0dd\ud55c \ud300\uc6d0 \uac04\uc758 \uac08\ub4f1\uc744 \ud574\uacb0\ud558\uae30 \uc704\ud574 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ud300 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uc2e4 \uc0ac\uc6a9\uc790\ub97c \ubaa8\uc9d1\ud558\uae30 \uc704\ud574 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ud300\uc5d0\uc11c \uad00\uc2ec\uc744 \uac00\uc9c0\uc9c0 \uc54a\ub294 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ub05d\uae4c\uc9c0 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ub0b4\uac00 \ub04c\ub9ac\ub294 \uc8fc\uc81c\uc5d0 \ub300\ud574 \uae4a\uc774 \uc788\uac8c \ud559\uc2b5\ud558\uace0 \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc801\uc6a9\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\uc0ac\uc6a9\uc790 \uacbd\ud5d8\uc744 \ud55c \ub2e8\uacc4 \ub354 \ub192\uc774\uae30 \uc704\ud574 \ub3c4\uc804\ud55c \uacbd\ud5d8",(0,a.kt)("br",{parentName:"p"}),"\n","\ub2f9\uc5f0\ud558\ub2e4 \uc0dd\uac01\ud558\ub294 \ud574\uacb0\ucc45\uc5d0 \uc758\uad6c\uc2ec\uc744 \uac00\uc9c0\uace0 \uc0c8\ub85c\uc6b4 \uc811\uadfc \ubc29\uc2dd\uc73c\ub85c \ub3c4\uc804\ud55c \uacbd\ud5d8 "),(0,a.kt)("h3",{id:"\uc790\uc2e0\uc5d0\uac8c-\ub358\uc838\ubd10\uc57c\ud560-\uc9c8\ubb38"},"\uc790\uc2e0\uc5d0\uac8c \ub358\uc838\ubd10\uc57c\ud560 \uc9c8\ubb38"),(0,a.kt)("p",null,"\ub098\ub294 \ud504\ub85c\uadf8\ub798\ubc0d \uc790\uccb4\ub97c \uc990\uae30\uace0 \uc788\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \uc65c \ud504\ub85c\uadf8\ub798\uba38\uac00 \ub418\ub824\uace0 \ud558\ub294\uac00?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \ub098\ub2f5\uac8c \uc0b4\uace0 \uc788\ub098?",(0,a.kt)("br",{parentName:"p"}),"\n","\ub098\ub294 \uc8fc\ub3c4\uc801\uc73c\ub85c \uc0b4\uace0 \uc788\ub098?"))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e2326195.26e8f74b.js b/assets/js/e2326195.26e8f74b.js new file mode 100644 index 000000000..d570703f8 --- /dev/null +++ b/assets/js/e2326195.26e8f74b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9467],{3905:(e,n,t)=>{t.d(n,{Zo:()=>s,kt:()=>d});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function c(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var i=r.createContext({}),p=function(e){var n=r.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},s=function(e){var n=p(e.components);return r.createElement(i.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},g=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),g=p(t),d=a,m=g["".concat(i,".").concat(d)]||g[d]||u[d]||o;return t?r.createElement(m,c(c({ref:n},s),{},{components:t})):r.createElement(m,c({ref:n},s))}));function d(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,c=new Array(o);c[0]=g;var l={};for(var i in n)hasOwnProperty.call(n,i)&&(l[i]=n[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var p=2;p{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=t(87462),a=(t(67294),t(3905));const o={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},c=void 0,l={permalink:"/log-async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",description:"\ubb38\uc81c \uc0c1\ud669",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.195,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ub85c\uae45",slug:"log-async-exception",tags:["async","exception"]},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},i={authorsImageUrls:[]},p=[{value:"\ubb38\uc81c \uc0c1\ud669",id:"\ubb38\uc81c-\uc0c1\ud669",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815",id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:p};function u(e){let{components:n,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},s,o,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\ubb38\uc81c-\uc0c1\ud669"},"\ubb38\uc81c \uc0c1\ud669"),(0,a.kt)("p",null,"\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Async"),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,a.kt)("inlineCode",{parentName:"p"},"@ControllerAdvice")," + ",(0,a.kt)("inlineCode",{parentName:"p"},"@ExceptionHandler"),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\uae30 \ub54c\ubb38\uc5d0 \ubc1c\uc0dd\ud55c \ubb38\uc81c\uc600\ub2e4. "),(0,a.kt)("h3",{id:"\ube44\ub3d9\uae30-\uc608\uc678-\ubc1c\uc0dd\uc2dc-\ub85c\uae45-\uc124\uc815"},"\ube44\ub3d9\uae30 \uc608\uc678 \ubc1c\uc0dd\uc2dc \ub85c\uae45 \uc124\uc815"),(0,a.kt)("p",null,"Spring\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 AsyncUncaughtExceptionHandler \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncExceptionHandler",title:"AsyncExceptionHandler"},'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n')),(0,a.kt)("p",null,"AsyncExceptionHandler\uc758 \uacbd\uc6b0 AsyncConfigurer\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","getAsyncUncaughtExceptionHandler() \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec AsyncExceptionHandler\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud558\uba74 \ub41c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("p",null,"\uc774\uc81c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 AsyncUncaughtExceptionHandler\uc758 \uad6c\ud604\uccb4\uc778 AsyncExceptionHandler\uac00 \uc608\uc678\ub97c \uc7a1\uc544\uc11c \ucc98\ub9ac\ub97c \ud574\uc900\ub2e4. "),(0,a.kt)("h3",{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c"},"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"),(0,a.kt)("p",null,"\ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc740 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\ub2e4. \ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc5c8\ub2e4. "),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-null.png",src:t(81450).Z,width:"2236",height:"426"})),(0,a.kt)("p",null,"Spring 4.3 \uc774\uc0c1\ubd80\ud130 \uc81c\uacf5\ub418\ub294 ",(0,a.kt)("a",{parentName:"p",href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html"},"TaskDecorator"),"\ub97c \uc774\uc6a9\ud558\uba74 TaskExecutor\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud560 \uc218 \uc788\ub2e4. TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud55c\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=MdcTaskDecorator",title:"MdcTaskDecorator"},"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n")),(0,a.kt)("p",null,"\ud574\ub2f9 Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("p",null,"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-not-null.png",src:t(97754).Z,width:"2620",height:"440"})),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://www.baeldung.com/spring-async"},"spring async, baeldung"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception"},"@Async will not call by @ControllerAdvice for global exception"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/"},"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/TaskDecorator.html"},"TaskDecorator, Spring docs")))}u.isMDXComponent=!0},97754:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file diff --git a/assets/js/e2326195.ed359df7.js b/assets/js/e2326195.ed359df7.js deleted file mode 100644 index d1d78baa5..000000000 --- a/assets/js/e2326195.ed359df7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[9467],{3905:(e,n,t)=>{t.d(n,{Zo:()=>s,kt:()=>g});var r=t(67294);function a(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function c(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var i=r.createContext({}),p=function(e){var n=r.useContext(i),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},s=function(e){var n=p(e.components);return r.createElement(i.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},d=r.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),d=p(t),g=a,m=d["".concat(i,".").concat(g)]||d[g]||u[g]||o;return t?r.createElement(m,c(c({ref:n},s),{},{components:t})):r.createElement(m,c({ref:n},s))}));function g(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,c=new Array(o);c[0]=d;var l={};for(var i in n)hasOwnProperty.call(n,i)&&(l[i]=n[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var p=2;p{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=t(87462),a=(t(67294),t(3905));const o={title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",slug:"async-exception",tags:["async","exception"]},c=void 0,l={permalink:"/async-exception",editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",source:"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",description:"\uac1c\uc694",date:"2023-09-18T00:00:00.000Z",formattedDate:"2023\ub144 9\uc6d4 18\uc77c",tags:[{label:"async",permalink:"/tags/async"},{label:"exception",permalink:"/tags/exception"}],readingTime:3.15,hasTruncateMarker:!1,authors:[],frontMatter:{title:"\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac",slug:"async-exception",tags:["async","exception"]},nextItem:{title:"\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0",permalink:"/tomcat-retrospective"}},i={authorsImageUrls:[]},p=[{value:"\uac1c\uc694",id:"\uac1c\uc694",level:3},{value:"\ube44\ub3d9\uae30 \uc608\uc678\ucc98\ub9ac",id:"\ube44\ub3d9\uae30-\uc608\uc678\ucc98\ub9ac",level:3},{value:"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c",id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c",level:3},{value:"\ucc38\uace0 \uc790\ub8cc",id:"\ucc38\uace0-\uc790\ub8cc",level:3}],s={toc:p};function u(e){let{components:n,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},s,o,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("h3",{id:"\uac1c\uc694"},"\uac1c\uc694"),(0,a.kt)("p",null,"\ud604\uc7ac \ud2b8\ub9bd\ub4dc\ub85c\uc6b0\uc758 \uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131 \uae30\ub2a5\uc740 \ube44\ub3d9\uae30\ub85c \ucc98\ub9ac\ub418\uace0 \uc788\ub2e4. \ub85c\uadf8\ub97c \ud655\uc778\ud558\ub294 \ub3c4\uc911 ",(0,a.kt)("inlineCode",{parentName:"p"},"@Async"),"\uac00 \uc801\uc6a9\ub41c \uba54\uc11c\ub4dc\uc5d0\uc11c \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 \ub85c\uadf8\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \ucd9c\ub825\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\ub2e4. "),(0,a.kt)("p",null,"\ud655\uc778\ud574 \ubcf4\ub2c8 Spring\uc758 ",(0,a.kt)("inlineCode",{parentName:"p"},"@ControllerAdvice")," + ",(0,a.kt)("inlineCode",{parentName:"p"},"@ExceptionHandler"),"\uc758 \uacbd\uc6b0 \ub3d9\uae30 \uc608\uc678\ub9cc \ucc98\ub9ac\ud558\uace0, \ube44\ub3d9\uae30 \uc608\uc678\ub97c \ucc98\ub9ac\ud558\uc9c0 \uc54a\uc558\ub2e4. \ub530\ub77c\uc11c Spring\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncUncaughtExceptionHandler")," \uc778\ud130\ud398\uc774\uc2a4\ub97c \uad6c\ud604\ud574\uc11c \uc608\uc678\ub97c \ucc98\ub9ac\ud558\ub294 \ud074\ub798\uc2a4\ub97c \uc0dd\uc131\ud588\ub2e4. "),(0,a.kt)("h3",{id:"\ube44\ub3d9\uae30-\uc608\uc678\ucc98\ub9ac"},"\ube44\ub3d9\uae30 \uc608\uc678\ucc98\ub9ac"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncExceptionHandler",title:"AsyncExceptionHandler"},'@Slf4j\npublic class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {\n\n private static final String LOG_FORMAT = "[%s] %s";\n\n @Override\n public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {\n log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);\n }\n}\n')),(0,a.kt)("p",null,"\ud574\ub2f9 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncExceptionHandler"),"\uc758 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncConfigurer"),"\ub97c \uad6c\ud604\ud55c Configuration \ud074\ub798\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc5ec \ub4f1\ub85d\ud560 \uc218 \uc788\ub2e4. ",(0,a.kt)("inlineCode",{parentName:"p"},"getAsyncUncaughtExceptionHandler")," \uba54\uc11c\ub4dc\ub97c \uc624\ubc84\ub77c\uc774\ub529\ud558\uc5ec \uc774\uc804\uc5d0 \uc0dd\uc131\ud574 \uc900 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncExceptionHandler"),"\ub97c \ubc18\ud658\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\uc774\ub807\uac8c \uc124\uc815\ud55c\ub2e4\uba74 \uc608\uc678\uac00 \ubc1c\uc0dd\ud558\ub294 \uacbd\uc6b0 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncUncaughtExceptionHandler"),"\uc758 \uad6c\ud604\uccb4\uc778 ",(0,a.kt)("inlineCode",{parentName:"p"},"AsyncExceptionHandler"),"\uac00 \uc608\uc678\ub97c \uc7a1\uc544\uc11c \ucc98\ub9ac\ub97c \ud574\uc900\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("h3",{id:"mdc-\uc815\ubcf4-\uc5f0\ub3d9-\ubb38\uc81c"},"MDC \uc815\ubcf4 \uc5f0\ub3d9 \ubb38\uc81c"),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-null.png",src:t(81450).Z,width:"2236",height:"426"})),(0,a.kt)("p",null,"\uae30\uc874 \uc608\uc678\uac00 \ubc1c\uc0dd\ud560 \ub54c \uc2e4\ud589 \ud750\ub984\uc744 \ucd94\uc801\ud558\uae30 \uc704\ud574 MDC(Mapped Diagnostic Context)\ub97c \uc0ac\uc6a9\ud55c\ub2e4.",(0,a.kt)("br",{parentName:"p"}),"\n","\ube44\ub3d9\uae30 \ucc98\ub9ac\uc758 \uacbd\uc6b0 \ubcc4\ub3c4\uc758 \uc2a4\ub808\ub4dc\uc5d0\uc11c \ub3d9\uc791\ud558\uae30 \ub54c\ubb38\uc5d0 ThreadLocal \uae30\ubc18\uc73c\ub85c \ub3d9\uc791\ud558\ub294 MDC\uc758 \uc815\ubcf4\ub97c \uc5bb\uc5b4\uc62c \uc218 \uc5c6\uc5c8\ub2e4. "),(0,a.kt)("p",null,"\uc774\ub97c \uc801\uc808\ud558\uac8c Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815\ud558\uc5ec MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud574\uc11c \ub118\uaca8\uc904 \uc218 \uc788\ub2e4. "),(0,a.kt)("p",null,"\ub2e4\uc74c\uacfc \uac19\uc774 TaskDecorator\ub97c \uad6c\ud604\ud55c \ud074\ub798\uc2a4\ub97c \ud558\ub098 \uc0dd\uc131\ud558\uace0, Task\uac00 \uc2e4\ud589\ub418\uae30 \uc804 MDC\uc758 \uc815\ubcf4\ub97c \ubcf5\uc0ac\ud558\ub3c4\ub85d \uc124\uc815\ud588\ub2e4. "),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=MdcTaskDecorator",title:"MdcTaskDecorator"},"public class MdcTaskDecorator implements TaskDecorator {\n\n @Override\n public Runnable decorate(final Runnable runnable) {\n Map threadContext = MDC.getCopyOfContextMap();\n return () -> {\n MDC.setContextMap(threadContext);\n runnable.run();\n };\n }\n}\n")),(0,a.kt)("p",null,"\ud574\ub2f9 Decorator \ud074\ub798\uc2a4\ub97c \uc124\uc815 \ud30c\uc77c\uc5d0 \ub4f1\ub85d\ud574 \uc900\ub2e4."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java",metastring:"title=AsyncConfig",title:"AsyncConfig"},"@RequiredArgsConstructor\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer {\n\n private final AsyncConfigurationProperties properties;\n\n @Bean\n public ThreadPoolTaskExecutor taskExecutor() {\n ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n executor.setCorePoolSize(properties.coreSize());\n executor.setMaxPoolSize(properties.maxSize());\n executor.setQueueCapacity(properties.queueCapacity());\n \n // highlight-next-line\n executor.setTaskDecorator(new MdcTaskDecorator());\n executor.setWaitForTasksToCompleteOnShutdown(true);\n executor.initialize();\n return executor;\n }\n\n @Override\n public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n return new AsyncExceptionHandler();\n }\n}\n")),(0,a.kt)("p",null,"\uc124\uc815 \ud6c4\uc5d0\ub294 \uc815\uc0c1\uc801\uc73c\ub85c MDC\uc5d0 \ub4e4\uc5b4\uac00 \uc788\ub294 UUID\uac00 \ucd9c\ub825\ub418\ub294 \uac83\uc744 \ubcfc \uc218 \uc788\ub2e4."),(0,a.kt)("p",null,(0,a.kt)("img",{alt:"./mdc-not-null.png",src:t(97754).Z,width:"2620",height:"440"})),(0,a.kt)("h3",{id:"\ucc38\uace0-\uc790\ub8cc"},"\ucc38\uace0 \uc790\ub8cc"),(0,a.kt)("p",null,(0,a.kt)("a",{parentName:"p",href:"https://www.baeldung.com/spring-async"},"spring async, baeldung"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://stackoverflow.com/questions/61885358/async-will-not-call-by-controlleradvice-for-global-exception"},"@Async will not call by @ControllerAdvice for global exception"),(0,a.kt)("br",{parentName:"p"}),"\n",(0,a.kt)("a",{parentName:"p",href:"https://blog.gangnamunni.com/post/mdc-context-task-decorator/"},"Spring \uc758 \ub3d9\uae30, \ube44\ub3d9\uae30, \ubc30\uce58 \ucc98\ub9ac\uc2dc \ud56d\uc0c1 context \ub97c \uc720\uc9c0\ud558\uace0 \ub85c\uae45\ud558\uae30, \uac15\ub0a8\uc5b8\ub2c8")))}u.isMDXComponent=!0},97754:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-not-null-2b12c13f4f420a335c9e55dbea503f1b.png"},81450:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/images/mdc-null-95b3bbdce99ef36ba843986413e0421a.png"}}]); \ No newline at end of file diff --git a/assets/js/f8409a7e.48009fa4.js b/assets/js/f8409a7e.d89eccfb.js similarity index 98% rename from assets/js/f8409a7e.48009fa4.js rename to assets/js/f8409a7e.d89eccfb.js index 7a2a9fbb4..0629d7255 100644 --- a/assets/js/f8409a7e.48009fa4.js +++ b/assets/js/f8409a7e.d89eccfb.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3206],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),f=p(r),d=o,m=f["".concat(l,".").concat(d)]||f[d]||s[d]||i;return r?n.createElement(m,a(a({ref:t},u),{},{components:r})):n.createElement(m,a({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=f;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>s,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(87462),o=(r(67294),r(3905));const i={id:"intro",title:"\ubb38\uc11c",slug:"/"},a=void 0,c={unversionedId:"intro",id:"intro",title:"\ubb38\uc11c",description:"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac",source:"@site/docs/intro.mdx",sourceDirName:".",slug:"/",permalink:"/docs/",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/intro.mdx",tags:[],version:"current",lastUpdatedAt:1695023693,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 18\uc77c",frontMatter:{id:"intro",title:"\ubb38\uc11c",slug:"/"},sidebar:"tutorialSidebar",previous:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",permalink:"/docs/nginx/static-file"},next:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",permalink:"/docs/etc/healthful-growth"}},l={},p=[],u={toc:p};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac"))}s.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[3206],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(67294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),f=p(r),d=o,m=f["".concat(l,".").concat(d)]||f[d]||s[d]||i;return r?n.createElement(m,a(a({ref:t},u),{},{components:r})):n.createElement(m,a({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=f;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>s,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(87462),o=(r(67294),r(3905));const i={id:"intro",title:"\ubb38\uc11c",slug:"/"},a=void 0,c={unversionedId:"intro",id:"intro",title:"\ubb38\uc11c",description:"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac",source:"@site/docs/intro.mdx",sourceDirName:".",slug:"/",permalink:"/docs/",draft:!1,editUrl:"https://github.com/greeng00se/greeng00se.github.io/tree/main/docs/intro.mdx",tags:[],version:"current",lastUpdatedAt:1695132461,formattedLastUpdatedAt:"2023\ub144 9\uc6d4 19\uc77c",frontMatter:{id:"intro",title:"\ubb38\uc11c",slug:"/"},sidebar:"tutorialSidebar",previous:{title:"\uc815\uc801 \ucee8\ud150\uce20 \uc81c\uacf5",permalink:"/docs/nginx/static-file"},next:{title:"\uac74\uac15\ud558\uac8c \ub098\uc544\uc9c0\uae30",permalink:"/docs/etc/healthful-growth"}},l={},p=[],u={toc:p};function s(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"\ub9c8\uc74c\uc5d0 \ub4e0 \ud0a4\uc6cc\ub4dc \uc815\ub9ac"))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/main.b4ffb42c.js b/assets/js/main.b4ffb42c.js deleted file mode 100644 index 6232046ad..000000000 --- a/assets/js/main.b4ffb42c.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.b4ffb42c.js.LICENSE.txt */ -(self.webpackChunkmy_website=self.webpackChunkmy_website||[]).push([[179],{20830:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});var a=n(67294);function r(){return a.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},a.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var a=n(67294),r=n(87462),o=n(68356),i=n.n(o),s=n(16887);const l={"00931cc3":[()=>n.e(5669).then(n.t.bind(n,92291,19)),"~blog/default/page-30-25c.json",92291],"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,24524)),"@theme/BlogTagsListPage",24524],"02689328":[()=>n.e(6346).then(n.t.bind(n,5577,19)),"~blog/default/tags-data-base-page-3-9db.json",5577],"0281109c":[()=>n.e(422).then(n.t.bind(n,25266,19)),"~blog/default/tags-jenkins-2e5-list.json",25266],"0462f8fc":[()=>n.e(4481).then(n.bind(n,37572)),"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd.mdx",37572],"04644f5f":[()=>n.e(2625).then(n.bind(n,73787)),"@site/docs/\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00.mdx",73787],"0571a526":[()=>n.e(6204).then(n.bind(n,77397)),"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",77397],"05b907fc":[()=>n.e(734).then(n.t.bind(n,92943,19)),"~blog/default/tags-retrospective-page-8-5ab-list.json",92943],"0746167d":[()=>n.e(1113).then(n.t.bind(n,19758,19)),"~blog/default/tags-elastic-beanstalk-119-list.json",19758],"08726fcf":[()=>n.e(5487).then(n.t.bind(n,38441,19)),"~blog/default/tags-java-page-4-c22-list.json",38441],"087c46fa":[()=>n.e(96).then(n.t.bind(n,25774,19)),"~blog/default/tags-spring-boot-889.json",25774],"08e37dbc":[()=>n.e(1328).then(n.bind(n,10634)),"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",10634],"09fbb6bd":[()=>n.e(5964).then(n.t.bind(n,41679,19)),"~blog/default/page-16-d6c.json",41679],"0a2eaa84":[()=>n.e(8942).then(n.t.bind(n,52930,19)),"~blog/default/tags-data-base-4e8.json",52930],"0c071de2":[()=>n.e(321).then(n.t.bind(n,23125,19)),"~blog/default/page-2-b45.json",23125],"0cb009d1":[()=>n.e(116).then(n.t.bind(n,66643,19)),"~blog/default/tags-event-f04.json",66643],"0d47646f":[()=>n.e(2342).then(n.bind(n,27019)),"@site/docs/\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131.mdx",27019],"0e33a907":[()=>n.e(3092).then(n.bind(n,81204)),"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx?truncated=true",81204],"101b58de":[()=>n.e(6084).then(n.bind(n,67365)),"@site/blog/2023-1/2023-01-08-JSR-310.mdx",67365],"101cf32b":[()=>n.e(9239).then(n.t.bind(n,30880,19)),"~blog/default/page-45-7ec.json",30880],"1236fad7":[()=>n.e(6515).then(n.bind(n,25088)),"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx",25088],"1251d98b":[()=>n.e(6276).then(n.bind(n,25075)),"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",25075],"12cbeba7":[()=>n.e(6508).then(n.t.bind(n,16134,19)),"~blog/default/page-29-e3c.json",16134],"130df38c":[()=>n.e(6493).then(n.bind(n,46963)),"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",46963],14164549:[()=>n.e(7268).then(n.t.bind(n,11279,19)),"~blog/default/tags-book-baf-list.json",11279],"14dc1923":[()=>n.e(7403).then(n.bind(n,25731)),"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx",25731],"16cc6f3a":[()=>n.e(425).then(n.t.bind(n,12946,19)),"~blog/default/tags-retrospective-page-15-26b.json",12946],"16f719ab":[()=>n.e(9875).then(n.bind(n,83377)),"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx",83377],"1781b1c4":[()=>n.e(5785).then(n.bind(n,10945)),"@site/blog/2023-2/2023-05-25-\uc9c0\ud558\ucca0 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",10945],17896441:[()=>Promise.all([n.e(532),n.e(4659),n.e(7918)]).then(n.bind(n,78945)),"@theme/DocItem",78945],"1893cb59":[()=>n.e(286).then(n.t.bind(n,16269,19)),"~blog/default/tags-java-page-2-8c6.json",16269],"18c69d70":[()=>n.e(9171).then(n.t.bind(n,7085,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",7085],"198f8d8a":[()=>n.e(9059).then(n.t.bind(n,17238,19)),"~blog/default/tags-java-page-3-b02-list.json",17238],"19f4ae8e":[()=>n.e(8161).then(n.t.bind(n,25680,19)),"~blog/default/tags-log-5ad.json",25680],"1a3abee6":[()=>n.e(5035).then(n.t.bind(n,87753,19)),"~blog/default/tags-retrospective-page-17-636.json",87753],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,39172)),"@theme/SearchPage",39172],"1a665c6f":[()=>n.e(454).then(n.t.bind(n,28767,19)),"~blog/default/tags-test-435-list.json",28767],"1a6b9123":[()=>n.e(9874).then(n.t.bind(n,14343,19)),"~blog/default/tags-teco-chat-page-3-007.json",14343],"1bb997fc":[()=>n.e(9713).then(n.t.bind(n,66014,19)),"~blog/default/page-44-cef.json",66014],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,19963)),"@theme/DocPage",19963],"1c93669b":[()=>n.e(6526).then(n.t.bind(n,37579,19)),"~docs/default/tag-docs-tags-monitoring-149.json",37579],"1d81daa1":[()=>n.e(7681).then(n.t.bind(n,76725,19)),"~blog/default/tags-mock-330.json",76725],"1f05d14a":[()=>Promise.all([n.e(532),n.e(656)]).then(n.bind(n,65945)),"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx?truncated=true",65945],"1f61820a":[()=>n.e(2233).then(n.bind(n,16432)),"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx?truncated=true",16432],"1fbde614":[()=>n.e(8243).then(n.t.bind(n,87304,19)),"~blog/default/tags-monitoring-a8a-list.json",87304],"20e99c2a":[()=>n.e(3530).then(n.t.bind(n,19507,19)),"~blog/default/tags-documentation-ee3-list.json",19507],"211d6170":[()=>n.e(3109).then(n.t.bind(n,41078,19)),"~docs/default/tag-docs-tags-package-d2b.json",41078],"21294bbb":[()=>n.e(9412).then(n.bind(n,86182)),"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",86182],"21d253a0":[()=>n.e(1853).then(n.t.bind(n,63986,19)),"~blog/default/tags-woowahan-techcourse-page-10-f03-list.json",63986],"21e890b0":[()=>n.e(8288).then(n.t.bind(n,551,19)),"~blog/default/tags-retrospective-page-14-99d-list.json",551],"226700de":[()=>n.e(6035).then(n.t.bind(n,41961,19)),"~blog/default/page-25-52d.json",41961],"24b9bc70":[()=>n.e(5798).then(n.bind(n,8518)),"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx",8518],"255134d9":[()=>n.e(8151).then(n.t.bind(n,30753,19)),"~blog/default/tags-composite-240.json",30753],"269a2f75":[()=>n.e(1994).then(n.t.bind(n,52358,19)),"~blog/default/tags-static-b68.json",52358],"26dc40bf":[()=>n.e(5237).then(n.bind(n,97783)),"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx?truncated=true",97783],"270346fa":[()=>n.e(7975).then(n.t.bind(n,89424,19)),"~blog/default/page-28-907.json",89424],"274c9143":[()=>n.e(6984).then(n.t.bind(n,90058,19)),"~blog/default/tags-java-a6e.json",90058],"280572f1":[()=>n.e(324).then(n.t.bind(n,77874,19)),"~blog/default/tags-mysql-331.json",77874],"2832e534":[()=>n.e(2476).then(n.t.bind(n,69870,19)),"~blog/default/page-13-99f.json",69870],"28a1570f":[()=>n.e(448).then(n.t.bind(n,92252,19)),"~blog/default/tags-elastic-beanstalk-119.json",92252],29476979:[()=>n.e(4030).then(n.bind(n,68804)),"@site/docs/\ub9ac\ub205\uc2a4/Swap_\uba54\ubaa8\ub9ac_\uc124\uc815.md",68804],"2a8faff0":[()=>n.e(7901).then(n.t.bind(n,1150,19)),"~blog/default/tags-test-435.json",1150],"2b22d492":[()=>n.e(7652).then(n.t.bind(n,56986,19)),"~blog/default/tags-retrospective-page-3-ee4-list.json",56986],"2b479afe":[()=>n.e(9591).then(n.t.bind(n,16973,19)),"~blog/default/tags-mockito-3c0-list.json",16973],"2bfe7c0b":[()=>n.e(1762).then(n.t.bind(n,82670,19)),"~blog/default/tags-book-page-2-bc6.json",82670],"2c9f5501":[()=>n.e(7775).then(n.bind(n,73917)),"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx?truncated=true",73917],"2d3b202f":[()=>n.e(1196).then(n.t.bind(n,42524,19)),"~blog/default/tags-book-baf.json",42524],"2d9296e4":[()=>n.e(3483).then(n.t.bind(n,89429,19)),"~blog/default/tags-pattern-b4e.json",89429],"2e10a69c":[()=>n.e(7581).then(n.t.bind(n,9981,19)),"~blog/default/page-38-d34.json",9981],"2f43e44a":[()=>n.e(6743).then(n.t.bind(n,52396,19)),"~blog/default/tags-grasp-418-list.json",52396],"302370be":[()=>n.e(1883).then(n.bind(n,91867)),"@site/docs/\ud14c\uc2a4\ud2b8/FIRST.mdx",91867],"303c1e60":[()=>n.e(2656).then(n.t.bind(n,39529,19)),"~blog/default/tags-retrospective-page-4-3a3.json",39529],"309173fa":[()=>n.e(1793).then(n.t.bind(n,22684,19)),"~blog/default/tags-data-base-4e8-list.json",22684],"32397cb2":[()=>n.e(548).then(n.t.bind(n,22050,19)),"~blog/default/tags-awt-page-2-eb4-list.json",22050],"327fa616":[()=>n.e(3407).then(n.bind(n,94634)),"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx",94634],"32b2299c":[()=>n.e(970).then(n.t.bind(n,5280,19)),"~blog/default/page-41-fe1.json",5280],33736670:[()=>n.e(2742).then(n.t.bind(n,80700,19)),"~blog/default/tags-class-eca.json",80700],"35293ec4":[()=>n.e(7697).then(n.t.bind(n,14,19)),"~blog/default/page-20-038.json",14],"35b2eb5a":[()=>n.e(372).then(n.t.bind(n,97815,19)),"~blog/default/tags-java-page-5-b71-list.json",97815],"366ddb85":[()=>n.e(3691).then(n.bind(n,2406)),"@site/docs/\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30.mdx",2406],"3720c009":[()=>Promise.all([n.e(532),n.e(3751)]).then(n.bind(n,10727)),"@theme/DocTagsListPage",10727],"372ccfe9":[()=>n.e(9111).then(n.bind(n,50673)),"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx?truncated=true",50673],"38bf29ad":[()=>n.e(1285).then(n.t.bind(n,26514,19)),"~docs/default/tag-docs-tags-load-balancing-180.json",26514],"38d8699e":[()=>n.e(471).then(n.t.bind(n,97481,19)),"~blog/default/page-15-208.json",97481],"3972c49f":[()=>n.e(6629).then(n.t.bind(n,91782,19)),"~blog/default/tags-web-socket-c6e-list.json",91782],"39ee6679":[()=>n.e(5717).then(n.t.bind(n,83636,19)),"~blog/default/tags-woowahan-techcourse-b50.json",83636],"3b0d95bc":[()=>n.e(5140).then(n.bind(n,38973)),"@site/docs/JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551.mdx",38973],"3b0f99e8":[()=>n.e(3553).then(n.t.bind(n,20034,19)),"~blog/default/tags-jenkins-2e5.json",20034],"3b18521e":[()=>n.e(2773).then(n.t.bind(n,8086,19)),"~blog/default/tags-mockito-3c0.json",8086],"3c5aea38":[()=>n.e(6250).then(n.t.bind(n,56516,19)),"~blog/default/tags-retrospective-page-12-8cf.json",56516],"3d6c40c1":[()=>n.e(8509).then(n.t.bind(n,3440,19)),"~blog/default/tags-monitoring-a8a.json",3440],"3dd4d232":[()=>n.e(7727).then(n.bind(n,74135)),"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx",74135],"3ed04b60":[()=>n.e(7157).then(n.t.bind(n,84792,19)),"~blog/default/tags-spring-de1.json",84792],"3f6ea930":[()=>n.e(5186).then(n.bind(n,42096)),"@site/blog/2023-1/2023-02-12-Parameterized Tests.mdx",42096],"3fc16fd0":[()=>n.e(3886).then(n.bind(n,42929)),"@site/docs/\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30.mdx",42929],"41b4728f":[()=>n.e(8628).then(n.t.bind(n,30171,19)),"~blog/default/tags-spring-boot-889-list.json",30171],"42957a8d":[()=>n.e(9312).then(n.bind(n,1335)),"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx",1335],"43a97218":[()=>n.e(4815).then(n.t.bind(n,65215,19)),"~blog/default/tags-retrospective-page-5-22d-list.json",65215],"43fcf0e9":[()=>n.e(6468).then(n.t.bind(n,94822,19)),"~blog/default/tags-woowahan-techcourse-page-9-065.json",94822],"4485017c":[()=>n.e(1906).then(n.bind(n,23224)),"@site/blog/2023-1/2023-03-14-\ube14\ub799\uc7ad \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",23224],"4515250b":[()=>n.e(9304).then(n.t.bind(n,88767,19)),"~blog/default/tags-exception-644-list.json",88767],"454a6d0d":[()=>n.e(4104).then(n.bind(n,33482)),"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx",33482],"459bd227":[()=>n.e(9094).then(n.bind(n,6693)),"@site/docs/\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30.mdx",6693],"489347ff":[()=>n.e(2793).then(n.t.bind(n,40526,19)),"~blog/default/tags-web-socket-c6e.json",40526],"48bd1d32":[()=>n.e(9563).then(n.bind(n,1683)),"@site/docs/\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59.mdx",1683],"48faf148":[()=>n.e(7328).then(n.bind(n,59455)),"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx?truncated=true",59455],"492a6565":[()=>n.e(4212).then(n.t.bind(n,44929,19)),"~blog/default/tags-lock-page-2-819-list.json",44929],"494882d1":[()=>n.e(4471).then(n.t.bind(n,2098,19)),"~blog/default/page-37-cb2.json",2098],"4959fc42":[()=>n.e(240).then(n.t.bind(n,80897,19)),"~blog/default/page-14-0a2.json",80897],"49b8d9dd":[()=>n.e(1103).then(n.t.bind(n,64420,19)),"~blog/default/tags-inno-db-59e.json",64420],"49f0f498":[()=>n.e(4433).then(n.t.bind(n,40719,19)),"~blog/default/tags-retrospective-page-16-226.json",40719],"4a1c8300":[()=>n.e(3324).then(n.bind(n,37750)),"@site/blog/2023-3/2023-08-19-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca83 \ud68c\uace0/2023-08-19-\ub808\ubca8 3 \ud68c\uace0.mdx",37750],"4b2fba3e":[()=>n.e(328).then(n.t.bind(n,98234,19)),"~blog/default/tags-image-page-3-942-list.json",98234],"4b79a3c9":[()=>Promise.all([n.e(532),n.e(5838)]).then(n.bind(n,60036)),"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx",60036],"4d43abad":[()=>n.e(3365).then(n.bind(n,4859)),"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx?truncated=true",4859],"5088fe06":[()=>n.e(80).then(n.t.bind(n,86819,19)),"~blog/default/tags-log-5ad-list.json",86819],"509d519c":[()=>n.e(743).then(n.t.bind(n,24469,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",24469],"52106a5f":[()=>n.e(9396).then(n.bind(n,63338)),"@site/blog/2023-1/2023-01-30-IntelliJ \uc124\uc815.mdx/index.mdx?truncated=true",63338],"533bfc57":[()=>n.e(5100).then(n.t.bind(n,4371,19)),"~blog/default/tags-retrospective-page-2-e2b-list.json",4371],"537817cb":[()=>n.e(3457).then(n.bind(n,49577)),"@site/blog/2023-1/2023-01-08-JSR-310.mdx?truncated=true",49577],"53e4509a":[()=>n.e(4722).then(n.t.bind(n,32259,19)),"~blog/default/page-46-6b3.json",32259],"54150be7":[()=>n.e(5088).then(n.t.bind(n,98707,19)),"~blog/default/tags-java-page-2-8c6-list.json",98707],"546ec22f":[()=>n.e(5635).then(n.t.bind(n,34223,19)),"~blog/default/tags-performance-test-2b7.json",34223],"54cb095e":[()=>n.e(7009).then(n.t.bind(n,95159,19)),"~blog/default/page-26-a44.json",95159],"55960ee5":[()=>n.e(4121).then(n.t.bind(n,88070,19)),"~docs/default/tags-list-current-prop-15a.json",88070],"562496aa":[()=>n.e(6161).then(n.t.bind(n,68146,19)),"~blog/default/tags-image-page-2-cc3.json",68146],"564337ec":[()=>n.e(5649).then(n.t.bind(n,8563,19)),"~blog/default/tags-retrospective-page-7-3e2-list.json",8563],"56e576e5":[()=>n.e(8262).then(n.t.bind(n,86556,19)),"~blog/default/tags-performance-test-2b7-list.json",86556],"5a29fbab":[()=>n.e(7857).then(n.t.bind(n,25381,19)),"~blog/default/tags-woowahan-techcourse-b50-list.json",25381],"5a6c6934":[()=>n.e(5953).then(n.t.bind(n,48630,19)),"~blog/default/tags-dto-cb6.json",48630],"5c38e66e":[()=>n.e(5521).then(n.t.bind(n,28638,19)),"~blog/default/tags-woowahan-techcourse-page-10-f03.json",28638],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,36809)),"@generated/docusaurus.config",36809],"5eed1665":[()=>n.e(8142).then(n.t.bind(n,19729,19)),"~blog/default/tags-lock-529-list.json",19729],"5f81b25c":[()=>n.e(4889).then(n.t.bind(n,29492,19)),"~blog/default/page-27-eb3.json",29492],"5ffd2c10":[()=>n.e(2100).then(n.t.bind(n,86515,19)),"~docs/default/tag-docs-tags-jpa-c8c.json",86515],"6093f82b":[()=>n.e(6017).then(n.t.bind(n,30708,19)),"~blog/default/page-9-361.json",30708],"633582b9":[()=>n.e(2448).then(n.t.bind(n,32401,19)),"~blog/default/tags-kotlin-6ac.json",32401],"635a92d5":[()=>n.e(7891).then(n.t.bind(n,72126,19)),"~blog/default/page-24-fbb.json",72126],"6412e40a":[()=>n.e(5421).then(n.t.bind(n,97677,19)),"~blog/default/tags-woowahan-techcourse-page-12-5ba-list.json",97677],"6425a984":[()=>n.e(5467).then(n.t.bind(n,95377,19)),"~blog/default/tags-woowahan-techcourse-page-4-bcd-list.json",95377],"64868a43":[()=>n.e(1501).then(n.t.bind(n,33159,19)),"~blog/default/page-39-76c.json",33159],"64f377d6":[()=>n.e(732).then(n.t.bind(n,62898,19)),"~blog/default/tags-woowahan-techcourse-page-11-6c9-list.json",62898],"6552f31f":[()=>n.e(917).then(n.bind(n,29693)),"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx",29693],"6675e9ab":[()=>n.e(1255).then(n.bind(n,72336)),"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx",72336],"66d1c769":[()=>n.e(7476).then(n.t.bind(n,80122,19)),"~blog/default/tags-data-base-page-2-3a7-list.json",80122],"672a376b":[()=>n.e(5753).then(n.t.bind(n,41690,19)),"~blog/default/tags-woowahan-techcourse-page-8-93a.json",41690],"6875c492":[()=>Promise.all([n.e(532),n.e(4659),n.e(6048),n.e(8610)]).then(n.bind(n,41714)),"@theme/BlogTagsPostsPage",41714],"69c28c32":[()=>n.e(1065).then(n.t.bind(n,99263,19)),"~blog/default/page-36-1da.json",99263],"6a19354d":[()=>n.e(693).then(n.t.bind(n,36232,19)),"~blog/default/tags-lock-529.json",36232],"6b54f6a4":[()=>Promise.all([n.e(532),n.e(4558)]).then(n.bind(n,23826)),"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx?truncated=true",23826],"6bc709ad":[()=>n.e(9393).then(n.t.bind(n,81399,19)),"~blog/default/tags-retrospective-page-6-594-list.json",81399],"6c674d03":[()=>n.e(7600).then(n.t.bind(n,80372,19)),"~docs/default/tag-docs-tags-network-cb4.json",80372],"6cfe3a99":[()=>n.e(5319).then(n.t.bind(n,91227,19)),"~blog/default/tags-cloudwatch-6c7-list.json",91227],"6d4355d3":[()=>n.e(3122).then(n.t.bind(n,37438,19)),"~blog/default/tags-async-page-2-246.json",37438],"6dd1c948":[()=>n.e(7064).then(n.t.bind(n,76376,19)),"~blog/default/page-34-16c.json",76376],"6f385a52":[()=>n.e(6608).then(n.bind(n,65468)),"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx?truncated=true",65468],"70275fcd":[()=>n.e(7412).then(n.t.bind(n,81191,19)),"~blog/default/page-42-ca9.json",81191],70834889:[()=>n.e(7344).then(n.bind(n,6777)),"@site/blog/2023-3/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8/2023-09-10-\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx?truncated=true",6777],"70a12cc4":[()=>n.e(5682).then(n.t.bind(n,17085,19)),"~blog/default/tags-static-b68-list.json",17085],"7159c7ff":[()=>n.e(3287).then(n.bind(n,92553)),"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx?truncated=true",92553],"72657f57":[()=>n.e(9581).then(n.bind(n,8046)),"@site/blog/2023-2/2023-05-02-\uc6f9 \uc790\ub3d9\ucc28 \ubbf8\uc158 \ud68c\uace0.mdx",8046],"73688d5c":[()=>n.e(6908).then(n.bind(n,60641)),"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx?truncated=true",60641],"7405ea58":[()=>n.e(2345).then(n.t.bind(n,40702,19)),"~blog/default/tags-retrospective-page-11-e3c-list.json",40702],"75121fd5":[()=>n.e(5335).then(n.t.bind(n,30674,19)),"~blog/default/tags-image-97d.json",30674],"754fb852":[()=>n.e(988).then(n.t.bind(n,38242,19)),"~blog/default/page-32-596.json",38242],"75f50328":[()=>n.e(7511).then(n.t.bind(n,58695,19)),"~blog/default/tags-mysql-331-list.json",58695],"7762a24e":[()=>n.e(2753).then(n.t.bind(n,55095,19)),"~blog/default/page-4-365.json",55095],"77f5fc5d":[()=>n.e(3625).then(n.t.bind(n,32215,19)),"~blog/default/tags-retrospective-page-16-226-list.json",32215],"79a97f4e":[()=>n.e(6412).then(n.bind(n,82792)),"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx?truncated=true",82792],"7af1d52f":[()=>n.e(2334).then(n.t.bind(n,59565,19)),"~blog/default/page-6-d10.json",59565],"7bbc420e":[()=>n.e(4311).then(n.t.bind(n,41691,19)),"~blog/default/tags-documentation-ee3.json",41691],"7c660760":[()=>n.e(2087).then(n.t.bind(n,91870,19)),"~blog/default/tags-woowahan-techcourse-page-9-065-list.json",91870],"7e4c1ed7":[()=>n.e(1653).then(n.t.bind(n,83297,19)),"~docs/default/tag-docs-tags-postmortem-ede.json",83297],"7e59392d":[()=>n.e(7281).then(n.t.bind(n,33202,19)),"~blog/default/tags-retrospective-page-9-473-list.json",33202],"7fbacf84":[()=>n.e(5797).then(n.t.bind(n,58701,19)),"~blog/default/tags-spring-de1-list.json",58701],"7fd9a574":[()=>n.e(2889).then(n.t.bind(n,5863,19)),"~blog/default/tags-retrospective-page-14-99d.json",5863],"80960b4b":[()=>n.e(7599).then(n.t.bind(n,28386,19)),"~blog/default/page-21-7a8.json",28386],"814f3328":[()=>n.e(2535).then(n.t.bind(n,45641,19)),"~blog/default/blog-post-list-prop-default.json",45641],"829fa7b9":[()=>n.e(9391).then(n.bind(n,22895)),"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx",22895],"86b4da3d":[()=>n.e(952).then(n.t.bind(n,44149,19)),"~blog/default/tags-woowahan-techcourse-page-2-567.json",44149],"87070fc3":[()=>n.e(6124).then(n.bind(n,74161)),"@site/docs/\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8.mdx",74161],"871c1e5a":[()=>n.e(5966).then(n.t.bind(n,71247,19)),"~blog/default/page-23-651.json",71247],"8720c147":[()=>n.e(470).then(n.bind(n,55810)),"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx",55810],"8a24850b":[()=>n.e(741).then(n.bind(n,12401)),"@site/blog/2023-1/2023-03-31-\uccb4\uc2a4 \ubbf8\uc158 \ud68c\uace0.mdx",12401],"8a27aeff":[()=>n.e(71).then(n.bind(n,17442)),"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx?truncated=true",17442],"8ad2f007":[()=>n.e(8360).then(n.bind(n,96431)),"@site/blog/2023-3/2023-07-30-Mockito \uc774\uc6a9\ud574\uc11c static \uba54\uc11c\ub4dc \ubaa8\ud0b9\ud558\uae30.mdx?truncated=true",96431],"8b79a48d":[()=>n.e(9287).then(n.t.bind(n,59070,19)),"~blog/default/tags-retrospective-page-9-473.json",59070],"8c6c0796":[()=>n.e(2816).then(n.t.bind(n,59123,19)),"~blog/default/tags-retrospective-2fb.json",59123],"8d05b77c":[()=>n.e(4149).then(n.t.bind(n,22801,19)),"~blog/default/page-5-264.json",22801],"8d7288fe":[()=>n.e(4801).then(n.t.bind(n,71830,19)),"~blog/default/tags-class-eca-list.json",71830],"8da65e83":[()=>n.e(9427).then(n.t.bind(n,1341,19)),"~blog/default/tags-woowahan-techcourse-page-4-bcd.json",1341],"8dc09bac":[()=>n.e(8338).then(n.t.bind(n,28881,19)),"~blog/default/tags-event-f04-list.json",28881],"8e498bb6":[()=>n.e(1436).then(n.t.bind(n,50257,19)),"~blog/default/tags-java-page-3-b02.json",50257],"8fbd512b":[()=>n.e(5873).then(n.t.bind(n,15,19)),"~blog/default/tags-async-326.json",15],"905ecccc":[()=>Promise.all([n.e(532),n.e(2939)]).then(n.bind(n,1057)),"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",1057],"92ade856":[()=>Promise.all([n.e(532),n.e(1772)]).then(n.bind(n,68499)),"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx?truncated=true",68499],"92fef07b":[()=>n.e(300).then(n.bind(n,21474)),"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx",21474],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"96adae60":[()=>n.e(172).then(n.t.bind(n,54217,19)),"~blog/default/page-19-21b.json",54217],"981f7647":[()=>n.e(2947).then(n.bind(n,51077)),"@site/docs/\uc124\uacc4/\ud328\ud0a4\uc9c0.mdx",51077],"9b43eac8":[()=>n.e(9286).then(n.bind(n,44284)),"@site/blog/2023-1/2023-01-02-2022\ub144 \ud68c\uace0.mdx",44284],"9b56b618":[()=>n.e(9538).then(n.t.bind(n,37e3,19)),"~blog/default/tags-awt-0e2-list.json",37e3],"9bad5ae7":[()=>n.e(2153).then(n.bind(n,2163)),"@site/blog/2023-2/2023-04-07-InnoDB \uc2a4\ud1a0\ub9ac\uc9c0 \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx?truncated=true",2163],"9bbc65ac":[()=>n.e(7210).then(n.t.bind(n,51020,19)),"~docs/default/tag-docs-tags-test-8ab.json",51020],"9ca52986":[()=>n.e(3490).then(n.t.bind(n,92016,19)),"~blog/default/tags-lock-page-2-819.json",92016],"9cfe8fd1":[()=>n.e(7725).then(n.t.bind(n,97113,19)),"~blog/default/page-18-46d.json",97113],"9d1fd2b0":[()=>n.e(7972).then(n.bind(n,15361)),"@site/blog/2023-2/2023-06-11-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca82 \ud68c\uace0.mdx",15361],"9d8ee3a8":[()=>n.e(5962).then(n.t.bind(n,71297,19)),"~blog/default/tags-oop-03c.json",71297],"9dc4119a":[()=>n.e(6490).then(n.t.bind(n,4408,19)),"~blog/default/tags-retrospective-page-10-4a6-list.json",4408],"9dec6b67":[()=>n.e(8524).then(n.t.bind(n,88221,19)),"~blog/default/tags-data-base-page-2-3a7.json",88221],"9e2e3982":[()=>n.e(7617).then(n.bind(n,57214)),"@site/blog/2023-3/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd/2023-07-27-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uae30\uc220 \uc120\ud0dd.mdx",57214],"9e4087bc":[()=>n.e(3608).then(n.bind(n,63169)),"@theme/BlogArchivePage",63169],"9e477a5e":[()=>n.e(8312).then(n.bind(n,54686)),"@site/docs/\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c.mdx",54686],"9e4ad429":[()=>n.e(5406).then(n.t.bind(n,16060,19)),"~docs/default/tag-docs-tags-performance-339.json",16060],"9f586ca3":[()=>n.e(3673).then(n.t.bind(n,41912,19)),"~blog/default/tags-async-page-2-246-list.json",41912],"9fae68e2":[()=>n.e(297).then(n.t.bind(n,77536,19)),"~blog/default/tags-kotlin-6ac-list.json",77536],a0410ab5:[()=>n.e(7843).then(n.t.bind(n,76970,19)),"~blog/default/tags-retrospective-page-7-3e2.json",76970],a1877440:[()=>n.e(7648).then(n.t.bind(n,23235,19)),"~blog/default/tags-async-326-list.json",23235],a3614f73:[()=>n.e(8474).then(n.bind(n,8797)),"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx",8797],a3dddb77:[()=>n.e(475).then(n.t.bind(n,5479,19)),"~blog/default/tags-java-page-4-c22.json",5479],a43f2942:[()=>n.e(104).then(n.bind(n,7894)),"@site/docs/\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8.mdx",7894],a4a1e915:[()=>n.e(3671).then(n.t.bind(n,60166,19)),"~blog/default/tags-retrospective-2fb-list.json",60166],a5557bb9:[()=>n.e(5991).then(n.t.bind(n,93885,19)),"~blog/default/index.json",93885],a59d28a9:[()=>n.e(2012).then(n.bind(n,44122)),"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx?truncated=true",44122],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(4659),n.e(6048),n.e(3089)]).then(n.bind(n,80046)),"@theme/BlogListPage",80046],a710d533:[()=>Promise.all([n.e(532),n.e(1711)]).then(n.bind(n,95220)),"@site/blog/2023-3/2023-09-11-\ud1b0\ucea3 \uad6c\ud604 \ubbf8\uc158 \ud68c\uace0.mdx",95220],a85e626a:[()=>n.e(9092).then(n.t.bind(n,48458,19)),"~blog/default/tags-jdbc-4bd.json",48458],a896be03:[()=>n.e(2526).then(n.t.bind(n,64030,19)),"~blog/default/tags-woowahan-techcourse-page-6-429.json",64030],a8cba70f:[()=>n.e(2261).then(n.bind(n,61629)),"@site/blog/2023-2/2023-04-01-\uc6b0\uc544\ud55c\ud14c\ud06c\ucf54\uc2a4 \ub808\ubca81 \ud68c\uace0.mdx?truncated=true",61629],a9221bd5:[()=>n.e(5507).then(n.t.bind(n,40319,19)),"~blog/default/tags-inno-db-59e-list.json",40319],aacfeabc:[()=>n.e(8909).then(n.bind(n,79407)),"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx?truncated=true",79407],abb0816f:[()=>n.e(4174).then(n.t.bind(n,82969,19)),"~blog/default/tags-woowahan-techcourse-page-7-5bd-list.json",82969],abc83b7f:[()=>n.e(2215).then(n.t.bind(n,8412,19)),"~blog/default/tags-retrospective-page-2-e2b.json",8412],ac23d7ee:[()=>n.e(3213).then(n.t.bind(n,43943,19)),"~blog/default/tags-woowahan-techcourse-page-3-9a8-list.json",43943],ad3b7b62:[()=>n.e(26).then(n.bind(n,55097)),"@site/blog/2023-2/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0/2023-05-12-\uc6f9 \uc7a5\ubc14\uad6c\ub2c8 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",55097],ae1d6508:[()=>n.e(2181).then(n.t.bind(n,83486,19)),"~blog/default/tags-composite-240-list.json",83486],ae3384b2:[()=>n.e(2965).then(n.t.bind(n,15745,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",15745],af81a133:[()=>n.e(7787).then(n.t.bind(n,13800,19)),"~blog/default/tags-teco-chat-d21.json",13800],b2b675dd:[()=>n.e(533).then(n.t.bind(n,28017,19)),"~blog/default/blog-c06.json",28017],b2c8756c:[()=>n.e(1213).then(n.bind(n,31419)),"@site/blog/2023-2/2023-06-04-\uc7a5\ubc14\uad6c\ub2c8 \uc8fc\ubb38 \ubbf8\uc158 \ud68c\uace0.mdx",31419],b2ebb6fd:[()=>n.e(4091).then(n.bind(n,34604)),"@site/blog/2023-2/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815/2023-04-30-Jenkins\ub85c \ubc30\ud3ec \uc790\ub3d9\ud654 \uc124\uc815.mdx",34604],b301b20b:[()=>n.e(3637).then(n.t.bind(n,83150,19)),"~blog/default/tags-replication-56b.json",83150],b36d2d1d:[()=>n.e(1257).then(n.t.bind(n,7903,19)),"~docs/default/tag-docs-tags-latency-735.json",7903],b421ebb7:[()=>n.e(8518).then(n.bind(n,20882)),"@site/docs/\uc131\ub2a5/Throughput\uacfc Latency.mdx",20882],b474adfe:[()=>n.e(573).then(n.t.bind(n,85419,19)),"~blog/default/tags-image-page-2-cc3-list.json",85419],b5f3dcc5:[()=>n.e(7723).then(n.t.bind(n,23005,19)),"~blog/default/tags-retrospective-page-15-26b-list.json",23005],b6ffb0cb:[()=>n.e(2156).then(n.bind(n,47682)),"@site/blog/2023-1/2023-02-14-\uc790\ub3d9\ucc28 \uacbd\uc8fc \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",47682],b7d33121:[()=>n.e(7153).then(n.t.bind(n,72005,19)),"~blog/default/tags-cloudwatch-6c7.json",72005],b88cb85b:[()=>n.e(2293).then(n.bind(n,18557)),"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998.mdx",18557],b9bcab37:[()=>n.e(7688).then(n.t.bind(n,43632,19)),"~blog/default/tags-grasp-418.json",43632],bace0b37:[()=>n.e(2362).then(n.bind(n,25831)),"@site/blog/2023-2/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5/2023-05-24-\uc911\ubcf5\uacfc \uc6b0\ubc1c\uc801 \uc911\ubcf5.mdx",25831],bb221eab:[()=>n.e(711).then(n.bind(n,59165)),"@site/blog/2023-2/2023-04-04-\ud14c\uc2a4\ud2b8 \ub300\uc5ed.mdx?truncated=true",59165],bbc01ba0:[()=>n.e(3009).then(n.t.bind(n,12333,19)),"~blog/default/tags-retrospective-page-10-4a6.json",12333],bbc3f62a:[()=>n.e(8894).then(n.t.bind(n,51842,19)),"~blog/default/tags-woowahan-techcourse-page-13-8ae-list.json",51842],bbceb8f1:[()=>n.e(653).then(n.t.bind(n,26529,19)),"~blog/default/tags-woowahan-techcourse-page-5-ac5-list.json",26529],bbdd7e52:[()=>n.e(3396).then(n.bind(n,31120)),"@site/blog/2023-2/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604/2023-06-01-\ud14c\ucf54\ucc57 3. \uae30\ub2a5 \uad6c\ud604.mdx",31120],bd2d06b5:[()=>n.e(9763).then(n.t.bind(n,93081,19)),"~blog/default/tags-retrospective-page-3-ee4.json",93081],bd4db8ee:[()=>n.e(6883).then(n.bind(n,93546)),"@site/blog/2023-2/2023-04-05-\ud2b8\ub79c\uc7ad\uc158\uacfc \uaca9\ub9ac\uc218\uc900.mdx",93546],be497a8d:[()=>n.e(6172).then(n.bind(n,45909)),"@site/blog/2023-2/2023-06-18-Docusaurus/2023-06-18-Docusaurus.mdx?truncated=true",45909],bf933b37:[()=>n.e(3095).then(n.t.bind(n,52954,19)),"~blog/default/tags-my-sql-46a-list.json",52954],c037d168:[()=>n.e(6587).then(n.t.bind(n,41235,19)),"~blog/default/tags-transaction-ea3-list.json",41235],c08e7a0d:[()=>n.e(7404).then(n.t.bind(n,27625,19)),"~docs/default/tag-docs-tags-throughput-8fc.json",27625],c0cb7215:[()=>n.e(7966).then(n.t.bind(n,66109,19)),"~blog/default/tags-book-page-2-bc6-list.json",66109],c189d18f:[()=>n.e(4962).then(n.t.bind(n,3470,19)),"~docs/default/tag-docs-tags-etc-c52.json",3470],c1b17b3f:[()=>n.e(8927).then(n.bind(n,29571)),"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md",29571],c29bedb9:[()=>n.e(9242).then(n.t.bind(n,44025,19)),"~blog/default/page-35-8fd.json",44025],c3ea66fe:[()=>n.e(6698).then(n.t.bind(n,63504,19)),"~blog/default/tags-isolation-79d.json",63504],c4f5d8e4:[()=>n.e(4195).then(n.bind(n,62841)),"@site/src/pages/index.js",62841],c55d205b:[()=>n.e(3438).then(n.bind(n,83859)),"@site/docs/Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4.mdx",83859],c573638f:[()=>n.e(964).then(n.t.bind(n,28866,19)),"~blog/default/tags-tags-c2b.json",28866],c6004f62:[()=>n.e(5892).then(n.t.bind(n,37567,19)),"~blog/default/tags-mock-330-list.json",37567],c60995f6:[()=>n.e(6199).then(n.t.bind(n,62474,19)),"~docs/default/tag-docs-tags-nginx-3b7.json",62474],c60ea0ff:[()=>n.e(3085).then(n.t.bind(n,14072,19)),"~blog/default/tags-teco-chat-page-2-d4f.json",14072],c6d04683:[()=>n.e(5436).then(n.bind(n,48905)),"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx",48905],c7015929:[()=>n.e(4185).then(n.t.bind(n,910,19)),"~blog/default/tags-python-687.json",910],c92f81ac:[()=>n.e(4393).then(n.t.bind(n,10767,19)),"~blog/default/tags-replication-56b-list.json",10767],caf1b628:[()=>n.e(7230).then(n.bind(n,16711)),"@site/docs/\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1.mdx",16711],cb6229c3:[()=>n.e(7204).then(n.bind(n,26930)),"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx",26930],cc3bdf2f:[()=>n.e(8817).then(n.t.bind(n,11135,19)),"~blog/default/tags-exception-644.json",11135],cc519f63:[()=>n.e(5323).then(n.bind(n,7771)),"@site/blog/2023-3/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604/2023-08-02-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \uad6c\ud604.mdx",7771],ccc49370:[()=>Promise.all([n.e(532),n.e(4659),n.e(6048),n.e(6103)]).then(n.bind(n,65203)),"@theme/BlogPostPage",65203],cd68cda1:[()=>n.e(8683).then(n.bind(n,66934)),"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx?truncated=true",66934],cef46b76:[()=>n.e(8644).then(n.bind(n,32390)),"@site/blog/2023-3/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c/2023-07-31-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ud30c\uc774\uc36c.mdx",32390],cf8e491a:[()=>n.e(5870).then(n.t.bind(n,19799,19)),"~blog/default/tags-awt-0e2.json",19799],d0277431:[()=>n.e(846).then(n.t.bind(n,4838,19)),"~blog/default/tags-dto-cb6-list.json",4838],d0840b01:[()=>n.e(8037).then(n.t.bind(n,20317,19)),"~blog/default/tags-transaction-ea3.json",20317],d09f7e4b:[()=>n.e(3098).then(n.t.bind(n,84057,19)),"~blog/default/tags-teco-chat-page-3-007-list.json",84057],d0e4cdf1:[()=>n.e(5465).then(n.t.bind(n,64020,19)),"~blog/default/page-7-3c3.json",64020],d126aabd:[()=>n.e(1675).then(n.t.bind(n,7220,19)),"~blog/default/tags-retrospective-page-4-3a3-list.json",7220],d1cef389:[()=>n.e(9310).then(n.t.bind(n,40836,19)),"~blog/default/page-17-62c.json",40836],d202e2c5:[()=>n.e(7175).then(n.t.bind(n,3395,19)),"~blog/default/tags-oop-03c-list.json",3395],d2611248:[()=>n.e(8561).then(n.t.bind(n,81667,19)),"~blog/default/page-43-b0a.json",81667],d2770bf7:[()=>n.e(843).then(n.t.bind(n,41156,19)),"~blog/default/tags-woowahan-techcourse-page-11-6c9.json",41156],d28e30d7:[()=>Promise.all([n.e(532),n.e(6671)]).then(n.bind(n,27464)),"@site/blog/2023-1/2023-01-16-Kotlin\uc5d0\uc11c null\uc744 \ub2e4\ub8e8\ub294 \ubc29\ubc95.mdx",27464],d2935d14:[()=>n.e(3259).then(n.t.bind(n,92158,19)),"~blog/default/tags-isolation-79d-list.json",92158],d361ad2d:[()=>n.e(2247).then(n.bind(n,40237)),"@site/docs/\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12.mdx",40237],d368e73e:[()=>n.e(7954).then(n.t.bind(n,71965,19)),"~blog/default/tags-image-97d-list.json",71965],d40f51e1:[()=>n.e(9633).then(n.t.bind(n,9415,19)),"~blog/default/tags-jdbc-4bd-list.json",9415],d50fd269:[()=>n.e(100).then(n.t.bind(n,38132,19)),"~blog/default/page-31-308.json",38132],d5bb232a:[()=>n.e(3651).then(n.bind(n,14345)),"@site/blog/2023-2/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30/2023-05-26-\ucef4\ud3ec\uc9c0\ud2b8 \ud328\ud134\uc73c\ub85c \uc694\uae08 \uc815\ucc45 \ucd94\uc0c1\ud654\ud558\uae30.mdx?truncated=true",14345],d5dfecc2:[()=>n.e(1677).then(n.t.bind(n,83335,19)),"~blog/default/tags-teco-chat-page-2-d4f-list.json",83335],d60e2b0c:[()=>n.e(8174).then(n.t.bind(n,36927,19)),"~blog/default/tags-retrospective-page-17-636-list.json",36927],d65e25b7:[()=>Promise.all([n.e(532),n.e(7776)]).then(n.bind(n,8e4)),"@site/blog/2023-3/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac/2023-08-13-\uacbd\ub85c \uc774\ubbf8\uc9c0 \uc0dd\uc131\ud558\uae30 - \ube44\ub3d9\uae30 \ucc98\ub9ac.mdx?truncated=true",8e4],d6a3d698:[()=>n.e(2890).then(n.t.bind(n,39477,19)),"~blog/default/tags-image-page-3-942.json",39477],d7955594:[()=>Promise.all([n.e(532),n.e(588)]).then(n.bind(n,89788)),"@site/blog/2023-2/2023-04-02-\ucee4\uc2a4\ud140 JdbcTemplate \ub9cc\ub4e4\uae30.mdx",89788],d86f7a37:[()=>n.e(3392).then(n.bind(n,10823)),"@site/docs/Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5.mdx",10823],d8775059:[()=>n.e(6387).then(n.bind(n,98809)),"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx",98809],d88bdb28:[()=>n.e(9788).then(n.t.bind(n,29417,19)),"~blog/default/tags-retrospective-page-13-49c.json",29417],d8cdf5ef:[()=>n.e(5919).then(n.bind(n,11311)),"@site/docs/\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8.mdx",11311],dab4c683:[()=>n.e(6058).then(n.t.bind(n,67315,19)),"~blog/default/tags-woowahan-techcourse-page-3-9a8.json",67315],daff1d93:[()=>n.e(1659).then(n.bind(n,26016)),"@site/blog/2023-2/2023-04-08-\uc0c1\uc790 \ubc16\uc5d0 \uc788\ub294 \uc0ac\ub78c.mdx?truncated=true",26016],db7928b3:[()=>n.e(5046).then(n.t.bind(n,11478,19)),"~blog/default/tags-intelli-j-2bf-list.json",11478],db86613e:[()=>n.e(9458).then(n.bind(n,58967)),"@site/blog/2023-2/2023-04-06-MySQL \uc5d4\uc9c4\uc758 \uc7a0\uae08.mdx?truncated=true",58967],dca6a1e3:[()=>n.e(3239).then(n.bind(n,52589)),"@site/blog/2023-2/2023-06-08-\ub808\ubca8 2 - \ub808\ubca8 \uc778\ud130\ubdf0 \ud68c\uace0.mdx?truncated=true",52589],dcf70953:[()=>n.e(1761).then(n.t.bind(n,83769,19)),"/home/runner/work/greeng00se.github.io/greeng00se.github.io/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",83769],ddf9e0bd:[()=>n.e(2542).then(n.t.bind(n,84039,19)),"~blog/default/tags-woowahan-techcourse-page-8-93a-list.json",84039],df147deb:[()=>n.e(5103).then(n.bind(n,78134)),"@site/blog/2023-1/2023-02-26-\uc0ac\ub2e4\ub9ac \ud0c0\uae30 \ubbf8\uc158 \ud68c\uace0.mdx?truncated=true",78134],df203c0f:[()=>n.e(9924).then(n.bind(n,40491)),"@theme/DocTagDocListPage",40491],df862072:[()=>n.e(7474).then(n.t.bind(n,24827,19)),"~blog/default/tags-book-page-3-a93.json",24827],dfa84138:[()=>n.e(1434).then(n.t.bind(n,22483,19)),"~blog/default/tags-data-base-page-3-9db-list.json",22483],dfc7013c:[()=>n.e(5857).then(n.bind(n,57515)),"@site/blog/2023-2/2023-04-03-\uc790\ubc14 \ud074\ub798\uc2a4\ud30c\uc77c \uad6c\uc870.mdx?truncated=true",57515],e073eb07:[()=>n.e(5819).then(n.t.bind(n,57743,19)),"~blog/default/tags-retrospective-page-11-e3c.json",57743],e0d68441:[()=>n.e(628).then(n.t.bind(n,75301,19)),"~blog/default/tags-retrospective-page-12-8cf-list.json",75301],e0e4666e:[()=>n.e(4665).then(n.t.bind(n,16482,19)),"~blog/default/tags-my-sql-46a.json",16482],e1735da7:[()=>n.e(1611).then(n.bind(n,9753)),"@site/blog/2023-2/2023-05-01-\ud14c\ucf54\ucc57 2. \ubc30\ud3ec.mdx?truncated=true",9753],e1a06456:[()=>n.e(9910).then(n.bind(n,34117)),"@site/blog/2023-2/2023-06-26-WebSocket.mdx",34117],e21c8cc4:[()=>n.e(6049).then(n.t.bind(n,48765,19)),"~blog/default/tags-retrospective-page-8-5ab.json",48765],e2326195:[()=>n.e(9467).then(n.bind(n,8169)),"@site/blog/2023-3/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac/2023-09-18-\ube44\ub3d9\uae30 \uc608\uc678 \ucc98\ub9ac.mdx",8169],e2de2dbb:[()=>n.e(6710).then(n.t.bind(n,47023,19)),"~blog/default/tags-java-page-5-b71.json",47023],e4ebfe18:[()=>n.e(9940).then(n.t.bind(n,57954,19)),"~blog/default/page-3-02e.json",57954],e6a6ed43:[()=>n.e(5300).then(n.bind(n,19463)),"@site/blog/2023-1/2023-03-30-GRASP.mdx?truncated=true",19463],e7d2a655:[()=>n.e(8652).then(n.t.bind(n,71501,19)),"~blog/default/tags-woowahan-techcourse-page-2-567-list.json",71501],e8d6e7ce:[()=>n.e(3912).then(n.t.bind(n,65245,19)),"~blog/default/tags-retrospective-page-6-594.json",65245],e9624b4f:[()=>n.e(4564).then(n.t.bind(n,11780,19)),"~blog/default/tags-retrospective-page-13-49c-list.json",11780],e9eabc5d:[()=>n.e(1112).then(n.bind(n,778)),"@site/blog/2023-1/2023-03-30-GRASP.mdx",778],e9ff60ad:[()=>n.e(2530).then(n.t.bind(n,10242,19)),"~blog/default/tags-pattern-b4e-list.json",10242],ee1dd2ad:[()=>n.e(5435).then(n.t.bind(n,48834,19)),"~blog/default/tags-woowahan-techcourse-page-13-8ae.json",48834],ee92877e:[()=>n.e(8716).then(n.t.bind(n,41106,19)),"~blog/default/tags-retrospective-page-5-22d.json",41106],eec33099:[()=>n.e(4953).then(n.t.bind(n,80133,19)),"~blog/default/page-40-397.json",80133],ef5b2427:[()=>n.e(9606).then(n.t.bind(n,50195,19)),"~blog/default/page-22-f33.json",50195],eff1d58f:[()=>n.e(4137).then(n.bind(n,93097)),"@site/blog/2023-2/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30/2023-04-22-\ud14c\ucf54\ucc57 1. \ud504\ub85c\ud1a0\ud0c0\uc785 \ub9cc\ub4e4\uae30.mdx?truncated=true",93097],f042b56c:[()=>n.e(8919).then(n.t.bind(n,27490,19)),"~blog/default/tags-teco-chat-d21-list.json",27490],f06cb3e2:[()=>Promise.all([n.e(532),n.e(2620)]).then(n.bind(n,7729)),"@site/blog/2023-3/2023-08-22-DB \ubcf5\uc81c, @Transactional\uc5d0 \ub530\ub77c \uc694\uccad \ubd84\ub9ac\ud574\ubcf4\uae30.mdx",7729],f078e301:[()=>n.e(1926).then(n.t.bind(n,18385,19)),"~blog/default/tags-woowahan-techcourse-page-6-429-list.json",18385],f0978ee1:[()=>n.e(7740).then(n.t.bind(n,69366,19)),"~blog/default/tags-awt-page-2-eb4.json",69366],f156dfb9:[()=>n.e(5602).then(n.t.bind(n,83311,19)),"~blog/default/tags-time-471.json",83311],f25de701:[()=>n.e(2245).then(n.bind(n,87875)),"@site/blog/2023-3/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131/2023-08-17-CloudWatch\ub97c \uc774\uc6a9\ud55c \ub85c\uae45, \uba54\ud2b8\ub9ad \ubaa8\ub2c8\ud130\ub9c1 \ud658\uacbd \uad6c\uc131.md?truncated=true",87875],f332d221:[()=>n.e(2717).then(n.t.bind(n,99371,19)),"~blog/default/page-10-857.json",99371],f3e308ad:[()=>n.e(6123).then(n.t.bind(n,16240,19)),"~blog/default/page-33-758.json",16240],f4c6e7e6:[()=>n.e(31).then(n.t.bind(n,77922,19)),"~docs/default/tag-docs-tags-book-8e4.json",77922],f4f49e13:[()=>n.e(6887).then(n.t.bind(n,26329,19)),"~blog/default/page-12-b6a.json",26329],f580a9d0:[()=>n.e(9887).then(n.t.bind(n,78989,19)),"~blog/default/tags-python-687-list.json",78989],f63a747b:[()=>n.e(5131).then(n.t.bind(n,81723,19)),"~blog/default/tags-woowahan-techcourse-page-7-5bd.json",81723],f75a8651:[()=>n.e(8882).then(n.t.bind(n,44633,19)),"~blog/default/page-8-8c2.json",44633],f7b9d2f4:[()=>n.e(2958).then(n.t.bind(n,53122,19)),"~blog/default/tags-woowahan-techcourse-page-12-5ba.json",53122],f8409a7e:[()=>n.e(3206).then(n.bind(n,69568)),"@site/docs/intro.mdx",69568],f87bdf62:[()=>n.e(6750).then(n.bind(n,19426)),"@site/blog/2023-2/2023-06-26-WebSocket.mdx?truncated=true",19426],f90d0c52:[()=>n.e(5294).then(n.bind(n,85749)),"@site/blog/2023-1/2023-01-07-\uac1d\uccb4\uc9c0\ud5a5\uc758 \uc0ac\uc2e4\uacfc \uc624\ud574.mdx",85749],fa3d3942:[()=>n.e(916).then(n.bind(n,53036)),"@site/blog/2023-1/2023-01-01-\uae00, \uc6b0\ub9ac\ub3c4 \uc798 \uc4f8 \uc218 \uc788\uc2b5\ub2c8\ub2e4.mdx",53036],fbd57548:[()=>n.e(6837).then(n.t.bind(n,30990,19)),"~blog/default/page-11-f65.json",30990],fcb446a5:[()=>n.e(3440).then(n.bind(n,84425)),"@site/docs/\ub9ac\ub205\uc2a4/\ud130\ubbf8\ub110_\uc258_\ud504\ub86c\ud504\ud2b8_\uc124\uc815.md",84425],fd5d2408:[()=>n.e(3614).then(n.t.bind(n,64631,19)),"~blog/default/tags-time-471-list.json",64631],fe273484:[()=>n.e(8355).then(n.t.bind(n,53034,19)),"~blog/default/tags-java-a6e-list.json",53034],fe8cce0a:[()=>n.e(955).then(n.t.bind(n,78535,19)),"~blog/default/tags-intelli-j-2bf.json",78535],fed8bc04:[()=>n.e(8110).then(n.t.bind(n,96375,19)),"~blog/default/tags-woowahan-techcourse-page-5-ac5.json",96375],ff4c6c5e:[()=>n.e(820).then(n.bind(n,23856)),"@site/blog/2023-3/2023-07-24-\uc790\ubc14 17, \uc2a4\ud504\ub9c1 6.0, \uc2a4\ud504\ub9c1 \ubd80\ud2b8 3.1.mdx",23856],ffb0fa11:[()=>n.e(7400).then(n.t.bind(n,58214,19)),"~blog/default/tags-book-page-3-a93-list.json",58214]};function c(e){let{error:t,retry:n,pastDelay:r}=e;return t?a.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},a.createElement("p",null,String(t)),a.createElement("div",null,a.createElement("button",{type:"button",onClick:n},"Retry"))):r?a.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},a.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},a.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},a.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},a.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),a.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},a.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),a.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),a.createElement("circle",{cx:"22",cy:"22",r:"8"},a.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(99670),d=n(30226);function f(e,t){if("*"===e)return i()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return a.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},a.createElement(n,t))}});const o=s[`${e}-${t}`],f={},p=[],g=[],m=(0,u.Z)(o);return Object.entries(m).forEach((e=>{let[t,n]=e;const a=l[n];a&&(f[t]=a[0],p.push(a[1]),g.push(a[2]))})),i().Map({loading:c,loader:f,modules:p,webpack:()=>g,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,a]=t;const r=a.default;if(!r)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof r&&"function"!=typeof r||Object.keys(a).filter((e=>"default"!==e)).forEach((e=>{r[e]=a[e]}));let o=i;const s=n.split(".");s.slice(0,-1).forEach((e=>{o=o[e]})),o[s[s.length-1]]=r}));const s=i.__comp;delete i.__comp;const l=i.__context;return delete i.__context,a.createElement(d.z,{value:l},a.createElement(s,(0,r.Z)({},i,n)))}})}const p=[{path:"/2022-retrospective",component:f("/2022-retrospective","624"),exact:!0},{path:"/accidental-duplication",component:f("/accidental-duplication","d17"),exact:!0},{path:"/async-exception",component:f("/async-exception","b15"),exact:!0},{path:"/blackjack-retrospective",component:f("/blackjack-retrospective","595"),exact:!0},{path:"/blog",component:f("/blog","3d8"),exact:!0},{path:"/book-leadership-and-self-deception",component:f("/book-leadership-and-self-deception","ddd"),exact:!0},{path:"/book-writer",component:f("/book-writer","3c9"),exact:!0},{path:"/chess-retrospective",component:f("/chess-retrospective","168"),exact:!0},{path:"/cloudwatch",component:f("/cloudwatch","cb1"),exact:!0},{path:"/composite",component:f("/composite","302"),exact:!0},{path:"/custom-jdbc-template",component:f("/custom-jdbc-template","cfa"),exact:!0},{path:"/db-replication",component:f("/db-replication","6f2"),exact:!0},{path:"/docs/tags",component:f("/docs/tags","820"),exact:!0},{path:"/docs/tags/book",component:f("/docs/tags/book","c20"),exact:!0},{path:"/docs/tags/etc",component:f("/docs/tags/etc","338"),exact:!0},{path:"/docs/tags/jpa",component:f("/docs/tags/jpa","f95"),exact:!0},{path:"/docs/tags/latency",component:f("/docs/tags/latency","e82"),exact:!0},{path:"/docs/tags/load-balancing",component:f("/docs/tags/load-balancing","0be"),exact:!0},{path:"/docs/tags/monitoring",component:f("/docs/tags/monitoring","50f"),exact:!0},{path:"/docs/tags/network",component:f("/docs/tags/network","322"),exact:!0},{path:"/docs/tags/nginx",component:f("/docs/tags/nginx","ecc"),exact:!0},{path:"/docs/tags/package",component:f("/docs/tags/package","593"),exact:!0},{path:"/docs/tags/performance",component:f("/docs/tags/performance","a3d"),exact:!0},{path:"/docs/tags/postmortem",component:f("/docs/tags/postmortem","4b0"),exact:!0},{path:"/docs/tags/test",component:f("/docs/tags/test","b58"),exact:!0},{path:"/docs/tags/throughput",component:f("/docs/tags/throughput","206"),exact:!0},{path:"/docusaurus",component:f("/docusaurus","926"),exact:!0},{path:"/grasp",component:f("/grasp","f9b"),exact:!0},{path:"/innodb-lock",component:f("/innodb-lock","d18"),exact:!0},{path:"/intellij-settings",component:f("/intellij-settings","80e"),exact:!0},{path:"/java-class-file",component:f("/java-class-file","50e"),exact:!0},{path:"/java-spring-springboot",component:f("/java-spring-springboot","bed"),exact:!0},{path:"/jenkins",component:f("/jenkins","48c"),exact:!0},{path:"/jsr-310",component:f("/jsr-310","7f9"),exact:!0},{path:"/kotlin-null",component:f("/kotlin-null","8d3"),exact:!0},{path:"/ladder-retrospective",component:f("/ladder-retrospective","7ea"),exact:!0},{path:"/level2-interview-retrospective",component:f("/level2-interview-retrospective","c75"),exact:!0},{path:"/mock-static-method",component:f("/mock-static-method","fd3"),exact:!0},{path:"/mysql-lock",component:f("/mysql-lock","3cb"),exact:!0},{path:"/order-retrospective",component:f("/order-retrospective","a11"),exact:!0},{path:"/page/10",component:f("/page/10","ef7"),exact:!0},{path:"/page/11",component:f("/page/11","f4d"),exact:!0},{path:"/page/12",component:f("/page/12","eea"),exact:!0},{path:"/page/13",component:f("/page/13","de0"),exact:!0},{path:"/page/14",component:f("/page/14","991"),exact:!0},{path:"/page/15",component:f("/page/15","35b"),exact:!0},{path:"/page/16",component:f("/page/16","b84"),exact:!0},{path:"/page/17",component:f("/page/17","af4"),exact:!0},{path:"/page/18",component:f("/page/18","5bf"),exact:!0},{path:"/page/19",component:f("/page/19","20a"),exact:!0},{path:"/page/2",component:f("/page/2","6af"),exact:!0},{path:"/page/20",component:f("/page/20","a50"),exact:!0},{path:"/page/21",component:f("/page/21","6fc"),exact:!0},{path:"/page/22",component:f("/page/22","c19"),exact:!0},{path:"/page/23",component:f("/page/23","a5d"),exact:!0},{path:"/page/24",component:f("/page/24","c12"),exact:!0},{path:"/page/25",component:f("/page/25","a83"),exact:!0},{path:"/page/26",component:f("/page/26","e6f"),exact:!0},{path:"/page/27",component:f("/page/27","296"),exact:!0},{path:"/page/28",component:f("/page/28","ecc"),exact:!0},{path:"/page/29",component:f("/page/29","59e"),exact:!0},{path:"/page/3",component:f("/page/3","9bb"),exact:!0},{path:"/page/30",component:f("/page/30","a7d"),exact:!0},{path:"/page/31",component:f("/page/31","e44"),exact:!0},{path:"/page/32",component:f("/page/32","f99"),exact:!0},{path:"/page/33",component:f("/page/33","018"),exact:!0},{path:"/page/34",component:f("/page/34","362"),exact:!0},{path:"/page/35",component:f("/page/35","1b5"),exact:!0},{path:"/page/36",component:f("/page/36","8c4"),exact:!0},{path:"/page/37",component:f("/page/37","cf2"),exact:!0},{path:"/page/38",component:f("/page/38","21d"),exact:!0},{path:"/page/39",component:f("/page/39","2a8"),exact:!0},{path:"/page/4",component:f("/page/4","c46"),exact:!0},{path:"/page/40",component:f("/page/40","021"),exact:!0},{path:"/page/41",component:f("/page/41","e8b"),exact:!0},{path:"/page/42",component:f("/page/42","709"),exact:!0},{path:"/page/43",component:f("/page/43","4ad"),exact:!0},{path:"/page/44",component:f("/page/44","bed"),exact:!0},{path:"/page/45",component:f("/page/45","622"),exact:!0},{path:"/page/46",component:f("/page/46","30a"),exact:!0},{path:"/page/5",component:f("/page/5","1f8"),exact:!0},{path:"/page/6",component:f("/page/6","840"),exact:!0},{path:"/page/7",component:f("/page/7","136"),exact:!0},{path:"/page/8",component:f("/page/8","bd3"),exact:!0},{path:"/page/9",component:f("/page/9","90d"),exact:!0},{path:"/parameterized-tests",component:f("/parameterized-tests","1fb"),exact:!0},{path:"/performance-test-type",component:f("/performance-test-type","df3"),exact:!0},{path:"/racing-car-retrospective",component:f("/racing-car-retrospective","ebc"),exact:!0},{path:"/route-image-async-with-event",component:f("/route-image-async-with-event","832"),exact:!0},{path:"/route-image-implementation",component:f("/route-image-implementation","b0f"),exact:!0},{path:"/route-image-intro",component:f("/route-image-intro","7e7"),exact:!0},{path:"/route-image-python",component:f("/route-image-python","dfd"),exact:!0},{path:"/search",component:f("/search","c1e"),exact:!0},{path:"/shopping-cart-retrospective",component:f("/shopping-cart-retrospective","28b"),exact:!0},{path:"/subway-retrospective",component:f("/subway-retrospective","7db"),exact:!0},{path:"/tags",component:f("/tags","4bf"),exact:!0},{path:"/tags/async",component:f("/tags/async","a21"),exact:!0},{path:"/tags/async/page/2",component:f("/tags/async/page/2","436"),exact:!0},{path:"/tags/awt",component:f("/tags/awt","9e3"),exact:!0},{path:"/tags/awt/page/2",component:f("/tags/awt/page/2","b68"),exact:!0},{path:"/tags/book",component:f("/tags/book","4df"),exact:!0},{path:"/tags/book/page/2",component:f("/tags/book/page/2","88a"),exact:!0},{path:"/tags/book/page/3",component:f("/tags/book/page/3","128"),exact:!0},{path:"/tags/class",component:f("/tags/class","d3d"),exact:!0},{path:"/tags/cloudwatch",component:f("/tags/cloudwatch","264"),exact:!0},{path:"/tags/composite",component:f("/tags/composite","931"),exact:!0},{path:"/tags/data-base",component:f("/tags/data-base","2fe"),exact:!0},{path:"/tags/data-base/page/2",component:f("/tags/data-base/page/2","049"),exact:!0},{path:"/tags/data-base/page/3",component:f("/tags/data-base/page/3","9ac"),exact:!0},{path:"/tags/documentation",component:f("/tags/documentation","86d"),exact:!0},{path:"/tags/dto",component:f("/tags/dto","bef"),exact:!0},{path:"/tags/elastic-beanstalk",component:f("/tags/elastic-beanstalk","164"),exact:!0},{path:"/tags/event",component:f("/tags/event","56a"),exact:!0},{path:"/tags/exception",component:f("/tags/exception","5b1"),exact:!0},{path:"/tags/grasp",component:f("/tags/grasp","130"),exact:!0},{path:"/tags/image",component:f("/tags/image","067"),exact:!0},{path:"/tags/image/page/2",component:f("/tags/image/page/2","88a"),exact:!0},{path:"/tags/image/page/3",component:f("/tags/image/page/3","acc"),exact:!0},{path:"/tags/inno-db",component:f("/tags/inno-db","2aa"),exact:!0},{path:"/tags/intelli-j",component:f("/tags/intelli-j","aaa"),exact:!0},{path:"/tags/isolation",component:f("/tags/isolation","bab"),exact:!0},{path:"/tags/java",component:f("/tags/java","60d"),exact:!0},{path:"/tags/java/page/2",component:f("/tags/java/page/2","d9f"),exact:!0},{path:"/tags/java/page/3",component:f("/tags/java/page/3","d2c"),exact:!0},{path:"/tags/java/page/4",component:f("/tags/java/page/4","c97"),exact:!0},{path:"/tags/java/page/5",component:f("/tags/java/page/5","6c7"),exact:!0},{path:"/tags/jdbc",component:f("/tags/jdbc","667"),exact:!0},{path:"/tags/jenkins",component:f("/tags/jenkins","590"),exact:!0},{path:"/tags/kotlin",component:f("/tags/kotlin","b84"),exact:!0},{path:"/tags/lock",component:f("/tags/lock","059"),exact:!0},{path:"/tags/lock/page/2",component:f("/tags/lock/page/2","2e3"),exact:!0},{path:"/tags/log",component:f("/tags/log","0ae"),exact:!0},{path:"/tags/mock",component:f("/tags/mock","9dd"),exact:!0},{path:"/tags/mockito",component:f("/tags/mockito","3de"),exact:!0},{path:"/tags/monitoring",component:f("/tags/monitoring","775"),exact:!0},{path:"/tags/my-sql",component:f("/tags/my-sql","214"),exact:!0},{path:"/tags/mysql",component:f("/tags/mysql","79d"),exact:!0},{path:"/tags/oop",component:f("/tags/oop","613"),exact:!0},{path:"/tags/pattern",component:f("/tags/pattern","5e4"),exact:!0},{path:"/tags/performance-test",component:f("/tags/performance-test","d3e"),exact:!0},{path:"/tags/python",component:f("/tags/python","7fe"),exact:!0},{path:"/tags/replication",component:f("/tags/replication","77b"),exact:!0},{path:"/tags/retrospective",component:f("/tags/retrospective","69e"),exact:!0},{path:"/tags/retrospective/page/10",component:f("/tags/retrospective/page/10","927"),exact:!0},{path:"/tags/retrospective/page/11",component:f("/tags/retrospective/page/11","792"),exact:!0},{path:"/tags/retrospective/page/12",component:f("/tags/retrospective/page/12","3a2"),exact:!0},{path:"/tags/retrospective/page/13",component:f("/tags/retrospective/page/13","21d"),exact:!0},{path:"/tags/retrospective/page/14",component:f("/tags/retrospective/page/14","178"),exact:!0},{path:"/tags/retrospective/page/15",component:f("/tags/retrospective/page/15","9bb"),exact:!0},{path:"/tags/retrospective/page/16",component:f("/tags/retrospective/page/16","0ea"),exact:!0},{path:"/tags/retrospective/page/17",component:f("/tags/retrospective/page/17","624"),exact:!0},{path:"/tags/retrospective/page/2",component:f("/tags/retrospective/page/2","599"),exact:!0},{path:"/tags/retrospective/page/3",component:f("/tags/retrospective/page/3","b13"),exact:!0},{path:"/tags/retrospective/page/4",component:f("/tags/retrospective/page/4","825"),exact:!0},{path:"/tags/retrospective/page/5",component:f("/tags/retrospective/page/5","f9f"),exact:!0},{path:"/tags/retrospective/page/6",component:f("/tags/retrospective/page/6","5ea"),exact:!0},{path:"/tags/retrospective/page/7",component:f("/tags/retrospective/page/7","21e"),exact:!0},{path:"/tags/retrospective/page/8",component:f("/tags/retrospective/page/8","520"),exact:!0},{path:"/tags/retrospective/page/9",component:f("/tags/retrospective/page/9","24d"),exact:!0},{path:"/tags/spring",component:f("/tags/spring","ab2"),exact:!0},{path:"/tags/spring-boot",component:f("/tags/spring-boot","eb7"),exact:!0},{path:"/tags/static",component:f("/tags/static","dd5"),exact:!0},{path:"/tags/teco-chat",component:f("/tags/teco-chat","7a9"),exact:!0},{path:"/tags/teco-chat/page/2",component:f("/tags/teco-chat/page/2","fbf"),exact:!0},{path:"/tags/teco-chat/page/3",component:f("/tags/teco-chat/page/3","c3d"),exact:!0},{path:"/tags/test",component:f("/tags/test","902"),exact:!0},{path:"/tags/time",component:f("/tags/time","f3d"),exact:!0},{path:"/tags/transaction",component:f("/tags/transaction","622"),exact:!0},{path:"/tags/web-socket",component:f("/tags/web-socket","e59"),exact:!0},{path:"/tags/woowahan-techcourse",component:f("/tags/woowahan-techcourse","03d"),exact:!0},{path:"/tags/woowahan-techcourse/page/10",component:f("/tags/woowahan-techcourse/page/10","294"),exact:!0},{path:"/tags/woowahan-techcourse/page/11",component:f("/tags/woowahan-techcourse/page/11","3b7"),exact:!0},{path:"/tags/woowahan-techcourse/page/12",component:f("/tags/woowahan-techcourse/page/12","490"),exact:!0},{path:"/tags/woowahan-techcourse/page/13",component:f("/tags/woowahan-techcourse/page/13","827"),exact:!0},{path:"/tags/woowahan-techcourse/page/2",component:f("/tags/woowahan-techcourse/page/2","901"),exact:!0},{path:"/tags/woowahan-techcourse/page/3",component:f("/tags/woowahan-techcourse/page/3","3cd"),exact:!0},{path:"/tags/woowahan-techcourse/page/4",component:f("/tags/woowahan-techcourse/page/4","8f1"),exact:!0},{path:"/tags/woowahan-techcourse/page/5",component:f("/tags/woowahan-techcourse/page/5","295"),exact:!0},{path:"/tags/woowahan-techcourse/page/6",component:f("/tags/woowahan-techcourse/page/6","89a"),exact:!0},{path:"/tags/woowahan-techcourse/page/7",component:f("/tags/woowahan-techcourse/page/7","fa8"),exact:!0},{path:"/tags/woowahan-techcourse/page/8",component:f("/tags/woowahan-techcourse/page/8","1fb"),exact:!0},{path:"/tags/woowahan-techcourse/page/9",component:f("/tags/woowahan-techcourse/page/9","2ae"),exact:!0},{path:"/tecochat-retrospective-1",component:f("/tecochat-retrospective-1","ed9"),exact:!0},{path:"/tecochat-retrospective-2",component:f("/tecochat-retrospective-2","fc4"),exact:!0},{path:"/tecochat-retrospective-3",component:f("/tecochat-retrospective-3","6f4"),exact:!0},{path:"/test-double",component:f("/test-double","8ea"),exact:!0},{path:"/the-essence-of-object-orientation",component:f("/the-essence-of-object-orientation","9a2"),exact:!0},{path:"/tomcat-retrospective",component:f("/tomcat-retrospective","5a3"),exact:!0},{path:"/transaction-and-isolation",component:f("/transaction-and-isolation","d60"),exact:!0},{path:"/web-racing-car-retrospective",component:f("/web-racing-car-retrospective","ccb"),exact:!0},{path:"/websocket",component:f("/websocket","5c1"),exact:!0},{path:"/woowacourse-level1-retrospective",component:f("/woowacourse-level1-retrospective","a6a"),exact:!0},{path:"/woowacourse-level2-retrospective",component:f("/woowacourse-level2-retrospective","758"),exact:!0},{path:"/woowacourse-level3-retrospective",component:f("/woowacourse-level3-retrospective","4e5"),exact:!0},{path:"/docs",component:f("/docs","5fb"),routes:[{path:"/docs",component:f("/docs","818"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/book/getting-out-of-the-box",component:f("/docs/book/getting-out-of-the-box","e0f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/culture/postmortem",component:f("/docs/culture/postmortem","b2f"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/design/package",component:f("/docs/design/package","274"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/communication",component:f("/docs/etc/communication","9c1"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/develop-with-spring",component:f("/docs/etc/develop-with-spring","9ab"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/experience-and-self-question",component:f("/docs/etc/experience-and-self-question","d25"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/etc/healthful-growth",component:f("/docs/etc/healthful-growth","b7b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/jpa/key",component:f("/docs/jpa/key","fed"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/linux/shell",component:f("/docs/linux/shell","a10"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/linux/swap",component:f("/docs/linux/swap","8f5"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/monitoring/intro",component:f("/docs/monitoring/intro","66d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/network/load-balancing",component:f("/docs/network/load-balancing","caa"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/network/load-balancing-algorithm",component:f("/docs/network/load-balancing-algorithm","a4d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nginx/command",component:f("/docs/nginx/command","0e3"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/nginx/static-file",component:f("/docs/nginx/static-file","629"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/performance/throughput",component:f("/docs/performance/throughput","56a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/performance/throughput-latency",component:f("/docs/performance/throughput-latency","12a"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/performance/types",component:f("/docs/performance/types","c08"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/benefit",component:f("/docs/test/benefit","163"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/first",component:f("/docs/test/first","566"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/heuristics",component:f("/docs/test/heuristics","a1d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/docs/test/stairstep",component:f("/docs/test/stairstep","364"),exact:!0,sidebar:"tutorialSidebar"}]},{path:"/",component:f("/","3ce"),exact:!0},{path:"/",component:f("/","b6d"),exact:!0},{path:"*",component:f("*")}]},98934:(e,t,n)=>{"use strict";n.d(t,{_:()=>r,t:()=>o});var a=n(67294);const r=a.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{o(!0)}),[]),a.createElement(r.Provider,{value:n},t)}},49383:(e,t,n)=>{"use strict";var a=n(67294),r=n(73935),o=n(73727),i=n(70405),s=n(10412);const l=[n(56657),n(32497),n(3310),n(18320),n(52295)];var c=n(723),u=n(16550),d=n(18790);function f(e){let{children:t}=e;return a.createElement(a.Fragment,null,t)}var p=n(87462),g=n(35742),m=n(52263),h=n(44996),b=n(86668),v=n(10833),y=n(94711),w=n(19727),_=n(43320),k=n(90197);function x(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,m.Z)(),n=(0,y.l)();return a.createElement(g.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:r}]=e;return a.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:r})})),a.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,m.Z)(),r=function(){const{siteConfig:{url:e}}=(0,m.Z)(),{pathname:t}=(0,u.TH)();return e+(0,h.Z)(t)}(),o=t?`${n}${t}`:r;return a.createElement(g.Z,null,a.createElement("meta",{property:"og:url",content:o}),a.createElement("link",{rel:"canonical",href:o}))}function S(){const{i18n:{currentLocale:e}}=(0,m.Z)(),{metadata:t,image:n}=(0,b.L)();return a.createElement(a.Fragment,null,a.createElement(g.Z,null,a.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),a.createElement("body",{className:w.h})),n&&a.createElement(v.d,{image:n}),a.createElement(E,null),a.createElement(x,null),a.createElement(k.Z,{tag:_.HX,locale:e}),a.createElement(g.Z,null,t.map(((e,t)=>a.createElement("meta",(0,p.Z)({key:t},e))))))}const T=new Map;function C(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var A=n(98934),L=n(58940);function P(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),a=1;a(t.default?.[e]??t[e])?.(...n)));return()=>r.forEach((e=>e?.()))}const N=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,a.useLayoutEffect)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const a=t.pathname===n.pathname,r=t.hash===n.hash,o=t.search===n.search;if(a&&r&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1));document.getElementById(e)?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),P("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class R extends a.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?P("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=P("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return a.createElement(N,{previousLocation:this.previousLocation,location:t},a.createElement(u.AW,{location:t,render:()=>e}))}}const M=R,I="docusaurus-base-url-issue-banner-container",j="docusaurus-base-url-issue-banner-suggestion-container",D="__DOCUSAURUS_INSERT_BASEURL_BANNER";function B(e){return`\nwindow['${D}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${D}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${I}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{window[D]=!1}),[]),a.createElement(a.Fragment,null,!s.Z.canUseDOM&&a.createElement(g.Z,null,a.createElement("script",null,B(e))),a.createElement("div",{id:I}))}function $(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,m.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?a.createElement(F,null):null}function U(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:o}}=(0,m.Z)(),i=(0,h.Z)(e),{htmlLang:s,direction:l}=o[r];return a.createElement(g.Z,null,a.createElement("html",{lang:s,dir:l}),a.createElement("title",null,t),a.createElement("meta",{property:"og:title",content:t}),a.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&a.createElement("link",{rel:"icon",href:i}))}var z=n(44763);function Z(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return a.createElement(z.Z,null,a.createElement(L.M,null,a.createElement(A.t,null,a.createElement(f,null,a.createElement(U,null),a.createElement(S,null),a.createElement($,null),a.createElement(M,{location:C(t)},e)))))}var H=n(16887);const V=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const a=document.createElement("link");a.setAttribute("rel","prefetch"),a.setAttribute("href",e),a.onload=()=>t(),a.onerror=()=>n();(document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode)?.appendChild(a)}))}:function(e){return new Promise(((t,n)=>{const a=new XMLHttpRequest;a.open("GET",e,!0),a.withCredentials=!0,a.onload=()=>{200===a.status?t():n()},a.send(null)}))};var W=n(99670);const G=new Set,q=new Set,K=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,Y={prefetch(e){if(!(e=>!K()&&!q.has(e)&&!G.has(e))(e))return!1;G.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(H).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,W.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?V(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!K()&&!q.has(e))(e)&&(q.add(e),O(e))},Q=Object.freeze(Y);if(s.Z.canUseDOM){window.docusaurus=Q;const e=r.hydrate;O(window.location.pathname).then((()=>{e(a.createElement(i.B6,null,a.createElement(o.VK,null,a.createElement(Z,null))),document.getElementById("__docusaurus"))}))}},58940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var a=n(67294),r=n(36809);const o=JSON.parse('{"docusaurus-plugin-google-gtag":{"default":{"trackingID":"G-17TREGCW4H","anonymizeIP":true,"id":"default"}},"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"intro","docs":[{"id":"intro","path":"/docs/","sidebar":"tutorialSidebar"},{"id":"JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551","path":"/docs/jpa/key","sidebar":"tutorialSidebar"},{"id":"Nginx/\uad6c\uc870_\ubc0f_\uba85\ub839\uc5b4","path":"/docs/nginx/command","sidebar":"tutorialSidebar"},{"id":"Nginx/\uc815\uc801_\ucee8\ud150\uce20_\uc81c\uacf5","path":"/docs/nginx/static-file","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\uac74\uac15\ud558\uac8c_\ub098\uc544\uc9c0\uae30","path":"/docs/etc/healthful-growth","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\uc2a4\ud504\ub9c1\uacfc \ud568\uaed8 \ub354 \ub098\uc740 \uac1c\ubc1c\uc790 \ub418\uae30","path":"/docs/etc/develop-with-spring","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\uc790\uae30 \uc8fc\ub3c4\uc801\uc73c\ub85c \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud55c \ub3c4\uc804 \uacbd\ud5d8","path":"/docs/etc/experience-and-self-question","sidebar":"tutorialSidebar"},{"id":"\uae30\ud0c0/\ucee4\ubba4\ub2c8\ucf00\uc774\uc158 \uc798\ud558\ub294 \uac1c\ubc1c\uc790\uc758 4\uac00\uc9c0 \uc2b5\uad00","path":"/docs/etc/communication","sidebar":"tutorialSidebar"},{"id":"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1","path":"/docs/network/load-balancing","sidebar":"tutorialSidebar"},{"id":"\ub124\ud2b8\uc6cc\ud06c/\ub85c\ub4dc \ubc38\ub7f0\uc2f1 \uc54c\uace0\ub9ac\uc998","path":"/docs/network/load-balancing-algorithm","sidebar":"tutorialSidebar"},{"id":"\ub3c4\uc11c/\uc0c1\uc790_\ubc16\uc73c\ub85c_\ud0c8\ucd9c\ud558\uae30","path":"/docs/book/getting-out-of-the-box","sidebar":"tutorialSidebar"},{"id":"\ub9ac\ub205\uc2a4/Swap_\uba54\ubaa8\ub9ac_\uc124\uc815","path":"/docs/linux/swap","sidebar":"tutorialSidebar"},{"id":"\ub9ac\ub205\uc2a4/\ud130\ubbf8\ub110_\uc258_\ud504\ub86c\ud504\ud2b8_\uc124\uc815","path":"/docs/linux/shell","sidebar":"tutorialSidebar"},{"id":"\ubaa8\ub2c8\ud130\ub9c1/\ubaa8\ub2c8\ud130\ub9c1_\ud658\uacbd_\uad6c\uc131","path":"/docs/monitoring/intro","sidebar":"tutorialSidebar"},{"id":"\ubb38\ud654/\ud3ec\uc2a4\ud2b8_\ubaa8\ud15c","path":"/docs/culture/postmortem","sidebar":"tutorialSidebar"},{"id":"\uc124\uacc4/\ud328\ud0a4\uc9c0","path":"/docs/design/package","sidebar":"tutorialSidebar"},{"id":"\uc131\ub2a5/Throughput \ubaa9\ud46f\uac12","path":"/docs/performance/throughput","sidebar":"tutorialSidebar"},{"id":"\uc131\ub2a5/Throughput\uacfc Latency","path":"/docs/performance/throughput-latency","sidebar":"tutorialSidebar"},{"id":"\uc131\ub2a5/\uc131\ub2a5 \ud14c\uc2a4\ud2b8","path":"/docs/performance/types","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/FIRST","path":"/docs/test/first","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/\uacc4\ub2e8_\ud14c\uc2a4\ud2b8","path":"/docs/test/stairstep","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\uc8fc\ub3c4_\uac1c\ubc1c_\uaddc\uce59","path":"/docs/test/heuristics","sidebar":"tutorialSidebar"},{"id":"\ud14c\uc2a4\ud2b8/\ud14c\uc2a4\ud2b8_\ucf54\ub4dc\uac00_\uc8fc\ub294_\ud61c\ud0dd","path":"/docs/test/benefit","sidebar":"tutorialSidebar"}],"draftIds":[],"sidebars":{"tutorialSidebar":{"link":{"path":"/docs/jpa/key","label":"JPA/\uae30\ubcf8_\ud0a4_\ub9e4\ud551"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"ko","locales":["ko"],"path":"i18n","currentLocale":"ko","localeConfigs":{"ko":{"label":"\ud55c\uad6d\uc5b4","direction":"ltr","htmlLang":"ko","calendar":"gregory","path":"ko"}}}');var s=n(57529);const l=JSON.parse('{"docusaurusVersion":"2.3.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.3.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.3.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.3.0"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"2.3.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.3.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.3.0"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"2.3.0"},"docusaurus-theme-mermaid":{"type":"package","name":"@docusaurus/theme-mermaid","version":"2.3.0"}}}'),c={siteConfig:r.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},u=a.createContext(c);function d(e){let{children:t}=e;return a.createElement(u.Provider,{value:c},t)}},44763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var a=n(67294),r=n(10412),o=n(35742),i=n(54774);function s(e){let{error:t,tryAgain:n}=e;return a.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",height:"50vh",width:"100%",fontSize:"20px"}},a.createElement("h1",null,"This page crashed."),a.createElement("p",null,t.message),a.createElement("button",{type:"button",onClick:n},"Try again"))}function l(e){let{error:t,tryAgain:n}=e;return a.createElement(u,{fallback:()=>a.createElement(s,{error:t,tryAgain:n})},a.createElement(o.Z,null,a.createElement("title",null,"Page Error")),a.createElement(i.Z,null,a.createElement(s,{error:t,tryAgain:n})))}const c=e=>a.createElement(l,e);class u extends a.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){r.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??c)(e)}return e??null}}},10412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const a="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,r={canUseDOM:a,canUseEventListeners:a&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:a&&"IntersectionObserver"in window,canUseViewport:a&&"screen"in window}},35742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294),r=n(70405);function o(e){return a.createElement(r.ql,e)}},39960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var a=n(87462),r=n(67294),o=n(73727),i=n(18780),s=n(52263),l=n(13919),c=n(10412);const u=r.createContext({collectLink:()=>{}});var d=n(44996);function f(e,t){let{isNavLink:n,to:f,href:p,activeClassName:g,isActive:m,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...v}=e;const{siteConfig:{trailingSlash:y,baseUrl:w}}=(0,s.Z)(),{withBaseUrl:_}=(0,d.C)(),k=(0,r.useContext)(u),x=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>x.current));const E=f||p;const S=(0,l.Z)(E),T=E?.replace("pathname://","");let C=void 0!==T?(A=T,b&&(e=>e.startsWith("/"))(A)?_(A):A):void 0;var A;C&&S&&(C=(0,i.applyTrailingSlash)(C,{trailingSlash:y,baseUrl:w}));const L=(0,r.useRef)(!1),P=n?o.OL:o.rU,N=c.Z.canUseIntersectionObserver,O=(0,r.useRef)(),R=()=>{L.current||null==C||(window.docusaurus.preload(C),L.current=!0)};(0,r.useEffect)((()=>(!N&&S&&null!=C&&window.docusaurus.prefetch(C),()=>{N&&O.current&&O.current.disconnect()})),[O,C,N,S]);const M=C?.startsWith("#")??!1,I=!C||!S||M;return I||h||k.collectLink(C),I?r.createElement("a",(0,a.Z)({ref:x,href:C},E&&!S&&{target:"_blank",rel:"noopener noreferrer"},v)):r.createElement(P,(0,a.Z)({},v,{onMouseEnter:R,onTouchStart:R,innerRef:e=>{x.current=e,N&&e&&S&&(O.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(O.current.unobserve(e),O.current.disconnect(),null!=C&&window.docusaurus.prefetch(C))}))})),O.current.observe(e))},to:C},n&&{isActive:m,activeClassName:g}))}const p=r.forwardRef(f)},95999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>s});var a=n(67294);function r(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,a.isValidElement)(e)))?n.map(((e,t)=>(0,a.isValidElement)(e)?a.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(57529);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function s(e,t){let{message:n,id:a}=e;return r(i({message:n,id:a}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const s=i({message:t,id:n});return a.createElement(a.Fragment,null,r(s,o))}},29935:(e,t,n)=>{"use strict";n.d(t,{m:()=>a});const a="default"},13919:(e,t,n)=>{"use strict";function a(e){return/^(?:\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}n.d(t,{Z:()=>r,b:()=>a})},44996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var a=n(67294),r=n(52263),o=n(13919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,r.Z)(),n=(0,a.useCallback)(((n,a)=>function(e,t,n,a){let{forcePrependBaseUrl:r=!1,absolute:i=!1}=void 0===a?{}:a;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(r)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,a)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},52263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294),r=n(58940);function o(){return(0,a.useContext)(r._)}},72389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294),r=n(98934);function o(){return(0,a.useContext)(r._)}},99670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});function a(e){const t={};return function e(n,a){Object.entries(n).forEach((n=>{let[r,o]=n;const i=a?`${a}.${r}`:r;var s;"object"==typeof(s=o)&&s&&Object.keys(s).length>0?e(o,i):t[i]=o}))}(e),t}},30226:(e,t,n)=>{"use strict";n.d(t,{_:()=>r,z:()=>o});var a=n(67294);const r=a.createContext(null);function o(e){let{children:t,value:n}=e;const o=a.useContext(r),i=(0,a.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const a={...t.data,...n?.data};return{plugin:t.plugin,data:a}}({parent:o,value:n})),[o,n]);return a.createElement(r.Provider,{value:i},t)}},80143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>b,gA:()=>p,WS:()=>g,_r:()=>d,Jo:()=>v,zh:()=>f,yW:()=>h,gB:()=>m});var a=n(16550),r=n(52263),o=n(29935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,a.LX)(t,{path:e.path,exact:!1,strict:!1})))}function c(e,t){const n=l(e,t),r=n?.docs.find((e=>!!(0,a.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:r,alternateDocVersions:r?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((a=>{a.id===t&&(n[e.name]=a)}))})),n}(r.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,f=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const a=i(e)?.[t];if(!a&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return a}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,a.TH)();return function(e,t,n){void 0===n&&(n={});const r=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,a.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=r?{pluginId:r[0],pluginData:r[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function g(e){void 0===e&&(e={});const t=p(e),{pathname:n}=(0,a.TH)();if(!t)return;return{activePlugin:t,activeVersion:l(t.pluginData,n)}}function m(e){return f(e).versions}function h(e){const t=f(e);return s(t)}function b(e){const t=f(e),{pathname:n}=(0,a.TH)();return c(t,n)}function v(e){const t=f(e),{pathname:n}=(0,a.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:c(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},56657:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});const a={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("event","page_view",{page_title:document.title,page_location:window.location.href,page_path:t.pathname+t.search+t.hash})}))}}},18320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var a=n(74865),r=n.n(a);r().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{r().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){r().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var a=n(87410),r=n(36809);!function(e){const{themeConfig:{prism:t}}=r.default,{additionalLanguages:a}=t;globalThis.Prism=e,a.forEach((e=>{n(52811)(`./prism-${e}`)})),delete globalThis.Prism}(a.Z)},39471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294);const r="iconExternalLink_nPIU";function o(e){let{width:t=13.5,height:n=13.5}=e;return a.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r},a.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},54774:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Ct});var a=n(67294),r=n(86010),o=n(44763),i=n(10833),s=n(87462),l=n(16550),c=n(95999),u=n(85936);const d="docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,a.useRef)(null),{action:t}=(0,l.k6)(),n=(0,a.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,u.S)((n=>{let{location:a}=n;e.current&&!a.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const g=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function m(e){const t=e.children??g,{containerRef:n,onClick:r}=p();return a.createElement("div",{ref:n,role:"region","aria-label":g},a.createElement("a",(0,s.Z)({},e,{href:`#${d}`,onClick:r}),t))}var h=n(35281),b=n(19727);const v="skipToContent_fXgn";function y(){return a.createElement(m,{className:v})}var w=n(86668),_=n(59689);function k(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:i,...l}=e;return a.createElement("svg",(0,s.Z)({viewBox:"0 0 15 15",width:t,height:n},l),a.createElement("g",{stroke:r,strokeWidth:o},a.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const x="closeButton_CVFx";function E(e){return a.createElement("button",(0,s.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,r.Z)("clean-btn close",x,e.className)}),a.createElement(k,{width:14,height:14,strokeWidth:3.1}))}const S="content_knG7";function T(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return a.createElement("div",(0,s.Z)({},e,{className:(0,r.Z)(S,e.className),dangerouslySetInnerHTML:{__html:n}}))}const C="announcementBar_mb4j",A="announcementBarPlaceholder_vyr4",L="announcementBarClose_gvF7",P="announcementBarContent_xLdY";function N(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,_.nT)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:i}=e;return a.createElement("div",{className:C,style:{backgroundColor:r,color:o},role:"banner"},i&&a.createElement("div",{className:A}),a.createElement(T,{className:P}),i&&a.createElement(E,{onClick:n,className:L}))}var O=n(93163),R=n(12466);var M=n(902),I=n(13102);const j=a.createContext(null);function D(e){let{children:t}=e;const n=function(){const e=(0,O.e)(),t=(0,I.HY)(),[n,r]=(0,a.useState)(!1),o=null!==t.component,i=(0,M.D9)(o);return(0,a.useEffect)((()=>{o&&!i&&r(!0)}),[o,i]),(0,a.useEffect)((()=>{o?e.shown||r(!0):r(!1)}),[e.shown,o]),(0,a.useMemo)((()=>[n,r]),[n])}();return a.createElement(j.Provider,{value:n},t)}function B(e){if(e.component){const t=e.component;return a.createElement(t,e.props)}}function F(){const e=(0,a.useContext)(j);if(!e)throw new M.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,r=(0,a.useCallback)((()=>n(!1)),[n]),o=(0,I.HY)();return(0,a.useMemo)((()=>({shown:t,hide:r,content:B(o)})),[r,o,t])}function $(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=F();return a.createElement("div",{className:"navbar-sidebar"},t,a.createElement("div",{className:(0,r.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},a.createElement("div",{className:"navbar-sidebar__item menu"},n),a.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var U=n(92949),z=n(72389);function Z(e){return a.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),a.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function H(e){return a.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),a.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const V={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function W(e){let{className:t,value:n,onChange:o}=e;const i=(0,z.Z)(),s=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===n?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return a.createElement("div",{className:(0,r.Z)(V.toggle,t)},a.createElement("button",{className:(0,r.Z)("clean-btn",V.toggleButton,!i&&V.toggleButtonDisabled),type:"button",onClick:()=>o("dark"===n?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite"},a.createElement(Z,{className:(0,r.Z)(V.toggleIcon,V.lightToggleIcon)}),a.createElement(H,{className:(0,r.Z)(V.toggleIcon,V.darkToggleIcon)})))}const G=a.memo(W);function q(e){let{className:t}=e;const n=(0,w.L)().colorMode.disableSwitch,{colorMode:r,setColorMode:o}=(0,U.I)();return n?null:a.createElement(G,{className:t,value:r,onChange:o})}var K=n(21327);function Y(){return a.createElement(K.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,O.e)();return a.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},a.createElement(k,{color:"var(--ifm-color-emphasis-600)"}))}function X(){return a.createElement("div",{className:"navbar-sidebar__brand"},a.createElement(Y,null),a.createElement(q,{className:"margin-right--md"}),a.createElement(Q,null))}var J=n(39960),ee=n(44996),te=n(13919),ne=n(98022),ae=n(39471);function re(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:i,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const f=(0,ee.Z)(r),p=(0,ee.Z)(t),g=(0,ee.Z)(o,{forcePrependBaseUrl:!0}),m=i&&o&&!(0,te.Z)(o),h=l?{dangerouslySetInnerHTML:{__html:l}}:{children:a.createElement(a.Fragment,null,i,m&&a.createElement(ae.Z,c&&{width:12,height:12}))};return o?a.createElement(J.Z,(0,s.Z)({href:u?g:o},d,h)):a.createElement(J.Z,(0,s.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?(0,ne.F)(n,t.pathname):t.pathname.startsWith(p)},d,h))}function oe(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=a.createElement(re,(0,s.Z)({className:(0,r.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?a.createElement("li",null,i):i}function ie(e){let{className:t,isDropdownItem:n,...o}=e;return a.createElement("li",{className:"menu__list-item"},a.createElement(re,(0,s.Z)({className:(0,r.Z)("menu__link",t)},o)))}function se(e){let{mobile:t=!1,position:n,...r}=e;const o=t?ie:oe;return a.createElement(o,(0,s.Z)({},r,{activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var le=n(86043),ce=n(48596),ue=n(52263);function de(e,t){return e.some((e=>function(e,t){return!!(0,ce.Mg)(e.to,t)||!!(0,ne.F)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function fe(e){let{items:t,position:n,className:o,onClick:i,...l}=e;const c=(0,a.useRef)(null),[u,d]=(0,a.useState)(!1);return(0,a.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e)}}),[c]),a.createElement("div",{ref:c,className:(0,r.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":u})},a.createElement(re,(0,s.Z)({"aria-haspopup":"true","aria-expanded":u,role:"button",href:l.to?void 0:"#",className:(0,r.Z)("navbar__link",o)},l,{onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!u))}}),l.children??l.label),a.createElement("ul",{className:"dropdown__menu"},t.map(((e,n)=>a.createElement(Ve,(0,s.Z)({isDropdownItem:!0,onKeyDown:e=>{if(n===t.length-1&&"Tab"===e.key){e.preventDefault(),d(!1);const t=c.current.nextElementSibling;if(t){(t instanceof HTMLAnchorElement?t:t.querySelector("a")).focus()}}},activeClassName:"dropdown__link--active"},e,{key:n}))))))}function pe(e){let{items:t,className:n,position:o,onClick:i,...c}=e;const u=function(){const{siteConfig:{baseUrl:e}}=(0,ue.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),d=de(t,u),{collapsed:f,toggleCollapsed:p,setCollapsed:g}=(0,le.u)({initialState:()=>!d});return(0,a.useEffect)((()=>{d&&g(!d)}),[u,d,g]),a.createElement("li",{className:(0,r.Z)("menu__list-item",{"menu__list-item--collapsed":f})},a.createElement(re,(0,s.Z)({role:"button",className:(0,r.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},c,{onClick:e=>{e.preventDefault(),p()}}),c.children??c.label),a.createElement(le.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:f},t.map(((e,t)=>a.createElement(Ve,(0,s.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function ge(e){let{mobile:t=!1,...n}=e;const r=t?pe:fe;return a.createElement(r,n)}var me=n(94711);function he(e){let{width:t=20,height:n=20,...r}=e;return a.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},r),a.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const be="iconLanguage_nlXk";function ve(){return a.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},a.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var ye=n(20830),we=["translations"];function _e(){return _e=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,a=new Array(t);n=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var Se="Ctrl";var Te=a.forwardRef((function(e,t){var n=e.translations,r=void 0===n?{}:n,o=Ee(e,we),i=r.buttonText,s=void 0===i?"Search":i,l=r.buttonAriaLabel,c=void 0===l?"Search":l,u=ke((0,a.useState)(null),2),d=u[0],f=u[1];return(0,a.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?f("\u2318"):f(Se))}),[]),a.createElement("button",_e({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:t}),a.createElement("span",{className:"DocSearch-Button-Container"},a.createElement(ye.W,null),a.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),a.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&a.createElement(a.Fragment,null,a.createElement("kbd",{className:"DocSearch-Button-Key"},d===Se?a.createElement(ve,null):d),a.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Ce=n(35742),Ae=n(66177),Le=n(239),Pe=n(43320);var Ne=n(73935);const Oe={button:{buttonText:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.I)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.I)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.I)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.I)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.I)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.I)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.I)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.I)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Re=null;function Me(e){let{hit:t,children:n}=e;return a.createElement(J.Z,{to:t.url},n)}function Ie(e){let{state:t,onClose:n}=e;const{generateSearchPageLink:r}=(0,Ae.O)();return a.createElement(J.Z,{to:r(t.query),onClick:n},a.createElement(c.Z,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits}},"See all {count} results"))}function je(e){let{contextualSearch:t,externalUrlRegex:r,...o}=e;const{siteMetadata:i}=(0,ue.Z)(),c=(0,Le.l)(),u=function(){const{locale:e,tags:t}=(0,Pe._q)();return[`language:${e}`,t.map((e=>`docusaurus_tag:${e}`))]}(),d=o.searchParameters?.facetFilters??[],f=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(u,d):d,p={...o.searchParameters,facetFilters:f},g=(0,l.k6)(),m=(0,a.useRef)(null),h=(0,a.useRef)(null),[b,v]=(0,a.useState)(!1),[y,w]=(0,a.useState)(void 0),_=(0,a.useCallback)((()=>Re?Promise.resolve():Promise.all([n.e(6780).then(n.bind(n,76780)),Promise.all([n.e(532),n.e(6945)]).then(n.bind(n,46945)),Promise.all([n.e(532),n.e(2090)]).then(n.bind(n,18894))]).then((e=>{let[{DocSearchModal:t}]=e;Re=t}))),[]),k=(0,a.useCallback)((()=>{_().then((()=>{m.current=document.createElement("div"),document.body.insertBefore(m.current,document.body.firstChild),v(!0)}))}),[_,v]),x=(0,a.useCallback)((()=>{v(!1),m.current?.remove()}),[v]),E=(0,a.useCallback)((e=>{_().then((()=>{v(!0),w(e.key)}))}),[_,v,w]),S=(0,a.useRef)({navigate(e){let{itemUrl:t}=e;(0,ne.F)(r,t)?window.location.href=t:g.push(t)}}).current,T=(0,a.useRef)((e=>o.transformItems?o.transformItems(e):e.map((e=>({...e,url:c(e.url)}))))).current,C=(0,a.useMemo)((()=>e=>a.createElement(Ie,(0,s.Z)({},e,{onClose:x}))),[x]),A=(0,a.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,r=e.onClose,o=e.onInput,i=e.searchButtonRef;a.useEffect((function(){function e(e){(27===e.keyCode&&t||"k"===e.key.toLowerCase()&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?r():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&o&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&o(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,r,o,i])}({isOpen:b,onOpen:k,onClose:x,onInput:E,searchButtonRef:h}),a.createElement(a.Fragment,null,a.createElement(Ce.Z,null,a.createElement("link",{rel:"preconnect",href:`https://${o.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})),a.createElement(Te,{onTouchStart:_,onFocus:_,onMouseOver:_,onClick:k,ref:h,translations:Oe.button}),b&&Re&&m.current&&(0,Ne.createPortal)(a.createElement(Re,(0,s.Z)({onClose:x,initialScrollY:window.scrollY,initialQuery:y,navigator:S,transformItems:T,hitComponent:Me,transformSearchClient:A},o.searchPagePath&&{resultsFooterComponent:C},o,{searchParameters:p,placeholder:Oe.placeholder,translations:Oe.modal})),m.current))}function De(){const{siteConfig:e}=(0,ue.Z)();return a.createElement(je,e.themeConfig.algolia)}const Be="searchBox_ZlJk";function Fe(e){let{children:t,className:n}=e;return a.createElement("div",{className:(0,r.Z)(n,Be)},t)}var $e=n(80143),Ue=n(53438);var ze=n(60373);const Ze=e=>e.docs.find((t=>t.id===e.mainDocId));const He={default:se,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,...o}=e;const{i18n:{currentLocale:i,locales:u,localeConfigs:d}}=(0,ue.Z)(),f=(0,me.l)(),{search:p,hash:g}=(0,l.TH)(),m=[...n,...u.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${g}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],h=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return a.createElement(ge,(0,s.Z)({},o,{mobile:t,label:a.createElement(a.Fragment,null,a.createElement(he,{className:be}),h),items:m}))},search:function(e){let{mobile:t,className:n}=e;return t?null:a.createElement(Fe,{className:n},a.createElement(De,null))},dropdown:ge,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const s=i?"li":"div";return a.createElement(s,{className:(0,r.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:i}=(0,$e.Iw)(r),l=(0,Ue.vY)(t,r);return null===l?null:a.createElement(se,(0,s.Z)({exact:!0},o,{isActive:()=>i?.path===l.path||!!i?.sidebar&&i.sidebar===l.sidebar,label:n??l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:i}=(0,$e.Iw)(r),l=(0,Ue.oz)(t,r).link;if(!l)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return a.createElement(se,(0,s.Z)({exact:!0},o,{isActive:()=>i?.sidebar===t,label:n??l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const i=(0,Ue.lO)(r)[0],l=t??i.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return a.createElement(se,(0,s.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:i,...u}=e;const{search:d,hash:f}=(0,l.TH)(),p=(0,$e.Iw)(n),g=(0,$e.gB)(n),{savePreferredVersionName:m}=(0,ze.J)(n),h=[...o,...g.map((e=>{const t=p.alternateDocVersions[e.name]??Ze(e);return{label:e.label,to:`${t.path}${d}${f}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...i],b=(0,Ue.lO)(n)[0],v=t&&h.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,y=t&&h.length>1?void 0:Ze(b).path;return h.length<=1?a.createElement(se,(0,s.Z)({},u,{mobile:t,label:v,to:y,isActive:r?()=>!1:void 0})):a.createElement(ge,(0,s.Z)({},u,{mobile:t,label:v,to:y,items:h,isActive:r?()=>!1:void 0}))}};function Ve(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=He[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return a.createElement(o,n)}function We(){const e=(0,O.e)(),t=(0,w.L)().navbar.items;return a.createElement("ul",{className:"menu__list"},t.map(((t,n)=>a.createElement(Ve,(0,s.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ge(e){return a.createElement("button",(0,s.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),a.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function qe(){const e=0===(0,w.L)().navbar.items.length,t=F();return a.createElement(a.Fragment,null,!e&&a.createElement(Ge,{onClick:()=>t.hide()}),t.content)}function Ke(){const e=(0,O.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,a.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?a.createElement($,{header:a.createElement(X,null),primaryMenu:a.createElement(We,null),secondaryMenu:a.createElement(qe,null)}):null}const Ye="navbarHideable_m1mJ",Qe="navbarHidden_jGov";function Xe(e){return a.createElement("div",(0,s.Z)({role:"presentation"},e,{className:(0,r.Z)("navbar-sidebar__backdrop",e.className)}))}function Je(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,O.e)(),{navbarRef:s,isNavbarVisible:l}=function(e){const[t,n]=(0,a.useState)(e),r=(0,a.useRef)(!1),o=(0,a.useRef)(0),i=(0,a.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,R.RF)(((t,a)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const a=t.location.hash;if(a?document.getElementById(a.substring(1)):void 0)return r.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return a.createElement("nav",{ref:s,"aria-label":(0,c.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,r.Z)("navbar","navbar--fixed-top",n&&[Ye,!l&&Qe],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,a.createElement(Xe,{onClick:i.toggle}),a.createElement(Ke,null))}function et(e){let{width:t=30,height:n=30,className:r,...o}=e;return a.createElement("svg",(0,s.Z)({className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function tt(){const{toggle:e,shown:t}=(0,O.e)();return a.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},a.createElement(et,null))}const nt="colorModeToggle_DEke";function at(e){let{items:t}=e;return a.createElement(a.Fragment,null,t.map(((e,t)=>a.createElement(Ve,(0,s.Z)({},e,{key:t})))))}function rt(e){let{left:t,right:n}=e;return a.createElement("div",{className:"navbar__inner"},a.createElement("div",{className:"navbar__items"},t),a.createElement("div",{className:"navbar__items navbar__items--right"},n))}function ot(){const e=(0,O.e)(),t=(0,w.L)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??"right")}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return a.createElement(rt,{left:a.createElement(a.Fragment,null,!e.disabled&&a.createElement(tt,null),a.createElement(Y,null),a.createElement(at,{items:n})),right:a.createElement(a.Fragment,null,a.createElement(at,{items:r}),a.createElement(q,{className:nt}),!o&&a.createElement(Fe,null,a.createElement(De,null)))})}function it(){return a.createElement(Je,null,a.createElement(ot,null))}function st(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:i,...l}=t,c=(0,ee.Z)(n),u=(0,ee.Z)(r,{forcePrependBaseUrl:!0});return a.createElement(J.Z,(0,s.Z)({className:"footer__link-item"},r?{href:i?u:r}:{to:c},l),o,r&&!(0,te.Z)(r)&&a.createElement(ae.Z,null))}function lt(e){let{item:t}=e;return t.html?a.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):a.createElement("li",{key:t.href??t.to,className:"footer__item"},a.createElement(st,{item:t}))}function ct(e){let{column:t}=e;return a.createElement("div",{className:"col footer__col"},a.createElement("div",{className:"footer__title"},t.title),a.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>a.createElement(lt,{key:t,item:e})))))}function ut(e){let{columns:t}=e;return a.createElement("div",{className:"row footer__links"},t.map(((e,t)=>a.createElement(ct,{key:t,column:e}))))}function dt(){return a.createElement("span",{className:"footer__link-separator"},"\xb7")}function ft(e){let{item:t}=e;return t.html?a.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):a.createElement(st,{item:t})}function pt(e){let{links:t}=e;return a.createElement("div",{className:"footer__links text--center"},a.createElement("div",{className:"footer__links"},t.map(((e,n)=>a.createElement(a.Fragment,{key:n},a.createElement(ft,{item:e}),t.length!==n+1&&a.createElement(dt,null))))))}function gt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?a.createElement(ut,{columns:t}):a.createElement(pt,{links:t})}var mt=n(50941);const ht="footerLogoLink_BH7S";function bt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,ee.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return a.createElement(mt.Z,{className:(0,r.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function vt(e){let{logo:t}=e;return t.href?a.createElement(J.Z,{href:t.href,className:ht,target:t.target},a.createElement(bt,{logo:t})):a.createElement(bt,{logo:t})}function yt(e){let{copyright:t}=e;return a.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function wt(e){let{style:t,links:n,logo:o,copyright:i}=e;return a.createElement("footer",{className:(0,r.Z)("footer",{"footer--dark":"dark"===t})},a.createElement("div",{className:"container container-fluid"},n,(o||i)&&a.createElement("div",{className:"footer__bottom text--center"},o&&a.createElement("div",{className:"margin-bottom--sm"},o),i)))}function _t(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return a.createElement(wt,{style:o,links:n&&n.length>0&&a.createElement(gt,{links:n}),logo:r&&a.createElement(vt,{logo:r}),copyright:t&&a.createElement(yt,{copyright:t})})}const kt=a.memo(_t),xt=(0,M.Qc)([U.S,_.pl,R.OC,ze.L5,i.VC,function(e){let{children:t}=e;return a.createElement(I.n2,null,a.createElement(O.M,null,a.createElement(D,null,t)))}]);function Et(e){let{children:t}=e;return a.createElement(xt,null,t)}function St(e){let{error:t,tryAgain:n}=e;return a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),a.createElement("p",null,t.message),a.createElement("div",null,a.createElement("button",{type:"button",onClick:n},a.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again when the page crashed"},"Try again"))))))}const Tt="mainWrapper_z2l0";function Ct(e){const{children:t,noFooter:n,wrapperClassName:s,title:l,description:c}=e;return(0,b.t)(),a.createElement(Et,null,a.createElement(i.d,{title:l,description:c}),a.createElement(y,null),a.createElement(N,null),a.createElement(it,null),a.createElement("div",{id:d,className:(0,r.Z)(h.k.wrapper.main,Tt,s)},a.createElement(o.Z,{fallback:e=>a.createElement(St,e)},t)),!n&&a.createElement(kt,null))}},21327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var a=n(87462),r=n(67294),o=n(39960),i=n(44996),s=n(52263),l=n(86668),c=n(50941);function u(e){let{logo:t,alt:n,imageClassName:a}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},s=r.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return a?r.createElement("div",{className:a},s):s}function d(e){const{siteConfig:{title:t}}=(0,s.Z)(),{navbar:{title:n,logo:c}}=(0,l.L)(),{imageClassName:d,titleClassName:f,...p}=e,g=(0,i.Z)(c?.href||"/"),m=n?"":t,h=c?.alt??m;return r.createElement(o.Z,(0,a.Z)({to:g},p,c?.target&&{target:c.target}),c&&r.createElement(u,{logo:c,alt:h,imageClassName:d}),null!=n&&r.createElement("b",{className:f},n))}},90197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var a=n(67294),r=n(35742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return a.createElement(r.Z,null,t&&a.createElement("meta",{name:"docusaurus_locale",content:t}),n&&a.createElement("meta",{name:"docusaurus_version",content:n}),o&&a.createElement("meta",{name:"docusaurus_tag",content:o}),i&&a.createElement("meta",{name:"docsearch:language",content:i}),n&&a.createElement("meta",{name:"docsearch:version",content:n}),o&&a.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},50941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var a=n(87462),r=n(67294),o=n(86010),i=n(72389),s=n(92949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,i.Z)(),{colorMode:n}=(0,s.I)(),{sources:c,className:u,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return r.createElement(r.Fragment,null,p.map((e=>r.createElement("img",(0,a.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l[`themedImage--${e}`],u)},f)))))}},86043:(e,t,n)=>{"use strict";n.d(t,{u:()=>i,z:()=>g});var a=n(87462),r=n(67294),o=n(10412);function i(e){let{initialState:t}=e;const[n,a]=(0,r.useState)(t??!1),o=(0,r.useCallback)((()=>{a((e=>!e))}),[]);return{collapsed:n,setCollapsed:a,toggleCollapsed:o}}const s={display:"none",overflow:"hidden",height:"0px"},l={display:"block",overflow:"visible",height:"auto"};function c(e,t){const n=t?s:l;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function u(e){let{collapsibleRef:t,collapsed:n,animation:a}=e;const o=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=a?.duration??function(e){const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${a?.easing??"ease-in-out"}`,height:`${t}px`}}function i(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return c(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(i(),requestAnimationFrame((()=>{e.style.height=s.height,e.style.overflow=s.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{i()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,a])}function d(e){if(!o.Z.canUseDOM)return e?s:l}function f(e){let{as:t="div",collapsed:n,children:a,animation:o,onCollapseTransitionEnd:i,className:s,disableSSRStyle:l}=e;const f=(0,r.useRef)(null);return u({collapsibleRef:f,collapsed:n,animation:o}),r.createElement(t,{ref:f,style:l?void 0:d(n),onTransitionEnd:e=>{"height"===e.propertyName&&(c(f.current,n),i?.(n))},className:s},a)}function p(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[s,l]=(0,r.useState)(t);return(0,r.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,r.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?r.createElement(f,(0,a.Z)({},n,{collapsed:s})):null}function g(e){let{lazy:t,...n}=e;const a=t?p:f;return r.createElement(a,n)}},59689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>g,pl:()=>p});var a=n(67294),r=n(72389),o=n(50012),i=n(902),s=n(86668);const l=(0,o.WA)("docusaurus.announcement.dismiss"),c=(0,o.WA)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),f=a.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,r.Z)(),[n,o]=(0,a.useState)((()=>!!t&&u()));(0,a.useEffect)((()=>{o(u())}),[]);const i=(0,a.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,a.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const a=t!==n;c.set(t),a&&d(!1),!a&&u()||o(!1)}),[e]),(0,a.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return a.createElement(f.Provider,{value:n},t)}function g(){const e=(0,a.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},92949:(e,t,n)=>{"use strict";n.d(t,{I:()=>h,S:()=>m});var a=n(67294),r=n(10412),o=n(902),i=n(50012),s=n(86668);const l=a.createContext(void 0),c="theme",u=(0,i.WA)(c),d="light",f="dark",p=e=>e===f?f:d;function g(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[o,i]=(0,a.useState)((e=>r.Z.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e))(e));(0,a.useEffect)((()=>{t&&u.del()}),[t]);const l=(0,a.useCallback)((function(t,a){void 0===a&&(a={});const{persist:r=!0}=a;t?(i(t),r&&(e=>{u.set(p(e))})(t)):(i(n?window.matchMedia("(prefers-color-scheme: dark)").matches?f:d:e),u.del())}),[n,e]);(0,a.useEffect)((()=>{document.documentElement.setAttribute("data-theme",p(o))}),[o]),(0,a.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&l(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,l]);const g=(0,a.useRef)(!1);return(0,a.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),a=()=>{window.matchMedia("print").matches||g.current?g.current=window.matchMedia("print").matches:l(null)};return e.addListener(a),()=>e.removeListener(a)}),[l,t,n]),(0,a.useMemo)((()=>({colorMode:o,setColorMode:l,get isDarkTheme(){return o===f},setLightTheme(){l(d)},setDarkTheme(){l(f)}})),[o,l])}function m(e){let{children:t}=e;const n=g();return a.createElement(l.Provider,{value:n},t)}function h(){const e=(0,a.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},60373:(e,t,n)=>{"use strict";n.d(t,{J:()=>y,L5:()=>b,Oh:()=>w});var a=n(67294),r=n(80143),o=n(29935),i=n(86668),s=n(53438),l=n(902),c=n(50012);const u=e=>`docs-preferred-version-${e}`,d=(e,t,n)=>{(0,c.WA)(u(e),{persistence:t}).set(n)},f=(e,t)=>(0,c.WA)(u(e),{persistence:t}).get(),p=(e,t)=>{(0,c.WA)(u(e),{persistence:t}).del()};const g=a.createContext(null);function m(){const e=(0,r._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,a.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,a.useState)((()=>(e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}]))))(n)));(0,a.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:a}=e;function r(e){const t=f(e,n);return a[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,r(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,a.useMemo)((()=>({savePreferredVersion:function(e,n){d(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function h(e){let{children:t}=e;const n=m();return a.createElement(g.Provider,{value:n},t)}function b(e){let{children:t}=e;return s.cE?a.createElement(h,null,t):a.createElement(a.Fragment,null,t)}function v(){const e=(0,a.useContext)(g);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=o.m);const t=(0,r.zh)(e),[n,i]=v(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,a.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function w(){const e=(0,r._r)(),[t]=v();function n(n){const a=e[n],{preferredVersionName:r}=t[n];return a.versions.find((e=>e.name===r))??null}const a=Object.keys(e);return Object.fromEntries(a.map((e=>[e,n(e)])))}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>s});var a=n(67294),r=n(902);const o=Symbol("EmptyContext"),i=a.createContext(o);function s(e){let{children:t,name:n,items:r}=e;const o=(0,a.useMemo)((()=>n&&r?{name:n,items:r}:null),[n,r]);return a.createElement(i.Provider,{value:o},t)}function l(){const e=(0,a.useContext)(i);if(e===o)throw new r.i6("DocsSidebarProvider");return e}},93163:(e,t,n)=>{"use strict";n.d(t,{M:()=>d,e:()=>f});var a=n(67294),r=n(13102),o=n(87524),i=n(91980),s=n(86668),l=n(902);const c=a.createContext(void 0);function u(){const e=function(){const e=(0,r.HY)(),{items:t}=(0,s.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[l,c]=(0,a.useState)(!1);(0,i.Rb)((()=>{if(l)return c(!1),!1}));const u=(0,a.useCallback)((()=>{c((e=>!e))}),[]);return(0,a.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,a.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function d(e){let{children:t}=e;const n=u();return a.createElement(c.Provider,{value:n},t)}function f(){const e=a.useContext(c);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},13102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>s,Zo:()=>l,n2:()=>i});var a=n(67294),r=n(902);const o=a.createContext(null);function i(e){let{children:t}=e;const n=(0,a.useState)({component:null,props:null});return a.createElement(o.Provider,{value:n},t)}function s(){const e=(0,a.useContext)(o);if(!e)throw new r.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const i=(0,a.useContext)(o);if(!i)throw new r.i6("NavbarSecondaryMenuContentProvider");const[,s]=i,l=(0,r.Ql)(n);return(0,a.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,a.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},19727:(e,t,n)=>{"use strict";n.d(t,{h:()=>r,t:()=>o});var a=n(67294);const r="navigation-with-keyboard";function o(){(0,a.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(r),"mousedown"===e.type&&document.body.classList.remove(r)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(r),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},66177:(e,t,n)=>{"use strict";n.d(t,{O:()=>s});var a=n(67294),r=n(16550),o=n(52263);const i="q";function s(){const e=(0,r.k6)(),{siteConfig:{baseUrl:t,themeConfig:n}}=(0,o.Z)(),{algolia:{searchPagePath:s}}=n,[l,c]=(0,a.useState)("");(0,a.useEffect)((()=>{const e=new URLSearchParams(window.location.search).get(i)??"";c(e)}),[]);return{searchQuery:l,setSearchQuery:(0,a.useCallback)((t=>{const n=new URLSearchParams(window.location.search);t?n.set(i,t):n.delete(i),e.replace({search:n.toString()}),c(t)}),[e]),generateSearchPageLink:(0,a.useCallback)((e=>`${t}${s}?q=${encodeURIComponent(e)}`),[t,s])}}},87524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var a=n(67294),r=n(10412);const o="desktop",i="mobile",s="ssr";function l(){return r.Z.canUseDOM?window.innerWidth>996?o:i:s}function c(){const[e,t]=(0,a.useState)((()=>l()));return(0,a.useEffect)((()=>{function e(){t(l())}return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(undefined)}}),[]),e}},35281:(e,t,n)=>{"use strict";n.d(t,{k:()=>a});const a={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},53438:(e,t,n)=>{"use strict";n.d(t,{Wl:()=>f,_F:()=>g,cE:()=>d,hI:()=>w,lO:()=>b,oz:()=>v,s1:()=>h,vY:()=>y});var a=n(67294),r=n(16550),o=n(18790),i=n(80143),s=n(60373),l=n(1116),c=n(67392),u=n(48596);const d=!!i._r;function f(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=f(t);if(e)return e}}}const p=(e,t)=>void 0!==e&&(0,u.Mg)(e,t);function g(e,t){return"link"===e.type?p(e.href,t):"category"===e.type&&(p(e.href,t)||((e,t)=>e.some((e=>g(e,t))))(e.items,t))}function m(e){let{sidebarItems:t,pathname:n,onlyCategories:a=!1}=e;const r=[];return function e(t){for(const o of t)if("category"===o.type&&((0,u.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,u.Mg)(o.href,n)){return a&&"category"!==o.type||r.unshift(o),!0}return!1}(t),r}function h(){const e=(0,l.V)(),{pathname:t}=(0,r.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?m({sidebarItems:e.items,pathname:t}):null}function b(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),r=(0,i.yW)(e);return(0,a.useMemo)((()=>(0,c.j)([t,n,r].filter(Boolean))),[t,n,r])}function v(e,t){const n=b(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),a=t.find((t=>t[0]===e));if(!a)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\n Available sidebar ids are:\n - ${Object.keys(t).join("\n- ")}`);return a[1]}),[e,n])}function y(e,t){const n=b(t);return(0,a.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),a=t.find((t=>t.id===e));if(!a){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`DocNavbarItem: couldn't find any doc with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,c.j)(t.map((e=>e.id))).join("\n- ")}`)}return a}),[e,n])}function w(e){let{route:t,versionMetadata:n}=e;const a=(0,r.TH)(),i=t.routes,s=i.find((e=>(0,r.LX)(a.pathname,e)));if(!s)return null;const l=s.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(i),sidebarName:l,sidebarItems:c}}},82128:(e,t,n)=>{"use strict";n.d(t,{p:()=>r});var a=n(52263);function r(e){const{siteConfig:t}=(0,a.Z)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}},91980:(e,t,n)=>{"use strict";n.d(t,{Rb:()=>s,_X:()=>l});var a=n(67294),r=n(16550),o=n(61688),i=n(902);function s(e){!function(e){const t=(0,r.k6)(),n=(0,i.zX)(e);(0,a.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function l(e){return function(e){const t=(0,r.k6)();return(0,o.useSyncExternalStore)(t.listen,(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}},67392:(e,t,n)=>{"use strict";function a(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,a)=>e.findIndex((e=>t(e,n)))!==a))}function r(e){return Array.from(new Set(e))}n.d(t,{j:()=>r,l:()=>a})},10833:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>u,VC:()=>p});var a=n(67294),r=n(86010),o=n(35742),i=n(30226);function s(){const e=a.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(44996),c=n(82128);function u(e){let{title:t,description:n,keywords:r,image:i,children:s}=e;const u=(0,c.p)(t),{withBaseUrl:d}=(0,l.C)(),f=i?d(i,{absolute:!0}):void 0;return a.createElement(o.Z,null,t&&a.createElement("title",null,u),t&&a.createElement("meta",{property:"og:title",content:u}),n&&a.createElement("meta",{name:"description",content:n}),n&&a.createElement("meta",{property:"og:description",content:n}),r&&a.createElement("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),f&&a.createElement("meta",{property:"og:image",content:f}),f&&a.createElement("meta",{name:"twitter:image",content:f}),s)}const d=a.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=a.useContext(d),s=(0,r.Z)(i,t);return a.createElement(d.Provider,{value:s},a.createElement(o.Z,null,a.createElement("html",{className:s})),n)}function p(e){let{children:t}=e;const n=s(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return a.createElement(f,{className:(0,r.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>c,Ql:()=>l,i6:()=>s,zX:()=>o});var a=n(67294);const r=n(10412).Z.canUseDOM?a.useLayoutEffect:a.useEffect;function o(e){const t=(0,a.useRef)(e);return r((()=>{t.current=e}),[e]),(0,a.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,a.useRef)();return r((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,a.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return a.createElement(a.Fragment,null,e.reduceRight(((e,t)=>a.createElement(t,null,e)),n))}}},98022:(e,t,n)=>{"use strict";function a(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{F:()=>a})},48596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var a=n(67294),r=n(723),o=n(52263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,a.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function a(e){return e.path===t&&!0===e.exact}function r(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(a)||e(t.filter(r).flatMap((e=>e.routes??[])))}(n)}({routes:r.Z,baseUrl:e})),[e])}},12466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>p,OC:()=>l,RF:()=>d,o5:()=>f});var a=n(67294),r=n(10412),o=n(72389),i=n(902);const s=a.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,a.useRef)(!0);return(0,a.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return a.createElement(s.Provider,{value:n},t)}function c(){const e=(0,a.useContext)(s);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const u=()=>r.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),r=(0,a.useRef)(u()),o=(0,i.zX)(e);(0,a.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,r.current),r.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=c(),t=function(){const e=(0,a.useRef)({elem:null,top:0}),t=(0,a.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,a.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const a=t.getBoundingClientRect().top-n;return a&&window.scrollBy({left:0,top:a}),e.current={elem:null,top:0},{restored:0!==a}}),[]);return(0,a.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,a.useRef)(void 0),r=(0,a.useCallback)((a=>{t.save(a),e.disableScrollEvents(),n.current=()=>{const{restored:a}=t.restore();if(n.current=void 0,a){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,a.useLayoutEffect)((()=>{n.current?.()})),{blockElementScrollPositionUntilNextRender:r}}function p(){const e=(0,a.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function a(){const r=document.documentElement.scrollTop;(n&&r>e||!n&&rt&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},43320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>i,_q:()=>l,os:()=>s});var a=n(80143),r=n(52263),o=n(60373);const i="default";function s(e,t){return`docs-${e}-${t}`}function l(){const{i18n:e}=(0,r.Z)(),t=(0,a._r)(),n=(0,a.WS)(),l=(0,o.Oh)();const c=[i,...Object.keys(t).map((function(e){const a=n?.activePlugin.pluginId===e?n.activeVersion:void 0,r=l[e],o=t[e].versions.find((e=>e.isLast));return s(e,(a??r??o).name)}))];return{locale:e.currentLocale,tags:c}}},50012:(e,t,n)=>{"use strict";n.d(t,{Nk:()=>d,WA:()=>u});var a=n(67294),r=n(61688);const o="localStorage";function i(e){let{key:t,oldValue:n,newValue:a,storage:r}=e;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,a,window.location.href,r),window.dispatchEvent(o)}function s(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,l||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),l=!0),null}var t}let l=!1;const c={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function u(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=s(t?.persistence);return null===n?c:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const a=n.getItem(e);n.setItem(e,t),i({key:e,oldValue:a,newValue:t,storage:n})}catch(a){console.error(`Docusaurus storage error, can't set ${e}=${t}`,a)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),i({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const a=a=>{a.storageArea===n&&a.key===e&&t(a)};return window.addEventListener("storage",a),()=>window.removeEventListener("storage",a)}catch(a){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,a),()=>{}}}}}function d(e,t){const n=(0,a.useRef)((()=>null===e?c:u(e,t))).current(),o=(0,a.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,r.useSyncExternalStore)(o,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},94711:(e,t,n)=>{"use strict";n.d(t,{l:()=>o});var a=n(52263),r=n(16550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,a.Z)(),{pathname:i}=(0,r.TH)(),s=o===n?e:e.replace(`/${o}/`,"/"),l=i.replace(e,"");return{createUrl:function(e){let{locale:a,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===n?`${s}`:`${s}${e}/`}(a)}${l}`}}}},85936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var a=n(67294),r=n(16550),o=n(902);function i(e){const t=(0,r.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,a.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},86668:(e,t,n)=>{"use strict";n.d(t,{L:()=>r});var a=n(52263);function r(){return(0,a.Z)().siteConfig.themeConfig}},6278:(e,t,n)=>{"use strict";n.d(t,{L:()=>r});var a=n(52263);function r(){const{siteConfig:{themeConfig:e}}=(0,a.Z)();return e}},239:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var a=n(67294),r=n(98022),o=n(44996),i=n(6278);function s(){const{withBaseUrl:e}=(0,o.C)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.L)();return(0,a.useCallback)((a=>{const o=new URL(a);if((0,r.F)(t,o.href))return a;const i=`${o.pathname+o.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:a}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[r]=e.split(/[#?]/),o="/"===r||r===a?r:(i=r,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(r,o)}},18780:function(e,t,n){"use strict";var a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="post-content";var r=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return a(r).default}})},86010:(e,t,n)=>{"use strict";function a(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;tr});const r=function(){for(var e,t,n=0,r="";n{"use strict";n.d(t,{lX:()=>x,q_:()=>L,ob:()=>m,PP:()=>N,Ep:()=>g,Hp:()=>h});var a=n(87462);function r(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,a=n+1,r=e.length;a=0;f--){var p=i[f];"."===p?o(i,f):".."===p?(o(i,f),d++):d&&(o(i,f),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&r(i[0])||i.unshift("");var g=i.join("/");return n&&"/"!==g.substr(-1)&&(g+="/"),g};function s(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}const l=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,a){return e(t,n[a])}));if("object"==typeof t||"object"==typeof n){var a=s(t),r=s(n);return a!==t||r!==n?e(a,r):Object.keys(Object.assign({},t,n)).every((function(a){return e(t[a],n[a])}))}return!1};var c=n(38776);function u(e){return"/"===e.charAt(0)?e:"/"+e}function d(e){return"/"===e.charAt(0)?e.substr(1):e}function f(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function p(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function g(e){var t=e.pathname,n=e.search,a=e.hash,r=t||"/";return n&&"?"!==n&&(r+="?"===n.charAt(0)?n:"?"+n),a&&"#"!==a&&(r+="#"===a.charAt(0)?a:"#"+a),r}function m(e,t,n,r){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",a="",r=t.indexOf("#");-1!==r&&(a=t.substr(r),t=t.substr(0,r));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===a?"":a}}(e),o.state=t):(void 0===(o=(0,a.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),r?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,r.pathname)):o.pathname=r.pathname:o.pathname||(o.pathname="/"),o}function h(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&l(e.state,t.state)}function b(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,a,r){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof a?a(o,r):r(!0):r(!1!==o)}else r(!0)},appendListener:function(e){var n=!0;function a(){n&&e.apply(void 0,arguments)}return t.push(a),function(){n=!1,t=t.filter((function(e){return e!==a}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),a=0;at?n.splice(t,n.length-t,r):n.push(r),d({action:a,location:r,index:t,entries:n})}}))},replace:function(e,t){var a="REPLACE",r=m(e,t,f(),w.location);u.confirmTransitionTo(r,a,n,(function(e){e&&(w.entries[w.index]=r,d({action:a,location:r}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var a=n(59864),r={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return a.isMemo(e)?i:s[e.$$typeof]||r}s[a.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[a.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,g=Object.prototype;e.exports=function e(t,n,a){if("string"!=typeof n){if(g){var r=p(n);r&&r!==g&&e(t,r,a)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),m=l(n),h=0;h{"use strict";e.exports=function(e,t,n,a,r,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,a,r,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},32497:(e,t,n)=>{"use strict";n.r(t)},52295:(e,t,n)=>{"use strict";n.r(t)},74865:function(e,t,n){var a,r;a=function(){var e,t,n={version:"0.2.0"},a=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function r(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var r;return(r="translate3d"===a.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===a.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,r}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(a[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=r(e,a.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(a.barSelector),u=a.speed,d=a.easing;return o.offsetWidth,s((function(t){""===a.positionUsing&&(a.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),a.trickleSpeed)};return a.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*r(Math.random()*t,.1,.95)),t=r(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*a.trickleRate)},e=0,t=0,n.promise=function(a){return a&&"resolved"!==a.state()?(0===t&&n.start(),e++,t++,a.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=a.template;var r,i=t.querySelector(a.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(a.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),a.showSpinner||(r=t.querySelector(a.spinnerSelector))&&p(r),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(a.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function a(t){var n=document.body.style;if(t in n)return t;for(var a,r=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);r--;)if((a=e[r]+o)in n)return a;return t}function r(e){return e=n(e),t[e]||(t[e]=a(e))}function o(e,t,n){t=r(t),e.style[t]=n}return function(e,t){var n,a,r=arguments;if(2==r.length)for(n in t)void 0!==(a=t[n])&&t.hasOwnProperty(n)&&o(e,n,a);else o(e,r[1],r[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),a=n+t;c(n,t)||(e.className=a.substring(1))}function d(e,t){var n,a=f(e);c(e,t)&&(n=a.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(r="function"==typeof a?a.call(t,n,t,e):a)||(e.exports=r)},27418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;function r(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var a={};return"abcdefghijklmnopqrst".split("").forEach((function(e){a[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},a)).join("")}catch(r){return!1}}()?Object.assign:function(e,o){for(var i,s,l=r(e),c=1;c{"use strict";n.d(t,{Z:()=>o});var a=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},a={util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);x+=k.value.length,k=k.next){var E=k.value;if(t.length>e.length)return;if(!(E instanceof r)){var S,T=1;if(v){if(!(S=o(_,x,e,b))||S.index>=e.length)break;var C=S.index,A=S.index+S[0].length,L=x;for(L+=k.value.length;C>=L;)L+=(k=k.next).value.length;if(x=L-=k.value.length,k.value instanceof r)continue;for(var P=k;P!==t.tail&&(Ld.reach&&(d.reach=M);var I=k.prev;if(O&&(I=l(t,I,O),x+=O.length),c(t,I,T),k=l(t,I,new r(f,h?a.tokenize(N,h):N,y,N)),R&&l(t,k,R),T>1){var j={cause:f+","+g,reach:M};i(e,t,n,k.prev,x,j),d&&j.reach>d.reach&&(d.reach=j.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var a=t.next,r={value:n,prev:t,next:a};return t.next=r,a.prev=r,e.length++,r}function c(e,t,n){for(var a=t.next,r=0;r"+o.content+""},a}(),r=a;a.default=a,r.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},r.languages.markup.tag.inside["attr-value"].inside.entity=r.languages.markup.entity,r.languages.markup.doctype.inside["internal-subset"].inside=r.languages.markup,r.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(r.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:r.languages[t]},n.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:r.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},r.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(r.languages.markup.tag,"addAttribute",{value:function(e,t){r.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:r.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),r.languages.html=r.languages.markup,r.languages.mathml=r.languages.markup,r.languages.svg=r.languages.markup,r.languages.xml=r.languages.extend("markup",{}),r.languages.ssml=r.languages.xml,r.languages.atom=r.languages.xml,r.languages.rss=r.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var r=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=a.variable[1].inside,i=0;i]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},r.languages.c=r.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),r.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),r.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},r.languages.c.string],char:r.languages.c.char,comment:r.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:r.languages.c}}}}),r.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete r.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(r),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(r),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var a={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},r={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:a,number:r,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:a,number:r})}(r),r.languages.javascript=r.languages.extend("clike",{"class-name":[r.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),r.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,r.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:r.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:r.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:r.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:r.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:r.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),r.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:r.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),r.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),r.languages.markup&&(r.languages.markup.tag.addInlined("script","javascript"),r.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),r.languages.js=r.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(r),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,a="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",r=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,(function(){return a})).replace(/<>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,(function(){return a}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,(function(){return a})).replace(/<>/g,(function(){return"(?:"+r+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(r),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(//g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var a=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,r=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return a})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+r+o+"(?:"+r+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+r+o+")(?:"+r+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(a),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+r+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+r+"$"),inside:{"table-header":{pattern:RegExp(a),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,a=t.length;n",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(r),r.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:r.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},r.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n0)){var s=f(/^\{$/,/^\}$/);if(-1===s)continue;for(var l=n;l=0&&p(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,a=t.inside.interpolation,r=a.inside["interpolation-punctuation"],o=a.pattern.source;function i(t,a){if(e.languages[t])return{pattern:RegExp("((?:"+a+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,a){var r={code:t,grammar:n,language:a};return e.hooks.run("before-tokenize",r),r.tokens=e.tokenize(r.code,r.grammar),e.hooks.run("after-tokenize",r),r.tokens}function c(t){var n={};n["interpolation-punctuation"]=r;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,a.alias,t)}function u(t,n,a){var r=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,u={},d=l(r.map((function(e){if("string"==typeof e)return e;for(var n,r=e.content;-1!==t.indexOf(n=s(i++,a)););return u[n]=r,n})).join(""),n,a),f=Object.keys(u);return i=0,function e(t){for(var n=0;n=f.length)return;var a=t[n];if("string"==typeof a||"string"==typeof a.content){var r=f[i],o="string"==typeof a?a:a.content,s=o.indexOf(r);if(-1!==s){++i;var l=o.substring(0,s),d=c(u[r]),p=o.substring(s+r.length),g=[];if(l&&g.push(l),g.push(d),p){var m=[p];e(m),g.push.apply(g,m)}"string"==typeof a?(t.splice.apply(t,[n,1].concat(g)),n+=g.length-1):a.content=g}}else{var h=a.content;Array.isArray(h)?e(h):e([h])}}}(d),new e.Token(a,d,"language-"+a,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var a=0,r=n.length;a]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(r),function(e){function t(e,t){return RegExp(e.replace(//g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:(?:\s*,\s*(?:\*\s*as\s+|\{[^{}]*\}))?|\*\s*as\s+|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],a=0;a*\.{3}(?:[^{}]|)*\})/.source;function o(e,t){return e=e.replace(//g,(function(){return n})).replace(//g,(function(){return a})).replace(//g,(function(){return r})),RegExp(e,t)}r=o(r).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},s=function(t){for(var n=[],a=0;a0&&n[n.length-1].tagName===i(r.content[0].content[1])&&n.pop():"/>"===r.content[r.content.length-1].content||n.push({tagName:i(r.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===r.type&&"{"===r.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===r.type&&"}"===r.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof r)&&n.length>0&&0===n[n.length-1].openedBraces){var l=i(r);a0&&("string"==typeof t[a-1]||"plain-text"===t[a-1].type)&&(l=i(t[a-1])+l,t.splice(a-1,1),a--),t[a]=new e.Token("plain-text",l,null,l)}r.content&&"string"!=typeof r.content&&s(r.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||s(e.tokens)}))}(r),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var a=t[n],r=[];/^\w+$/.test(n)||r.push(/\w+/.exec(n)[0]),"diff"===n&&r.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+a+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:r,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(r),r.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},r.languages.go=r.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),r.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete r.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,r,o){if(n.language===a){var i=n.tokenStack=[];n.code=n.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,s=i.length;-1!==n.code.indexOf(r=t(a,s));)++s;return i[s]=e,r})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var r=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[r],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(a,u),g=f.indexOf(p);if(g>-1){++r;var m=f.substring(0,g),h=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),b=f.substring(g+p.length),v=[];m&&v.push.apply(v,i([m])),v.push(h),b&&v.push.apply(v,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(v)):c.content=v}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(r),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(r),r.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},r.languages.webmanifest=r.languages.json,r.languages.less=r.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),r.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),r.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},r.languages.objectivec=r.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete r.languages.objectivec["class-name"],r.languages.objc=r.languages.objectivec,r.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},r.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},r.languages.python["string-interpolation"].inside.interpolation.inside.rest=r.languages.python,r.languages.py=r.languages.python,r.languages.reason=r.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),r.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete r.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(r),r.languages.scss=r.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),r.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),r.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),r.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),r.languages.scss.atrule.inside.rest=r.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},a={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};a.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:a}},a.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:a}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:a}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:a}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:a}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:a.interpolation}},rest:a}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:a.interpolation,comment:a.comment,punctuation:/[{},]/}},func:a.func,string:a.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:a.interpolation,punctuation:/[{}()\[\];:.]/}}(r),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(r),r.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=r},40485:()=>{!function(e){var t={pattern:/((?:^|[^\\$])(?:\\{2})*)\$(?:\w+|\{[^{}]*\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}};e.languages.groovy=e.languages.extend("clike",{string:{pattern:/'''(?:[^\\]|\\[\s\S])*?'''|'(?:\\.|[^\\'\r\n])*'/,greedy:!0},keyword:/\b(?:abstract|as|assert|boolean|break|byte|case|catch|char|class|const|continue|def|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|in|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),e.languages.insertBefore("groovy","string",{shebang:{pattern:/#!.+/,alias:"comment",greedy:!0},"interpolation-string":{pattern:/"""(?:[^\\]|\\[\s\S])*?"""|(["/])(?:\\.|(?!\1)[^\\\r\n])*\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}}}),e.languages.insertBefore("groovy","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),e.languages.insertBefore("groovy","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),t.inside.expression.inside=e.languages.groovy}(Prism)},52503:()=>{!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,a={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[a,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:a.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:a.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:a.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)},32334:()=>{!function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"];var t={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:e.languages.kotlin}};e.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:t},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:t},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete e.languages.kotlin.string,e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(Prism)},52811:(e,t,n)=>{var a={"./prism-groovy":40485,"./prism-java":52503,"./prism-kotlin":32334};function r(e){var t=o(e);return n(t)}function o(e){if(!n.o(a,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return a[e]}r.keys=function(){return Object.keys(a)},r.resolve=o,e.exports=r,r.id=52811},92703:(e,t,n)=>{"use strict";var a=n(50414);function r(){}function o(){}o.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,o,i){if(i!==a){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:r};return n.PropTypes=n,n}},45697:(e,t,n)=>{e.exports=n(92703)()},50414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},64448:(e,t,n)=>{"use strict";var a=n(67294),r=n(27418),o=n(63840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n
+ + \ No newline at end of file diff --git a/docs/etc/communication.html b/docs/etc/communication.html index 77c4e360b..82a09345e 100644 --- a/docs/etc/communication.html +++ b/docs/etc/communication.html @@ -13,15 +13,15 @@ - - + +

커뮤니케이션 잘하는 개발자의 4가지 습관

커뮤니케이션 잘 하는 개발자?

스펙 구현형 개발자 vs 문제 해결형 개발자

개발자 != 스펙을 주면 잘 구현하는 사람
구현에 집중한다면 일의 시야가 좁아진다.

의도와 맥락을 이해해서, 더 좋은 스펙을 만들어내려고 하는 개발자가 되어야 한다.

변화를 만들려면 습관이 필요하다.

주니어 개발자는 스펙 구현 개발자에서 시작한다.
-변화를 위해 실제로 행동하는 습관이 필요하다.

좋은 습관 4가지

  1. 해결하려는 문제의도/상황에 대해 묻는다.
  2. 상대방의 말을 듣고 내가 이해한 바를 요약하여 공유한다.
    • 한 번 정리한다면 1... 2... 이렇게 이해했는데 맞을까요?
  3. 안 된다고 말할 때는 상대방에 관점에서 대안을 제시한다.
    • 제약을 덜 받는 다른 방향성/대안 제시
  4. 문제를 해결할 또 다른 방법은 없을지 고민해본다.
    • 단정대신 한 번 더 질문하고 생각

참고 자료

커뮤니케이션 잘하는 개발자의 4가지 습관 - 송범근, INFCON 2023

- - +변화를 위해 실제로 행동하는 습관이 필요하다.

좋은 습관 4가지

  1. 해결하려는 문제의도/상황에 대해 묻는다.
  2. 상대방의 말을 듣고 내가 이해한 바를 요약하여 공유한다.
    • 한 번 정리한다면 1... 2... 이렇게 이해했는데 맞을까요?
  3. 안 된다고 말할 때는 상대방에 관점에서 대안을 제시한다.
    • 제약을 덜 받는 다른 방향성/대안 제시
  4. 문제를 해결할 또 다른 방법은 없을지 고민해본다.
    • 단정대신 한 번 더 질문하고 생각

참고 자료

커뮤니케이션 잘하는 개발자의 4가지 습관 - 송범근, INFCON 2023

+ + \ No newline at end of file diff --git a/docs/etc/develop-with-spring.html b/docs/etc/develop-with-spring.html index ffb3a4567..551c24e83 100644 --- a/docs/etc/develop-with-spring.html +++ b/docs/etc/develop-with-spring.html @@ -13,8 +13,8 @@ - - + +
@@ -31,8 +31,8 @@ 초기 개발 생산성, 변경 용이성 등을 관찰

공유와 논쟁

문서, 발표 자료로 정리
정리에 시간을 많이 들이면 효율성이 떨어지기에 중요한 부분만 정리
간단한 작성, 검색이 가능한 도구 활용
-나만의 정의와 설명을 만들어가기 -> 한 문장, 한 문단, 5분간 설명, 점점 늘려가며

참고 자료

스프링과 함께 더 나은 개발자 되기 - 토비, INFCON 2023

- - +나만의 정의와 설명을 만들어가기 -> 한 문장, 한 문단, 5분간 설명, 점점 늘려가며

참고 자료

스프링과 함께 더 나은 개발자 되기 - 토비, INFCON 2023

+ + \ No newline at end of file diff --git a/docs/etc/experience-and-self-question.html b/docs/etc/experience-and-self-question.html index f86023d64..5e9124df7 100644 --- a/docs/etc/experience-and-self-question.html +++ b/docs/etc/experience-and-self-question.html @@ -13,8 +13,8 @@ - - + +
@@ -27,8 +27,8 @@ 당연하다 생각하는 해결책에 의구심을 가지고 새로운 접근 방식으로 도전한 경험

자신에게 던져봐야할 질문

나는 프로그래밍 자체를 즐기고 있는가?
나는 왜 프로그래머가 되려고 하는가?
나는 나답게 살고 있나?
-나는 주도적으로 살고 있나?

- - +나는 주도적으로 살고 있나?

+ + \ No newline at end of file diff --git a/docs/etc/healthful-growth.html b/docs/etc/healthful-growth.html index b543daa6f..aff464bb3 100644 --- a/docs/etc/healthful-growth.html +++ b/docs/etc/healthful-growth.html @@ -13,8 +13,8 @@ - - + +
@@ -36,8 +36,8 @@ 커뮤니케이션 방법, 신뢰 자산을 확보하는 방법, 문화를 만들어가는 방법, 결정의 기준과 같은 부분을 학습할 수 있다.

보상

시련 뒤에는 항상 보물이 기다리고 있다.
보상을 통해 꾸준함을 유지할 수 있도록 만들어라.

남을 설득하는 방법 배우기

팀원들이 매번 내 의견을 반대한다면 완벽한 논리가 중요한게 아니다.
어떻게 하면 신뢰 자산을 확보할 수 있는가?
-커뮤니케이션, 협업, 소프트 스킬에서 부족함이 있으면 안된다.

- - +커뮤니케이션, 협업, 소프트 스킬에서 부족함이 있으면 안된다.

+ + \ No newline at end of file diff --git a/docs/jpa/key.html b/docs/jpa/key.html index 9395b179e..370c3e38c 100644 --- a/docs/jpa/key.html +++ b/docs/jpa/key.html @@ -13,8 +13,8 @@ - - + +
@@ -29,8 +29,8 @@ MySQL의 경우 IDENTITY Oracle의 경우 SEQUENCE를 선택한다.

UUID

JPA 3.1.0 UUID 생성 전략이 추가되었다.
Hibernate 6.2부터 JPA 3.1.0을 지원하기 때문에 스프링 부트 3.1 이상인 경우 사용할 수 있다.

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Member {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
@UuidGenerator(style = Style.RANDOM)
private Long id;
}

UuidGenerator를 이용하여 UUID 생성 방식도 설정할 수 있다.
생성 방식은 3가지가 있다.

  • RANDOM - 난수 기반 UUID 생성(uuid v4)
  • TIME – 시간 기반 UUID 생성(uuid v1)
  • AUTO – 기본 옵션, RANDOM과 동일

UUID의 경우 많은 양의 저장 공간을 필요로 하고, 성능 문제가 발생할 수 있기에 UUID를 사용해야 하는 경우 TSID를 고려할 수 있을 것 같다.

참고 자료

자바 ORM 표준 JPA 프로그래밍, 김영한 p.131 ~ p.144
-Generate UUIDs as Primary Keys With Hibernate

- - +Generate UUIDs as Primary Keys With Hibernate

+ + \ No newline at end of file diff --git a/docs/linux/shell.html b/docs/linux/shell.html index df22ada6e..c7084ec0f 100644 --- a/docs/linux/shell.html +++ b/docs/linux/shell.html @@ -13,8 +13,8 @@ - - + +
@@ -23,7 +23,7 @@ ~/.bashrc 파일에 PS1에 대한 값을 설정하여 동일한 계정으로 재접속하여도 설정을 유지할 수 있다.

이스케이프 문자

이스케이프 문자를 사용하여 쉘 프롬프트에 서버에 대한 정보를 추가할 수 있다.

이스케이프 문자설명
\u사용자 이름
\h호스트 이름
\w현재 작업 디렉토리 (전체 경로)
\W현재 작업 디렉토리 (디렉토리 이름)
\d현재 날짜 (YYYY-MM-DD)
\t현재 시간 (HH:MM:SS)
\n줄 바꿈 문자
\$일반 사용자 $ root의 경우 #

색상 설정

\e[ - 색상 변경을 시작하고 싶을 때 사용한다.
색상코드m - 색상을 선택한다.
\e[0m - 색상 변경을 종료하고 싶을 때 사용한다.

빨간색 hello world → "\e[31mhello world!\e[0m"

echo -e 옵션을 사용하여 색상이 정상적으로 적용되었는지 확인할 수 있다.

echo -e "\e[31mhello world! \e[0m"

색상표

색상글자색배경색
Black3040
Red3141
Green3242
Yellow3343
Blue3444
Purple3545
Cyan3646
White3747

~/.bashrc 파일에 적용

sudo vim ~/.bashrc 을 입력하여 설정 파일을 연 후에 적용하고 싶은 문자를 PS1 환경변수에 할당하고 저장한다.

~/.bashrc
PS1="\e[32m[\t TRIPDRAW-DEV \u]\$ \e[0m"

적용은 source 명령어를 이용하면 된다.

source ~/.bashrc

참고 자료

Linux Hint

- - + + \ No newline at end of file diff --git a/docs/linux/swap.html b/docs/linux/swap.html index d94f24084..b6fb0d3ab 100644 --- a/docs/linux/swap.html +++ b/docs/linux/swap.html @@ -13,8 +13,8 @@ - - + +
@@ -24,7 +24,7 @@ /etc/fstab 파일을 수정하여 Swap 메모리를 영구적으로 적용할 수 있다.

  • 해당 파일은 리눅스 부팅시 마운트정보를 저장하고 있다.
# vim을 이용하여 해당 파일을 수정한다.
sudo vim /etc/fstab
# 최하단에 다음과 같이 설정하면 된다.
/swapfile swap swap defaults 0 0

Swap 메모리 적용되었는지 확인

리눅스에서는 free 명령어를 통해 메모리를 확인할 수 있다.
-h 옵션을 주면 좀 더 읽기 편한 형태로 출력된다.

free -h
total used free shared buff/cache available
Mem: 905Mi 570Mi 65Mi 0.0Ki 270Mi 186Mi
Swap: 2.0Gi 626Mi 1.4Gi

아래에 Swap 메모리가 적용되어있는 것을 확인할 수 있다.
추가로 swapon 명령어로도 확인할 수 있다.

Swap 메모리 비활성화

swapoff 명령어를 사용하여 비활성화 한 후 파일을 삭제하면 된다.

# swap 설정한 파일 비활성화
sudo swapoff -v /swapfile
# 삭제
sudo rm /swapfile

만약 /etc/fstab에 값을 설정했을 경우 해당 값을 지워야한다.

참고 자료

How to Add Swap Space on Ubuntu 20.04, Lunuxize

- - + + \ No newline at end of file diff --git a/docs/monitoring/intro.html b/docs/monitoring/intro.html index e4bac50b1..d664dff1d 100644 --- a/docs/monitoring/intro.html +++ b/docs/monitoring/intro.html @@ -13,8 +13,8 @@ - - + +
@@ -26,8 +26,8 @@ 핀포인트, 스카우트, 와탭, 제니퍼

로그

가장 세세한 추적
같은 HTTP 요청을 묶어서 확인할 수 있는 방법이 중요하다.
MDC(Mapped Diagnostic Context) 적용

파일로 직접 로그를 남기는 경우 → 일반 로그와 에러 로그 파일을 구분해서 남겨야 한다.
-클라우드에 저장하는 경우 → 검색이 잘 되도록 구분한다.

모니터링

관찰의 경우 전체 → 좁게

알람

알람의 경우 2가지 종류(경고, 심각)로 구분해서 관리한다.

참고 자료

스프링 부트 핵심 원리와 활용, 김영한

- - +클라우드에 저장하는 경우 → 검색이 잘 되도록 구분한다.

모니터링

관찰의 경우 전체 → 좁게

알람

알람의 경우 2가지 종류(경고, 심각)로 구분해서 관리한다.

참고 자료

스프링 부트 핵심 원리와 활용, 김영한

+ + \ No newline at end of file diff --git a/docs/network/load-balancing-algorithm.html b/docs/network/load-balancing-algorithm.html index 923d2c37b..ca8452810 100644 --- a/docs/network/load-balancing-algorithm.html +++ b/docs/network/load-balancing-algorithm.html @@ -13,8 +13,8 @@ - - + +
@@ -22,8 +22,8 @@ Hashing key는 클라이언트의 IP + port 혹은 IP 주소만으로 결정
사용자가 항상 동일한 서버로 연결되는 것을 보장

최소 응답 시간 방식(Least Response Time Method)

서버의 현재 연결 상태, 응답 시간 고려하여 트래픽을 전송
가장 적은 연결 상태와 가장 짧은 응답 시간을 보이는 서버에 우선적으로 로드를 배분하는 방식

참고 자료

load balancing, AWS
-로드 밸런싱에 대해 알아보자, 테코블

- - +로드 밸런싱에 대해 알아보자, 테코블

+ + \ No newline at end of file diff --git a/docs/network/load-balancing.html b/docs/network/load-balancing.html index 4b2fcad5b..02fd7c17f 100644 --- a/docs/network/load-balancing.html +++ b/docs/network/load-balancing.html @@ -13,8 +13,8 @@ - - + +
@@ -25,8 +25,8 @@ 트래픽이 증가하는 경우 AutoScaling을 통해 서버를 자동으로 확장(Scale-out)
트래픽이 감소하는 경우 축소(Scale-in)

보안

분산 서비스 거부 공격(DDoS)이 발생하는 경우 해당 트래픽을 부하 분산할 수 있다.

성능

서버 간 로드를 균등하게 배포하여 애플리케이션의 성능을 향상 시킨다.
클라이언트 요청을 지리적으로 더 가까운 서버로 리다이렉션하여 지연 시간을 단축시킨다.

내결함성(Fault Tolerance)과 확장성(Scalability)

내결함성: 시스템의 일부 구성 요소가 작동하지 않더라도 계속 작동할 수 있는 기능
-확장성: 대규모적인 재설계/재설치 등의 필요없이 확장이 얼마나 쉽고 가능한가에 대한 용이성

참고 자료

load balancing, AWS

- - +확장성: 대규모적인 재설계/재설치 등의 필요없이 확장이 얼마나 쉽고 가능한가에 대한 용이성

참고 자료

load balancing, AWS

+ + \ No newline at end of file diff --git a/docs/nginx/command.html b/docs/nginx/command.html index 16dd0472d..be25e6f86 100644 --- a/docs/nginx/command.html +++ b/docs/nginx/command.html @@ -13,8 +13,8 @@ - - + +
@@ -24,8 +24,8 @@ conf.d 디렉터리 대신 site-enabled 디렉터리와 symlink를 통해 설정 파일을 연결하는 방법은 더 이상 사용하지 않는다.

NIGNX 설정

nginx 설정의 경우 include 구문을 활용해 구조화하여 설정 파일을 간결하게 유지하는 것이 좋다.

/var/log/nginx/

엔진엑스 로그가 저장되는 디렉터리로 access 로그와 error 로그를 확인할 수 있다.
로그 형식의 경우 설정 파일의 log_format 구문을 이용해서 변경할 수 있다.

명령어

nginx -t

nginx 설정이 정상인지 확인한다.

nginx -T

nginx 설정 확인의 결과를 조금 더 자세하게 출력해준다.

nginx -s <SIGNAL>

여기서 SIGNAL은 다음 중 하나를 선택할 수 있다.

  • quit: 정상적으로 종료(SIGQUIT)
  • reload: 설정 파일 리로드(SIGHUP)
  • reopen: 로그 파일을 다시 열도록 요청(SIGUSR1)
  • stop: 종료 요청(SIGTERM)

여기서 SIGQUIT & SIGTREM 모두 graceful shutdown을 수행한다.

참고 자료

NGINX 쿡북, 데릭 디용기 p.22 ~ p.23
https://docs.nginx.com/
-https://docs.nginx.com/nginx/admin-guide/monitoring/logging/

- - +https://docs.nginx.com/nginx/admin-guide/monitoring/logging/

+ + \ No newline at end of file diff --git a/docs/nginx/static-file.html b/docs/nginx/static-file.html index 733b21385..e92b03bb6 100644 --- a/docs/nginx/static-file.html +++ b/docs/nginx/static-file.html @@ -13,15 +13,15 @@ - - + +
본문으로 건너뛰기

정적 컨텐츠 제공

root

클라이언트에게 파일을 제공할 때 사용되는 경로를 지정하는 데 사용한다.
root의 경우 locaiton으로 넘어온 경로를 root 경로 뒤에 추가한다.

root
# localhost/images/1.png 호출 /var/www/images/images/1.png 검색
location /images/ {
root /var/www/images;
}

alias

location으로 매칭된 부분을 제거한다.

alias
# localhost/images/1.png 호출 /var/www/images/1.png 검색
location /images/ {
alias /var/www/images;
}

try_files

try_files 디렉티브를 이용해서 파일이 존재하지 않으면 적절한 값을 반환할 수 있다.
-설정하지 않으면 기본으로 404를 반환한다.

location /images/ {
alias /var/www/images;
try_files $uri $uri/ =404;
}

다음과 같이 proxy 설정으로도 구성할 수도 있다.

location /images/ {
root /root;
try_files $uri $uri/ default-image;
}

location default-image {
proxy_pass http://localhost/images/default_image.jpg;
}

참고 자료

Serving Static Content

- - +설정하지 않으면 기본으로 404를 반환한다.

location /images/ {
alias /var/www/images;
try_files $uri $uri/ =404;
}

다음과 같이 proxy 설정으로도 구성할 수도 있다.

location /images/ {
root /root;
try_files $uri $uri/ default-image;
}

location default-image {
proxy_pass http://localhost/images/default_image.jpg;
}

참고 자료

Serving Static Content

+ + \ No newline at end of file diff --git a/docs/performance/throughput-latency.html b/docs/performance/throughput-latency.html index 2b37d994d..02b3d990e 100644 --- a/docs/performance/throughput-latency.html +++ b/docs/performance/throughput-latency.html @@ -13,8 +13,8 @@ - - + +
@@ -26,8 +26,8 @@ Latency는 다음과 같이 두 가지로 구분할 수 있다.

사용자가 본 처리 시간: 사용자가 요청을 보내고 응답을 받을 때까지의 시간
시스템에서 본 처리 시간: 시스템이 요청을 받고 응답을 보낼 때까지의 시간

사용자가 본 처리 시간의 경우 네트워크에 대한 시간이 포함된다.
따라서 성능 측정과 개선은 시스템에서 본 처리 시간으로 측정하고 개선하는 것이 더 정확해 보인다.

다음과 같은 시스템이 있다고 가정해보자.

  • 시스템 A: 요청시 평균 200ms 내 응답
  • 시스템 B: 요청시 평균 100ms 내 응답

시스템 B가 요청에 대한 응답이 더 빠르니, 시스템 B의 성능이 더 좋다고 할 수 있다.

참고 자료

아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄
-difference between throughput and latency, AWS - 해당 내용은 네트워크 기준이다.

- - +difference between throughput and latency, AWS - 해당 내용은 네트워크 기준이다.

+ + \ No newline at end of file diff --git a/docs/performance/throughput.html b/docs/performance/throughput.html index ea47abf2b..823076334 100644 --- a/docs/performance/throughput.html +++ b/docs/performance/throughput.html @@ -13,8 +13,8 @@ - - + +
@@ -23,8 +23,8 @@ 최대 rps: 1일 평균 rps x 최대 피크 때의 비율(평균 접속 수 대비)

최대 rps * 안전계수(2 ~ 3배)를 Throughput의 목표치로 한다.

계산 예시

DAU: 10만명
1명당 평균 접속수: 10회
평균 접속 수 대비 최대 피크 비율: 4배
-안전계수: 3배

100000 x 10 / 86400 x 4 x 3 -> 약 138rps

참고 자료

아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

- - +안전계수: 3배

100000 x 10 / 86400 x 4 x 3 -> 약 138rps

참고 자료

아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

+ + \ No newline at end of file diff --git a/docs/performance/types.html b/docs/performance/types.html index cad8a0873..f13001e24 100644 --- a/docs/performance/types.html +++ b/docs/performance/types.html @@ -13,13 +13,13 @@ - - + +
-
본문으로 건너뛰기

성능 테스트 유형

테스트설명
지연 테스트(latency test)요청에 대한 응답 시간을 측정
처리율 테스트(throughput test)시스템 성능이 급락하기 직전, 최대 처리율 수치를 측정
부하 테스트(load test)비즈니스 이벤트를 대비해 트래픽을 견딜 수 있는지 확인
스트레스 테스트(stress test)시스템의 한계점을 확인
내구 테스트(endurance test)장시간 실행할 경우 성능 이상이 발생하는지 확인
용량 계획 테스트(capacity planning test)리소스를 추가한 만큼 시스템이 확장되는지 확인
저하 테스트(degradation test)시스템이 부분적으로 실패할 경우 어떤 일이 발생하는지 확인(장애 복구 및 회복 등)

참고 자료

자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드

- - +
본문으로 건너뛰기

성능 테스트 유형

테스트설명
지연 테스트(latency test)요청에 대한 응답 시간을 측정
처리율 테스트(throughput test)시스템 성능이 급락하기 직전, 최대 처리율 수치를 측정
부하 테스트(load test)비즈니스 이벤트를 대비해 트래픽을 견딜 수 있는지 확인
스트레스 테스트(stress test)시스템의 한계점을 확인
내구 테스트(endurance test)장시간 실행할 경우 성능 이상이 발생하는지 확인
용량 계획 테스트(capacity planning test)리소스를 추가한 만큼 시스템이 확장되는지 확인
저하 테스트(degradation test)시스템이 부분적으로 실패할 경우 어떤 일이 발생하는지 확인(장애 복구 및 회복 등)

참고 자료

자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드

+ + \ No newline at end of file diff --git a/docs/tags.html b/docs/tags.html index a57f77a79..15ea05037 100644 --- a/docs/tags.html +++ b/docs/tags.html @@ -13,13 +13,13 @@ - - + + - - + + \ No newline at end of file diff --git a/docs/tags/book.html b/docs/tags/book.html index c17cadce3..2dbbe9cf6 100644 --- a/docs/tags/book.html +++ b/docs/tags/book.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "book" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/etc.html b/docs/tags/etc.html index 27ecb9f6c..7ec721e53 100644 --- a/docs/tags/etc.html +++ b/docs/tags/etc.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

4개 문서가 "etc" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/jpa.html b/docs/tags/jpa.html index 3c5e1a4cb..1e81fbd32 100644 --- a/docs/tags/jpa.html +++ b/docs/tags/jpa.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "JPA" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/latency.html b/docs/tags/latency.html index e3310e819..54d2aa8fd 100644 --- a/docs/tags/latency.html +++ b/docs/tags/latency.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "latency" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/load-balancing.html b/docs/tags/load-balancing.html index 23fcc5d2f..3f24ed65b 100644 --- a/docs/tags/load-balancing.html +++ b/docs/tags/load-balancing.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

2개 문서가 "load balancing" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/monitoring.html b/docs/tags/monitoring.html index f5c73b2a0..1b079af26 100644 --- a/docs/tags/monitoring.html +++ b/docs/tags/monitoring.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "monitoring" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/network.html b/docs/tags/network.html index 2e7fc3434..df5a0d450 100644 --- a/docs/tags/network.html +++ b/docs/tags/network.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

2개 문서가 "network" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/nginx.html b/docs/tags/nginx.html index 66cbd86ff..7e7331dd8 100644 --- a/docs/tags/nginx.html +++ b/docs/tags/nginx.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

2개 문서가 "nginx" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/package.html b/docs/tags/package.html index e9475ee9b..3631f60e5 100644 --- a/docs/tags/package.html +++ b/docs/tags/package.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "package" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/performance.html b/docs/tags/performance.html index 69652a523..80c9ea759 100644 --- a/docs/tags/performance.html +++ b/docs/tags/performance.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "performance" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/postmortem.html b/docs/tags/postmortem.html index 42257a729..8690d5009 100644 --- a/docs/tags/postmortem.html +++ b/docs/tags/postmortem.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

1개 문서가 "postmortem" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/test.html b/docs/tags/test.html index 7012e7df9..fd62b1977 100644 --- a/docs/tags/test.html +++ b/docs/tags/test.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

5개 문서가 "test" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/tags/throughput.html b/docs/tags/throughput.html index 89fd8fdaf..599db2652 100644 --- a/docs/tags/throughput.html +++ b/docs/tags/throughput.html @@ -13,13 +13,13 @@ - - + +
본문으로 건너뛰기

2개 문서가 "throughput" 태그에 분류되었습니다

모든 태그 보기
- - + + \ No newline at end of file diff --git a/docs/test/benefit.html b/docs/test/benefit.html index 3d2cd311b..e2b326af1 100644 --- a/docs/test/benefit.html +++ b/docs/test/benefit.html @@ -13,8 +13,8 @@ - - + +
@@ -24,8 +24,8 @@ 리팩터링할 때 자신감을 가지고 변경 사항을 반영할 수 있다.

더 나은 문서 자료

하나의 행위만 집중해 검증하는 테스트는 실행 가능한 문서와 같다.
이 때 테스트는 명확하고 간결해야지만 문서 자료로서의 역할을 훌륭히 수행할 수 있다.

더 단순한 리뷰

정확성, 극단 상황, 오류 상황 등의 다양한 측면에서 코드를 검사해주는 테스트가 준비되어 있다면 리뷰어가 검증하는 시간을 크게 줄여준다.

사려 깊은 설계

새로 작성한 코드의 테스트를 작성하는 일은 실질적으로 해당 코드의 API가 잘 설계되어 있는지를 시험하는 행위다.
테스트하기 어려운 코드는 너무 많은 책임을 가지고 있거나, 의존성이 복잡한 경우가 많다.
-잘 설계된 코드라면 모듈화가 잘 되어있어야 한다.

고품질의 릴리스를 빠르게

자동화된 테스트를 갖춘다면 새로운 버전을 릴리스할 때 불안에 떨지 않아도 된다.

참고 자료

구글 엔지니어는 이렇게 일한다, 타이터스 윈터스, 톰 맨쉬렉, 하이럼 라이트 p.288

- - +잘 설계된 코드라면 모듈화가 잘 되어있어야 한다.

고품질의 릴리스를 빠르게

자동화된 테스트를 갖춘다면 새로운 버전을 릴리스할 때 불안에 떨지 않아도 된다.

참고 자료

구글 엔지니어는 이렇게 일한다, 타이터스 윈터스, 톰 맨쉬렉, 하이럼 라이트 p.288

+ + \ No newline at end of file diff --git a/docs/test/first.html b/docs/test/first.html index f783e06e2..b25e589d6 100644 --- a/docs/test/first.html +++ b/docs/test/first.html @@ -13,8 +13,8 @@ - - + +
@@ -27,8 +27,8 @@ JUnit과 같은 자동화된 테스트 도구를 사용해야 한다.

Timely(적시에)

테스트는 적시에 작성해야 한다.
단위 테스트는 테스트 하려는 실제 코드를 구현하기 직전에 구현해야 한다.(TDD)
실제 코드를 구현한 다음에 테스트 코드를 작성한다면, 테스트 하기 어려운 코드를 작성했다는 것을 뒤늦게 발견할 수 있다.

참고 자료

A clean test, TDD Manifasto
-Clean Code 9장 단위테스트, 로버트 C. 마틴

- - +Clean Code 9장 단위테스트, 로버트 C. 마틴

+ + \ No newline at end of file diff --git a/docs/test/heuristics.html b/docs/test/heuristics.html index 16e3ccd71..1a5f76284 100644 --- a/docs/test/heuristics.html +++ b/docs/test/heuristics.html @@ -13,13 +13,13 @@ - - + +
-
본문으로 건너뛰기

TDD heuristics

TDD heuristics

  1. 여러분이 작성하고 싶은 코드를 작성하도록 만드는 테스트를 작성하라.
  2. 실패시켜라. 통과시켜라. 그리고 정리하라.
  3. 최상의 결과를 추구하지 말라.
  4. 실패하는 가장 간단하고, 가장 구체적이며, 가장 퇴화한 테스트를 작성하라.
  5. 가능하면 일반화하라.
  6. 코드가 틀렸다고 느껴지면 잠시 멈춰서 설계를 고쳐라.
  7. 더 복잡한 다음 경우로 넘어가기 전, 지금 다루고 있는 더 단순한 경우를 모조리 테스트하라.
  8. 현재 테스트를 통과시키기 위해 너무 많은 구현을 해야 한다면, 테스트를 지우고 더 쉽게 통과할 수 있는 더 단순한 테스트를 작성하라.
  9. 테스트 공간(test space)을 전부 포괄하는 신중하고 점진적인 패턴을 따르라.
  10. 필요 없는 것을 여러분의 테스트에 넣지 말라.
  11. 테스트에 실제 서비스 데이터를 사용하지 말라.
  12. 테스트 구조를 제품 코드 구조로부터 분리하라.
  13. 테스트가 구체적(specific)이 될수록 코드는 일반적(generic)이 된다.
  14. 변환을 적용한 결과 최적이 아닌 해답에 도달했다면 다른 변환을 시도해보라.
  15. 디버거 사용을 피하라

참고 자료

소프트웨어 장인 정신 이야기, 로버트 C. 마틴 p.44 ~ p.209

- - +
본문으로 건너뛰기

TDD heuristics

TDD heuristics

  1. 여러분이 작성하고 싶은 코드를 작성하도록 만드는 테스트를 작성하라.
  2. 실패시켜라. 통과시켜라. 그리고 정리하라.
  3. 최상의 결과를 추구하지 말라.
  4. 실패하는 가장 간단하고, 가장 구체적이며, 가장 퇴화한 테스트를 작성하라.
  5. 가능하면 일반화하라.
  6. 코드가 틀렸다고 느껴지면 잠시 멈춰서 설계를 고쳐라.
  7. 더 복잡한 다음 경우로 넘어가기 전, 지금 다루고 있는 더 단순한 경우를 모조리 테스트하라.
  8. 현재 테스트를 통과시키기 위해 너무 많은 구현을 해야 한다면, 테스트를 지우고 더 쉽게 통과할 수 있는 더 단순한 테스트를 작성하라.
  9. 테스트 공간(test space)을 전부 포괄하는 신중하고 점진적인 패턴을 따르라.
  10. 필요 없는 것을 여러분의 테스트에 넣지 말라.
  11. 테스트에 실제 서비스 데이터를 사용하지 말라.
  12. 테스트 구조를 제품 코드 구조로부터 분리하라.
  13. 테스트가 구체적(specific)이 될수록 코드는 일반적(generic)이 된다.
  14. 변환을 적용한 결과 최적이 아닌 해답에 도달했다면 다른 변환을 시도해보라.
  15. 디버거 사용을 피하라

참고 자료

소프트웨어 장인 정신 이야기, 로버트 C. 마틴 p.44 ~ p.209

+ + \ No newline at end of file diff --git a/docs/test/stairstep.html b/docs/test/stairstep.html index 831ecbc6d..f2a45c763 100644 --- a/docs/test/stairstep.html +++ b/docs/test/stairstep.html @@ -13,15 +13,15 @@ - - + +
본문으로 건너뛰기

계단 테스트

계단 테스트(Stairstep Test)

추후에 필요로 할 클래스, 함수, 다른 구조를 만들도록 강제하기 위해 작성하는 테스트
아무런 단정문이 없을 수도 있고, 기능이 조금 더 구현된다면 제거하고 포괄적인 테스트로 대신할 수 있다.
-복잡도를 필요한 수준까지 점진적으로 증가시킬 수 있게 도와주는 계단 역할을 하기 때문에 계단 테스트라고 부른다.

참고 자료

소프트웨어 장인 정신 이야기, 로버트 C. 마틴 p.74

- - +복잡도를 필요한 수준까지 점진적으로 증가시킬 수 있게 도와주는 계단 역할을 하기 때문에 계단 테스트라고 부른다.

참고 자료

소프트웨어 장인 정신 이야기, 로버트 C. 마틴 p.74

+ + \ No newline at end of file diff --git a/docusaurus.html b/docusaurus.html index 470aaeb99..236c56551 100644 --- a/docusaurus.html +++ b/docusaurus.html @@ -13,12 +13,12 @@ - - + +
-
본문으로 건너뛰기

Docusaurus

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus

배포

배포 안내 문서
+

Docusaurus

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus

배포

배포 안내 문서
netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

레포지토리 생성

github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

설정 파일 수정

docusaurus.config
module.exports = {
// ...
url: 'https://greeng00se.github.io',
baseUrl: '/',
projectName: 'greeng00se.github.io',
organizationName: 'greeng00se',
trailingSlash: false,
// ...
};

토큰 설정

github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
@@ -39,7 +39,7 @@ jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

brew install jq

다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper

docusaurus 설정

전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

docusaurus.config
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
...
algolia: {
appId: 'MVIU5UEMOM', // Application ID
apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
indexName: 'teco', // config.json에 설정한 인덱스명
contextualSearch: true,
},
})

부가 설정

화면 상단 Github Icon

파일 최하단에 아래 css 구문을 추가한다.

/src/css/custom.css
.header-github-link:hover {
opacity: 0.6;
}

.header-github-link:before {
content: '';
width: 24px;
height: 24px;
display: flex;
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

html[data-theme='dark'] .header-github-link:before {
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

themeconfig -> navbar에 github link를 설정한다.

docusaurus.config
navbar: {
title: 'HELLO',
items: [
{
href: 'https://github.com/greeng00se',
position: 'right',
className: 'header-github-link',
'aria-label': 'GitHub repository',
},
],
},

코드블럭

java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
prism 설정을 아래와 같이 변경해 준다.

docusaurus.config
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ['java', 'kotlin'],
}

mermaid

mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

yarn add @docusaurus/theme-mermaid

설치 후 아래와 같이 설정을 추가한다.

docusaurus.config
const config = {
...
markdown: {
mermaid: true,
},
themes: [
'@docusaurus/theme-mermaid'
],
};

themeConfig에서 mermaid의 테마를 지정할 수 있다.

docusaurus.config
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
...
mermaid: {
theme: {
light: 'neutral',
dark: 'dark'
},
},
}),

국제화 설정

국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

docusaurus.config
i18n: {
defaultLocale: "ko",
locales: ["ko"],
},

블로그 글 author

팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

author

authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

/blog/authors.yml
herb:
name: 허브
title: Backend
url: https://github.com/greeng00se
image_url: https://github.com/greeng00se.png

mallang:
name: 말랑
title: Backend
url: https://github.com/shin-mallang
image_url: https://github.com/shin-mallang.png

블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

---
slug: 1
title: Hello World
authors: [herb, mallang]
tags: [hello, docusaurus]
---

첫 번째 문서 내용
- - + + \ No newline at end of file diff --git a/grasp.html b/grasp.html index aa85bc3ed..bf0191004 100644 --- a/grasp.html +++ b/grasp.html @@ -13,15 +13,15 @@ - - + +
-

일반적인 책임 할당을 위한 패턴

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) +

일반적인 책임 할당을 위한 패턴

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) 객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

  • 오브젝트 p.17

결합도를 낮춘다면 다음과 같은 이점이 있다.

  • 다른 구성 요소의 변화에 영향을 받지 않는다.
  • 재사용이 편리해진다.
  • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)

높은 응집도 패턴(High Cohesion)

Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

응집도(Cohesion) 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

  • 오브젝트 p.26

변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

  • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
  • 유지보수가 쉬워진다.
  • 낮은 결합도 또한 지원한다.
  • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.

컨트롤러 패턴(Controller)

Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

어떤 서브시스템이 존재한다고 가정할 때

  • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
  • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
  • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.

다형성 패턴(Polymorphism)

Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

변경 보호 패턴(Protected Variations)

Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

간접 참조 패턴(Indirection)

Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

순수한 가공물 패턴(Pure Fabrication)

Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

  • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
  • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.

참고 자료

오브젝트 5장. 책임 할당하기, 조영호

Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

GRASP, 한빛 네트워크

- - + + \ No newline at end of file diff --git a/index.html b/index.html index 2035c7e6e..7556630b5 100644 --- a/index.html +++ b/index.html @@ -13,13 +13,13 @@ - - + +
- - + + \ No newline at end of file diff --git a/innodb-lock.html b/innodb-lock.html index 89b7ff256..669a4c9e8 100644 --- a/innodb-lock.html +++ b/innodb-lock.html @@ -13,12 +13,12 @@ - - + +
-

InnoDB 스토리지 엔진의 잠금

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
+

InnoDB 스토리지 엔진의 잠금

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

낙관적 동시성 제어(OCC, Optimistic concurrency control)

트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

비관적 동시성 제어(PCC, Pessimistic Concurrency Control)

트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

Shared & Exclusive Locks

InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

공유 잠금(S, shared lock)

데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
@@ -38,7 +38,7 @@ MySQL Innodb Locks, cecil1018
MySQL 8.0 InnoDB Locks, MySQL
Locks Set by Different SQL Statements in InnoDB, MySQL

- - + + \ No newline at end of file diff --git a/intellij-settings.html b/intellij-settings.html index 1e5346ef9..8a4b70987 100644 --- a/intellij-settings.html +++ b/intellij-settings.html @@ -13,13 +13,13 @@ - - + +
-

IntelliJ 설정

· 약 1분

Import 자동 적용

Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

auto-import

저장시 동작

Prefrences > Tools > Actions on Save

actions-on-save

Reformat Code: Code Reformmating

Optimize imports: 사용하지 않는 Import 제거

Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

메소드 추출, 변수 추출시 final 적용

Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

final-modifier

- - +

IntelliJ 설정

· 약 1분

Import 자동 적용

Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

auto-import

저장시 동작

Prefrences > Tools > Actions on Save

actions-on-save

Reformat Code: Code Reformmating

Optimize imports: 사용하지 않는 Import 제거

Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

메소드 추출, 변수 추출시 final 적용

Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

final-modifier

+ + \ No newline at end of file diff --git a/java-class-file.html b/java-class-file.html index 40b6355ea..8f4a2e05f 100644 --- a/java-class-file.html +++ b/java-class-file.html @@ -13,12 +13,12 @@ - - + +
-

자바 클래스 파일 구조

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
+

자바 클래스 파일 구조

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
컴파일된 클래스파일은 어떤 구조로 되어있을까?

클래스 파일의 데이터 형식

8비트 바이트의 스트림으로 구성된다.
16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
멀티바이트의 경우 항상 big endian 순서로 저장된다.

u1 → unsigned 1byte
@@ -36,7 +36,7 @@ Class file in Java, File Format
java se11 Class 파일 형식, Oracle
java se17 Class 파일 형식, Oracle

- - + + \ No newline at end of file diff --git a/java-spring-springboot.html b/java-spring-springboot.html index e76fe2a37..252c7be9b 100644 --- a/java-spring-springboot.html +++ b/java-spring-springboot.html @@ -13,12 +13,12 @@ - - + +
-

자바 17, 스프링 6.0, 스프링 부트 3.1

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
+

자바 17, 스프링 6.0, 스프링 부트 3.1

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

자바 변경 사항

우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

Switch Expressions(Java 14)

Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

enum RESULT {
WIN, LOSE, DRAW
}

RESULT result = RESULT.WIN;

int prize = switch (result) {
case WIN -> 10_000_000;
case LOSE, DRAW -> 5_000_000;
default -> 0;
};

주요 특징은 다음과 같다.

  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • break 문이 필요 없다.
  • default 블록을 통해 기본 값을 지정할 수 있다.

Text Block(Java 15)

Java 15에는 새로운 문자열 표현방식이 추가되었다.
긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("""
SELECT p FROM Post p
WHERE p.title LIKE %:keyword%
OR p.content LIKE %:keyword%
""")
List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
}

NPE 메시지(Java 15)

String name = null;
name.chars();

/**
# before
java.lang.NullPointerException
at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)

# after
Cannot invoke "String.chars()" because "name" is null
java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
*/

Record(Java 16)

Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
@@ -34,7 +34,7 @@ What's New in Spring Framework 6.x
Spring Boot 3.0 Release Notes
Spring Boot 3.1 Release Notes

- - + + \ No newline at end of file diff --git a/jenkins.html b/jenkins.html index 218251796..a58184161 100644 --- a/jenkins.html +++ b/jenkins.html @@ -13,12 +13,12 @@ - - + +
-

Jenkins로 CI/CD 설정

· 약 8분

설정 환경

소프트웨어 이미지: Amazon Linux 2023 AMI
+

- - + + \ No newline at end of file diff --git a/jsr-310.html b/jsr-310.html index b81363745..80729ce0d 100644 --- a/jsr-310.html +++ b/jsr-310.html @@ -13,19 +13,19 @@ - - + +
-

JSR-310

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
+

JSR-310

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
ISO-8601을 기반으로 작성
설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

ISO-8601

날짜와 시간에 관련된 데이터를 다루는 국제 표준

LocalDate, LocalTime, LocalDateTime

날짜와 시간을 표현하는 클래스

Instant

유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
기계의 관점에서 시간 표현

Duration, Period

간격을 표현하는 클래스

TemporalAdjusters

복잡한 날짜 조정이 필요할 때 사용
필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}

DateTimeFormatter

날짜와 시간 포맷 클래스
특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

ZoneId, ZoneOffset

ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

Instant instant = Instant.now();
LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

참고 자료

- - + + \ No newline at end of file diff --git a/kotlin-null.html b/kotlin-null.html index 32da59739..186b78e3d 100644 --- a/kotlin-null.html +++ b/kotlin-null.html @@ -13,12 +13,12 @@ - - + +
-

Kotlin에서 null을 다루는 방법

· 약 5분

nullable 타입

코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
+

Kotlin에서 null을 다루는 방법

· 약 5분

nullable 타입

코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

val number: Int?

타입 뒤에 ?를 붙여 해당 값이 null이 될 수 있다는 것을 의미한다.
만약 ?를 붙이지 않을 때 null을 받는 경우 컴파일 시 오류가 발생한다.

?. Safe Calls 연산자

자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
@@ -30,7 +30,7 @@ 사용하기 쉽지만, 리스크가 크고 혹시나 해당 값이 추후에는 null이 될 수 있기 때문에 지양해야 된다고 생각한다.

val length: Int = word!!.length

as? 안전한 캐스팅

타입 변환을 할 때 지정한 타입으로 변경할 수 없다면 ClassCastException이 발생한다.
코틀린에서는 as 뒤에 ?를 붙여 안전하게 타입 변환을 할 수 있다.
따라서 미리 변환 가능한 타입인지 확인하지 않고, 안전하게 타입을 변환 할 수 있다.

타입 변환이 불가능 할 경우 예외를 발생시키지 않고 null을 반환한다.

val value: Int? = something as? Int

List에서의 null 처리

List에는 null이 아닌 값만 반환하는 filterNotNull 유틸리티 메서드를 제공한다.

val foodsWithNull: List<String?> = listOf("Pizza", "Cheese", null, "Potato")
val foods = foodsWithNull.filterNotNull()

참고 자료

- - + + \ No newline at end of file diff --git a/ladder-retrospective.html b/ladder-retrospective.html index 5a4551296..3d7b5a6ae 100644 --- a/ladder-retrospective.html +++ b/ladder-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

사다리 타기 미션 회고

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
+

사다리 타기 미션 회고

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

2단계에서는 2가지 방법으로 구현해봤다.

  1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
  2. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법

Position 기준으로 사다리 게임을 진행하는 방법

사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

public LadderGameResult play() {
final Map<Player, Item> result = new LinkedHashMap<>();
// 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
for (Position position : Position.range(players.count())) {
final Position resultPosition = ladder.play(position);
result.put(players.get(position), items.get(resultPosition));
}
return new LadderGameResult(result);
}

Player에게 Ladder를 전달하여 게임을 진행하는 방법

Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
@@ -50,7 +50,7 @@ 또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

- - + + \ No newline at end of file diff --git a/level2-interview-retrospective.html b/level2-interview-retrospective.html index 8f40904e7..1408d0a89 100644 --- a/level2-interview-retrospective.html +++ b/level2-interview-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

레벨 2 - 레벨 인터뷰 회고

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
+

레벨 2 - 레벨 인터뷰 회고

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

API 문서 도구 선택

큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
@@ -31,7 +31,7 @@ 생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
이전에 공부했던거 되돌아 보는 시간 가지기

- - + + \ No newline at end of file diff --git a/log-async-exception.html b/log-async-exception.html new file mode 100644 index 000000000..1380b20aa --- /dev/null +++ b/log-async-exception.html @@ -0,0 +1,30 @@ + + + + + +비동기 예외 로깅 | GG + + + + + + + + + + + + + +
+

비동기 예외 로깅

· 약 4분

문제 상황

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
+확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

비동기 예외 발생시 로깅 설정

Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
+getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

이제 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

MDC 정보 연동 문제

트립드로우의 애플리케이션은 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다. 비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

./mdc-null.png

Spring 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
+@Async will not call by @ControllerAdvice for global exception
+Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
+TaskDecorator, Spring docs

+ + + + \ No newline at end of file diff --git a/mock-static-method.html b/mock-static-method.html index 395dbde9e..cd98a672e 100644 --- a/mock-static-method.html +++ b/mock-static-method.html @@ -13,12 +13,12 @@ - - + +
-

Mockito 이용해서 static 메서드 모킹하기

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
+

Mockito 이용해서 static 메서드 모킹하기

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

public void upload(BufferedImage bufferedImage) {
File file = new File(파일경로);
try {
ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
} catch (IOException e) {
throw new DrawException(IMAGE_SAVE_FAIL);
}
}

Mocking static methods

Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
@@ -27,7 +27,7 @@ 항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

참고 자료

Mocking static methods
Mockito mock static methods
Enable mocking static methods in Mockito

- - + + \ No newline at end of file diff --git a/mysql-lock.html b/mysql-lock.html index c018c33a0..c539c2d7f 100644 --- a/mysql-lock.html +++ b/mysql-lock.html @@ -13,12 +13,12 @@ - - + +
-

MySQL 엔진의 잠금

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
+

MySQL 엔진의 잠금

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

글로벌 락(Global lock)

MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

  • 영향을 미치는 범위는 해당 서버 전체이다.
  • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.

한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

-- GLOBAL LOCK
FLUSH TABLES WITH READ LOCK;
-- UNLOCK
UNLOCK TABLES;

-- BACKUP LOCK
LOCK INSTANCE FOR BACKUP;
-- UNLOCK
UNLOCK INSTANCE;
- - + + \ No newline at end of file diff --git a/order-retrospective.html b/order-retrospective.html index b87956015..f7b56e688 100644 --- a/order-retrospective.html +++ b/order-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

장바구니 주문 미션 회고

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
+

장바구니 주문 미션 회고

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

배포

이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
배포 스크립트를 작성하는 경험을 해볼 수 있었다.
@@ -35,7 +35,7 @@ 추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

DAO에 @Transactional 적용

DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

- - + + \ No newline at end of file diff --git a/page/10.html b/page/10.html index c64b834ac..23dbd7253 100644 --- a/page/10.html +++ b/page/10.html @@ -13,12 +13,12 @@ - - + +
-

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
+

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

public void upload(BufferedImage bufferedImage) {
File file = new File(파일경로);
try {
ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
} catch (IOException e) {
throw new DrawException(IMAGE_SAVE_FAIL);
}
}

Mocking static methods

Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
@@ -27,7 +27,7 @@ 항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

참고 자료

Mocking static methods
Mockito mock static methods
Enable mocking static methods in Mockito

- - + + \ No newline at end of file diff --git a/page/11.html b/page/11.html index 5cea58a95..5ec67f94d 100644 --- a/page/11.html +++ b/page/11.html @@ -13,19 +13,19 @@ - - + +
-

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
+

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

  • 이미지 생성
  • 선과 점 표현
  • 투명한 배경색

현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

고려한 기술

백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

  • Python의 Matplotlib
  • AWT(Abstract Window Toolkit) [최종 선택]
  • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
  • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)

Python & Matplotlib

데이터 시각화 라이브러리
이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

  • 코드가 간단해서 유지 보수성이 좋다.
  • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
  • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.

Java AWT 이외의 라이브러리

Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

라이브러리설명제외 이유
SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음

Java & AWT(Abstract Window Toolkit)

그래픽과 이미지를 그리기 위한 도구
이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

  • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
  • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
  • 추가적인 api 호출을 하지 않아도 된다.

기술 선택

AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

유지 보수

AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
따라서 다음과 같은 방법으로 공유하기로 했다.

  1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
  2. AWT를 사용한 부분을 문서화하여 공유한다.

레벨 3를 마무리하며 내용 추가

기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

- - + + \ No newline at end of file diff --git a/page/12.html b/page/12.html index 74e6a5e36..6a91d81aa 100644 --- a/page/12.html +++ b/page/12.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
+

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

자바 변경 사항

우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

Switch Expressions(Java 14)

Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

enum RESULT {
WIN, LOSE, DRAW
}

RESULT result = RESULT.WIN;

int prize = switch (result) {
case WIN -> 10_000_000;
case LOSE, DRAW -> 5_000_000;
default -> 0;
};

주요 특징은 다음과 같다.

  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • break 문이 필요 없다.
  • default 블록을 통해 기본 값을 지정할 수 있다.

Text Block(Java 15)

Java 15에는 새로운 문자열 표현방식이 추가되었다.
긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("""
SELECT p FROM Post p
WHERE p.title LIKE %:keyword%
OR p.content LIKE %:keyword%
""")
List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
}

NPE 메시지(Java 15)

String name = null;
name.chars();

/**
# before
java.lang.NullPointerException
at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)

# after
Cannot invoke "String.chars()" because "name" is null
java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
*/

Record(Java 16)

Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
@@ -34,7 +34,7 @@ What's New in Spring Framework 6.x
Spring Boot 3.0 Release Notes
Spring Boot 3.1 Release Notes

- - + + \ No newline at end of file diff --git a/page/13.html b/page/13.html index b1df6b910..491bba313 100644 --- a/page/13.html +++ b/page/13.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

웹소켓

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
+

· 약 5분

웹소켓

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

웹소켓 등장 배경

웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

polling, long polling, streaming

Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

  • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
  • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.

Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

  • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.

Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

  • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.

웹소켓의 동작

1. Upgrade 요청

WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
이는 HTTP와 같이 80, 443 포트를 사용한다.
@@ -32,7 +32,7 @@ https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
https://docs.spring.io/spring-framework/reference/web/websocket.html

- - + + \ No newline at end of file diff --git a/page/14.html b/page/14.html index 211454741..4e836cc88 100644 --- a/page/14.html +++ b/page/14.html @@ -13,12 +13,12 @@ - - + +
-

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus

배포

배포 안내 문서
+

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus

배포

배포 안내 문서
netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

레포지토리 생성

github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

설정 파일 수정

docusaurus.config
module.exports = {
// ...
url: 'https://greeng00se.github.io',
baseUrl: '/',
projectName: 'greeng00se.github.io',
organizationName: 'greeng00se',
trailingSlash: false,
// ...
};

토큰 설정

github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
@@ -39,7 +39,7 @@ jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

brew install jq

다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper

docusaurus 설정

전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

docusaurus.config
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
...
algolia: {
appId: 'MVIU5UEMOM', // Application ID
apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
indexName: 'teco', // config.json에 설정한 인덱스명
contextualSearch: true,
},
})

부가 설정

화면 상단 Github Icon

파일 최하단에 아래 css 구문을 추가한다.

/src/css/custom.css
.header-github-link:hover {
opacity: 0.6;
}

.header-github-link:before {
content: '';
width: 24px;
height: 24px;
display: flex;
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

html[data-theme='dark'] .header-github-link:before {
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

themeconfig -> navbar에 github link를 설정한다.

docusaurus.config
navbar: {
title: 'HELLO',
items: [
{
href: 'https://github.com/greeng00se',
position: 'right',
className: 'header-github-link',
'aria-label': 'GitHub repository',
},
],
},

코드블럭

java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
prism 설정을 아래와 같이 변경해 준다.

docusaurus.config
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ['java', 'kotlin'],
}

mermaid

mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

yarn add @docusaurus/theme-mermaid

설치 후 아래와 같이 설정을 추가한다.

docusaurus.config
const config = {
...
markdown: {
mermaid: true,
},
themes: [
'@docusaurus/theme-mermaid'
],
};

themeConfig에서 mermaid의 테마를 지정할 수 있다.

docusaurus.config
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
...
mermaid: {
theme: {
light: 'neutral',
dark: 'dark'
},
},
}),

국제화 설정

국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

docusaurus.config
i18n: {
defaultLocale: "ko",
locales: ["ko"],
},

블로그 글 author

팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

author

authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

/blog/authors.yml
herb:
name: 허브
title: Backend
url: https://github.com/greeng00se
image_url: https://github.com/greeng00se.png

mallang:
name: 말랑
title: Backend
url: https://github.com/shin-mallang
image_url: https://github.com/shin-mallang.png

블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

---
slug: 1
title: Hello World
authors: [herb, mallang]
tags: [hello, docusaurus]
---

첫 번째 문서 내용
- - + + \ No newline at end of file diff --git a/page/15.html b/page/15.html index 22ff4cf0b..f0e89800e 100644 --- a/page/15.html +++ b/page/15.html @@ -13,12 +13,12 @@ - - + +
-

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
+

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
빠르게 지나가서 조금 아쉽다.

학습

회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
@@ -29,7 +29,7 @@ 이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

레벨 3 때부터 본격적으로 프로젝트가 시작된다.
팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

레벨 2를 마무리하며

회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. 읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

- - + + \ No newline at end of file diff --git a/page/16.html b/page/16.html index 93abe542f..a2371c28e 100644 --- a/page/16.html +++ b/page/16.html @@ -13,12 +13,12 @@ - - + +
-

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
+

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

API 문서 도구 선택

큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
@@ -31,7 +31,7 @@ 생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
이전에 공부했던거 되돌아 보는 시간 가지기

- - + + \ No newline at end of file diff --git a/page/17.html b/page/17.html index 629fcfb96..fcf1eb46a 100644 --- a/page/17.html +++ b/page/17.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
+

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

배포

이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
배포 스크립트를 작성하는 경험을 해볼 수 있었다.
@@ -35,7 +35,7 @@ 추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

DAO에 @Transactional 적용

DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

- - + + \ No newline at end of file diff --git a/page/18.html b/page/18.html index 67e15047d..252b544c5 100644 --- a/page/18.html +++ b/page/18.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
+

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

나의 채팅 확인하고 이어하는 기능

GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

chat1

좋아요와 댓글 기능

다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
@@ -32,7 +32,7 @@ 제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

향후 계획

실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

- - + + \ No newline at end of file diff --git a/page/19.html b/page/19.html index 48f56ea11..1dff8735a 100644 --- a/page/19.html +++ b/page/19.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • 노선별 추가 요금 정책
  • 연령별 요금 할인 정책

인터페이스 사용

요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
+

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • 노선별 추가 요금 정책
  • 연령별 요금 할인 정책

인터페이스 사용

요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
요금을 계산하는 메서드는 최단 경로 계산의 결과, 사용자의 정보, 요금을 받아 요금을 계산한다.

public interface FarePolicy {
int calculate(Path path, Passenger passenger, int fare);
}

public class BaseFarePolicy implements FarePolicy { ... }
public class DistanceFarePolicy implements FarePolicy { ... }
public class AgeDiscountFarePolicy implements FarePolicy { ... }

composite1

모든 요금 정책을 포함하는 새로운 요금 정책 만들기

나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

public class SubwayFarePolicy implements FarePolicy {

private final List<FarePolicy> farePolicies;

public SubwayFarePolicy(final List<FarePolicy> farePolicies) {
this.farePolicies = farePolicies;
}

@Override
public int calculate(final Path path, final Passenger passenger, final int fare) {
int calculatedFare = fare;
for (FarePolicy farePolicy : farePolicies) {
calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);
}
return calculatedFare;
}
}

따라서 그림으로 본다면 다음과 같은 구조가 된다.

composite2

정책의 순서

지하철 요구사항은 순서가 중요했다.
금액의 총합을 구하고, 그 후에 할인 정책이 들어가야했다.
@@ -31,7 +31,7 @@ 패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
항상 트레이드오프를 생각하자!

참고 자료

컴포지트 패턴, GoF의 디자인 패턴
디자인 패턴과 프레임워크, 오브젝트

- - + + \ No newline at end of file diff --git a/page/2.html b/page/2.html index 0bd542479..d5b5b1e79 100644 --- a/page/2.html +++ b/page/2.html @@ -13,12 +13,12 @@ - - + +
-

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
+

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

다이어그램

Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
@@ -47,7 +47,7 @@ Apache Tomcat 8 Configuration Reference
Apache Tomcat Tuning, Terry Cho
maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

- - + + \ No newline at end of file diff --git a/page/20.html b/page/20.html index e343361fc..016e1799e 100644 --- a/page/20.html +++ b/page/20.html @@ -13,12 +13,12 @@ - - + +
-

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
+

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
지하철 미션은 밀리랑 페어를 진행했다.
간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
@@ -39,7 +39,7 @@ 또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

편한 분위기

전체적으로 페어 할 때 편하게 진행했던 것 같다.
일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
나는 과연 다른 사람들에게 편한 사람일까?

- - + + \ No newline at end of file diff --git a/page/21.html b/page/21.html index c204dc4a5..7688aa61c 100644 --- a/page/21.html +++ b/page/21.html @@ -13,12 +13,12 @@ - - + +
-

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
+

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
요청에 담긴 Body를 통해 전달받은 값을 DTO로 매핑하여 추가와 수정을 했다.

장바구니 미션에서의 상품 추가 및 수정

중복1

클래스명을 제외하고 필드와 검증로직 그 외 모든게 같은 DTO를 보며 중복이라고 생각했다.
하지만 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
위 경우는 중복일까? 중복이 아닐까?

이 부분에 대해서 다음과 같은 리뷰를 받았다.

ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

질문에 대해 아래와 같이 답변을 했다.

저장과 수정할 때 필요한 필드값이 동일하여 현재 구조에서는 하나로 사용해도 된다고 생각을 하지만, 말씀해주신대로 요구사항이 변경된다면 달라질 가능성이 높다고 판단하였습니다!

중복과 우발적 중복

로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러가지 종류로 나누어 설명하고 있다.

  • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
  • 거짓된 중복, 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.

추가와 수정은 초기에는 중복으로 보이지만 초기 생성시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다. @@ -32,7 +32,7 @@ 상황에 맞춰 적재적소에 의존 역전을 이용해보는 것도 좋을 것 같다.

참고 자료

클린 아키텍처 16장 독립성, 로버트 C. 마틴
https://techblog.woowahan.com/2647/
https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

- - + + \ No newline at end of file diff --git a/page/22.html b/page/22.html index b5a2ab300..4eb0a142f 100644 --- a/page/22.html +++ b/page/22.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
+

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
@@ -32,7 +32,7 @@ 추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

의견 일치시키기

페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

- - + + \ No newline at end of file diff --git a/page/23.html b/page/23.html index b3ff24e72..af9a36ac2 100644 --- a/page/23.html +++ b/page/23.html @@ -13,12 +13,12 @@ - - + +
-

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
+

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
웹 자동차 미션에서는 비버와 페어가 매칭되었다.
레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
@@ -37,7 +37,7 @@ 추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
나도 5월부터 조금 더 화이팅 해야겠다.

- - + + \ No newline at end of file diff --git a/page/24.html b/page/24.html index 6c53c7c46..24e74156f 100644 --- a/page/24.html +++ b/page/24.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
+

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

백엔드

최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
@@ -37,7 +37,7 @@ 오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

참고 자료

Elastic Beanstalk, AWS
EC2 AWS Graviton, AWS
Default Memory Settings, AWS

- - + + \ No newline at end of file diff --git a/page/25.html b/page/25.html index 8df565ff1..9dbe38798 100644 --- a/page/25.html +++ b/page/25.html @@ -13,12 +13,12 @@ - - + +
-

· 약 8분

설정 환경

소프트웨어 이미지: Amazon Linux 2023 AMI
+

- - + + \ No newline at end of file diff --git a/page/26.html b/page/26.html index ae0bdcc8a..2c73570be 100644 --- a/page/26.html +++ b/page/26.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
+

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
@@ -41,7 +41,7 @@ 추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
변환하는 로직은 GPT의 도움을 많이 받았다.

const replaceCodeFences = (input: String) => {
const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
return input
.replace(codeFencesRegex, (match, p1, p2) => {
const languageClass = p1 ? ` class="language-${p1}"` : "";
return `<pre><code${languageClass}>${p2}</code></pre>`;
})
.replace(/\n/g, "<br>");
};

Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

tecochat

폰트 및 favicon 적용

타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
추가로 favicon도 간단하게 적용해서 만족스러웠다.

- - + + \ No newline at end of file diff --git a/page/27.html b/page/27.html index 6e2341ad5..cb342fbbb 100644 --- a/page/27.html +++ b/page/27.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

책 정보

상자 밖에 있는 사람
+

· 약 6분

책 정보

상자 밖에 있는 사람
아빈저연구소

자기기만과 자기배반

책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

  • 자기기만: 자신의 문제를 인정하지 않는 것
  • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위

자기배반을 한다면 자기기만 상태가 된다.
자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

읽고 나서

최근에 읽은 책 중 가장 마음이 불편했다.
그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
@@ -48,7 +48,7 @@ 우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
p.280

- - + + \ No newline at end of file diff --git a/page/28.html b/page/28.html index 0da9317e7..705e2e606 100644 --- a/page/28.html +++ b/page/28.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
+

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

낙관적 동시성 제어(OCC, Optimistic concurrency control)

트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

비관적 동시성 제어(PCC, Pessimistic Concurrency Control)

트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

Shared & Exclusive Locks

InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

공유 잠금(S, shared lock)

데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
@@ -38,7 +38,7 @@ MySQL Innodb Locks, cecil1018
MySQL 8.0 InnoDB Locks, MySQL
Locks Set by Different SQL Statements in InnoDB, MySQL

- - + + \ No newline at end of file diff --git a/page/29.html b/page/29.html index 85d8334ad..546ef43a7 100644 --- a/page/29.html +++ b/page/29.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
+

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

글로벌 락(Global lock)

MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

  • 영향을 미치는 범위는 해당 서버 전체이다.
  • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.

한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

-- GLOBAL LOCK
FLUSH TABLES WITH READ LOCK;
-- UNLOCK
UNLOCK TABLES;

-- BACKUP LOCK
LOCK INSTANCE FOR BACKUP;
-- UNLOCK
UNLOCK INSTANCE;
- - + + \ No newline at end of file diff --git a/page/3.html b/page/3.html index 41bb78393..72825947f 100644 --- a/page/3.html +++ b/page/3.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

성능 테스트

API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
+

· 약 6분

성능 테스트

API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
다양한 상황에 대비해서 성능 테스트를 해야한다.

./test.png

스모크 테스트(Smoke Test)

최소한의 부하를 주어 시스템이 정상적으로 동작하는지 확인하는 테스트

VU를 최소한으로 두고, 짧은 시간을 가지고 테스트한다.
다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

가상 사용자(VU)

가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
@@ -33,7 +33,7 @@ 다만 Auto Scaling이 적용된 클라우드 환경에서는 진행하지 않아야 한다.

참고 자료

Load test types, k6
자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드
아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

- - + + \ No newline at end of file diff --git a/page/30.html b/page/30.html index f5b1f9915..5e1d679a6 100644 --- a/page/30.html +++ b/page/30.html @@ -13,12 +13,12 @@ - - + +
-

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
+

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

트랜잭션의 속성(ACID)

원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
@@ -42,7 +42,7 @@ 예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

팬텀 리드(Phantom read, Phantom row)

한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

참고 자료

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
Isolation Level, MySQL

- - + + \ No newline at end of file diff --git a/page/31.html b/page/31.html index 669f4811f..5d3688720 100644 --- a/page/31.html +++ b/page/31.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
+

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

테스트 대역의 타입 계층 구조

더미(Dummy)

가장 단순하고, 원시적인 유형의 테스트 대역이다.
기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
@@ -36,7 +36,7 @@ 테스트 더블, Martin Fowler
테스트 관련 용어 정리, Johngrib
Test Double, Gerard Meszaros

- - + + \ No newline at end of file diff --git a/page/32.html b/page/32.html index 2c914707d..906396c25 100644 --- a/page/32.html +++ b/page/32.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
+

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
컴파일된 클래스파일은 어떤 구조로 되어있을까?

클래스 파일의 데이터 형식

8비트 바이트의 스트림으로 구성된다.
16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
멀티바이트의 경우 항상 big endian 순서로 저장된다.

u1 → unsigned 1byte
@@ -36,7 +36,7 @@ Class file in Java, File Format
java se11 Class 파일 형식, Oracle
java se17 Class 파일 형식, Oracle

- - + + \ No newline at end of file diff --git a/page/33.html b/page/33.html index 59a9c4914..f14eedabd 100644 --- a/page/33.html +++ b/page/33.html @@ -13,12 +13,12 @@ - - + +
-

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
+

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

기존 코드

public class User {
private final int id;
private final String name;

public User(final int id, final String name) {
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public String getName() {
return name;
}
}

SELECT, DELETE 중복 제거

변하지 않는 부분: try-with-resource, preparedStatement를 사용하는 부분, executeUpdate로 실행 등등
변하는 부분: SQL Query, 매개변수

다음과 같이 쿼리를 실행하는 부분을 분리하고 가변인수를 사용한다면 SELECT와 DELETE의 중복을 제거할 수 있다.

public void insert(final String name) {
final String query = "INSERT INTO User (name) VALUES (?)";
executeUpdate(query, name);
}

public void delete(final int userId) {
final String query = "DELETE FROM user WHERE user_id = ?";
executeUpdate(query, userId);
}

private void executeUpdate(final String query, final Object... parameters) {
final Connection connection = connectionPool.getConnection();
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
for (int i = 1; i <= parameters.length; i++) {
preparedStatement.setObject(i, parameters[i - 1]);
}
preparedStatement.executeUpdate();
} catch (final SQLException e) {
throw new IllegalArgumentException(e.getMessage());
}
}

조회 분리하기 - 1. 콜백을 위한 인터페이스 정의

조회는 INSERT, DELETE와 달리 값을 반환받아야 하기 때문에 다른 방법을 사용해야 한다.
@@ -30,7 +30,7 @@ 아래와 같이 제네릭을 적용하여 다른 Dao에서도 사용 가능하도록 변경할 수 있다.

@FunctionalInterface
public interface RowMapper<T> {
T mapRow(final ResultSet resultSet) throws SQLException;
}

private <T> List<T> query(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
private <T> T queryForSingleResult(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}

메서드 분리한 부분 클래스로 분리하기 + Optional 사용하기

메서드로 분리한 부분을 JdbcTemplate이라는 클래스를 만들어 옮긴다.
또한 null을 반환하기 보단 Optional로 감싸서 반환하도록 변경한다.
최종적으로 아래와 같은 코드가 완성된다.

public class UserDao {
private final RowMapper<User> rowMapper = resultSet -> {
final int id = resultSet.getInt("id");
final String name = resultSet.getString("name");
return new User(id, name);
};
private final JdbcTemplate jdbcTemplate;

public UserDao(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

public void insert(final String name) {
final String query = "INSERT INTO User (name) VALUES (?)";
jdbcTemplate.executeUpdate(query, name);
}

public void delete(final int userId) {
final String query = "DELETE FROM user WHERE user_id = ?";
jdbcTemplate.executeUpdate(query, userId);
}

public Optional<User> findById(final int userId) {
final String query = "SELECT * FROM user WHERE id = ?";
return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);
}

public List<User> findAll() {
final String query = "SELECT * FROM user";
return jdbcTemplate.query(query, rowMapper);
}
}
- - + + \ No newline at end of file diff --git a/page/34.html b/page/34.html index 392371fcb..5e7632308 100644 --- a/page/34.html +++ b/page/34.html @@ -13,12 +13,12 @@ - - + +
-

· 약 8분

레벨 1이 끝났다.
+

· 약 8분

레벨 1이 끝났다.
우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

Keep

나만의 루틴 만들기

스스로가 외부의 영향을 많이 받는다고 생각한다.
@@ -50,7 +50,7 @@ 블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

레벨 1을 마무리하며

시간이 빠르게 흘러갔다.
타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

- - + + \ No newline at end of file diff --git a/page/35.html b/page/35.html index 33c3b7bc3..abe3b259e 100644 --- a/page/35.html +++ b/page/35.html @@ -13,12 +13,12 @@ - - + +
-

· 약 8분

체스

체스 미션에는 가비와 페어가 매칭되었다!
+

· 약 8분

체스

체스 미션에는 가비와 페어가 매칭되었다!
체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
@@ -53,7 +53,7 @@ 모르는게 있으면 솔직하게 말해주는 부분
나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
솔직함은 페어할 때 중요한 부분인 것 같다.

마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

- - + + \ No newline at end of file diff --git a/page/36.html b/page/36.html index 8c39f9f57..ee75bd295 100644 --- a/page/36.html +++ b/page/36.html @@ -13,15 +13,15 @@ - - + +
-

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) +

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) 객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

  • 오브젝트 p.17

결합도를 낮춘다면 다음과 같은 이점이 있다.

  • 다른 구성 요소의 변화에 영향을 받지 않는다.
  • 재사용이 편리해진다.
  • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)

높은 응집도 패턴(High Cohesion)

Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

응집도(Cohesion) 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

  • 오브젝트 p.26

변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

  • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
  • 유지보수가 쉬워진다.
  • 낮은 결합도 또한 지원한다.
  • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.

컨트롤러 패턴(Controller)

Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

어떤 서브시스템이 존재한다고 가정할 때

  • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
  • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
  • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.

다형성 패턴(Polymorphism)

Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

변경 보호 패턴(Protected Variations)

Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

간접 참조 패턴(Indirection)

Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

순수한 가공물 패턴(Pure Fabrication)

Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

  • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
  • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.

참고 자료

오브젝트 5장. 책임 할당하기, 조영호

Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

GRASP, 한빛 네트워크

- - + + \ No newline at end of file diff --git a/page/37.html b/page/37.html index fd19028b1..b0366625a 100644 --- a/page/37.html +++ b/page/37.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
+

· 약 6분

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
@@ -48,7 +48,7 @@ 회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

도메인 언어에 신경쓰는 부분
클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
요구사항 정리도 깔끔하게 잘하는 것 같다.

후추 최고 👍

- - + + \ No newline at end of file diff --git a/page/38.html b/page/38.html index 4b7068d61..922b7d984 100644 --- a/page/38.html +++ b/page/38.html @@ -13,12 +13,12 @@ - - + +
-

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
+

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

2단계에서는 2가지 방법으로 구현해봤다.

  1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
  2. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법

Position 기준으로 사다리 게임을 진행하는 방법

사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

public LadderGameResult play() {
final Map<Player, Item> result = new LinkedHashMap<>();
// 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
for (Position position : Position.range(players.count())) {
final Position resultPosition = ladder.play(position);
result.put(players.get(position), items.get(resultPosition));
}
return new LadderGameResult(result);
}

Player에게 Ladder를 전달하여 게임을 진행하는 방법

Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
@@ -50,7 +50,7 @@ 또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

- - + + \ No newline at end of file diff --git a/page/39.html b/page/39.html index bb5a93bd8..466cb4bf2 100644 --- a/page/39.html +++ b/page/39.html @@ -13,12 +13,12 @@ - - + +
-

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
+

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

  • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
  • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.

미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
@@ -44,7 +44,7 @@ 그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
이건 바로 배울 수 없지만.
나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

- - + + \ No newline at end of file diff --git a/page/4.html b/page/4.html index ac1ff4395..5286d9122 100644 --- a/page/4.html +++ b/page/4.html @@ -13,12 +13,12 @@ - - + +
-

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
+

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

복제를 하는 이유

1. 스케일 아웃

사용자의 트래픽이 증가하는 경우, 데이터베이스에 가해지는 부하도 자연스럽게 증가한다.
이를 처리하기 위해 복제를 통한 스케일 아웃을 적용하여 애플리케이션에서 사용하는 쿼리들을 각각의 데이터베이스로 분산 시킬 수 있다.

2. 데이터 백업

실제 운영되는 서비스가 사용하고 있는 DB에서 백업을 진행하는 경우, 서비스에 영향을 미칠 수 있다.
따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

3. 데이터 분석

백업과 마찬가지로 복잡하고 무거운 분석용 쿼리의 서비스에 영향을 미칠 수 있다.
@@ -71,7 +71,7 @@ 데이터베이스 레플리케이션을 통한 쿼리 성능 개선 (feat. Mysql, SpringBoot)
부하 분산을 위한 MySQL Replication 구성 및 쿼리 요청 분기
Use Docker Compose, Docker

- - + + \ No newline at end of file diff --git a/page/40.html b/page/40.html index 0249c6cee..26859e0ab 100644 --- a/page/40.html +++ b/page/40.html @@ -13,12 +13,12 @@ - - + +
-

· 약 4분

테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
+

· 약 4분

테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

Argument Sources

@ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

Value Source

값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

  • short, int, long, float, double
  • byte, char, boolean, String, Class
@ParameterizedTest
@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
void valueTest(final int value) {
Assertions.assertThat(value).isPositive();
}

Null & Empty Source

null 값, 빈 값을 제공한다.
Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

  • String
  • java.util.List, java.util.Set, java.util.Map
  • primitive arrays — ex) int[]
  • object arrays — ex) String[]
@ParameterizedTest
@NullAndEmptySource
void nullAndEmptyTest(final String value) {
Assertions.assertThat(value).isNullOrEmpty();
}

Enum Source

EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

@ParameterizedTest
@EnumSource(Day.class)
void enumTest(final Day day) {
assertThat(day).isInstanceOf(Day.class);
}

다음과 같이 mode 값을 이용하여 특징 Enum을 제외하거나, 포함시킬 수 있다. (default: Mode.Include)

@ParameterizedTest
@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)
void enumTest(final Day day) {
// MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
assertThat(day).isInstanceOf(Day.class);
}

CSV Source

csv 형식의 값을 이용하여 매개변수를 제공한다.
@@ -26,7 +26,7 @@ 개인적으로 2개 정도의 값을 매개변수로 전달하는 경우 CsvSource를 사용한다.

@ParameterizedTest
@CsvSource({"1,1", "2,4", "3,9", "4,16"})
void csvTest(final int number, final int result) {
assertThat(number * number).isEqualTo(result);
}

Method Source

복잡한 타입의 값을 전달할 때 사용한다.
메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

@ParameterizedTest
@MethodSource
void methodTest(final List<Integer> numbers, final int count) {
assertThat(numbers).hasSize(count);
}

private static Stream<Arguments> methodTest() {
return Stream.of(
Arguments.of(List.of(1), 1),
Arguments.of(List.of(1, 2), 2),
Arguments.of(List.of(1, 2, 3), 3)
);
}

ETC.

위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

  • CSV 파일을 이용한 CsvFileSource
  • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource

참고 자료

- - + + \ No newline at end of file diff --git a/page/41.html b/page/41.html index 384147cfa..781a4d730 100644 --- a/page/41.html +++ b/page/41.html @@ -13,13 +13,13 @@ - - + +
-

· 약 1분

Import 자동 적용

Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

auto-import

저장시 동작

Prefrences > Tools > Actions on Save

actions-on-save

Reformat Code: Code Reformmating

Optimize imports: 사용하지 않는 Import 제거

Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

메소드 추출, 변수 추출시 final 적용

Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

final-modifier

- - +

· 약 1분

Import 자동 적용

Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

auto-import

저장시 동작

Prefrences > Tools > Actions on Save

actions-on-save

Reformat Code: Code Reformmating

Optimize imports: 사용하지 않는 Import 제거

Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

메소드 추출, 변수 추출시 final 적용

Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

final-modifier

+ + \ No newline at end of file diff --git a/page/42.html b/page/42.html index 45b6cc4a3..055999af6 100644 --- a/page/42.html +++ b/page/42.html @@ -13,12 +13,12 @@ - - + +
-

· 약 5분

nullable 타입

코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
+

· 약 5분

nullable 타입

코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

val number: Int?

타입 뒤에 ?를 붙여 해당 값이 null이 될 수 있다는 것을 의미한다.
만약 ?를 붙이지 않을 때 null을 받는 경우 컴파일 시 오류가 발생한다.

?. Safe Calls 연산자

자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
@@ -30,7 +30,7 @@ 사용하기 쉽지만, 리스크가 크고 혹시나 해당 값이 추후에는 null이 될 수 있기 때문에 지양해야 된다고 생각한다.

val length: Int = word!!.length

as? 안전한 캐스팅

타입 변환을 할 때 지정한 타입으로 변경할 수 없다면 ClassCastException이 발생한다.
코틀린에서는 as 뒤에 ?를 붙여 안전하게 타입 변환을 할 수 있다.
따라서 미리 변환 가능한 타입인지 확인하지 않고, 안전하게 타입을 변환 할 수 있다.

타입 변환이 불가능 할 경우 예외를 발생시키지 않고 null을 반환한다.

val value: Int? = something as? Int

List에서의 null 처리

List에는 null이 아닌 값만 반환하는 filterNotNull 유틸리티 메서드를 제공한다.

val foodsWithNull: List<String?> = listOf("Pizza", "Cheese", null, "Potato")
val foods = foodsWithNull.filterNotNull()

참고 자료

- - + + \ No newline at end of file diff --git a/page/43.html b/page/43.html index 4cbbbd984..e031b44a8 100644 --- a/page/43.html +++ b/page/43.html @@ -13,19 +13,19 @@ - - + +
-

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
+

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
ISO-8601을 기반으로 작성
설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

ISO-8601

날짜와 시간에 관련된 데이터를 다루는 국제 표준

LocalDate, LocalTime, LocalDateTime

날짜와 시간을 표현하는 클래스

Instant

유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
기계의 관점에서 시간 표현

Duration, Period

간격을 표현하는 클래스

TemporalAdjusters

복잡한 날짜 조정이 필요할 때 사용
필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}

DateTimeFormatter

날짜와 시간 포맷 클래스
특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

ZoneId, ZoneOffset

ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

Instant instant = Instant.now();
LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

참고 자료

- - + + \ No newline at end of file diff --git a/page/44.html b/page/44.html index af0ea0975..46e31a399 100644 --- a/page/44.html +++ b/page/44.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

책 정보

객체지향의 사실과 오해
+

· 약 6분

책 정보

객체지향의 사실과 오해
조영호

읽고 나서

조영호님의 오브젝트를 읽고 나서 다시 한 번 읽어보았다.
아직 이해가 안되는 부분이 많지만, 그래도 항상 새로움을 느낀다.
더할 나위 없이 휼륭한 객체지향 책이고, 조금 더 공부하고 다시 읽어봐야될 것 같다.

커피 전문점, 지하철 노선도, 이상한 나라의 엘리스를 예시로 든 설명이 너무 좋았고
@@ -38,7 +38,7 @@ ’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. 여기서 ‘어떤 행위’가 바로 메시지다. p.158

- - + + \ No newline at end of file diff --git a/page/45.html b/page/45.html index 8dbddcda1..48c0258eb 100644 --- a/page/45.html +++ b/page/45.html @@ -13,12 +13,12 @@ - - + +
-

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
+

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

조금 더 미래에 대한 생각을 해볼걸 그랬다.
전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

자바

전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
@@ -33,7 +33,7 @@ 적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

2023년에는

마음의 여유가 없었던 2022년이었던 것 같다.
하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

- - + + \ No newline at end of file diff --git a/page/46.html b/page/46.html index 5a2fe4fd4..04863cac6 100644 --- a/page/46.html +++ b/page/46.html @@ -13,18 +13,18 @@ - - + +
-

· 약 5분

책 정보

글, 우리도 잘 쓸 수 있습니다.
+

· 약 5분

책 정보

글, 우리도 잘 쓸 수 있습니다.
박솔미

읽고 나서

저자의 경험과 함께 글쓰기에 대한 가벼운 조언이 담겨있어 가볍게 읽기 좋았다.
글을 잘 작성해 보고 싶을 때 적용해 볼 수 있는 정보가 많아서 도움이 되었다.

우아한 테크코스의 프리코스를 진행할 때 후기를 작성하고 나면 항상 글이 딱딱하다는 느낌을 받았다.
다른 지원자들의 읽기 편하고, 밝은 느낌을 주는 글을 보면 부러운 마음을 가지기도 했다.
이 책을 읽었으니 2023년에는 조금 더 글을 잘 적어보려고 한다.

밑줄 친 문장들

문장이 심심하고 지루하다면 내용을 일목요연하게 정리했고, 글의 의도도 삐뚤지 않고, 단어도 적절한 것으로 골랐는데… 그런데도 어딘가가 심심하고 지루하다면? 축축 처지고 따분하다면? 말꼬리를 모조리 ‘~다’로 통일한 건 아닌지 점검해 보세요.

말꼬리를 잘 갖고 놀아야 합니다. 문장의 마지막 글자를 매번 다르게 고쳐쓰는 것만으로도 글에 활기를 더할 수 있죠. 때론 문장을 다 마치지 않고, 단어로만 끝맺는 것도 방법. 문장과 문장 사이에 쉼표가 들어서며 글 전체에 활기가 돌게 돼요. 문장의 길이도 다채로워지는 덕분에 덤으로 얻게 되는 것도 있습니다. 바로, 글의 리듬.

이전 문장에서 끝난 글자로, 다음 문장을 끝맺지 않기. 한두 문단마다 단어 수준의 아주 짧은 문장 배치하기.

글의 진짜 이유, 글의 진짜 목적, 글의 진짜 대상을 찾으려고 애썼습니다. 지금처럼 틀을 떠올린다거나, 눈치를 본다거나, 정치적인 셈도 하지 않았어요.

제목은 짧게, 보기 쉽게, 읽기 쉽게, 발음이 비슷하게, 순서를 바꿔서

글을 마지막으로 다듬을 때, 노래에 가까워질 방법은 없을지 고민해봅니다. 감히 가 닿을 수 없는 목표이겠지만, 할 수 있는 최소한의 리듬이라도 붙여주고 싶어요.

여는 말과 마지막 말에 작정하고 마음을 담는 연습을 해봅시다. 글의 어느 구석이라도 뻔한 글자는 남기지 않겠노라 다짐하며 써보는 겁니다. 나만이 가진 유일한 메시지에 집중하면서요. 그럼 생각이 달라지고, 고르는 단어도 달라지고, 남긴 문장도 달라져요. 결국에는 글을 쓴 사람인 나 자신도 남달라질 겁니다.

맞춤법은 중요합니다. 하지만 맞춤법보다 더 중요한 건 거기에 담긴 마음입니다. 내 마음을 글에 담아 실어 보내기 전, 맞춤법을 점검하는 이유 역시 그겁니다. 오직 내 마음이 남에게 읽히는 동안 방해가 되지 않기를 바라기 때문이죠. 내가 쓴 글도, 남이 쓴 글도. 언제나 그 안에 담긴 마음이 먼저입니다.

글을 쓴다고 글이 완성되는 게 아니에요. 글과 닮은 모습으로 살 때, 글은 비로소 완성됩니다.

- - + + \ No newline at end of file diff --git a/page/5.html b/page/5.html index aeb3842e6..a438e3f13 100644 --- a/page/5.html +++ b/page/5.html @@ -13,12 +13,12 @@ - - + +
-

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
+

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

아쉬운 점

문서화

개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
@@ -33,7 +33,7 @@ 아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

기술 선택의 이유

기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

마치며

플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

- - + + \ No newline at end of file diff --git a/page/6.html b/page/6.html index be34ecc1c..89e8bfd71 100644 --- a/page/6.html +++ b/page/6.html @@ -13,12 +13,12 @@ - - + +
-

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
+

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
지표를 감시하여 알림을 보내는 기능도 제공한다.
프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
요금 정보에 대한 자세한 정보는 다음 링크에서 확인할 수 있다.

CloudWatch Metrics

기본적으로 5분마다 지표에 대한 정보가 수집된다.
@@ -38,7 +38,7 @@ 서버에 CloudWatch 에이전트 설치 및 실행
CloudWatch Agent를 Parameter Store에서 관리해 보기
CloudWatch에이전트 구성 파일

- - + + \ No newline at end of file diff --git a/page/7.html b/page/7.html index 84b0795d2..9cf21b6ed 100644 --- a/page/7.html +++ b/page/7.html @@ -13,12 +13,12 @@ - - + +
-

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
+

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
경로 이미지 생성하기 - 구현

개요

현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

주기능의 응답속도 개선

여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
@@ -45,7 +45,7 @@ 응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

참고 자료

7.7. Task Execution and Scheduling, Spring Boot Docs
Spring Events, Baeldung
회원시스템 이벤트기반 아키텍처 구축하기

- - + + \ No newline at end of file diff --git a/page/8.html b/page/8.html index 2cb1accef..0792affa8 100644 --- a/page/8.html +++ b/page/8.html @@ -13,12 +13,12 @@ - - + +
-

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
+

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

구현 결과

./result.png

예시 데이터는 다음과 같다.
서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

예시 데이터
List<Double> x = List.of(
126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
);
List<Double> y = List.of(
37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
);
List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);

IMAGE_SIZE & ROUTE_SIZE

RouteImageGenerator.java
private static final int IMAGE_SIZE = 800;
private static final int ROUTE_SIZE = 600;

코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
@@ -29,7 +29,7 @@ BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

./800.png

따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

x 값 → 계산한 offset 그대로 더한다.
y 값 → imageSize(800)에서 y + offset 값을 뺀다.

RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
그림을 그리기 위해 설정한 상수들이 존재한다.

RouteImageDrawer.java
// RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
// 이를 RGBA라고 부른다.
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
// 배경 투명색
private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
// 경로를 위한 STROKE
private static final int LINE_STROKE_WIDTH = 7;
private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 위치 점을 위한 STROKE
private static final int POINT_STROKE_WIDTH = 20;
private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 안티앨리어싱 등 화질 개선을 위한 설정
private static final Map<Object, Object> renderingHints = Map.of(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
);

RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

  • drawLine: 선을 그린다.
  • drawPoint: 점을 찍는다.
  • dispose: 자원 할당을 해제한다.

dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

이미지 생성 Flow

1. 이미지 생성 준비

2. 선 그리기 요청

3. 위치 점 그리기 요청

4. 업로드 요청

전체 Flow

- - + + \ No newline at end of file diff --git a/page/9.html b/page/9.html index c43da4b83..bc6580794 100644 --- a/page/9.html +++ b/page/9.html @@ -13,12 +13,12 @@ - - + +
-

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
+

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
이미지 생성: matplotlib
서비스: AWS Lambda, AWS API Gateway
이미지 저장 및 URL: AWS S3, AWS CloudFront

플로우는 다음과 같다.

요구사항

./route.png

우측 상단의 경로 이미지를 생성하려고 한다.
@@ -39,7 +39,7 @@ Python Lambda 함수에 대한 .zip 파일 아카이브 작업
No module named 'numpy.core._multiarray_umath'
사례별로 알아본 안전한 S3 사용 가이드

- - + + \ No newline at end of file diff --git a/parameterized-tests.html b/parameterized-tests.html index 9fca013f6..16425e3a2 100644 --- a/parameterized-tests.html +++ b/parameterized-tests.html @@ -13,12 +13,12 @@ - - + +
-

Parameterized Tests

· 약 4분

테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
+

Parameterized Tests

· 약 4분

테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

Argument Sources

@ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

Value Source

값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

  • short, int, long, float, double
  • byte, char, boolean, String, Class
@ParameterizedTest
@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
void valueTest(final int value) {
Assertions.assertThat(value).isPositive();
}

Null & Empty Source

null 값, 빈 값을 제공한다.
Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

  • String
  • java.util.List, java.util.Set, java.util.Map
  • primitive arrays — ex) int[]
  • object arrays — ex) String[]
@ParameterizedTest
@NullAndEmptySource
void nullAndEmptyTest(final String value) {
Assertions.assertThat(value).isNullOrEmpty();
}

Enum Source

EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

@ParameterizedTest
@EnumSource(Day.class)
void enumTest(final Day day) {
assertThat(day).isInstanceOf(Day.class);
}

다음과 같이 mode 값을 이용하여 특징 Enum을 제외하거나, 포함시킬 수 있다. (default: Mode.Include)

@ParameterizedTest
@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)
void enumTest(final Day day) {
// MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
assertThat(day).isInstanceOf(Day.class);
}

CSV Source

csv 형식의 값을 이용하여 매개변수를 제공한다.
@@ -26,7 +26,7 @@ 개인적으로 2개 정도의 값을 매개변수로 전달하는 경우 CsvSource를 사용한다.

@ParameterizedTest
@CsvSource({"1,1", "2,4", "3,9", "4,16"})
void csvTest(final int number, final int result) {
assertThat(number * number).isEqualTo(result);
}

Method Source

복잡한 타입의 값을 전달할 때 사용한다.
메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

@ParameterizedTest
@MethodSource
void methodTest(final List<Integer> numbers, final int count) {
assertThat(numbers).hasSize(count);
}

private static Stream<Arguments> methodTest() {
return Stream.of(
Arguments.of(List.of(1), 1),
Arguments.of(List.of(1, 2), 2),
Arguments.of(List.of(1, 2, 3), 3)
);
}

ETC.

위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

  • CSV 파일을 이용한 CsvFileSource
  • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource

참고 자료

- - + + \ No newline at end of file diff --git a/performance-test-type.html b/performance-test-type.html index 05195989f..307e20840 100644 --- a/performance-test-type.html +++ b/performance-test-type.html @@ -13,12 +13,12 @@ - - + +
-

성능 테스트 종류

· 약 6분

성능 테스트

API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
+

성능 테스트 종류

· 약 6분

성능 테스트

API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
다양한 상황에 대비해서 성능 테스트를 해야한다.

./test.png

스모크 테스트(Smoke Test)

최소한의 부하를 주어 시스템이 정상적으로 동작하는지 확인하는 테스트

VU를 최소한으로 두고, 짧은 시간을 가지고 테스트한다.
다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

가상 사용자(VU)

가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
@@ -33,7 +33,7 @@ 다만 Auto Scaling이 적용된 클라우드 환경에서는 진행하지 않아야 한다.

참고 자료

Load test types, k6
자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드
아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

- - + + \ No newline at end of file diff --git a/racing-car-retrospective.html b/racing-car-retrospective.html index 39b9e8442..b66a0a62a 100644 --- a/racing-car-retrospective.html +++ b/racing-car-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

자동차 경주 미션 회고

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
+

자동차 경주 미션 회고

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

  • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
  • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.

미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
@@ -44,7 +44,7 @@ 그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
이건 바로 배울 수 없지만.
나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

- - + + \ No newline at end of file diff --git a/route-image-async-with-event.html b/route-image-async-with-event.html index a88f02776..9dac55b4c 100644 --- a/route-image-async-with-event.html +++ b/route-image-async-with-event.html @@ -13,12 +13,12 @@ - - + +
-

경로 이미지 생성하기 - 비동기 처리

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
+

경로 이미지 생성하기 - 비동기 처리

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
경로 이미지 생성하기 - 구현

개요

현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

주기능의 응답속도 개선

여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
@@ -45,7 +45,7 @@ 응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

참고 자료

7.7. Task Execution and Scheduling, Spring Boot Docs
Spring Events, Baeldung
회원시스템 이벤트기반 아키텍처 구축하기

- - + + \ No newline at end of file diff --git a/route-image-implementation.html b/route-image-implementation.html index d15f141b6..701f4cc47 100644 --- a/route-image-implementation.html +++ b/route-image-implementation.html @@ -13,12 +13,12 @@ - - + +
-

경로 이미지 생성하기 - 구현

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
+

경로 이미지 생성하기 - 구현

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

구현 결과

./result.png

예시 데이터는 다음과 같다.
서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

예시 데이터
List<Double> x = List.of(
126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
);
List<Double> y = List.of(
37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
);
List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);

IMAGE_SIZE & ROUTE_SIZE

RouteImageGenerator.java
private static final int IMAGE_SIZE = 800;
private static final int ROUTE_SIZE = 600;

코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
@@ -29,7 +29,7 @@ BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

./800.png

따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

x 값 → 계산한 offset 그대로 더한다.
y 값 → imageSize(800)에서 y + offset 값을 뺀다.

RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
그림을 그리기 위해 설정한 상수들이 존재한다.

RouteImageDrawer.java
// RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
// 이를 RGBA라고 부른다.
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
// 배경 투명색
private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
// 경로를 위한 STROKE
private static final int LINE_STROKE_WIDTH = 7;
private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 위치 점을 위한 STROKE
private static final int POINT_STROKE_WIDTH = 20;
private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 안티앨리어싱 등 화질 개선을 위한 설정
private static final Map<Object, Object> renderingHints = Map.of(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
);

RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

  • drawLine: 선을 그린다.
  • drawPoint: 점을 찍는다.
  • dispose: 자원 할당을 해제한다.

dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

이미지 생성 Flow

1. 이미지 생성 준비

2. 선 그리기 요청

3. 위치 점 그리기 요청

4. 업로드 요청

전체 Flow

- - + + \ No newline at end of file diff --git a/route-image-intro.html b/route-image-intro.html index 4d9161f1d..bfb74aa47 100644 --- a/route-image-intro.html +++ b/route-image-intro.html @@ -13,19 +13,19 @@ - - + +
-

경로 이미지 생성하기 - 기술 선택

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
+

경로 이미지 생성하기 - 기술 선택

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

  • 이미지 생성
  • 선과 점 표현
  • 투명한 배경색

현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

고려한 기술

백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

  • Python의 Matplotlib
  • AWT(Abstract Window Toolkit) [최종 선택]
  • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
  • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)

Python & Matplotlib

데이터 시각화 라이브러리
이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

  • 코드가 간단해서 유지 보수성이 좋다.
  • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
  • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.

Java AWT 이외의 라이브러리

Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

라이브러리설명제외 이유
SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음

Java & AWT(Abstract Window Toolkit)

그래픽과 이미지를 그리기 위한 도구
이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

  • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
  • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
  • 추가적인 api 호출을 하지 않아도 된다.

기술 선택

AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

유지 보수

AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
따라서 다음과 같은 방법으로 공유하기로 했다.

  1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
  2. AWT를 사용한 부분을 문서화하여 공유한다.

레벨 3를 마무리하며 내용 추가

기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

- - + + \ No newline at end of file diff --git a/route-image-python.html b/route-image-python.html index 6c0368618..fdaff7ca6 100644 --- a/route-image-python.html +++ b/route-image-python.html @@ -13,12 +13,12 @@ - - + +
-

경로 이미지 생성하기 - 파이썬

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
+

- - + + \ No newline at end of file diff --git a/rss.xml b/rss.xml index 34ae84ed2..aa6890855 100644 --- a/rss.xml +++ b/rss.xml @@ -9,16 +9,17 @@ https://github.com/jpmonette/feed ko - <![CDATA[비동기 예외 처리]]> - https://greeng00se.github.io/async-exception - https://greeng00se.github.io/async-exception + <![CDATA[비동기 예외 로깅]]> + https://greeng00se.github.io/log-async-exception + https://greeng00se.github.io/log-async-exception Mon, 18 Sep 2023 00:00:00 GMT - - 개요

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.

확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았다. 따라서 Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

비동기 예외처리

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

해당 AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다. getAsyncUncaughtExceptionHandler 메서드를 오버라이딩하여 이전에 생성해 준 AsyncExceptionHandler를 반환하도록 설정했다.
-이렇게 설정한다면 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

MDC 정보 연동 문제

./mdc-null.png

기존 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용한다.
-비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

이를 적절하게 Decorator 클래스를 설정하여 MDC의 정보를 복사해서 넘겨줄 수 있다.

다음과 같이 TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정했다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
+ + 문제 상황

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
+확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

비동기 예외 발생시 로깅 설정

Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
+getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

이제 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

MDC 정보 연동 문제

트립드로우의 애플리케이션은 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다. 비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

./mdc-null.png

Spring 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
@Async will not call by @ControllerAdvice for global exception
-Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니

]]>
+Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
+TaskDecorator, Spring docs

]]> async exception
diff --git a/search.html b/search.html index 702142741..eb54daf5c 100644 --- a/search.html +++ b/search.html @@ -13,13 +13,13 @@ - - + + - - + + \ No newline at end of file diff --git a/shopping-cart-retrospective.html b/shopping-cart-retrospective.html index c50aca081..7a7033f06 100644 --- a/shopping-cart-retrospective.html +++ b/shopping-cart-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

웹 장바구니 미션 회고

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
+

웹 장바구니 미션 회고

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
@@ -32,7 +32,7 @@ 추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

의견 일치시키기

페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

- - + + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 4be82832c..d820245c0 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://greeng00se.github.io/2022-retrospectiveweekly0.5https://greeng00se.github.io/accidental-duplicationweekly0.5https://greeng00se.github.io/async-exceptionweekly0.5https://greeng00se.github.io/blackjack-retrospectiveweekly0.5https://greeng00se.github.io/blogweekly0.5https://greeng00se.github.io/book-leadership-and-self-deceptionweekly0.5https://greeng00se.github.io/book-writerweekly0.5https://greeng00se.github.io/chess-retrospectiveweekly0.5https://greeng00se.github.io/cloudwatchweekly0.5https://greeng00se.github.io/compositeweekly0.5https://greeng00se.github.io/custom-jdbc-templateweekly0.5https://greeng00se.github.io/db-replicationweekly0.5https://greeng00se.github.io/docs/tagsweekly0.5https://greeng00se.github.io/docs/tags/bookweekly0.5https://greeng00se.github.io/docs/tags/etcweekly0.5https://greeng00se.github.io/docs/tags/jpaweekly0.5https://greeng00se.github.io/docs/tags/latencyweekly0.5https://greeng00se.github.io/docs/tags/load-balancingweekly0.5https://greeng00se.github.io/docs/tags/monitoringweekly0.5https://greeng00se.github.io/docs/tags/networkweekly0.5https://greeng00se.github.io/docs/tags/nginxweekly0.5https://greeng00se.github.io/docs/tags/packageweekly0.5https://greeng00se.github.io/docs/tags/performanceweekly0.5https://greeng00se.github.io/docs/tags/postmortemweekly0.5https://greeng00se.github.io/docs/tags/testweekly0.5https://greeng00se.github.io/docs/tags/throughputweekly0.5https://greeng00se.github.io/docusaurusweekly0.5https://greeng00se.github.io/graspweekly0.5https://greeng00se.github.io/innodb-lockweekly0.5https://greeng00se.github.io/intellij-settingsweekly0.5https://greeng00se.github.io/java-class-fileweekly0.5https://greeng00se.github.io/java-spring-springbootweekly0.5https://greeng00se.github.io/jenkinsweekly0.5https://greeng00se.github.io/jsr-310weekly0.5https://greeng00se.github.io/kotlin-nullweekly0.5https://greeng00se.github.io/ladder-retrospectiveweekly0.5https://greeng00se.github.io/level2-interview-retrospectiveweekly0.5https://greeng00se.github.io/mock-static-methodweekly0.5https://greeng00se.github.io/mysql-lockweekly0.5https://greeng00se.github.io/order-retrospectiveweekly0.5https://greeng00se.github.io/page/10weekly0.5https://greeng00se.github.io/page/11weekly0.5https://greeng00se.github.io/page/12weekly0.5https://greeng00se.github.io/page/13weekly0.5https://greeng00se.github.io/page/14weekly0.5https://greeng00se.github.io/page/15weekly0.5https://greeng00se.github.io/page/16weekly0.5https://greeng00se.github.io/page/17weekly0.5https://greeng00se.github.io/page/18weekly0.5https://greeng00se.github.io/page/19weekly0.5https://greeng00se.github.io/page/2weekly0.5https://greeng00se.github.io/page/20weekly0.5https://greeng00se.github.io/page/21weekly0.5https://greeng00se.github.io/page/22weekly0.5https://greeng00se.github.io/page/23weekly0.5https://greeng00se.github.io/page/24weekly0.5https://greeng00se.github.io/page/25weekly0.5https://greeng00se.github.io/page/26weekly0.5https://greeng00se.github.io/page/27weekly0.5https://greeng00se.github.io/page/28weekly0.5https://greeng00se.github.io/page/29weekly0.5https://greeng00se.github.io/page/3weekly0.5https://greeng00se.github.io/page/30weekly0.5https://greeng00se.github.io/page/31weekly0.5https://greeng00se.github.io/page/32weekly0.5https://greeng00se.github.io/page/33weekly0.5https://greeng00se.github.io/page/34weekly0.5https://greeng00se.github.io/page/35weekly0.5https://greeng00se.github.io/page/36weekly0.5https://greeng00se.github.io/page/37weekly0.5https://greeng00se.github.io/page/38weekly0.5https://greeng00se.github.io/page/39weekly0.5https://greeng00se.github.io/page/4weekly0.5https://greeng00se.github.io/page/40weekly0.5https://greeng00se.github.io/page/41weekly0.5https://greeng00se.github.io/page/42weekly0.5https://greeng00se.github.io/page/43weekly0.5https://greeng00se.github.io/page/44weekly0.5https://greeng00se.github.io/page/45weekly0.5https://greeng00se.github.io/page/46weekly0.5https://greeng00se.github.io/page/5weekly0.5https://greeng00se.github.io/page/6weekly0.5https://greeng00se.github.io/page/7weekly0.5https://greeng00se.github.io/page/8weekly0.5https://greeng00se.github.io/page/9weekly0.5https://greeng00se.github.io/parameterized-testsweekly0.5https://greeng00se.github.io/performance-test-typeweekly0.5https://greeng00se.github.io/racing-car-retrospectiveweekly0.5https://greeng00se.github.io/route-image-async-with-eventweekly0.5https://greeng00se.github.io/route-image-implementationweekly0.5https://greeng00se.github.io/route-image-introweekly0.5https://greeng00se.github.io/route-image-pythonweekly0.5https://greeng00se.github.io/searchweekly0.5https://greeng00se.github.io/shopping-cart-retrospectiveweekly0.5https://greeng00se.github.io/subway-retrospectiveweekly0.5https://greeng00se.github.io/tagsweekly0.5https://greeng00se.github.io/tags/asyncweekly0.5https://greeng00se.github.io/tags/async/page/2weekly0.5https://greeng00se.github.io/tags/awtweekly0.5https://greeng00se.github.io/tags/awt/page/2weekly0.5https://greeng00se.github.io/tags/bookweekly0.5https://greeng00se.github.io/tags/book/page/2weekly0.5https://greeng00se.github.io/tags/book/page/3weekly0.5https://greeng00se.github.io/tags/classweekly0.5https://greeng00se.github.io/tags/cloudwatchweekly0.5https://greeng00se.github.io/tags/compositeweekly0.5https://greeng00se.github.io/tags/data-baseweekly0.5https://greeng00se.github.io/tags/data-base/page/2weekly0.5https://greeng00se.github.io/tags/data-base/page/3weekly0.5https://greeng00se.github.io/tags/documentationweekly0.5https://greeng00se.github.io/tags/dtoweekly0.5https://greeng00se.github.io/tags/elastic-beanstalkweekly0.5https://greeng00se.github.io/tags/eventweekly0.5https://greeng00se.github.io/tags/exceptionweekly0.5https://greeng00se.github.io/tags/graspweekly0.5https://greeng00se.github.io/tags/imageweekly0.5https://greeng00se.github.io/tags/image/page/2weekly0.5https://greeng00se.github.io/tags/image/page/3weekly0.5https://greeng00se.github.io/tags/inno-dbweekly0.5https://greeng00se.github.io/tags/intelli-jweekly0.5https://greeng00se.github.io/tags/isolationweekly0.5https://greeng00se.github.io/tags/javaweekly0.5https://greeng00se.github.io/tags/java/page/2weekly0.5https://greeng00se.github.io/tags/java/page/3weekly0.5https://greeng00se.github.io/tags/java/page/4weekly0.5https://greeng00se.github.io/tags/java/page/5weekly0.5https://greeng00se.github.io/tags/jdbcweekly0.5https://greeng00se.github.io/tags/jenkinsweekly0.5https://greeng00se.github.io/tags/kotlinweekly0.5https://greeng00se.github.io/tags/lockweekly0.5https://greeng00se.github.io/tags/lock/page/2weekly0.5https://greeng00se.github.io/tags/logweekly0.5https://greeng00se.github.io/tags/mockweekly0.5https://greeng00se.github.io/tags/mockitoweekly0.5https://greeng00se.github.io/tags/monitoringweekly0.5https://greeng00se.github.io/tags/my-sqlweekly0.5https://greeng00se.github.io/tags/mysqlweekly0.5https://greeng00se.github.io/tags/oopweekly0.5https://greeng00se.github.io/tags/patternweekly0.5https://greeng00se.github.io/tags/performance-testweekly0.5https://greeng00se.github.io/tags/pythonweekly0.5https://greeng00se.github.io/tags/replicationweekly0.5https://greeng00se.github.io/tags/retrospectiveweekly0.5https://greeng00se.github.io/tags/retrospective/page/10weekly0.5https://greeng00se.github.io/tags/retrospective/page/11weekly0.5https://greeng00se.github.io/tags/retrospective/page/12weekly0.5https://greeng00se.github.io/tags/retrospective/page/13weekly0.5https://greeng00se.github.io/tags/retrospective/page/14weekly0.5https://greeng00se.github.io/tags/retrospective/page/15weekly0.5https://greeng00se.github.io/tags/retrospective/page/16weekly0.5https://greeng00se.github.io/tags/retrospective/page/17weekly0.5https://greeng00se.github.io/tags/retrospective/page/2weekly0.5https://greeng00se.github.io/tags/retrospective/page/3weekly0.5https://greeng00se.github.io/tags/retrospective/page/4weekly0.5https://greeng00se.github.io/tags/retrospective/page/5weekly0.5https://greeng00se.github.io/tags/retrospective/page/6weekly0.5https://greeng00se.github.io/tags/retrospective/page/7weekly0.5https://greeng00se.github.io/tags/retrospective/page/8weekly0.5https://greeng00se.github.io/tags/retrospective/page/9weekly0.5https://greeng00se.github.io/tags/springweekly0.5https://greeng00se.github.io/tags/spring-bootweekly0.5https://greeng00se.github.io/tags/staticweekly0.5https://greeng00se.github.io/tags/teco-chatweekly0.5https://greeng00se.github.io/tags/teco-chat/page/2weekly0.5https://greeng00se.github.io/tags/teco-chat/page/3weekly0.5https://greeng00se.github.io/tags/testweekly0.5https://greeng00se.github.io/tags/timeweekly0.5https://greeng00se.github.io/tags/transactionweekly0.5https://greeng00se.github.io/tags/web-socketweekly0.5https://greeng00se.github.io/tags/woowahan-techcourseweekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/10weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/11weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/12weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/13weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/2weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/3weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/4weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/5weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/6weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/7weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/8weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/9weekly0.5https://greeng00se.github.io/tecochat-retrospective-1weekly0.5https://greeng00se.github.io/tecochat-retrospective-2weekly0.5https://greeng00se.github.io/tecochat-retrospective-3weekly0.5https://greeng00se.github.io/test-doubleweekly0.5https://greeng00se.github.io/the-essence-of-object-orientationweekly0.5https://greeng00se.github.io/tomcat-retrospectiveweekly0.5https://greeng00se.github.io/transaction-and-isolationweekly0.5https://greeng00se.github.io/web-racing-car-retrospectiveweekly0.5https://greeng00se.github.io/websocketweekly0.5https://greeng00se.github.io/woowacourse-level1-retrospectiveweekly0.5https://greeng00se.github.io/woowacourse-level2-retrospectiveweekly0.5https://greeng00se.github.io/woowacourse-level3-retrospectiveweekly0.5https://greeng00se.github.io/docsweekly0.5https://greeng00se.github.io/docs/book/getting-out-of-the-boxweekly0.5https://greeng00se.github.io/docs/culture/postmortemweekly0.5https://greeng00se.github.io/docs/design/packageweekly0.5https://greeng00se.github.io/docs/etc/communicationweekly0.5https://greeng00se.github.io/docs/etc/develop-with-springweekly0.5https://greeng00se.github.io/docs/etc/experience-and-self-questionweekly0.5https://greeng00se.github.io/docs/etc/healthful-growthweekly0.5https://greeng00se.github.io/docs/jpa/keyweekly0.5https://greeng00se.github.io/docs/linux/shellweekly0.5https://greeng00se.github.io/docs/linux/swapweekly0.5https://greeng00se.github.io/docs/monitoring/introweekly0.5https://greeng00se.github.io/docs/network/load-balancingweekly0.5https://greeng00se.github.io/docs/network/load-balancing-algorithmweekly0.5https://greeng00se.github.io/docs/nginx/commandweekly0.5https://greeng00se.github.io/docs/nginx/static-fileweekly0.5https://greeng00se.github.io/docs/performance/throughputweekly0.5https://greeng00se.github.io/docs/performance/throughput-latencyweekly0.5https://greeng00se.github.io/docs/performance/typesweekly0.5https://greeng00se.github.io/docs/test/benefitweekly0.5https://greeng00se.github.io/docs/test/firstweekly0.5https://greeng00se.github.io/docs/test/heuristicsweekly0.5https://greeng00se.github.io/docs/test/stairstepweekly0.5https://greeng00se.github.io/weekly0.5https://greeng00se.github.io/weekly0.5 \ No newline at end of file +https://greeng00se.github.io/2022-retrospectiveweekly0.5https://greeng00se.github.io/accidental-duplicationweekly0.5https://greeng00se.github.io/blackjack-retrospectiveweekly0.5https://greeng00se.github.io/blogweekly0.5https://greeng00se.github.io/book-leadership-and-self-deceptionweekly0.5https://greeng00se.github.io/book-writerweekly0.5https://greeng00se.github.io/chess-retrospectiveweekly0.5https://greeng00se.github.io/cloudwatchweekly0.5https://greeng00se.github.io/compositeweekly0.5https://greeng00se.github.io/custom-jdbc-templateweekly0.5https://greeng00se.github.io/db-replicationweekly0.5https://greeng00se.github.io/docs/tagsweekly0.5https://greeng00se.github.io/docs/tags/bookweekly0.5https://greeng00se.github.io/docs/tags/etcweekly0.5https://greeng00se.github.io/docs/tags/jpaweekly0.5https://greeng00se.github.io/docs/tags/latencyweekly0.5https://greeng00se.github.io/docs/tags/load-balancingweekly0.5https://greeng00se.github.io/docs/tags/monitoringweekly0.5https://greeng00se.github.io/docs/tags/networkweekly0.5https://greeng00se.github.io/docs/tags/nginxweekly0.5https://greeng00se.github.io/docs/tags/packageweekly0.5https://greeng00se.github.io/docs/tags/performanceweekly0.5https://greeng00se.github.io/docs/tags/postmortemweekly0.5https://greeng00se.github.io/docs/tags/testweekly0.5https://greeng00se.github.io/docs/tags/throughputweekly0.5https://greeng00se.github.io/docusaurusweekly0.5https://greeng00se.github.io/graspweekly0.5https://greeng00se.github.io/innodb-lockweekly0.5https://greeng00se.github.io/intellij-settingsweekly0.5https://greeng00se.github.io/java-class-fileweekly0.5https://greeng00se.github.io/java-spring-springbootweekly0.5https://greeng00se.github.io/jenkinsweekly0.5https://greeng00se.github.io/jsr-310weekly0.5https://greeng00se.github.io/kotlin-nullweekly0.5https://greeng00se.github.io/ladder-retrospectiveweekly0.5https://greeng00se.github.io/level2-interview-retrospectiveweekly0.5https://greeng00se.github.io/log-async-exceptionweekly0.5https://greeng00se.github.io/mock-static-methodweekly0.5https://greeng00se.github.io/mysql-lockweekly0.5https://greeng00se.github.io/order-retrospectiveweekly0.5https://greeng00se.github.io/page/10weekly0.5https://greeng00se.github.io/page/11weekly0.5https://greeng00se.github.io/page/12weekly0.5https://greeng00se.github.io/page/13weekly0.5https://greeng00se.github.io/page/14weekly0.5https://greeng00se.github.io/page/15weekly0.5https://greeng00se.github.io/page/16weekly0.5https://greeng00se.github.io/page/17weekly0.5https://greeng00se.github.io/page/18weekly0.5https://greeng00se.github.io/page/19weekly0.5https://greeng00se.github.io/page/2weekly0.5https://greeng00se.github.io/page/20weekly0.5https://greeng00se.github.io/page/21weekly0.5https://greeng00se.github.io/page/22weekly0.5https://greeng00se.github.io/page/23weekly0.5https://greeng00se.github.io/page/24weekly0.5https://greeng00se.github.io/page/25weekly0.5https://greeng00se.github.io/page/26weekly0.5https://greeng00se.github.io/page/27weekly0.5https://greeng00se.github.io/page/28weekly0.5https://greeng00se.github.io/page/29weekly0.5https://greeng00se.github.io/page/3weekly0.5https://greeng00se.github.io/page/30weekly0.5https://greeng00se.github.io/page/31weekly0.5https://greeng00se.github.io/page/32weekly0.5https://greeng00se.github.io/page/33weekly0.5https://greeng00se.github.io/page/34weekly0.5https://greeng00se.github.io/page/35weekly0.5https://greeng00se.github.io/page/36weekly0.5https://greeng00se.github.io/page/37weekly0.5https://greeng00se.github.io/page/38weekly0.5https://greeng00se.github.io/page/39weekly0.5https://greeng00se.github.io/page/4weekly0.5https://greeng00se.github.io/page/40weekly0.5https://greeng00se.github.io/page/41weekly0.5https://greeng00se.github.io/page/42weekly0.5https://greeng00se.github.io/page/43weekly0.5https://greeng00se.github.io/page/44weekly0.5https://greeng00se.github.io/page/45weekly0.5https://greeng00se.github.io/page/46weekly0.5https://greeng00se.github.io/page/5weekly0.5https://greeng00se.github.io/page/6weekly0.5https://greeng00se.github.io/page/7weekly0.5https://greeng00se.github.io/page/8weekly0.5https://greeng00se.github.io/page/9weekly0.5https://greeng00se.github.io/parameterized-testsweekly0.5https://greeng00se.github.io/performance-test-typeweekly0.5https://greeng00se.github.io/racing-car-retrospectiveweekly0.5https://greeng00se.github.io/route-image-async-with-eventweekly0.5https://greeng00se.github.io/route-image-implementationweekly0.5https://greeng00se.github.io/route-image-introweekly0.5https://greeng00se.github.io/route-image-pythonweekly0.5https://greeng00se.github.io/searchweekly0.5https://greeng00se.github.io/shopping-cart-retrospectiveweekly0.5https://greeng00se.github.io/subway-retrospectiveweekly0.5https://greeng00se.github.io/tagsweekly0.5https://greeng00se.github.io/tags/asyncweekly0.5https://greeng00se.github.io/tags/async/page/2weekly0.5https://greeng00se.github.io/tags/awtweekly0.5https://greeng00se.github.io/tags/awt/page/2weekly0.5https://greeng00se.github.io/tags/bookweekly0.5https://greeng00se.github.io/tags/book/page/2weekly0.5https://greeng00se.github.io/tags/book/page/3weekly0.5https://greeng00se.github.io/tags/classweekly0.5https://greeng00se.github.io/tags/cloudwatchweekly0.5https://greeng00se.github.io/tags/compositeweekly0.5https://greeng00se.github.io/tags/data-baseweekly0.5https://greeng00se.github.io/tags/data-base/page/2weekly0.5https://greeng00se.github.io/tags/data-base/page/3weekly0.5https://greeng00se.github.io/tags/documentationweekly0.5https://greeng00se.github.io/tags/dtoweekly0.5https://greeng00se.github.io/tags/elastic-beanstalkweekly0.5https://greeng00se.github.io/tags/eventweekly0.5https://greeng00se.github.io/tags/exceptionweekly0.5https://greeng00se.github.io/tags/graspweekly0.5https://greeng00se.github.io/tags/imageweekly0.5https://greeng00se.github.io/tags/image/page/2weekly0.5https://greeng00se.github.io/tags/image/page/3weekly0.5https://greeng00se.github.io/tags/inno-dbweekly0.5https://greeng00se.github.io/tags/intelli-jweekly0.5https://greeng00se.github.io/tags/isolationweekly0.5https://greeng00se.github.io/tags/javaweekly0.5https://greeng00se.github.io/tags/java/page/2weekly0.5https://greeng00se.github.io/tags/java/page/3weekly0.5https://greeng00se.github.io/tags/java/page/4weekly0.5https://greeng00se.github.io/tags/java/page/5weekly0.5https://greeng00se.github.io/tags/jdbcweekly0.5https://greeng00se.github.io/tags/jenkinsweekly0.5https://greeng00se.github.io/tags/kotlinweekly0.5https://greeng00se.github.io/tags/lockweekly0.5https://greeng00se.github.io/tags/lock/page/2weekly0.5https://greeng00se.github.io/tags/logweekly0.5https://greeng00se.github.io/tags/mockweekly0.5https://greeng00se.github.io/tags/mockitoweekly0.5https://greeng00se.github.io/tags/monitoringweekly0.5https://greeng00se.github.io/tags/my-sqlweekly0.5https://greeng00se.github.io/tags/mysqlweekly0.5https://greeng00se.github.io/tags/oopweekly0.5https://greeng00se.github.io/tags/patternweekly0.5https://greeng00se.github.io/tags/performance-testweekly0.5https://greeng00se.github.io/tags/pythonweekly0.5https://greeng00se.github.io/tags/replicationweekly0.5https://greeng00se.github.io/tags/retrospectiveweekly0.5https://greeng00se.github.io/tags/retrospective/page/10weekly0.5https://greeng00se.github.io/tags/retrospective/page/11weekly0.5https://greeng00se.github.io/tags/retrospective/page/12weekly0.5https://greeng00se.github.io/tags/retrospective/page/13weekly0.5https://greeng00se.github.io/tags/retrospective/page/14weekly0.5https://greeng00se.github.io/tags/retrospective/page/15weekly0.5https://greeng00se.github.io/tags/retrospective/page/16weekly0.5https://greeng00se.github.io/tags/retrospective/page/17weekly0.5https://greeng00se.github.io/tags/retrospective/page/2weekly0.5https://greeng00se.github.io/tags/retrospective/page/3weekly0.5https://greeng00se.github.io/tags/retrospective/page/4weekly0.5https://greeng00se.github.io/tags/retrospective/page/5weekly0.5https://greeng00se.github.io/tags/retrospective/page/6weekly0.5https://greeng00se.github.io/tags/retrospective/page/7weekly0.5https://greeng00se.github.io/tags/retrospective/page/8weekly0.5https://greeng00se.github.io/tags/retrospective/page/9weekly0.5https://greeng00se.github.io/tags/springweekly0.5https://greeng00se.github.io/tags/spring-bootweekly0.5https://greeng00se.github.io/tags/staticweekly0.5https://greeng00se.github.io/tags/teco-chatweekly0.5https://greeng00se.github.io/tags/teco-chat/page/2weekly0.5https://greeng00se.github.io/tags/teco-chat/page/3weekly0.5https://greeng00se.github.io/tags/testweekly0.5https://greeng00se.github.io/tags/timeweekly0.5https://greeng00se.github.io/tags/transactionweekly0.5https://greeng00se.github.io/tags/web-socketweekly0.5https://greeng00se.github.io/tags/woowahan-techcourseweekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/10weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/11weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/12weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/13weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/2weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/3weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/4weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/5weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/6weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/7weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/8weekly0.5https://greeng00se.github.io/tags/woowahan-techcourse/page/9weekly0.5https://greeng00se.github.io/tecochat-retrospective-1weekly0.5https://greeng00se.github.io/tecochat-retrospective-2weekly0.5https://greeng00se.github.io/tecochat-retrospective-3weekly0.5https://greeng00se.github.io/test-doubleweekly0.5https://greeng00se.github.io/the-essence-of-object-orientationweekly0.5https://greeng00se.github.io/tomcat-retrospectiveweekly0.5https://greeng00se.github.io/transaction-and-isolationweekly0.5https://greeng00se.github.io/web-racing-car-retrospectiveweekly0.5https://greeng00se.github.io/websocketweekly0.5https://greeng00se.github.io/woowacourse-level1-retrospectiveweekly0.5https://greeng00se.github.io/woowacourse-level2-retrospectiveweekly0.5https://greeng00se.github.io/woowacourse-level3-retrospectiveweekly0.5https://greeng00se.github.io/docsweekly0.5https://greeng00se.github.io/docs/book/getting-out-of-the-boxweekly0.5https://greeng00se.github.io/docs/culture/postmortemweekly0.5https://greeng00se.github.io/docs/design/packageweekly0.5https://greeng00se.github.io/docs/etc/communicationweekly0.5https://greeng00se.github.io/docs/etc/develop-with-springweekly0.5https://greeng00se.github.io/docs/etc/experience-and-self-questionweekly0.5https://greeng00se.github.io/docs/etc/healthful-growthweekly0.5https://greeng00se.github.io/docs/jpa/keyweekly0.5https://greeng00se.github.io/docs/linux/shellweekly0.5https://greeng00se.github.io/docs/linux/swapweekly0.5https://greeng00se.github.io/docs/monitoring/introweekly0.5https://greeng00se.github.io/docs/network/load-balancingweekly0.5https://greeng00se.github.io/docs/network/load-balancing-algorithmweekly0.5https://greeng00se.github.io/docs/nginx/commandweekly0.5https://greeng00se.github.io/docs/nginx/static-fileweekly0.5https://greeng00se.github.io/docs/performance/throughputweekly0.5https://greeng00se.github.io/docs/performance/throughput-latencyweekly0.5https://greeng00se.github.io/docs/performance/typesweekly0.5https://greeng00se.github.io/docs/test/benefitweekly0.5https://greeng00se.github.io/docs/test/firstweekly0.5https://greeng00se.github.io/docs/test/heuristicsweekly0.5https://greeng00se.github.io/docs/test/stairstepweekly0.5https://greeng00se.github.io/weekly0.5https://greeng00se.github.io/weekly0.5 \ No newline at end of file diff --git a/subway-retrospective.html b/subway-retrospective.html index d1a831938..42a705c00 100644 --- a/subway-retrospective.html +++ b/subway-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

지하철 미션 회고

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
+

지하철 미션 회고

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
지하철 미션은 밀리랑 페어를 진행했다.
간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
@@ -39,7 +39,7 @@ 또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

편한 분위기

전체적으로 페어 할 때 편하게 진행했던 것 같다.
일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
나는 과연 다른 사람들에게 편한 사람일까?

- - + + \ No newline at end of file diff --git a/tags.html b/tags.html index 2b559dee7..c1b8b2460 100644 --- a/tags.html +++ b/tags.html @@ -13,13 +13,13 @@ - - + + - - +
+ + \ No newline at end of file diff --git a/tags/async.html b/tags/async.html index 3cf395640..f04809233 100644 --- a/tags/async.html +++ b/tags/async.html @@ -13,17 +13,18 @@ - - + +
-

"async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

개요

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.

확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았다. 따라서 Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

비동기 예외처리

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

해당 AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다. getAsyncUncaughtExceptionHandler 메서드를 오버라이딩하여 이전에 생성해 준 AsyncExceptionHandler를 반환하도록 설정했다.
-이렇게 설정한다면 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

MDC 정보 연동 문제

./mdc-null.png

기존 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용한다.
-비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

이를 적절하게 Decorator 클래스를 설정하여 MDC의 정보를 복사해서 넘겨줄 수 있다.

다음과 같이 TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정했다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
+

"async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

문제 상황

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
+확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

비동기 예외 발생시 로깅 설정

Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
+getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

이제 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

MDC 정보 연동 문제

트립드로우의 애플리케이션은 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다. 비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

./mdc-null.png

Spring 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
@Async will not call by @ControllerAdvice for global exception
-Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니

- - +Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
+TaskDecorator, Spring docs

+ + \ No newline at end of file diff --git a/tags/async/page/2.html b/tags/async/page/2.html index c05f1ccad..e4240d262 100644 --- a/tags/async/page/2.html +++ b/tags/async/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
+

"async" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
경로 이미지 생성하기 - 구현

개요

현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

주기능의 응답속도 개선

여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
@@ -45,7 +45,7 @@ 응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

참고 자료

7.7. Task Execution and Scheduling, Spring Boot Docs
Spring Events, Baeldung
회원시스템 이벤트기반 아키텍처 구축하기

- - + + \ No newline at end of file diff --git a/tags/awt.html b/tags/awt.html index 4cc420dad..b80eeb95a 100644 --- a/tags/awt.html +++ b/tags/awt.html @@ -13,12 +13,12 @@ - - + +
-

"awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
+

"awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

구현 결과

./result.png

예시 데이터는 다음과 같다.
서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

예시 데이터
List<Double> x = List.of(
126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
);
List<Double> y = List.of(
37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
);
List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);

IMAGE_SIZE & ROUTE_SIZE

RouteImageGenerator.java
private static final int IMAGE_SIZE = 800;
private static final int ROUTE_SIZE = 600;

코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
@@ -29,7 +29,7 @@ BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

./800.png

따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

x 값 → 계산한 offset 그대로 더한다.
y 값 → imageSize(800)에서 y + offset 값을 뺀다.

RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
그림을 그리기 위해 설정한 상수들이 존재한다.

RouteImageDrawer.java
// RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
// 이를 RGBA라고 부른다.
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
// 배경 투명색
private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
// 경로를 위한 STROKE
private static final int LINE_STROKE_WIDTH = 7;
private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 위치 점을 위한 STROKE
private static final int POINT_STROKE_WIDTH = 20;
private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 안티앨리어싱 등 화질 개선을 위한 설정
private static final Map<Object, Object> renderingHints = Map.of(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
);

RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

  • drawLine: 선을 그린다.
  • drawPoint: 점을 찍는다.
  • dispose: 자원 할당을 해제한다.

dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

이미지 생성 Flow

1. 이미지 생성 준비

2. 선 그리기 요청

3. 위치 점 그리기 요청

4. 업로드 요청

전체 Flow

- - + + \ No newline at end of file diff --git a/tags/awt/page/2.html b/tags/awt/page/2.html index ff25e3e41..ce34ba748 100644 --- a/tags/awt/page/2.html +++ b/tags/awt/page/2.html @@ -13,19 +13,19 @@ - - + +
-

"awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
+

"awt" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

  • 이미지 생성
  • 선과 점 표현
  • 투명한 배경색

현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

고려한 기술

백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

  • Python의 Matplotlib
  • AWT(Abstract Window Toolkit) [최종 선택]
  • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
  • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)

Python & Matplotlib

데이터 시각화 라이브러리
이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

  • 코드가 간단해서 유지 보수성이 좋다.
  • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
  • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.

Java AWT 이외의 라이브러리

Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

라이브러리설명제외 이유
SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음

Java & AWT(Abstract Window Toolkit)

그래픽과 이미지를 그리기 위한 도구
이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

  • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
  • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
  • 추가적인 api 호출을 하지 않아도 된다.

기술 선택

AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

유지 보수

AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
따라서 다음과 같은 방법으로 공유하기로 했다.

  1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
  2. AWT를 사용한 부분을 문서화하여 공유한다.

레벨 3를 마무리하며 내용 추가

기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

- - + + \ No newline at end of file diff --git a/tags/book.html b/tags/book.html index 6c0e599d8..0885e4a32 100644 --- a/tags/book.html +++ b/tags/book.html @@ -13,12 +13,12 @@ - - + +
-

"Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

책 정보

상자 밖에 있는 사람
+

"Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

책 정보

상자 밖에 있는 사람
아빈저연구소

자기기만과 자기배반

책에서는 자기기만과 자기배반에 대한 내용을 다룬다.

  • 자기기만: 자신의 문제를 인정하지 않는 것
  • 자기배반: 다른 사람을 위해 무언가 해야만 한다는 생각을 반하는 행위

자기배반을 한다면 자기기만 상태가 된다.
자기기만 상태에 빠지는 것을 책에서는 상자 안에 들어간다고 표현한다.

읽고 나서

최근에 읽은 책 중 가장 마음이 불편했다.
그렇기에 더더욱 나에게 필요한 내용이 담겨있었다.

살면서 많은 선택의 순간이 존재했고, 그 순간마다 자기배반을 택하는 경우가 많았다.
@@ -48,7 +48,7 @@ 우리가 그들과 진정으로 함께 소통하기 전까지는 우리는 그들의 가치를 잘 모릅니다.
우리의 위대함이란 다른 사람들의 위대한 점을 발견해 주는 것에 있습니다.
p.280

- - + + \ No newline at end of file diff --git a/tags/book/page/2.html b/tags/book/page/2.html index 499fb92fd..e0afad8fa 100644 --- a/tags/book/page/2.html +++ b/tags/book/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

책 정보

객체지향의 사실과 오해
+

"Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

책 정보

객체지향의 사실과 오해
조영호

읽고 나서

조영호님의 오브젝트를 읽고 나서 다시 한 번 읽어보았다.
아직 이해가 안되는 부분이 많지만, 그래도 항상 새로움을 느낀다.
더할 나위 없이 휼륭한 객체지향 책이고, 조금 더 공부하고 다시 읽어봐야될 것 같다.

커피 전문점, 지하철 노선도, 이상한 나라의 엘리스를 예시로 든 설명이 너무 좋았고
@@ -38,7 +38,7 @@ ’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. 여기서 ‘어떤 행위’가 바로 메시지다. p.158

- - + + \ No newline at end of file diff --git a/tags/book/page/3.html b/tags/book/page/3.html index e0bb45407..edc29cab2 100644 --- a/tags/book/page/3.html +++ b/tags/book/page/3.html @@ -13,18 +13,18 @@ - - + +
-

"Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

책 정보

글, 우리도 잘 쓸 수 있습니다.
+

"Book" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

책 정보

글, 우리도 잘 쓸 수 있습니다.
박솔미

읽고 나서

저자의 경험과 함께 글쓰기에 대한 가벼운 조언이 담겨있어 가볍게 읽기 좋았다.
글을 잘 작성해 보고 싶을 때 적용해 볼 수 있는 정보가 많아서 도움이 되었다.

우아한 테크코스의 프리코스를 진행할 때 후기를 작성하고 나면 항상 글이 딱딱하다는 느낌을 받았다.
다른 지원자들의 읽기 편하고, 밝은 느낌을 주는 글을 보면 부러운 마음을 가지기도 했다.
이 책을 읽었으니 2023년에는 조금 더 글을 잘 적어보려고 한다.

밑줄 친 문장들

문장이 심심하고 지루하다면 내용을 일목요연하게 정리했고, 글의 의도도 삐뚤지 않고, 단어도 적절한 것으로 골랐는데… 그런데도 어딘가가 심심하고 지루하다면? 축축 처지고 따분하다면? 말꼬리를 모조리 ‘~다’로 통일한 건 아닌지 점검해 보세요.

말꼬리를 잘 갖고 놀아야 합니다. 문장의 마지막 글자를 매번 다르게 고쳐쓰는 것만으로도 글에 활기를 더할 수 있죠. 때론 문장을 다 마치지 않고, 단어로만 끝맺는 것도 방법. 문장과 문장 사이에 쉼표가 들어서며 글 전체에 활기가 돌게 돼요. 문장의 길이도 다채로워지는 덕분에 덤으로 얻게 되는 것도 있습니다. 바로, 글의 리듬.

이전 문장에서 끝난 글자로, 다음 문장을 끝맺지 않기. 한두 문단마다 단어 수준의 아주 짧은 문장 배치하기.

글의 진짜 이유, 글의 진짜 목적, 글의 진짜 대상을 찾으려고 애썼습니다. 지금처럼 틀을 떠올린다거나, 눈치를 본다거나, 정치적인 셈도 하지 않았어요.

제목은 짧게, 보기 쉽게, 읽기 쉽게, 발음이 비슷하게, 순서를 바꿔서

글을 마지막으로 다듬을 때, 노래에 가까워질 방법은 없을지 고민해봅니다. 감히 가 닿을 수 없는 목표이겠지만, 할 수 있는 최소한의 리듬이라도 붙여주고 싶어요.

여는 말과 마지막 말에 작정하고 마음을 담는 연습을 해봅시다. 글의 어느 구석이라도 뻔한 글자는 남기지 않겠노라 다짐하며 써보는 겁니다. 나만이 가진 유일한 메시지에 집중하면서요. 그럼 생각이 달라지고, 고르는 단어도 달라지고, 남긴 문장도 달라져요. 결국에는 글을 쓴 사람인 나 자신도 남달라질 겁니다.

맞춤법은 중요합니다. 하지만 맞춤법보다 더 중요한 건 거기에 담긴 마음입니다. 내 마음을 글에 담아 실어 보내기 전, 맞춤법을 점검하는 이유 역시 그겁니다. 오직 내 마음이 남에게 읽히는 동안 방해가 되지 않기를 바라기 때문이죠. 내가 쓴 글도, 남이 쓴 글도. 언제나 그 안에 담긴 마음이 먼저입니다.

글을 쓴다고 글이 완성되는 게 아니에요. 글과 닮은 모습으로 살 때, 글은 비로소 완성됩니다.

- - + + \ No newline at end of file diff --git a/tags/class.html b/tags/class.html index 66bf753c8..7c8b0b109 100644 --- a/tags/class.html +++ b/tags/class.html @@ -13,12 +13,12 @@ - - + +
-

"Class" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
+

"Class" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
컴파일된 클래스파일은 어떤 구조로 되어있을까?

클래스 파일의 데이터 형식

8비트 바이트의 스트림으로 구성된다.
16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
멀티바이트의 경우 항상 big endian 순서로 저장된다.

u1 → unsigned 1byte
@@ -36,7 +36,7 @@ Class file in Java, File Format
java se11 Class 파일 형식, Oracle
java se17 Class 파일 형식, Oracle

- - + + \ No newline at end of file diff --git a/tags/cloudwatch.html b/tags/cloudwatch.html index 78ddfe394..8dc3e8301 100644 --- a/tags/cloudwatch.html +++ b/tags/cloudwatch.html @@ -13,12 +13,12 @@ - - + +
-

"cloudwatch" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
+

"cloudwatch" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
지표를 감시하여 알림을 보내는 기능도 제공한다.
프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
요금 정보에 대한 자세한 정보는 다음 링크에서 확인할 수 있다.

CloudWatch Metrics

기본적으로 5분마다 지표에 대한 정보가 수집된다.
@@ -38,7 +38,7 @@ 서버에 CloudWatch 에이전트 설치 및 실행
CloudWatch Agent를 Parameter Store에서 관리해 보기
CloudWatch에이전트 구성 파일

- - + + \ No newline at end of file diff --git a/tags/composite.html b/tags/composite.html index c6cb013d5..a538ee052 100644 --- a/tags/composite.html +++ b/tags/composite.html @@ -13,12 +13,12 @@ - - + +
-

"Composite" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • 노선별 추가 요금 정책
  • 연령별 요금 할인 정책

인터페이스 사용

요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
+

"Composite" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • 노선별 추가 요금 정책
  • 연령별 요금 할인 정책

인터페이스 사용

요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
요금을 계산하는 메서드는 최단 경로 계산의 결과, 사용자의 정보, 요금을 받아 요금을 계산한다.

public interface FarePolicy {
int calculate(Path path, Passenger passenger, int fare);
}

public class BaseFarePolicy implements FarePolicy { ... }
public class DistanceFarePolicy implements FarePolicy { ... }
public class AgeDiscountFarePolicy implements FarePolicy { ... }

composite1

모든 요금 정책을 포함하는 새로운 요금 정책 만들기

나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

public class SubwayFarePolicy implements FarePolicy {

private final List<FarePolicy> farePolicies;

public SubwayFarePolicy(final List<FarePolicy> farePolicies) {
this.farePolicies = farePolicies;
}

@Override
public int calculate(final Path path, final Passenger passenger, final int fare) {
int calculatedFare = fare;
for (FarePolicy farePolicy : farePolicies) {
calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);
}
return calculatedFare;
}
}

따라서 그림으로 본다면 다음과 같은 구조가 된다.

composite2

정책의 순서

지하철 요구사항은 순서가 중요했다.
금액의 총합을 구하고, 그 후에 할인 정책이 들어가야했다.
@@ -31,7 +31,7 @@ 패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
항상 트레이드오프를 생각하자!

참고 자료

컴포지트 패턴, GoF의 디자인 패턴
디자인 패턴과 프레임워크, 오브젝트

- - + + \ No newline at end of file diff --git a/tags/data-base.html b/tags/data-base.html index 1ae8a48ec..470a0aaf9 100644 --- a/tags/data-base.html +++ b/tags/data-base.html @@ -13,12 +13,12 @@ - - + +
-

"DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
+

"DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

낙관적 동시성 제어(OCC, Optimistic concurrency control)

트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

비관적 동시성 제어(PCC, Pessimistic Concurrency Control)

트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

Shared & Exclusive Locks

InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

공유 잠금(S, shared lock)

데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
@@ -38,7 +38,7 @@ MySQL Innodb Locks, cecil1018
MySQL 8.0 InnoDB Locks, MySQL
Locks Set by Different SQL Statements in InnoDB, MySQL

- - + + \ No newline at end of file diff --git a/tags/data-base/page/2.html b/tags/data-base/page/2.html index fe2e875e3..dbacc4d11 100644 --- a/tags/data-base/page/2.html +++ b/tags/data-base/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
+

"DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

글로벌 락(Global lock)

MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

  • 영향을 미치는 범위는 해당 서버 전체이다.
  • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.

한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

-- GLOBAL LOCK
FLUSH TABLES WITH READ LOCK;
-- UNLOCK
UNLOCK TABLES;

-- BACKUP LOCK
LOCK INSTANCE FOR BACKUP;
-- UNLOCK
UNLOCK INSTANCE;
- - + + \ No newline at end of file diff --git a/tags/data-base/page/3.html b/tags/data-base/page/3.html index bf9b4c497..9dafdb592 100644 --- a/tags/data-base/page/3.html +++ b/tags/data-base/page/3.html @@ -13,12 +13,12 @@ - - + +
-

"DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
+

"DataBase" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

트랜잭션의 속성(ACID)

원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
@@ -42,7 +42,7 @@ 예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

팬텀 리드(Phantom read, Phantom row)

한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

참고 자료

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
Isolation Level, MySQL

- - + + \ No newline at end of file diff --git a/tags/documentation.html b/tags/documentation.html index 606ce5404..a51151601 100644 --- a/tags/documentation.html +++ b/tags/documentation.html @@ -13,12 +13,12 @@ - - + +
-

"Documentation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus

배포

배포 안내 문서
+

"Documentation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 11분

팀 블로그 또는 문서화를 위해 Docusaurus를 사용하는 방법을 정리하려고 한다.

설치

공식 홈페이지에 들어가서 최신 버전을 설치한다.

yarn create docusaurus

배포

배포 안내 문서
netlify나 vercel 같은 서버리스 플랫폼을 추천하고 있고, 간단하고, 빠른 시간 안에 배포를 할 수 있다.
이 글에서는 github pages를 이용해서 배포하는 방법을 설명한다.

레포지토리 생성

github pages를 이용하려면 예시와 같이 username.github.io 형태의 레포지토리를 생성해야 한다.
이때 organization을 사용하는 경우 organization.github.io 형태의 레포지토리를 생성해서 사용한다.

설정 파일 수정

docusaurus.config
module.exports = {
// ...
url: 'https://greeng00se.github.io',
baseUrl: '/',
projectName: 'greeng00se.github.io',
organizationName: 'greeng00se',
trailingSlash: false,
// ...
};

토큰 설정

github action을 위해 배포용 토큰을 하나 생성하여 생성한 레포지토리에 Repository secrets으로 설정한다.
@@ -39,7 +39,7 @@ jq가 설치되어 있지 않으면 mac 기준 brew를 이용해서 설치할 수 있다.

brew install jq

다음 명령어를 이용하여 .env와 config.json을 이용하여 크롤링을 한다.

docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper

docusaurus 설정

전에 확인한 APP ID, Search-Only API KEY, IndexName을 이용하여 docusaurus.config 파일에 설정한다.

docusaurus.config
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
...
algolia: {
appId: 'MVIU5UEMOM', // Application ID
apiKey: 'b68f378013817d9a190df88cdde226a0', // Search-Only API Key
indexName: 'teco', // config.json에 설정한 인덱스명
contextualSearch: true,
},
})

부가 설정

화면 상단 Github Icon

파일 최하단에 아래 css 구문을 추가한다.

/src/css/custom.css
.header-github-link:hover {
opacity: 0.6;
}

.header-github-link:before {
content: '';
width: 24px;
height: 24px;
display: flex;
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

html[data-theme='dark'] .header-github-link:before {
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")
no-repeat;
}

themeconfig -> navbar에 github link를 설정한다.

docusaurus.config
navbar: {
title: 'HELLO',
items: [
{
href: 'https://github.com/greeng00se',
position: 'right',
className: 'header-github-link',
'aria-label': 'GitHub repository',
},
],
},

코드블럭

java나 kotlin의 경우 기본적으로 하이라이팅을 지원해 주지 않는다.
prism 설정을 아래와 같이 변경해 준다.

docusaurus.config
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ['java', 'kotlin'],
}

mermaid

mermaid를 사용하려면 @docusaurus/theme-mermaid 를 설치해야 한다.

yarn add @docusaurus/theme-mermaid

설치 후 아래와 같이 설정을 추가한다.

docusaurus.config
const config = {
...
markdown: {
mermaid: true,
},
themes: [
'@docusaurus/theme-mermaid'
],
};

themeConfig에서 mermaid의 테마를 지정할 수 있다.

docusaurus.config
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
...
mermaid: {
theme: {
light: 'neutral',
dark: 'dark'
},
},
}),

국제화 설정

국제화 설정을 한다면 Older Entries 형태의 설명이 다음 페이지 로 변경된다.
설정파일에서 i18n에 있는 로케일 설정을 ko로 변경하면 된다.

docusaurus.config
i18n: {
defaultLocale: "ko",
locales: ["ko"],
},

블로그 글 author

팀원 별로 문서를 관리한다면 다음과 같이 어떤 팀원이 글을 작성했는지 설정해야 한다.

author

authors.yml 파일을 이용하여 사용자에 대한 기본 설정을 할 수 있다.

/blog/authors.yml
herb:
name: 허브
title: Backend
url: https://github.com/greeng00se
image_url: https://github.com/greeng00se.png

mallang:
name: 말랑
title: Backend
url: https://github.com/shin-mallang
image_url: https://github.com/shin-mallang.png

블로그 글을 작성할 때 다음과 같이 authors에 넣어주기만 하면 된다.

---
slug: 1
title: Hello World
authors: [herb, mallang]
tags: [hello, docusaurus]
---

첫 번째 문서 내용
- - + + \ No newline at end of file diff --git a/tags/dto.html b/tags/dto.html index c0c9a9672..67aafda5f 100644 --- a/tags/dto.html +++ b/tags/dto.html @@ -13,12 +13,12 @@ - - + +
-

"DTO" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
+

"DTO" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

장바구니 미션에서는 상품 추가와 상품 수정에 대한 요구사항이 있었다.
요청에 담긴 Body를 통해 전달받은 값을 DTO로 매핑하여 추가와 수정을 했다.

장바구니 미션에서의 상품 추가 및 수정

중복1

클래스명을 제외하고 필드와 검증로직 그 외 모든게 같은 DTO를 보며 중복이라고 생각했다.
하지만 반대로 용도가 다르기 때문에 중복이 아니라고 생각하기도 했다.
위 경우는 중복일까? 중복이 아닐까?

이 부분에 대해서 다음과 같은 리뷰를 받았다.

ProductSaveRequestProductUpdateRequest가 완전히 동일한데, 재사용할 수 없을까? 라는 리뷰를 남겼었어요. 사실 생성과 수정은 서로 달라질 개연성이 높아서 미리 분리해놓는 게 더 좋은 방법이긴 한데, 그래도 중복은 싫어서 저도 요즘 이런저런 방법들을 시도해보는 중 입니다. 허브는 이 부분에 대해 어떤 생각을 가지고 있을지 궁금하네요 ㅎㅎ

질문에 대해 아래와 같이 답변을 했다.

저장과 수정할 때 필요한 필드값이 동일하여 현재 구조에서는 하나로 사용해도 된다고 생각을 하지만, 말씀해주신대로 요구사항이 변경된다면 달라질 가능성이 높다고 판단하였습니다!

중복과 우발적 중복

로버트 마틴님이 집필하신 클린 아키텍처는 아래와 같이 중복을 여러가지 종류로 나누어 설명하고 있다.

  • 진짜 중복: 한 인스턴스가 변경되면, 동일한 변경을 그 인스턴스의 모드 복사본에 반드시 적용해야 한다.
  • 거짓된 중복, 우발적 중복: 중복으로 보이는 두 코드 영역이 각자의 경로로 발전한다면, 즉 서로 다른 속도와 다른 이유로 변경된다면 이 두 코드는 진짜 중복이 아니다.

추가와 수정은 초기에는 중복으로 보이지만 초기 생성시에만 기입하는 데이터들이 추가되거나, 시간이 지나면서 서로 달라질 가능성이 높아진다. @@ -32,7 +32,7 @@ 상황에 맞춰 적재적소에 의존 역전을 이용해보는 것도 좋을 것 같다.

참고 자료

클린 아키텍처 16장 독립성, 로버트 C. 마틴
https://techblog.woowahan.com/2647/
https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/

- - + + \ No newline at end of file diff --git a/tags/elastic-beanstalk.html b/tags/elastic-beanstalk.html index c31c2e60f..df744c88a 100644 --- a/tags/elastic-beanstalk.html +++ b/tags/elastic-beanstalk.html @@ -13,12 +13,12 @@ - - + +
-

"Elastic Beanstalk" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

설정 환경

소프트웨어 이미지: Amazon Linux 2023 AMI
+

"Elastic Beanstalk" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기
- - + + \ No newline at end of file diff --git a/tags/event.html b/tags/event.html index 925718feb..be6a4d8b6 100644 --- a/tags/event.html +++ b/tags/event.html @@ -13,12 +13,12 @@ - - + +
-

"event" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
+

"event" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

이전 글

경로 이미지 생성하기 - 기술 선택
경로 이미지 생성하기 - 구현

개요

현재 여행을 마치는 경우, 감상을 생성하는 경우 이미지 생성 요청이 이루어진다.
경로 이미지 생성의 경우 위치 정보의 개수에 정비례하여 생성 시간이 증가한다.
따라서 비동기로 이미지 생성 요청을 처리하여 사용자의 경험을 개선시킬 수 있다고 생각했다.

주기능의 응답속도 개선

여행 종료와 감상 생성이 주기능이고, 이미지 생성 기능은 부기능이다.
@@ -45,7 +45,7 @@ 응답 시간에 이미지 생성 시간이 포함되지 않아서 성능이 개선된 것을 볼 수 있다.

참고 자료

7.7. Task Execution and Scheduling, Spring Boot Docs
Spring Events, Baeldung
회원시스템 이벤트기반 아키텍처 구축하기

- - + + \ No newline at end of file diff --git a/tags/exception.html b/tags/exception.html index 69895abeb..f7e21a52a 100644 --- a/tags/exception.html +++ b/tags/exception.html @@ -13,17 +13,18 @@ - - + +
-

"exception" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

개요

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.

확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았다. 따라서 Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

비동기 예외처리

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

해당 AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다. getAsyncUncaughtExceptionHandler 메서드를 오버라이딩하여 이전에 생성해 준 AsyncExceptionHandler를 반환하도록 설정했다.
-이렇게 설정한다면 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

MDC 정보 연동 문제

./mdc-null.png

기존 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용한다.
-비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

이를 적절하게 Decorator 클래스를 설정하여 MDC의 정보를 복사해서 넘겨줄 수 있다.

다음과 같이 TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정했다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
+

"exception" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

문제 상황

현재 트립드로우의 경로 이미지 생성 기능은 비동기로 처리되고 있다. 로그를 확인하는 도중 @Async가 적용된 메서드에서 예외가 발생하는 경우 로그가 정상적으로 출력되지 않는 문제가 발생했다.
+확인해 보니 Spring의 @ControllerAdvice + @ExceptionHandler의 경우 동기 예외만 처리하고, 비동기 예외를 처리하지 않았기 때문에 발생한 문제였다.

비동기 예외 발생시 로깅 설정

Spring에서 지원해 주는 AsyncUncaughtExceptionHandler 인터페이스를 구현해서 예외를 처리하는 클래스를 생성했다.

AsyncExceptionHandler
@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

private static final String LOG_FORMAT = "[%s] %s";

@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info(String.format(LOG_FORMAT, MDC.get(REQUEST_ID.key()), throwable.getMessage()), throwable);
}
}

AsyncExceptionHandler의 경우 AsyncConfigurer를 구현한 Configuration 클래스를 사용하여 등록할 수 있다.
+getAsyncUncaughtExceptionHandler() 메서드를 오버라이딩하여 AsyncExceptionHandler를 반환하도록 설정하면 된다.

AsyncConfig
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

이제 예외가 발생하는 경우 AsyncUncaughtExceptionHandler의 구현체인 AsyncExceptionHandler가 예외를 잡아서 처리를 해준다.

MDC 정보 연동 문제

트립드로우의 애플리케이션은 예외가 발생할 때 실행 흐름을 추적하기 위해 MDC(Mapped Diagnostic Context)를 사용하고 있다. 비동기 처리의 경우 별도의 스레드에서 동작하기 때문에 ThreadLocal 기반으로 동작하는 MDC의 정보를 얻어올 수 없었다.

./mdc-null.png

Spring 4.3 이상부터 제공되는 TaskDecorator를 이용하면 TaskExecutor를 커스터마이징 할 수 있다. TaskDecorator를 구현한 클래스를 하나 생성하고, Task가 실행되기 전 MDC의 정보를 복사하도록 설정한다.

MdcTaskDecorator
public class MdcTaskDecorator implements TaskDecorator {

@Override
public Runnable decorate(final Runnable runnable) {
Map<String, String> threadContext = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(threadContext);
runnable.run();
};
}
}

해당 Decorator 클래스를 설정 파일에 등록해 준다.

AsyncConfig
@RequiredArgsConstructor
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {

private final AsyncConfigurationProperties properties;

@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.coreSize());
executor.setMaxPoolSize(properties.maxSize());
executor.setQueueCapacity(properties.queueCapacity());

executor.setTaskDecorator(new MdcTaskDecorator());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

설정 후에는 정상적으로 MDC에 들어가 있는 UUID가 출력되는 것을 볼 수 있다.

./mdc-not-null.png

참고 자료

spring async, baeldung
@Async will not call by @ControllerAdvice for global exception
-Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니

- - +Spring 의 동기, 비동기, 배치 처리시 항상 context 를 유지하고 로깅하기, 강남언니
+TaskDecorator, Spring docs

+ + \ No newline at end of file diff --git a/tags/grasp.html b/tags/grasp.html index 46b15bcab..e3ebcfb2b 100644 --- a/tags/grasp.html +++ b/tags/grasp.html @@ -13,15 +13,15 @@ - - + +
-

"GRASP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) +

"GRASP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) 객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

  • 오브젝트 p.17

결합도를 낮춘다면 다음과 같은 이점이 있다.

  • 다른 구성 요소의 변화에 영향을 받지 않는다.
  • 재사용이 편리해진다.
  • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)

높은 응집도 패턴(High Cohesion)

Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

응집도(Cohesion) 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

  • 오브젝트 p.26

변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

  • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
  • 유지보수가 쉬워진다.
  • 낮은 결합도 또한 지원한다.
  • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.

컨트롤러 패턴(Controller)

Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

어떤 서브시스템이 존재한다고 가정할 때

  • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
  • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
  • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.

다형성 패턴(Polymorphism)

Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

변경 보호 패턴(Protected Variations)

Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

간접 참조 패턴(Indirection)

Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

순수한 가공물 패턴(Pure Fabrication)

Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

  • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
  • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.

참고 자료

오브젝트 5장. 책임 할당하기, 조영호

Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

GRASP, 한빛 네트워크

- - + + \ No newline at end of file diff --git a/tags/image.html b/tags/image.html index 294527fe0..ab410c55c 100644 --- a/tags/image.html +++ b/tags/image.html @@ -13,12 +13,12 @@ - - + +
-

"image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
+

"image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 12분

개요

여행에 대한 경로를 보여주기 위해 경로 이미지를 생성하는 기능을 추가했다.
경로 이미지에 대한 요구사항 및 기술 선택에 대한 내용은 링크에 있다.

구현 결과

./result.png

예시 데이터는 다음과 같다.
서울역(점) → 신사역 → 노량진역 → 홍대입구역 → 종로3가역 → 옥수역 → 구로역(점) → 신림역 → 발산역

예시 데이터
List<Double> x = List.of(
126.97094933811682, 127.02154822802501, 126.94218991864345, 126.92402556641424,
126.99265358592287, 127.01779856076462, 126.88474839801178, 126.92900751277035, 126.83930056313639
);
List<Double> y = List.of(
37.55302829553499, 37.51619698970427, 37.51294119442773, 37.5565933969331,
37.57034879708931, 37.54027238225762, 37.50129417536773, 37.48258811529137, 37.557607696911184
);
List<Double> xPoints = List.of(126.97094933811682, 126.88474839801178);
List<Double> yPoints = List.of(37.55302829553499, 37.50129417536773);

IMAGE_SIZE & ROUTE_SIZE

RouteImageGenerator.java
private static final int IMAGE_SIZE = 800;
private static final int ROUTE_SIZE = 600;

코드를 보면 IMAGE_SIZE와 ROUTE_SIZE가 있다.
IMAGE_SIZE는 말 그대로 이미지의 width와 height를 의미한다.
@@ -29,7 +29,7 @@ BufferedImage를 사용할 때 왼쪽 상단의 좌표 (0, 0) 기준으로 아래로 내려갈수록 y 값이 커지고, 오른쪽으로 갈 수록 x 값이 커진다.

./800.png

따라서 최종적으로 이미지를 생성하기 위한 값을 다음과 같이 구했다.

x 값 → 계산한 offset 그대로 더한다.
y 값 → imageSize(800)에서 y + offset 값을 뺀다.

RouteImageDrawer(실제 이미지에 경로를 그려주는 클래스)

BufferedImage, Graphics2D를 필드로 가지고 있는 클래스다.
그림을 그리기 위해 설정한 상수들이 존재한다.

RouteImageDrawer.java
// RGB에 각각 8비트씩 할당한 값을 24비트 트루컬러라 부른다.
// 해당 설정은 24비트 + 8비트(alpha, 투명도)를 추가한 32비트 이미지 타입이다.
// 이를 RGBA라고 부른다.
private static final int IMAGE_TYPE = BufferedImage.TYPE_INT_ARGB;
// 배경 투명색
private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
// 경로를 위한 STROKE
private static final int LINE_STROKE_WIDTH = 7;
private static final Stroke LINE_STROKE = new BasicStroke(LINE_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 위치 점을 위한 STROKE
private static final int POINT_STROKE_WIDTH = 20;
private static final Stroke POINT_STROKE = new BasicStroke(POINT_STROKE_WIDTH, CAP_ROUND, JOIN_ROUND);
// 안티앨리어싱 등 화질 개선을 위한 설정
private static final Map<Object, Object> renderingHints = Map.of(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON,
RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY,
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC
);

RouteImageDrawer 클래스에는 다음 세 개의 인터페이스가 존재한다.

  • drawLine: 선을 그린다.
  • drawPoint: 점을 찍는다.
  • dispose: 자원 할당을 해제한다.

dispose의 경우 내부에서 생성된 graphics2D에 대한 자원 할당을 해제하는 메서드인 graphics2D.dispose를 호출한다.

이미지 생성 Flow

1. 이미지 생성 준비

2. 선 그리기 요청

3. 위치 점 그리기 요청

4. 업로드 요청

전체 Flow

- - + + \ No newline at end of file diff --git a/tags/image/page/2.html b/tags/image/page/2.html index 45bb40f18..ea0ce8a90 100644 --- a/tags/image/page/2.html +++ b/tags/image/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
+

"image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
이미지 생성: matplotlib
서비스: AWS Lambda, AWS API Gateway
이미지 저장 및 URL: AWS S3, AWS CloudFront

플로우는 다음과 같다.

요구사항

./route.png

우측 상단의 경로 이미지를 생성하려고 한다.
@@ -39,7 +39,7 @@ Python Lambda 함수에 대한 .zip 파일 아카이브 작업
No module named 'numpy.core._multiarray_umath'
사례별로 알아본 안전한 S3 사용 가이드

- - + + \ No newline at end of file diff --git a/tags/image/page/3.html b/tags/image/page/3.html index e62b71511..2a4db6d41 100644 --- a/tags/image/page/3.html +++ b/tags/image/page/3.html @@ -13,19 +13,19 @@ - - + +
-

"image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
+

"image" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

./route.png

이미지 생성의 책임

위 와이어 프레임에서 여행 히스토리여행에 대한 감상을 위한 경로 이미지의 경우 네이버 지도를 사용하여 해당 기능을 구현할 수 없으니 당연히 맵 API에서 제공하는 도형 그리기 API(네이버 맵 API 기준 Polyline)를 사용할 수 없다.
따라서 이미지를 직접 생성하거나, 클라이언트에서 직접 위경도를 이용하여 그려야 한다.

해당 요구사항을 해결하기 위해서는 다음과 같은 기능을 가진 라이브러리가 필요하다.

  • 이미지 생성
  • 선과 점 표현
  • 투명한 배경색

현재 클라이언트의 바쁜 일정과 기능 구현에 있어 약간의 연산이 들어간다는 부분을 고려하여 백엔드에서 이미지를 생성하기로 결정을 내렸다.

고려한 기술

백엔드에서 이미지 생성을 하기 위해 다음과 같은 라이브러리 또는 기술들을 확인해 보았다.

  • Python의 Matplotlib
  • AWT(Abstract Window Toolkit) [최종 선택]
  • 이미지 처리 라이브러리 및 Java에서 내부적으로 Matplotlib 사용할 수 있는 라이브러리 (원하는 기능 없음)
  • Java Swing, Java FX (단순한 선 그리기 + 점 찍기라 불필요)

Python & Matplotlib

데이터 시각화 라이브러리
이미지 생성 및 로컬에 저장까지 걸리는 시간: 0.2초

  • 코드가 간단해서 유지 보수성이 좋다.
  • AWS Lambda 같은 서버리스 컴퓨팅 서비스나 FastAPI와 같은 웹 프레임워크로 추가적인 API를 구현해야 한다.
  • Spring Boot에서 추가적인 API 호출을 해야하고, 확장성과 비동기 처리 등 고려 해야 할 부분이 많다.

Java AWT 이외의 라이브러리

Python이 아닌 Java에서의 라이브러리도 고려를 해봤지만 요구사항에 적합하지 않거나, 적은 요구사항에 비해 무거운 라이브러리들이 많아서 제외했다.

라이브러리설명제외 이유
SwingAWT 이후에 나온 GUI 라이브러리, 네이티브 UI를 사용하지 않고 모든 운영체제 상에서 동일한 UI를 가지도록 함요구사항에 비해 무겁고 복잡도가 높음
JavaFXSwing 이후에 나온 GUI 라이브러리, 3차원 그래픽을 지원함요구사항에 비해 무겁고 복잡도가 높음
simple-java-plotAWT로 구현된 플로팅 라이브러리AWT 기반이긴 하지만 직접 AWT를 사용하는 것에 비해 메리트가 없음, 커스텀 설정 기능이 없음
matplotlib4jMatplotlib를 Java에서 사용할 수 있게 하는 라이브러리내부적으로 파이썬 사용하기에 무거움, 배경 투명화 기능 없음

Java & AWT(Abstract Window Toolkit)

그래픽과 이미지를 그리기 위한 도구
이미지 생성 및 로컬에 저장까지 걸리는 시간: 1.75초

  • 플로팅 라이브러리를 사용하는 것보다 구현의 난이도가 다소 존재한다.
  • 이미지 생성 시간이 다소 소요되기 때문에 빠른 응답 반환을 위해 비동기 처리를 고려할 수 있을 것 같다.
  • 추가적인 api 호출을 하지 않아도 된다.

기술 선택

AWT의 경우 Matplotlib에 비해 구현의 난이도가 다소 있고, 이미지 생성 시간이 더 많이 걸리는 단점이 있다.
하지만 추가적인 api 호출을 하지 않아도 되는 부분, Python을 사용하는 경우 추가적인 웹 프레임워크의 학습 비용을 고려하여 AWT를 사용하기로 결정했다.

유지 보수

AWT라는 생소한 기술을 사용하기 때문에 유지 보수성을 위해 팀원들과 공유하는 것이 중요하다고 생각했다.
따라서 다음과 같은 방법으로 공유하기로 했다.

  1. 코드 리뷰와 PR을 통해 작성한 AWT 코드에 대한 설명 및 리뷰 받는다.
  2. AWT를 사용한 부분을 문서화하여 공유한다.

레벨 3를 마무리하며 내용 추가

기술 선택을 하기 위한 실행 시간 측정에 오류가 있었다.
AWT를 사용하는 부분에서 애플리케이션 실행 시간을 제외하면 파이썬과 비슷한 시간안에 이미지를 생성할 수 있었다.

- - + + \ No newline at end of file diff --git a/tags/inno-db.html b/tags/inno-db.html index f264956cd..4c1761e1c 100644 --- a/tags/inno-db.html +++ b/tags/inno-db.html @@ -13,12 +13,12 @@ - - + +
-

"InnoDB" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
+

"InnoDB" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

낙관적 동시성 제어(OCC, Optimistic concurrency control)

트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

비관적 동시성 제어(PCC, Pessimistic Concurrency Control)

트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

Shared & Exclusive Locks

InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

공유 잠금(S, shared lock)

데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
@@ -38,7 +38,7 @@ MySQL Innodb Locks, cecil1018
MySQL 8.0 InnoDB Locks, MySQL
Locks Set by Different SQL Statements in InnoDB, MySQL

- - + + \ No newline at end of file diff --git a/tags/intelli-j.html b/tags/intelli-j.html index b693cc6e6..0caa5b048 100644 --- a/tags/intelli-j.html +++ b/tags/intelli-j.html @@ -13,13 +13,13 @@ - - + +
-

"IntelliJ" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 1분

Import 자동 적용

Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

auto-import

저장시 동작

Prefrences > Tools > Actions on Save

actions-on-save

Reformat Code: Code Reformmating

Optimize imports: 사용하지 않는 Import 제거

Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

메소드 추출, 변수 추출시 final 적용

Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

final-modifier

- - +

"IntelliJ" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 1분

Import 자동 적용

Prefrences > Editor > General > Auto Import > Add unambiguous imports on the fly

auto-import

저장시 동작

Prefrences > Tools > Actions on Save

actions-on-save

Reformat Code: Code Reformmating

Optimize imports: 사용하지 않는 Import 제거

Rearrange: Code Style > Arrangement 설정 기반 코드 재정렬

메소드 추출, 변수 추출시 final 적용

Prefrences > Editor > Code Style > Java > Code Generation > Final Modifier

final-modifier

+ + \ No newline at end of file diff --git a/tags/isolation.html b/tags/isolation.html index 34d94837d..47bab1e77 100644 --- a/tags/isolation.html +++ b/tags/isolation.html @@ -13,12 +13,12 @@ - - + +
-

"Isolation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
+

"Isolation" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

트랜잭션의 속성(ACID)

원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
@@ -42,7 +42,7 @@ 예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

팬텀 리드(Phantom read, Phantom row)

한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

참고 자료

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
Isolation Level, MySQL

- - + + \ No newline at end of file diff --git a/tags/java.html b/tags/java.html index 655c01929..3a3183a85 100644 --- a/tags/java.html +++ b/tags/java.html @@ -13,12 +13,12 @@ - - + +
-

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
+

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

자바 변경 사항

우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

Switch Expressions(Java 14)

Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

enum RESULT {
WIN, LOSE, DRAW
}

RESULT result = RESULT.WIN;

int prize = switch (result) {
case WIN -> 10_000_000;
case LOSE, DRAW -> 5_000_000;
default -> 0;
};

주요 특징은 다음과 같다.

  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • break 문이 필요 없다.
  • default 블록을 통해 기본 값을 지정할 수 있다.

Text Block(Java 15)

Java 15에는 새로운 문자열 표현방식이 추가되었다.
긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("""
SELECT p FROM Post p
WHERE p.title LIKE %:keyword%
OR p.content LIKE %:keyword%
""")
List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
}

NPE 메시지(Java 15)

String name = null;
name.chars();

/**
# before
java.lang.NullPointerException
at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)

# after
Cannot invoke "String.chars()" because "name" is null
java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
*/

Record(Java 16)

Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
@@ -34,7 +34,7 @@ What's New in Spring Framework 6.x
Spring Boot 3.0 Release Notes
Spring Boot 3.1 Release Notes

- - + + \ No newline at end of file diff --git a/tags/java/page/2.html b/tags/java/page/2.html index f8b62a282..d09fa7559 100644 --- a/tags/java/page/2.html +++ b/tags/java/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
+

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
컴파일된 클래스파일은 어떤 구조로 되어있을까?

클래스 파일의 데이터 형식

8비트 바이트의 스트림으로 구성된다.
16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
멀티바이트의 경우 항상 big endian 순서로 저장된다.

u1 → unsigned 1byte
@@ -36,7 +36,7 @@ Class file in Java, File Format
java se11 Class 파일 형식, Oracle
java se17 Class 파일 형식, Oracle

- - + + \ No newline at end of file diff --git a/tags/java/page/3.html b/tags/java/page/3.html index a4b49f791..2bf8ab85a 100644 --- a/tags/java/page/3.html +++ b/tags/java/page/3.html @@ -13,12 +13,12 @@ - - + +
-

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
+

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

기존 코드

public class User {
private final int id;
private final String name;

public User(final int id, final String name) {
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public String getName() {
return name;
}
}

SELECT, DELETE 중복 제거

변하지 않는 부분: try-with-resource, preparedStatement를 사용하는 부분, executeUpdate로 실행 등등
변하는 부분: SQL Query, 매개변수

다음과 같이 쿼리를 실행하는 부분을 분리하고 가변인수를 사용한다면 SELECT와 DELETE의 중복을 제거할 수 있다.

public void insert(final String name) {
final String query = "INSERT INTO User (name) VALUES (?)";
executeUpdate(query, name);
}

public void delete(final int userId) {
final String query = "DELETE FROM user WHERE user_id = ?";
executeUpdate(query, userId);
}

private void executeUpdate(final String query, final Object... parameters) {
final Connection connection = connectionPool.getConnection();
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
for (int i = 1; i <= parameters.length; i++) {
preparedStatement.setObject(i, parameters[i - 1]);
}
preparedStatement.executeUpdate();
} catch (final SQLException e) {
throw new IllegalArgumentException(e.getMessage());
}
}

조회 분리하기 - 1. 콜백을 위한 인터페이스 정의

조회는 INSERT, DELETE와 달리 값을 반환받아야 하기 때문에 다른 방법을 사용해야 한다.
@@ -30,7 +30,7 @@ 아래와 같이 제네릭을 적용하여 다른 Dao에서도 사용 가능하도록 변경할 수 있다.

@FunctionalInterface
public interface RowMapper<T> {
T mapRow(final ResultSet resultSet) throws SQLException;
}

private <T> List<T> query(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
private <T> T queryForSingleResult(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}

메서드 분리한 부분 클래스로 분리하기 + Optional 사용하기

메서드로 분리한 부분을 JdbcTemplate이라는 클래스를 만들어 옮긴다.
또한 null을 반환하기 보단 Optional로 감싸서 반환하도록 변경한다.
최종적으로 아래와 같은 코드가 완성된다.

public class UserDao {
private final RowMapper<User> rowMapper = resultSet -> {
final int id = resultSet.getInt("id");
final String name = resultSet.getString("name");
return new User(id, name);
};
private final JdbcTemplate jdbcTemplate;

public UserDao(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

public void insert(final String name) {
final String query = "INSERT INTO User (name) VALUES (?)";
jdbcTemplate.executeUpdate(query, name);
}

public void delete(final int userId) {
final String query = "DELETE FROM user WHERE user_id = ?";
jdbcTemplate.executeUpdate(query, userId);
}

public Optional<User> findById(final int userId) {
final String query = "SELECT * FROM user WHERE id = ?";
return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);
}

public List<User> findAll() {
final String query = "SELECT * FROM user";
return jdbcTemplate.query(query, rowMapper);
}
}
- - + + \ No newline at end of file diff --git a/tags/java/page/4.html b/tags/java/page/4.html index 92a0468a4..3a63e11b9 100644 --- a/tags/java/page/4.html +++ b/tags/java/page/4.html @@ -13,12 +13,12 @@ - - + +
-

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
+

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

테스트를 작성하다보면 매개변수에 따라 반복이 되는 테스트들이 생긴다.
이 때 @ParameterizedTest를 사용하면 단일 테스트를 매개변수를 사용하여 여러 번 반복할 수 있다.

Argument Sources

@ParameterizedTest를 사용하려면 최소 하나 이상의 Source 애노테이션이 필요하다.
JUnit이 제공하는 다양한 Source가 있기 때문에, 테스트에 맞춰 다양하게 사용할 수 있다.

Value Source

값을 이용하여 제공하는 형태로, 다음과 같은 타입의 값을 매개변수로 제공할 수 있다.

  • short, int, long, float, double
  • byte, char, boolean, String, Class
@ParameterizedTest
@ValueSource(ints = {1, 100, Integer.MAX_VALUE})
void valueTest(final int value) {
Assertions.assertThat(value).isPositive();
}

Null & Empty Source

null 값, 빈 값을 제공한다.
Empty Source의 경우 다음과 같은 타입에 한해 매개변수로 제공할 수 있다.

  • String
  • java.util.List, java.util.Set, java.util.Map
  • primitive arrays — ex) int[]
  • object arrays — ex) String[]
@ParameterizedTest
@NullAndEmptySource
void nullAndEmptyTest(final String value) {
Assertions.assertThat(value).isNullOrEmpty();
}

Enum Source

EnumSource를 이용하여 Enum 또한 매개변수로 제공할 수 있다.

enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

@ParameterizedTest
@EnumSource(Day.class)
void enumTest(final Day day) {
assertThat(day).isInstanceOf(Day.class);
}

다음과 같이 mode 값을 이용하여 특징 Enum을 제외하거나, 포함시킬 수 있다. (default: Mode.Include)

@ParameterizedTest
@EnumSource(value = Day.class, names = {"SATURDAY", "SUNDAY"}, mode = Mode.EXCLUDE)
void enumTest(final Day day) {
// MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
assertThat(day).isInstanceOf(Day.class);
}

CSV Source

csv 형식의 값을 이용하여 매개변수를 제공한다.
@@ -26,7 +26,7 @@ 개인적으로 2개 정도의 값을 매개변수로 전달하는 경우 CsvSource를 사용한다.

@ParameterizedTest
@CsvSource({"1,1", "2,4", "3,9", "4,16"})
void csvTest(final int number, final int result) {
assertThat(number * number).isEqualTo(result);
}

Method Source

복잡한 타입의 값을 전달할 때 사용한다.
메서드명을 입력하여 매개변수를 제공하는 메서드를 지정할 수 있다.
메서드명을 따로 입력하지 않으면 테스트명과 동일한 static 메서드가 지정된다.

@ParameterizedTest
@MethodSource
void methodTest(final List<Integer> numbers, final int count) {
assertThat(numbers).hasSize(count);
}

private static Stream<Arguments> methodTest() {
return Stream.of(
Arguments.of(List.of(1), 1),
Arguments.of(List.of(1, 2), 2),
Arguments.of(List.of(1, 2, 3), 3)
);
}

ETC.

위에서 언급한 방법 이외에도 다양한 방법으로 매개변수를 제공할 수 있다.

  • CSV 파일을 이용한 CsvFileSource
  • ArgumentsProvider 구현한 클래스를 이용하는 ArgumentsSource

참고 자료

- - + + \ No newline at end of file diff --git a/tags/java/page/5.html b/tags/java/page/5.html index 82d10cb1c..550a693e6 100644 --- a/tags/java/page/5.html +++ b/tags/java/page/5.html @@ -13,19 +13,19 @@ - - + +
-

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
+

"Java" 태그로 연결된 5개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
ISO-8601을 기반으로 작성
설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

ISO-8601

날짜와 시간에 관련된 데이터를 다루는 국제 표준

LocalDate, LocalTime, LocalDateTime

날짜와 시간을 표현하는 클래스

Instant

유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
기계의 관점에서 시간 표현

Duration, Period

간격을 표현하는 클래스

TemporalAdjusters

복잡한 날짜 조정이 필요할 때 사용
필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}

DateTimeFormatter

날짜와 시간 포맷 클래스
특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

ZoneId, ZoneOffset

ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

Instant instant = Instant.now();
LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

참고 자료

- - + + \ No newline at end of file diff --git a/tags/jdbc.html b/tags/jdbc.html index abc5817a8..d92fee9a6 100644 --- a/tags/jdbc.html +++ b/tags/jdbc.html @@ -13,12 +13,12 @@ - - + +
-

"JDBC" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
+

"JDBC" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

체스 미션에서는 데이터베이스에서 값을 가져오기 위해 DAO를 사용했다.
이 때 JDBC를 사용할 때 데이터베이스의 커넥션을 얻고, try-with-resource를 사용하는 부분이 반복되었다.
템플릿 콜백 패턴을 이용하여 나만의 JdbcTemplate을 만들어보았다.

기존 코드

public class User {
private final int id;
private final String name;

public User(final int id, final String name) {
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public String getName() {
return name;
}
}

SELECT, DELETE 중복 제거

변하지 않는 부분: try-with-resource, preparedStatement를 사용하는 부분, executeUpdate로 실행 등등
변하는 부분: SQL Query, 매개변수

다음과 같이 쿼리를 실행하는 부분을 분리하고 가변인수를 사용한다면 SELECT와 DELETE의 중복을 제거할 수 있다.

public void insert(final String name) {
final String query = "INSERT INTO User (name) VALUES (?)";
executeUpdate(query, name);
}

public void delete(final int userId) {
final String query = "DELETE FROM user WHERE user_id = ?";
executeUpdate(query, userId);
}

private void executeUpdate(final String query, final Object... parameters) {
final Connection connection = connectionPool.getConnection();
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
for (int i = 1; i <= parameters.length; i++) {
preparedStatement.setObject(i, parameters[i - 1]);
}
preparedStatement.executeUpdate();
} catch (final SQLException e) {
throw new IllegalArgumentException(e.getMessage());
}
}

조회 분리하기 - 1. 콜백을 위한 인터페이스 정의

조회는 INSERT, DELETE와 달리 값을 반환받아야 하기 때문에 다른 방법을 사용해야 한다.
@@ -30,7 +30,7 @@ 아래와 같이 제네릭을 적용하여 다른 Dao에서도 사용 가능하도록 변경할 수 있다.

@FunctionalInterface
public interface RowMapper<T> {
T mapRow(final ResultSet resultSet) throws SQLException;
}

private <T> List<T> query(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}
private <T> T queryForSingleResult(final String query, final RowMapper<T> rowMapper, final Object... parameters) {...}

메서드 분리한 부분 클래스로 분리하기 + Optional 사용하기

메서드로 분리한 부분을 JdbcTemplate이라는 클래스를 만들어 옮긴다.
또한 null을 반환하기 보단 Optional로 감싸서 반환하도록 변경한다.
최종적으로 아래와 같은 코드가 완성된다.

public class UserDao {
private final RowMapper<User> rowMapper = resultSet -> {
final int id = resultSet.getInt("id");
final String name = resultSet.getString("name");
return new User(id, name);
};
private final JdbcTemplate jdbcTemplate;

public UserDao(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

public void insert(final String name) {
final String query = "INSERT INTO User (name) VALUES (?)";
jdbcTemplate.executeUpdate(query, name);
}

public void delete(final int userId) {
final String query = "DELETE FROM user WHERE user_id = ?";
jdbcTemplate.executeUpdate(query, userId);
}

public Optional<User> findById(final int userId) {
final String query = "SELECT * FROM user WHERE id = ?";
return jdbcTemplate.queryForSingleResult(query, rowMapper, userId);
}

public List<User> findAll() {
final String query = "SELECT * FROM user";
return jdbcTemplate.query(query, rowMapper);
}
}
- - + + \ No newline at end of file diff --git a/tags/jenkins.html b/tags/jenkins.html index 219b530c9..98c962158 100644 --- a/tags/jenkins.html +++ b/tags/jenkins.html @@ -13,12 +13,12 @@ - - + +
-

"Jenkins" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

설정 환경

소프트웨어 이미지: Amazon Linux 2023 AMI
+

"Jenkins" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기
- - + + \ No newline at end of file diff --git a/tags/kotlin.html b/tags/kotlin.html index c93037a01..702fcb432 100644 --- a/tags/kotlin.html +++ b/tags/kotlin.html @@ -13,12 +13,12 @@ - - + +
-

"Kotlin" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

nullable 타입

코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
+

"Kotlin" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

nullable 타입

코틀린은 NullPointerException 예외를 최대한 발생시키지 않기 위해 타입 시스템이 설계되어 있다.
이는 실행 시점이 아닌 컴파일 시 미리 오류가 발생할 가능성이 있는 부분을 미리 감지하여 NPE 발생의 가능성을 줄여준다.

코틀린의 경우 nullable 타입을 다음과 같이 표현한다.

val number: Int?

타입 뒤에 ?를 붙여 해당 값이 null이 될 수 있다는 것을 의미한다.
만약 ?를 붙이지 않을 때 null을 받는 경우 컴파일 시 오류가 발생한다.

?. Safe Calls 연산자

자바에서 NPE를 발생시키지 않기 위해 null을 처리하는 가장 간단한 방법으로는 분기를 사용하는 방법이 있다.

코틀린은 안전한 호출 연산자인 ?. 연산자를 지원한다.
따라서 참조 값이 null이 아닐 경우에만 메서드 호출을 할 수 있다.
@@ -30,7 +30,7 @@ 사용하기 쉽지만, 리스크가 크고 혹시나 해당 값이 추후에는 null이 될 수 있기 때문에 지양해야 된다고 생각한다.

val length: Int = word!!.length

as? 안전한 캐스팅

타입 변환을 할 때 지정한 타입으로 변경할 수 없다면 ClassCastException이 발생한다.
코틀린에서는 as 뒤에 ?를 붙여 안전하게 타입 변환을 할 수 있다.
따라서 미리 변환 가능한 타입인지 확인하지 않고, 안전하게 타입을 변환 할 수 있다.

타입 변환이 불가능 할 경우 예외를 발생시키지 않고 null을 반환한다.

val value: Int? = something as? Int

List에서의 null 처리

List에는 null이 아닌 값만 반환하는 filterNotNull 유틸리티 메서드를 제공한다.

val foodsWithNull: List<String?> = listOf("Pizza", "Cheese", null, "Potato")
val foods = foodsWithNull.filterNotNull()

참고 자료

- - + + \ No newline at end of file diff --git a/tags/lock.html b/tags/lock.html index 2c05d6258..bbd3a81f5 100644 --- a/tags/lock.html +++ b/tags/lock.html @@ -13,12 +13,12 @@ - - + +
-

"Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
+

"Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

InnoDB 스토리지 엔진의 잠금

MySQL에서 제공하는 잠금과 별개로 스토리지 엔진 내부에서 로우 단위의 잠금을 지원한다.
보통 명시적으로 잠금을 사용하는 경우는 드물고, 격리 수준에 따라 묵시적으로 잠금이 사용된다.

동시성 제어 방식에는 낙관적인 방식과 비관적인 방식이 있다.
InnoDB는 기본적으로 MVCC(다중 버전 동시성 제어)를 통해 낙관적인 방식을 사용하고 락을 통해 특정 상황에서 비관적인 방식을 사용한다.

낙관적 동시성 제어(OCC, Optimistic concurrency control)

트랜잭션이 서로 충돌하지 않는다고 가정하는 방식

비관적 동시성 제어(PCC, Pessimistic Concurrency Control)

트랜잭션이 충돌하는 가정하에 잠금을 거는 방식
일반적으로 Shared Lock, Exclusive Lock을 통해 이를 구현한다.

Shared & Exclusive Locks

InnoDB는 로우 단위의 잠금을 수행할 때 공유 잠금과 배타적 잠금을 사용한다.

공유 잠금(S, shared lock)

데이터 조회를 위한 락, 읽기 잠금(read lock)으로도 불린다.
@@ -38,7 +38,7 @@ MySQL Innodb Locks, cecil1018
MySQL 8.0 InnoDB Locks, MySQL
Locks Set by Different SQL Statements in InnoDB, MySQL

- - + + \ No newline at end of file diff --git a/tags/lock/page/2.html b/tags/lock/page/2.html index bb8c41fb7..a97ef2318 100644 --- a/tags/lock/page/2.html +++ b/tags/lock/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
+

"Lock" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

글로벌 락(Global lock)

MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

  • 영향을 미치는 범위는 해당 서버 전체이다.
  • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.

한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

-- GLOBAL LOCK
FLUSH TABLES WITH READ LOCK;
-- UNLOCK
UNLOCK TABLES;

-- BACKUP LOCK
LOCK INSTANCE FOR BACKUP;
-- UNLOCK
UNLOCK INSTANCE;
- - + + \ No newline at end of file diff --git a/tags/log.html b/tags/log.html index 85ee019e6..aeed545bc 100644 --- a/tags/log.html +++ b/tags/log.html @@ -13,12 +13,12 @@ - - + +
-

"log" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
+

"log" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
지표를 감시하여 알림을 보내는 기능도 제공한다.
프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
요금 정보에 대한 자세한 정보는 다음 링크에서 확인할 수 있다.

CloudWatch Metrics

기본적으로 5분마다 지표에 대한 정보가 수집된다.
@@ -38,7 +38,7 @@ 서버에 CloudWatch 에이전트 설치 및 실행
CloudWatch Agent를 Parameter Store에서 관리해 보기
CloudWatch에이전트 구성 파일

- - + + \ No newline at end of file diff --git a/tags/mock.html b/tags/mock.html index a05ef86a4..9fe84696d 100644 --- a/tags/mock.html +++ b/tags/mock.html @@ -13,12 +13,12 @@ - - + +
-

"Mock" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
+

"Mock" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

테스트 대역의 타입 계층 구조

더미(Dummy)

가장 단순하고, 원시적인 유형의 테스트 대역이다.
기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
@@ -36,7 +36,7 @@ 테스트 더블, Martin Fowler
테스트 관련 용어 정리, Johngrib
Test Double, Gerard Meszaros

- - + + \ No newline at end of file diff --git a/tags/mockito.html b/tags/mockito.html index e77acf401..b0570125f 100644 --- a/tags/mockito.html +++ b/tags/mockito.html @@ -13,12 +13,12 @@ - - + +
-

"Mockito" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
+

"Mockito" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

public void upload(BufferedImage bufferedImage) {
File file = new File(파일경로);
try {
ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
} catch (IOException e) {
throw new DrawException(IMAGE_SAVE_FAIL);
}
}

Mocking static methods

Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
@@ -27,7 +27,7 @@ 항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

참고 자료

Mocking static methods
Mockito mock static methods
Enable mocking static methods in Mockito

- - + + \ No newline at end of file diff --git a/tags/monitoring.html b/tags/monitoring.html index 260d94191..3d27a462a 100644 --- a/tags/monitoring.html +++ b/tags/monitoring.html @@ -13,12 +13,12 @@ - - + +
-

"monitoring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
+

"monitoring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

CloudWatch

AWS 리소스와 애플리케이션의 지표와 로그에 대한 모니터링을 제공하는 서비스다.
지표를 감시하여 알림을 보내는 기능도 제공한다.
프리티어를 사용하지 않는 경우 대시보드당 3$/M 의 비용이 청구되고, 지표나 로그의 양에 따라 비용이 추가적으로 청구된다.
요금 정보에 대한 자세한 정보는 다음 링크에서 확인할 수 있다.

CloudWatch Metrics

기본적으로 5분마다 지표에 대한 정보가 수집된다.
@@ -38,7 +38,7 @@ 서버에 CloudWatch 에이전트 설치 및 실행
CloudWatch Agent를 Parameter Store에서 관리해 보기
CloudWatch에이전트 구성 파일

- - + + \ No newline at end of file diff --git a/tags/my-sql.html b/tags/my-sql.html index d035c8d62..e9a85534e 100644 --- a/tags/my-sql.html +++ b/tags/my-sql.html @@ -13,12 +13,12 @@ - - + +
-

"MySQL" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
+

"MySQL" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

MySQL 엔진의 잠금

MySQL에서의 락은 스토리지 엔진 레벨과, MySQL 엔진 레벨로 나눌 수 있다.
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다.

글로벌 락(Global lock)

MySQL에서 제공하는 잠금 중 가장 넓은 범위를 가지고 있는 잠금이다.

  • 영향을 미치는 범위는 해당 서버 전체이다.
  • 작업 대상 테이블, 데이터베이스 상관 없이 동일하게 영향을 받는다.

한 세션에서 글로벌 락을 획득하면 해제 될 때 까지 조회를 제외한 대부분의 명령이 대기 상태가 된다.
데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 일관된 백업을 받아야할 때 사용한다.
InnoDB 스토리지 엔진에서는 백업 시 조금 더 가벼운 백업 락을 사용할 수 있다.

-- GLOBAL LOCK
FLUSH TABLES WITH READ LOCK;
-- UNLOCK
UNLOCK TABLES;

-- BACKUP LOCK
LOCK INSTANCE FOR BACKUP;
-- UNLOCK
UNLOCK INSTANCE;
- - + + \ No newline at end of file diff --git a/tags/mysql.html b/tags/mysql.html index 047a95d9e..8a8b56d81 100644 --- a/tags/mysql.html +++ b/tags/mysql.html @@ -13,12 +13,12 @@ - - + +
-

"mysql" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
+

"mysql" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

복제를 하는 이유

1. 스케일 아웃

사용자의 트래픽이 증가하는 경우, 데이터베이스에 가해지는 부하도 자연스럽게 증가한다.
이를 처리하기 위해 복제를 통한 스케일 아웃을 적용하여 애플리케이션에서 사용하는 쿼리들을 각각의 데이터베이스로 분산 시킬 수 있다.

2. 데이터 백업

실제 운영되는 서비스가 사용하고 있는 DB에서 백업을 진행하는 경우, 서비스에 영향을 미칠 수 있다.
따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

3. 데이터 분석

백업과 마찬가지로 복잡하고 무거운 분석용 쿼리의 서비스에 영향을 미칠 수 있다.
@@ -71,7 +71,7 @@ 데이터베이스 레플리케이션을 통한 쿼리 성능 개선 (feat. Mysql, SpringBoot)
부하 분산을 위한 MySQL Replication 구성 및 쿼리 요청 분기
Use Docker Compose, Docker

- - + + \ No newline at end of file diff --git a/tags/oop.html b/tags/oop.html index 9fd112141..b592c9728 100644 --- a/tags/oop.html +++ b/tags/oop.html @@ -13,15 +13,15 @@ - - + +
-

"OOP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) +

"OOP" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 9분

GRASP(General Responsibility Assignment Software Pattern)

크레이그 라만의 Applying UML and Patterns이라는 책에서 나온 책임 할당을 위한 패턴

각 패턴마다 Solution과 Problem로 구성되어 있다.

정보 전문가 패턴(Information Expert)

Q: 객체에 책임을 할당하는 기본 원칙은 무엇인가?

A: 책임을 수행하는 데 필요한 정보를 가진 클래스(정보 전문가)에게 책임을 할당한다.

정보와 행동을 가까운 곳에 위치시키기 때문에 캡슐화를 유지할 수 있다.

필요한 정보를 가진 객체들로 책임이 분산된다.

창조자 패턴(Creator)

Q: 누가 객체 A를 생성하는가?

A: 다음의 조건을 최대한 많이 만족하는 객체에게 객체 생성 책임을 할당해야 한다.

  • B가 A 객체를 포함 또는 참조한다.
  • B가 A 객체를 기록한다.
  • B가 A 객체를 긴밀하게 사용한다.
  • B가 A 객체의 초기값을 가지고 있다.

생성 예정인 객체와 연관되어 있는 객체가 생성 책임을 가지고 있게 된다면, 이미 해당 객체와 결합되어있다고 생각할 수 있다. 따라서 전체적인 결합도를 낮게 유지할 수 있다.

낮은 결합도 패턴(Low Coupling)

Q: 의존성을 낮추고 변화의 영향을 줄이며 재사용성을 증가시키는 방법은?

A: 전체적인 결합이 낮게 유지되도록 책임을 할당해야 한다.

결합도(Coupling) 객체 사이의 의존성이 과한 경우 결합도가 높다고 말한다.

  • 오브젝트 p.17

결합도를 낮춘다면 다음과 같은 이점이 있다.

  • 다른 구성 요소의 변화에 영향을 받지 않는다.
  • 재사용이 편리해진다.
  • 해당 클래스에 대한 이해가 쉬워진다. (의존하는 클래스가 적기 때문에)

높은 응집도 패턴(High Cohesion)

Q. 객체를 관리하기 쉽게 하려면 어떻게 해야 할까?

A. 높은 응집도를 유지할 수 있게 책임을 할당해야 한다.

응집도(Cohesion) 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임하는 객체를 가리켜 응집도가 높다고 말한다.

  • 오브젝트 p.26

변경의 이유에 따라 클래스를 분리한다면 응집도를 높일 수 있고, 응집도가 높아진다면 다음과 같은 이점이 있다.

  • 해당 클래스에 대한 이해가 쉬워진다. (할당된 책임만을 수행하고 있기 때문에)
  • 유지보수가 쉬워진다.
  • 낮은 결합도 또한 지원한다.
  • 응집도가 높은 클래스는 특정한 목적에 사용할 수 있기 때문에 재사용하기 좋다.

컨트롤러 패턴(Controller)

Q. 사용자의 요청을 처리하는 것은 누가 담당해야 하는가?

A. 사용자의 요청을 처리하는 Controller 객체를 만들어서 사용해야 한다.

어떤 서브시스템이 존재한다고 가정할 때

  • 직접적으로 객체에 접근하여 프로그램을 사용한다면 결합도가 상승한다.
  • 서브 시스템에 들어오는 요청을 처리해주는 컨트롤러가 있다면 사용하는 입장에서는 해당 컨트롤러만 알면 된다.
  • 만약 서브 시스템의 변경이 생겼을 때 외부에 미치는 영향도 줄어든다.

다형성 패턴(Polymorphism)

Q. 객체의 타입에 따라 행동이 바뀐다면 책임을 어떻게 할당해야 할까?

A. OOP가 지원하는 다형성을 적극적으로 활용한다. (인터페이스를 두고 행동에 대한 부분을 구현)

객체의 종류에 따라 분기하는 조건문이 아닌 다형성을 사용하는 것이 좋은 방법이다.

새로운 타입이 추가되었을 때 조건문을 사용한다면 기존의 조건문을 수정해야 하지만 다형성을 활용하면 쉽게 확장할 수 있다.

변경 보호 패턴(Protected Variations)

Q. 어떻게 하면 변경이 다른 요소에 영향을 미치지 않도록 방지할 수 있을까?

A. 변화가 예상되는 지점을 식별하고, 주위에 안정된 인터페이스를 형성하도록 책임을 할당해야 한다.

간접 참조 패턴(Indirection)

Q. 두 객체 사이의 직접적인 연결을 피하고 싶다면 어떻게 해야 할까?

A. 두 객체 사이에 또 다른 객체를 두어 직접적인 연결을 피할 수 있다.

중재자 패턴을 사용하여 두 객체 사이에 또 하나의 객체를 추가하여 복잡한 관계를 단순화할 수 있다.

중간에 인터페이스를 둔다면 변경 보호 패턴(Protected Variations)에 해당된다.

순수한 가공물 패턴(Pure Fabrication)

Q. 책임을 할당한 도메인 객체가 Low Coupling, High Cohesion, 재사용성 등의 목적을 위반한다면 어떻게 해야 할까?

A. 도메인 개념을 포함하지 않는 클래스를 하나 만들고 매우 응집된 책임을 할당할 수 있다.

행동을 추가할 때, 해당 책임을 수행할 도메인 개념이 존재하지 않는다면 도메인과 무관한 인공적인 객체를 만든다음 해당 객체에게 책임을 할당한다.

객체가 데이터베이스에 저장해야 할 값을 가지고 있다고, 정보 전문가 패턴을 적용하여 데이터베이스에 저장하라는 책임을 가지라고 하지 않는다.

예) 상점과 고객 클래스가 있고 서로 다른 통화를 사용하고 있다고 가정

  • 서로 다른 통화를 사용하고 있기 때문에 거래를 하려면 환전을 해야한다.
  • 두 클래스 다 환전에 대한 책임을 부여하기 애매하다면 환전을 책임하는 클래스를 추가하고 사용할 수 있다.

참고 자료

오브젝트 5장. 책임 할당하기, 조영호

Applying UML and Patterns Chapter 16, Chapter 21 GRASP, Craig Larman

GRASP, 한빛 네트워크

- - + + \ No newline at end of file diff --git a/tags/pattern.html b/tags/pattern.html index d5db02b21..708922a84 100644 --- a/tags/pattern.html +++ b/tags/pattern.html @@ -13,12 +13,12 @@ - - + +
-

"Pattern" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • 노선별 추가 요금 정책
  • 연령별 요금 할인 정책

인터페이스 사용

요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
+

"Pattern" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

요구사항

지하철 미션에는 다음과 같은 요구사항이 있었다.

  • 거리별 추가 요금 정책
  • 노선별 추가 요금 정책
  • 연령별 요금 할인 정책

인터페이스 사용

요금 정책은 다음과 같이 인터페이스로 표현할 수 있다.
요금을 계산하는 메서드는 최단 경로 계산의 결과, 사용자의 정보, 요금을 받아 요금을 계산한다.

public interface FarePolicy {
int calculate(Path path, Passenger passenger, int fare);
}

public class BaseFarePolicy implements FarePolicy { ... }
public class DistanceFarePolicy implements FarePolicy { ... }
public class AgeDiscountFarePolicy implements FarePolicy { ... }

composite1

모든 요금 정책을 포함하는 새로운 요금 정책 만들기

나머지 구현체를 모두 가지고 있는 하나의 구현체를 만들었다.
이 또한 FarePolicy를 구현한 형태가 되고, 필드로는 나머지 구현체들을 가지고 있다.

public class SubwayFarePolicy implements FarePolicy {

private final List<FarePolicy> farePolicies;

public SubwayFarePolicy(final List<FarePolicy> farePolicies) {
this.farePolicies = farePolicies;
}

@Override
public int calculate(final Path path, final Passenger passenger, final int fare) {
int calculatedFare = fare;
for (FarePolicy farePolicy : farePolicies) {
calculatedFare = farePolicy.calculate(path, passenger, calculatedFare);
}
return calculatedFare;
}
}

따라서 그림으로 본다면 다음과 같은 구조가 된다.

composite2

정책의 순서

지하철 요구사항은 순서가 중요했다.
금액의 총합을 구하고, 그 후에 할인 정책이 들어가야했다.
@@ -31,7 +31,7 @@ 패턴을 맹목적으로 사용해서는 안되고, 현재의 요구사항에 따라 패턴을 유동적으로 수정해가면서 적용하는 것이 좋다.
항상 트레이드오프를 생각하자!

참고 자료

컴포지트 패턴, GoF의 디자인 패턴
디자인 패턴과 프레임워크, 오브젝트

- - + + \ No newline at end of file diff --git a/tags/performance-test.html b/tags/performance-test.html index 0469f6e3b..4bfc2e8f2 100644 --- a/tags/performance-test.html +++ b/tags/performance-test.html @@ -13,12 +13,12 @@ - - + +
-

"performance test" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

성능 테스트

API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
+

"performance test" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

성능 테스트

API의 요청이 많은 상황에서 서버가 어떻게 동작하는지 확인하는 테스트

시스템에 부하가 걸리면 문제 상황이 발생할 수 있다.
다양한 상황에 대비해서 성능 테스트를 해야한다.

./test.png

스모크 테스트(Smoke Test)

최소한의 부하를 주어 시스템이 정상적으로 동작하는지 확인하는 테스트

VU를 최소한으로 두고, 짧은 시간을 가지고 테스트한다.
다른 테스트를 시작하기 전에 스모크 테스트를 함으로써 테스트 스크립트에 오류가 없는지 확인할 수 있고, 성능 지표가 정상적으로 수집, 모니터링 되고 있는지 확인할 수 있다.

가상 사용자(VU)

가상 사용자는 서버 애플리케이션에 대해 특정 테스트를 실행한다.
이는 다른 가상 사용자와 독립적으로 실행되며, 여러 가상 사용자를 사용하여 동시 연결을 할 수 있다.
@@ -33,7 +33,7 @@ 다만 Auto Scaling이 적용된 클라우드 환경에서는 진행하지 않아야 한다.

참고 자료

Load test types, k6
자바 최적화 - 벤저민 J. 에번스, 제임스 고프, 크리스 뉴랜드
아마존 웹 서비스 부하 테스트 입문 - 나카가와 타루하치, 모리시타 켄

- - + + \ No newline at end of file diff --git a/tags/python.html b/tags/python.html index c04e29929..057c235ee 100644 --- a/tags/python.html +++ b/tags/python.html @@ -13,12 +13,12 @@ - - + +
-

"Python" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
+

"Python" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 7분

개요

이전에 기술 구현 가능 여부를 조사하면서 파이썬을 사용한 내용을 정리한 내용이다.

사용 기술

언어: Python 3.10
이미지 생성: matplotlib
서비스: AWS Lambda, AWS API Gateway
이미지 저장 및 URL: AWS S3, AWS CloudFront

플로우는 다음과 같다.

요구사항

./route.png

우측 상단의 경로 이미지를 생성하려고 한다.
@@ -39,7 +39,7 @@ Python Lambda 함수에 대한 .zip 파일 아카이브 작업
No module named 'numpy.core._multiarray_umath'
사례별로 알아본 안전한 S3 사용 가이드

- - + + \ No newline at end of file diff --git a/tags/replication.html b/tags/replication.html index 6149f073e..e5be6f80b 100644 --- a/tags/replication.html +++ b/tags/replication.html @@ -13,12 +13,12 @@ - - + +
-

"replication" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
+

"replication" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 21분

복제(Replication)

한 서버에서 다른 서버로 데이터를 동기화하는 것을 의미한다.
원본 데이터를 가지는 서버를 Primary 또는 Source 라고 부르고, 복제된 데이터를 가지는 서버를 Secondary 또는 Replica 라고 부른다.

복제를 하는 이유

1. 스케일 아웃

사용자의 트래픽이 증가하는 경우, 데이터베이스에 가해지는 부하도 자연스럽게 증가한다.
이를 처리하기 위해 복제를 통한 스케일 아웃을 적용하여 애플리케이션에서 사용하는 쿼리들을 각각의 데이터베이스로 분산 시킬 수 있다.

2. 데이터 백업

실제 운영되는 서비스가 사용하고 있는 DB에서 백업을 진행하는 경우, 서비스에 영향을 미칠 수 있다.
따라서 실제 서비스에 영향이 가지 않도록 복제를 통해 Replica 서버를 구축하여, Replica 서버에서 복제를 진행하는 방법으로 영향을 최소화 할 수 있다.

3. 데이터 분석

백업과 마찬가지로 복잡하고 무거운 분석용 쿼리의 서비스에 영향을 미칠 수 있다.
@@ -71,7 +71,7 @@ 데이터베이스 레플리케이션을 통한 쿼리 성능 개선 (feat. Mysql, SpringBoot)
부하 분산을 위한 MySQL Replication 구성 및 쿼리 요청 분기
Use Docker Compose, Docker

- - + + \ No newline at end of file diff --git a/tags/retrospective.html b/tags/retrospective.html index 702297b1a..aab90b061 100644 --- a/tags/retrospective.html +++ b/tags/retrospective.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

다이어그램

Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
@@ -47,7 +47,7 @@ Apache Tomcat 8 Configuration Reference
Apache Tomcat Tuning, Terry Cho
maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/10.html b/tags/retrospective/page/10.html index c58bfc1f9..28b44a4f5 100644 --- a/tags/retrospective/page/10.html +++ b/tags/retrospective/page/10.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

백엔드

최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
@@ -37,7 +37,7 @@ 오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

참고 자료

Elastic Beanstalk, AWS
EC2 AWS Graviton, AWS
Default Memory Settings, AWS

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/11.html b/tags/retrospective/page/11.html index 2867387f7..2990bfba2 100644 --- a/tags/retrospective/page/11.html +++ b/tags/retrospective/page/11.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
@@ -41,7 +41,7 @@ 추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
변환하는 로직은 GPT의 도움을 많이 받았다.

const replaceCodeFences = (input: String) => {
const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
return input
.replace(codeFencesRegex, (match, p1, p2) => {
const languageClass = p1 ? ` class="language-${p1}"` : "";
return `<pre><code${languageClass}>${p2}</code></pre>`;
})
.replace(/\n/g, "<br>");
};

Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

tecochat

폰트 및 favicon 적용

타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
추가로 favicon도 간단하게 적용해서 만족스러웠다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/12.html b/tags/retrospective/page/12.html index caa52a678..19bc3fb6e 100644 --- a/tags/retrospective/page/12.html +++ b/tags/retrospective/page/12.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

레벨 1이 끝났다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

레벨 1이 끝났다.
우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

Keep

나만의 루틴 만들기

스스로가 외부의 영향을 많이 받는다고 생각한다.
@@ -50,7 +50,7 @@ 블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

레벨 1을 마무리하며

시간이 빠르게 흘러갔다.
타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/13.html b/tags/retrospective/page/13.html index cfd13be5b..ab8ddfd63 100644 --- a/tags/retrospective/page/13.html +++ b/tags/retrospective/page/13.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

체스

체스 미션에는 가비와 페어가 매칭되었다!
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

체스

체스 미션에는 가비와 페어가 매칭되었다!
체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
@@ -53,7 +53,7 @@ 모르는게 있으면 솔직하게 말해주는 부분
나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
솔직함은 페어할 때 중요한 부분인 것 같다.

마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/14.html b/tags/retrospective/page/14.html index 749c0e6cc..5d27540ba 100644 --- a/tags/retrospective/page/14.html +++ b/tags/retrospective/page/14.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
@@ -48,7 +48,7 @@ 회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

도메인 언어에 신경쓰는 부분
클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
요구사항 정리도 깔끔하게 잘하는 것 같다.

후추 최고 👍

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/15.html b/tags/retrospective/page/15.html index a2f6f90e8..ef24090b1 100644 --- a/tags/retrospective/page/15.html +++ b/tags/retrospective/page/15.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

2단계에서는 2가지 방법으로 구현해봤다.

  1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
  2. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법

Position 기준으로 사다리 게임을 진행하는 방법

사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

public LadderGameResult play() {
final Map<Player, Item> result = new LinkedHashMap<>();
// 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
for (Position position : Position.range(players.count())) {
final Position resultPosition = ladder.play(position);
result.put(players.get(position), items.get(resultPosition));
}
return new LadderGameResult(result);
}

Player에게 Ladder를 전달하여 게임을 진행하는 방법

Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
@@ -50,7 +50,7 @@ 또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/16.html b/tags/retrospective/page/16.html index ba7100afa..e0ab315bf 100644 --- a/tags/retrospective/page/16.html +++ b/tags/retrospective/page/16.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

  • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
  • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.

미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
@@ -44,7 +44,7 @@ 그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
이건 바로 배울 수 없지만.
나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/17.html b/tags/retrospective/page/17.html index 6fdc89422..daea43f29 100644 --- a/tags/retrospective/page/17.html +++ b/tags/retrospective/page/17.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

적당한 전환점, 2022년을 돌아보며

전역

약 1년 6개월간의 공군 정보보호병 생활을 마치고 전역을 했다.
조기 전역 때문에 2021년 12월에 나왔지만, 실제 전역 날짜는 2022년이니 회고에 적어도 상관없겠지.

조금 더 미래에 대한 생각을 해볼걸 그랬다.
전역을 했지만 뭐 하나 제대로 할 줄 아는 것도 없으니 넓은 바닷속에 덩그러니 놓아진 기분이 괜히 들었었다.
일찍 생각을 정리하여 방향을 잡지 못했기에 아쉬움이 많이 남았다.

자바

전역을 하고 진로를 고민하다 향로님의 자바 공화국 포스팅을 읽고 나서 자바 공부를 시작했다.
@@ -33,7 +33,7 @@ 적지 않은 시간을 투자해 준비를 했고, 감사하게도 이번에는 최종 합격을 했다.

난 사람들과 소통하고, 협업하는 능력이 부족하다고 생각을 많이 했다.
우아한 테크코스를 통해 그 빈 부분을 채우도록 노력해야겠다.

2023년에는

마음의 여유가 없었던 2022년이었던 것 같다.
하고 싶은 건 많지만, 이번에는 여유를 가지고 할 수 있는 것에 최선을 다해야겠다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/2.html b/tags/retrospective/page/2.html index dfb05275b..e5b95ddc4 100644 --- a/tags/retrospective/page/2.html +++ b/tags/retrospective/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

아쉬운 점

문서화

개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
@@ -33,7 +33,7 @@ 아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

기술 선택의 이유

기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

마치며

플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/3.html b/tags/retrospective/page/3.html index df79785de..e23527af7 100644 --- a/tags/retrospective/page/3.html +++ b/tags/retrospective/page/3.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
빠르게 지나가서 조금 아쉽다.

학습

회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
@@ -29,7 +29,7 @@ 이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

레벨 3 때부터 본격적으로 프로젝트가 시작된다.
팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

레벨 2를 마무리하며

회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. 읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/4.html b/tags/retrospective/page/4.html index 26d5665d4..b3da0dbb6 100644 --- a/tags/retrospective/page/4.html +++ b/tags/retrospective/page/4.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

API 문서 도구 선택

큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
@@ -31,7 +31,7 @@ 생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
이전에 공부했던거 되돌아 보는 시간 가지기

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/5.html b/tags/retrospective/page/5.html index dedec3bee..25a60ba57 100644 --- a/tags/retrospective/page/5.html +++ b/tags/retrospective/page/5.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

배포

이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
배포 스크립트를 작성하는 경험을 해볼 수 있었다.
@@ -35,7 +35,7 @@ 추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

DAO에 @Transactional 적용

DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/6.html b/tags/retrospective/page/6.html index 95301e2ef..2d230f617 100644 --- a/tags/retrospective/page/6.html +++ b/tags/retrospective/page/6.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

나의 채팅 확인하고 이어하는 기능

GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

chat1

좋아요와 댓글 기능

다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
@@ -32,7 +32,7 @@ 제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

향후 계획

실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/7.html b/tags/retrospective/page/7.html index efa858647..f52ced045 100644 --- a/tags/retrospective/page/7.html +++ b/tags/retrospective/page/7.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
지하철 미션은 밀리랑 페어를 진행했다.
간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
@@ -39,7 +39,7 @@ 또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

편한 분위기

전체적으로 페어 할 때 편하게 진행했던 것 같다.
일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
나는 과연 다른 사람들에게 편한 사람일까?

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/8.html b/tags/retrospective/page/8.html index 6f32e6083..19f4ebb2f 100644 --- a/tags/retrospective/page/8.html +++ b/tags/retrospective/page/8.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
@@ -32,7 +32,7 @@ 추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

의견 일치시키기

페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

- - + + \ No newline at end of file diff --git a/tags/retrospective/page/9.html b/tags/retrospective/page/9.html index 916d5a313..5c189450f 100644 --- a/tags/retrospective/page/9.html +++ b/tags/retrospective/page/9.html @@ -13,12 +13,12 @@ - - + +
-

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
+

"Retrospective" 태그로 연결된 17개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
웹 자동차 미션에서는 비버와 페어가 매칭되었다.
레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
@@ -37,7 +37,7 @@ 추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
나도 5월부터 조금 더 화이팅 해야겠다.

- - + + \ No newline at end of file diff --git a/tags/spring-boot.html b/tags/spring-boot.html index 072122528..861127931 100644 --- a/tags/spring-boot.html +++ b/tags/spring-boot.html @@ -13,12 +13,12 @@ - - + +
-

"Spring Boot" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
+

"Spring Boot" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

자바 변경 사항

우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

Switch Expressions(Java 14)

Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

enum RESULT {
WIN, LOSE, DRAW
}

RESULT result = RESULT.WIN;

int prize = switch (result) {
case WIN -> 10_000_000;
case LOSE, DRAW -> 5_000_000;
default -> 0;
};

주요 특징은 다음과 같다.

  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • break 문이 필요 없다.
  • default 블록을 통해 기본 값을 지정할 수 있다.

Text Block(Java 15)

Java 15에는 새로운 문자열 표현방식이 추가되었다.
긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("""
SELECT p FROM Post p
WHERE p.title LIKE %:keyword%
OR p.content LIKE %:keyword%
""")
List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
}

NPE 메시지(Java 15)

String name = null;
name.chars();

/**
# before
java.lang.NullPointerException
at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)

# after
Cannot invoke "String.chars()" because "name" is null
java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
*/

Record(Java 16)

Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
@@ -34,7 +34,7 @@ What's New in Spring Framework 6.x
Spring Boot 3.0 Release Notes
Spring Boot 3.1 Release Notes

- - + + \ No newline at end of file diff --git a/tags/spring.html b/tags/spring.html index 649e4677d..8a2f3d450 100644 --- a/tags/spring.html +++ b/tags/spring.html @@ -13,12 +13,12 @@ - - + +
-

"Spring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
+

"Spring" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

자바 17, 스프링 6.0, 스프링 부트 3.1

팀 프로젝트를 진행하면서 스프링 부트 3.1을 사용하게 되었다.
2.7 버전을 사용할 수도 있었지만 LTS 기간과 취약점 패치로 인한 버전업 등을 고려했을 때 3.1과 자바 17을 사용하는 것이 더 효율적이라고 판단했다.

자바 변경 사항

우아한테크코스 레벨 2까지는 자바 11을 사용했었다.
따라서 자바 11부터 자바 17까지의 변경사항을 정식 릴리즈 기준으로 정리해보려고 한다.

Switch Expressions(Java 14)

Java 14에서는 기존의 Switch 문을 간결하게 작성할 수 있는 Switch 식이 추가되었다.

enum RESULT {
WIN, LOSE, DRAW
}

RESULT result = RESULT.WIN;

int prize = switch (result) {
case WIN -> 10_000_000;
case LOSE, DRAW -> 5_000_000;
default -> 0;
};

주요 특징은 다음과 같다.

  • -> 연산자를 이용하여 각 case에 대한 결과를 바로 반환할 수 있다.
  • case를 콤마(,)로 연결하여 하나의 case에 여러 값을 지정할 수 있다.
  • break 문이 필요 없다.
  • default 블록을 통해 기본 값을 지정할 수 있다.

Text Block(Java 15)

Java 15에는 새로운 문자열 표현방식이 추가되었다.
긴 문자열을 + 연산자의 도움 없이 가독성있게 작성할 수 있다.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("""
SELECT p FROM Post p
WHERE p.title LIKE %:keyword%
OR p.content LIKE %:keyword%
""")
List<Post> findPostsByTitleOrContentContainingKeyword(String keyword);
}

NPE 메시지(Java 15)

String name = null;
name.chars();

/**
# before
java.lang.NullPointerException
at com.example.DiscountPolicyTest.test(NullPointerExceptionTest.java:61)

# after
Cannot invoke "String.chars()" because "name" is null
java.lang.NullPointerException: Cannot invoke "String.chars()" because "name" is null
*/

Record(Java 16)

Lombok의 @Data, kotlin의 data 클래스와 유사한 기능을 제공한다.
@@ -34,7 +34,7 @@ What's New in Spring Framework 6.x
Spring Boot 3.0 Release Notes
Spring Boot 3.1 Release Notes

- - + + \ No newline at end of file diff --git a/tags/static.html b/tags/static.html index baf675788..ae766111c 100644 --- a/tags/static.html +++ b/tags/static.html @@ -13,12 +13,12 @@ - - + +
-

"static" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
+

"static" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

개요

정적 팩터리 메서드를 모킹한다는 것은 객체지향적인 관점에서 볼 때 안티패턴이다.
하지만 특수한 경우에는 정적 메서드를 모킹하는 것이 필요할 수 있다고 생각한다.

예를 들어 레거시 코드를 테스트 한다던지, IO 관련한 부분을 테스트 할 때 정말 필요한 부분에만 적용할 수 있을 것이다.

프로젝트를 진행하며 ImageIo.write 메서드가 호출되는 지 검증이 필요했다.
해당 static 메서드를 호출하는 부분을 따로 RouteImageUploader 클래스로 최대한 분리했다.
이미지 저장 기능 자체가 외부로 나가는 상호작용이고, 호출 횟수를 검사하는데는 mock을 사용하는게 적절하다고 판단했다.

public void upload(BufferedImage bufferedImage) {
File file = new File(파일경로);
try {
ImageIO.write(bufferedImage, ROUTE_IMAGE_FORMAT, file);
} catch (IOException e) {
throw new DrawException(IMAGE_SAVE_FAIL);
}
}

Mocking static methods

Mockito 3.4.0 이후에는 static method를 모킹할 수 있는 Mockito.mockStatic 메서드를 지원한다.
@@ -27,7 +27,7 @@ 항상 상황을 고려하고 간결함을 포기할 만큼 중요한 부분인지 적절한 트레이드오프를 고려하자.

참고 자료

Mocking static methods
Mockito mock static methods
Enable mocking static methods in Mockito

- - + + \ No newline at end of file diff --git a/tags/teco-chat.html b/tags/teco-chat.html index 9c1c5b608..dd125813c 100644 --- a/tags/teco-chat.html +++ b/tags/teco-chat.html @@ -13,12 +13,12 @@ - - + +
-

"TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
+

"TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

나의 채팅 확인하고 이어하는 기능

GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

chat1

좋아요와 댓글 기능

다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
@@ -32,7 +32,7 @@ 제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

향후 계획

실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

- - + + \ No newline at end of file diff --git a/tags/teco-chat/page/2.html b/tags/teco-chat/page/2.html index 5ede53954..49af06fa0 100644 --- a/tags/teco-chat/page/2.html +++ b/tags/teco-chat/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
+

"TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

백엔드

최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
@@ -37,7 +37,7 @@ 오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

참고 자료

Elastic Beanstalk, AWS
EC2 AWS Graviton, AWS
Default Memory Settings, AWS

- - + + \ No newline at end of file diff --git a/tags/teco-chat/page/3.html b/tags/teco-chat/page/3.html index 38d03fc7d..c61c23292 100644 --- a/tags/teco-chat/page/3.html +++ b/tags/teco-chat/page/3.html @@ -13,12 +13,12 @@ - - + +
-

"TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
+

"TecoChat" 태그로 연결된 3개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
@@ -41,7 +41,7 @@ 추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
변환하는 로직은 GPT의 도움을 많이 받았다.

const replaceCodeFences = (input: String) => {
const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
return input
.replace(codeFencesRegex, (match, p1, p2) => {
const languageClass = p1 ? ` class="language-${p1}"` : "";
return `<pre><code${languageClass}>${p2}</code></pre>`;
})
.replace(/\n/g, "<br>");
};

Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

tecochat

폰트 및 favicon 적용

타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
추가로 favicon도 간단하게 적용해서 만족스러웠다.

- - + + \ No newline at end of file diff --git a/tags/test.html b/tags/test.html index 56590338a..b37593e65 100644 --- a/tags/test.html +++ b/tags/test.html @@ -13,12 +13,12 @@ - - + +
-

"Test" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
+

"Test" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

테스트 대역의 타입 계층 구조

더미(Dummy)

가장 단순하고, 원시적인 유형의 테스트 대역이다.
기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
@@ -36,7 +36,7 @@ 테스트 더블, Martin Fowler
테스트 관련 용어 정리, Johngrib
Test Double, Gerard Meszaros

- - + + \ No newline at end of file diff --git a/tags/time.html b/tags/time.html index 0c89cb69b..e61ee69e4 100644 --- a/tags/time.html +++ b/tags/time.html @@ -13,19 +13,19 @@ - - + +
-

"Time" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
+

"Time" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 2분

이전에 많은 문제가 있던 자바의 클래스(Calendar, Date)를 대체하는 날짜와 시간 API
ISO-8601을 기반으로 작성
설계 목표 → 불변, Fluent API, 명확하고 명시적, 확장 가능성

ISO-8601

날짜와 시간에 관련된 데이터를 다루는 국제 표준

LocalDate, LocalTime, LocalDateTime

날짜와 시간을 표현하는 클래스

Instant

유닉스 시간(1970-01-01, 00:00:00 UTC) 기준으로 특정 지점까지의 시간을 초로 표현하는 클래스
기계의 관점에서 시간 표현

Duration, Period

간격을 표현하는 클래스

TemporalAdjusters

복잡한 날짜 조정이 필요할 때 사용
필요한 경우 다음 인터페이스를 구현하여 커스텀 TemporalAdjuster를 구현 가능

@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}

DateTimeFormatter

날짜와 시간 포맷 클래스
특정 날짜 패턴이나, DateTimeFormatterBuilder를 이용해서 커스텀한 포맷을 생성 가능

ZoneId, ZoneOffset

ZoneId는 지역 ID는 ‘지역/도시’ 형식, ZoneOffset은 시차 UTC 기준 고정된 시간 차이 이용
ZoneId의 경우 IANA Time Zone Database에서 제공하는 지역 집합 정보 사용

Instant instant = Instant.now();
LocalDateTime utc = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

참고 자료

- - + + \ No newline at end of file diff --git a/tags/transaction.html b/tags/transaction.html index 6a8728d74..873c8cc40 100644 --- a/tags/transaction.html +++ b/tags/transaction.html @@ -13,12 +13,12 @@ - - + +
-

"Transaction" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
+

"Transaction" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

트랜잭션의 속성(ACID)

원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
@@ -42,7 +42,7 @@ 예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

팬텀 리드(Phantom read, Phantom row)

한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

참고 자료

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
Isolation Level, MySQL

- - + + \ No newline at end of file diff --git a/tags/web-socket.html b/tags/web-socket.html index 6b36ae563..d224138b3 100644 --- a/tags/web-socket.html +++ b/tags/web-socket.html @@ -13,12 +13,12 @@ - - + +
-

"WebSocket" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

웹소켓

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
+

"WebSocket" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

웹소켓

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

웹소켓 등장 배경

웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

polling, long polling, streaming

Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

  • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
  • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.

Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

  • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.

Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

  • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.

웹소켓의 동작

1. Upgrade 요청

WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
이는 HTTP와 같이 80, 443 포트를 사용한다.
@@ -32,7 +32,7 @@ https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
https://docs.spring.io/spring-framework/reference/web/websocket.html

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse.html b/tags/woowahan-techcourse.html index d4926cc39..d1f16fba8 100644 --- a/tags/woowahan-techcourse.html +++ b/tags/woowahan-techcourse.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

다이어그램

Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
@@ -47,7 +47,7 @@ Apache Tomcat 8 Configuration Reference
Apache Tomcat Tuning, Terry Cho
maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/10.html b/tags/woowahan-techcourse/page/10.html index 96fcb2863..4d2e937ff 100644 --- a/tags/woowahan-techcourse/page/10.html +++ b/tags/woowahan-techcourse/page/10.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

체스

체스 미션에는 가비와 페어가 매칭되었다!
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

체스

체스 미션에는 가비와 페어가 매칭되었다!
체스는 이전 미션들보다 훨씬 복잡한 도메인이었다.
하지만 가비와 나는 체스 도메인이 익숙해서 더 편한 마음으로 시작할 수 있었다.
미션을 진행하면서 어려웠던 부분은 기물의 이동, 이동시 경로에 기물이 존재하는지 확인하는 부분이었다.

가비가 집에가서도 기물의 이동 관련해 생각 정리한 글을 보내줘서 더욱 빨리 진행할 수 있었다.
@@ -53,7 +53,7 @@ 모르는게 있으면 솔직하게 말해주는 부분
나의 의견을 정리하지 못한 상태로 전달할 때 이해가 안되었다고 정확히 전달해주는 부분
솔직함은 페어할 때 중요한 부분인 것 같다.

마지막으로 찰리🍫 체스 미션때 꼼꼼하게 리뷰 남겨주셔서 감사합니다!

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/11.html b/tags/woowahan-techcourse/page/11.html index c675d549a..2c791f337 100644 --- a/tags/woowahan-techcourse/page/11.html +++ b/tags/woowahan-techcourse/page/11.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 6분

블랙잭

블랙잭 미션에서는 후추와 페어(조미료 듀오?)가 매칭되었다.
이번에는 실수하지 않고, 바로 미션을 진행하지 않고 친해지기 부터 시작했다.

블랙잭은 구현해야 될 내용이 많아 시간이 많이 부족할 것 같았지만
후추와 함께 전략적(삼일절에 미션 이야기 나누기)으로 미션을 진행해 시간 내에 제출할 수 있었다.

미션을 끝나고 회고를 했을 때 후추가 고민거리를 하나 내줬다.
"페어를 진행할 때 압박감을 느끼는 페어가 있다면 허브가 해줄 수 있는게 뭐가 있을까?"

곰곰히 생각해봤지만 쉽게 답을 내릴 수 없었다.
@@ -48,7 +48,7 @@ 회고때도 서로 솔직하게 의견을 주고 받아서 좋았다.

도메인 언어에 신경쓰는 부분
클래스명, 변수명과 같은 언어를 세심하게 신경쓴다.
요구사항 정리도 깔끔하게 잘하는 것 같다.

후추 최고 👍

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/12.html b/tags/woowahan-techcourse/page/12.html index 519f049bd..64988337f 100644 --- a/tags/woowahan-techcourse/page/12.html +++ b/tags/woowahan-techcourse/page/12.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 11분

사다리 타기

사다리 타기 미션에서는 우가와 페어가 매칭되었다.
이전 미션과 달리 TDD로 진행하는 것이 필수였기 때문에 익숙하지 않았지만, 우가와 미션에 관한 소통이 잘 되어서 큰 문제 없이 미션을 마무리할 수 있었다.

우가와 이야기가 잘 통해서 그런지 1단계는 크게 어렵지 않게 진행할 수 있었는데, 2단계에서 많이 고전한 것 같다.

2단계에서는 2가지 방법으로 구현해봤다.

  1. LadderGame에서 Position 기준으로 사다리 게임을 진행하는 방법
  2. Player에게 Ladder를 넘겨서 Ladder에게 Position을 넘겨주며 메시지를 보내는 방법

Position 기준으로 사다리 게임을 진행하는 방법

사실상 index를 Ladder에게 넘겨주고, 해당 index에 대한 결과를 받는 방법과 유사했다.
구현하고 나니 다른 클래스들이 Position에 대한 의존도가 너무 높은 것 같았다.
또한 Players가 별다른 책임을 가지고 있지 않다고 느꼈다.

public LadderGameResult play() {
final Map<Player, Item> result = new LinkedHashMap<>();
// 사용자 수만큼 Position을 가져와서 사다리 게임을 진행한다.
for (Position position : Position.range(players.count())) {
final Position resultPosition = ladder.play(position);
result.put(players.get(position), items.get(resultPosition));
}
return new LadderGameResult(result);
}

Player에게 Ladder를 전달하여 게임을 진행하는 방법

Position에 대한 값을 가지고 있는 Player에게 Ladder를 넘겨서, Player가 Ladder에게 메시지를 보내도록 구현하였다.
@@ -50,7 +50,7 @@ 또한 페어 진행이 느린 것 같다고 말해줘서 안정적으로 시간 안에 미션을 완료할 수 있었다.
페어프로그래밍 진행 속도에 대해 조금 더 생각을 해봐야겠다!

항상 지나갈 때마다 웃어주는데, 나도 자주 웃어야겠다고 생각했다.
웃는 것만으로도 사람이 밝아 보여서 너무 좋은 것 같다!

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/13.html b/tags/woowahan-techcourse/page/13.html index f601a64a6..01a873141 100644 --- a/tags/woowahan-techcourse/page/13.html +++ b/tags/woowahan-techcourse/page/13.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

자동차 경주

자동차 경주 미션에서는 다즐과 페어가 매칭되었다.
우테코 들어와서 첫 페어프로그래밍이라 많이 떨렸지만, 다즐이 대화를 잘 이끌어줘 너무 즐거웠다.

첫날은 간단히 컨벤션과 환경을 설정하는 시간을 가졌고 다음 날부터 자동차 경주를 시작했다.
시작은 간단하게 요구사항을 정리하고, 어떻게 코드를 작성할지 같이 고민했다.

시작하기 전 아래와 같이 mermaid를 이용하여 의존성 방향에 대해서 간단한 다이어그램을 만들고 시작했다.
mermaid는 코드로 다이어그램을 생성 해주는 도구로 다음과 같은 장점이 있다고 생각한다.

  • 코드 기반이라 빠른 시간 안에 생각한 것을 시각화할 수 있다.
  • github에서 mermaid를 지원하기 때문에 리뷰어에게 코드를 이해할 수 있는 부가적인 정보를 제공할 수 있다.

미션을 진행하는 데 큰 어려움이 있지는 않았고, 페어를 마치기 전 서로 고민되는 부분을 정리했을 때 좋았다.

페어하면서 잘했다고 생각했던 점은 서로의 생각과 리뷰 받은 것을 공유한 것이다.
@@ -44,7 +44,7 @@ 그래서 즐거운 마음으로 페어 프로그래밍을 했었던 것 같다.

어떤 이유 때문인지 모르겠지만 같이 페어하는데 편한 마음이 들었다.
이건 바로 배울 수 없지만.
나도 같이 일할 때 편한 사람, 같이 일하고 싶은 사람이 되기 위해 깊이 고민해봐야겠다.

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/2.html b/tags/woowahan-techcourse/page/2.html index 9527028e3..801ee758d 100644 --- a/tags/woowahan-techcourse/page/2.html +++ b/tags/woowahan-techcourse/page/2.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

아쉬운 점

문서화

개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
@@ -33,7 +33,7 @@ 아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

기술 선택의 이유

기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

마치며

플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/3.html b/tags/woowahan-techcourse/page/3.html index 1a41daf8d..5553d4bb4 100644 --- a/tags/woowahan-techcourse/page/3.html +++ b/tags/woowahan-techcourse/page/3.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
빠르게 지나가서 조금 아쉽다.

학습

회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
@@ -29,7 +29,7 @@ 이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

레벨 3 때부터 본격적으로 프로젝트가 시작된다.
팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

레벨 2를 마무리하며

회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. 읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/4.html b/tags/woowahan-techcourse/page/4.html index 4560a5ffe..9079350f0 100644 --- a/tags/woowahan-techcourse/page/4.html +++ b/tags/woowahan-techcourse/page/4.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

레벨 인터뷰

레벨 1 때는 준비해둔 내용으로 인터뷰를 진행해서 그렇게 특별한 부분이 없었다.
따라서 레벨 1 레벨 인터뷰 회고는 레벨 1 회고를 작성할 때 끼워넣었다.
이번에는 범위도 제한되어 있어 어떻게 준비해야 할지 당황했고, 답변에도 부족한 부분이 많았었다.
기억이 사라지기 전에 큰 문제 없이 답변한 내용을 제외하고, 기억 남는 것 위주로 작성해 보려고 한다.

API 문서 도구 선택

큰 문제 없이 답변을 했는데 앞으로도 팀 프로젝트를 하면서 도움 될 것 같은 내용이 있어서 남겨두려고 한다.
@@ -31,7 +31,7 @@ 생각할 시간을 가졌을 때 "다시 말씀드려도 될까요?"라고 말하고 답변을 이어나가기
기술적으로 깊이가 부족하다고 생각이 많이 들어서 조금 더 깊게 공부하고 정리하기
이전에 공부했던거 되돌아 보는 시간 가지기

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/5.html b/tags/woowahan-techcourse/page/5.html index fe0338098..df4433e2f 100644 --- a/tags/woowahan-techcourse/page/5.html +++ b/tags/woowahan-techcourse/page/5.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

장바구니 주문 미션

배포 및 협업을 할 수 있는 미션이었다.
마코, 우가, 우코, 우스 그리고 나까지 합쳐서 5명이 한 팀이 되었다.

배포

이전 미션들과 달리 AWS를 이용해 배포를 해야 했다.
각자 하나의 EC2 인스턴스를 제공받을 수 있었고, 팀 별로 DB를 위한 추가 인스턴스를 제공받았다.
배포 스크립트를 작성하는 경험을 해볼 수 있었다.
@@ -35,7 +35,7 @@ 추가로 현업에서는 고가용성 내결함성 등을 위하여 클러스터를 구성하여 사용하는 경우가 많고, 이 경우 readOnly 설정이 되어있다면 읽기 전용 DB로 질의가 들어가서 부하 분산의 효과가 있다고 한다.

DAO에 @Transactional 적용

DAO에 트랜잭션을 보장해 보는 건 어떻겠냐고 리뷰가 달려서 고민을 많이 했다.
Service 계층에 이미 트랜잭션을 보장해 주고 있기에 필요 없지 않을까 생각했었다.
DAO를 다른 곳에서 사용하더라도 트랜잭션을 보장하기 위해(확장성 고려) @Transactional을 적용하는 것도 괜찮은 것 같다.

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/6.html b/tags/woowahan-techcourse/page/6.html index 0bd0bdb8a..f6fab653f 100644 --- a/tags/woowahan-techcourse/page/6.html +++ b/tags/woowahan-techcourse/page/6.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

지하철 미션

점점 일정이 많아지는 느낌이 들면서 회고가 늦어진다.
지하철 미션은 밀리랑 페어를 진행했다.
간단한 CRUD만 있던 이전 미션들과 달리, 조금 복잡한 도메인 요구사항이 있었다.
이때 API, 테이블, 도메인 설계를 해야 했는데 어떤 것부터 해야 할지 고민을 많이 했다.
@@ -39,7 +39,7 @@ 또한 코딩할 때 내가 평소에 사용하는 코딩 컨벤션에 맞춰주는 것 같아서 페어 할 때 편했다!

편한 분위기

전체적으로 페어 할 때 편하게 진행했던 것 같다.
일정도 그렇고, 페어 진행할 때도 그렇고 큰 문제가 없었던 것 같아서 좋았다.
나는 과연 다른 사람들에게 편한 사람일까?

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/7.html b/tags/woowahan-techcourse/page/7.html index 4ef9bdebe..41e1ab225 100644 --- a/tags/woowahan-techcourse/page/7.html +++ b/tags/woowahan-techcourse/page/7.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 5분

웹 장바구니 미션

장바구니 미션은 블랙캣이랑 진행했다.
요구사항이 엄청 복잡한 미션은 아니었고, 스프링을 사용하여 기본적인 CRUD를 구현하는 미션이었다.
2단계에서는 Basic 인증을 통해 자신의 장바구니에만 상품을 담고, 제거할 수 있도록 구현하는 요구사항이 추가되었다.
Interceptor나 Argument Resolver에 대한 이해도가 높지 않았는데, 이번 미션을 통해 조금 더 알아간 느낌이다.
@@ -32,7 +32,7 @@ 추가적으로 이모지를 적극적으로 사용하여 더욱 좋았다!

의견 일치시키기

페어 시간은 한정되어 있고, 기간 내 요구사항을 만족해야 한다.
따라서 적당히 타협을 봐서 의견을 빠르게 수용해 데드라인을 맞추는 것도 중요하다고 생각한다.
블랙캣은 내 의견을 잘 들어줬고, 덕분에 막히는 부분 없이 빠르게 미션을 진행할 수 있었다.

빨리 친해졌고, 의사소통이 잘 돼서 재밌게 코딩할 수 있었다!

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/8.html b/tags/woowahan-techcourse/page/8.html index 758522bd1..aa11a6b67 100644 --- a/tags/woowahan-techcourse/page/8.html +++ b/tags/woowahan-techcourse/page/8.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
웹 자동차 미션에서는 비버와 페어가 매칭되었다.
레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
@@ -37,7 +37,7 @@ 추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
나도 5월부터 조금 더 화이팅 해야겠다.

- - + + \ No newline at end of file diff --git a/tags/woowahan-techcourse/page/9.html b/tags/woowahan-techcourse/page/9.html index 71d833648..59a13e69d 100644 --- a/tags/woowahan-techcourse/page/9.html +++ b/tags/woowahan-techcourse/page/9.html @@ -13,12 +13,12 @@ - - + +
-

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

레벨 1이 끝났다.
+

"Woowahan Techcourse" 태그로 연결된 13개 게시물개의 게시물이 있습니다.

모든 태그 보기

· 약 8분

레벨 1이 끝났다.
우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

Keep

나만의 루틴 만들기

스스로가 외부의 영향을 많이 받는다고 생각한다.
@@ -50,7 +50,7 @@ 블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

레벨 1을 마무리하며

시간이 빠르게 흘러갔다.
타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

- - + + \ No newline at end of file diff --git a/tecochat-retrospective-1.html b/tecochat-retrospective-1.html index 42295a723..d0442db4c 100644 --- a/tecochat-retrospective-1.html +++ b/tecochat-retrospective-1.html @@ -13,12 +13,12 @@ - - + +
-

[테코챗] 1. 프로토타입 만들기

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
+

[테코챗] 1. 프로토타입 만들기

· 약 6분

4월 21일 금요일

레벨 2를 시작한 뒤 내가 학습에 대한 방향을 잃어버렸다는 생각이 들었다.
레벨 3, 4에서 나만의 강점을 가지고 싶어 고민을 많이 했다.
단순히 스프링을 깊게 공부하는 건 효율이 많이 떨어진다고 생각했다.
글쓰기 수상으로 받은 쿠폰을 사용해 브라운에게 커피챗을 신청했고, 사이드 프로젝트를 해보라는 답을 받았다.

나는 아이디어를 못내는 편인데 브라운이 아이디어까지 던져주셨다.
@@ -41,7 +41,7 @@ 추가로 띄어쓰기도 적용되지 않아서 \n<br>태그로 변환했다.
변환하는 로직은 GPT의 도움을 많이 받았다.

const replaceCodeFences = (input: String) => {
const codeFencesRegex = /```([\w-]*)\n([\s\S]*?)\n```/g;
return input
.replace(codeFencesRegex, (match, p1, p2) => {
const languageClass = p1 ? ` class="language-${p1}"` : "";
return `<pre><code${languageClass}>${p2}</code></pre>`;
})
.replace(/\n/g, "<br>");
};

Tiptap을 적용하니 다음과 같이 깔끔한 코드 블록을 볼 수 있었다.

tecochat

폰트 및 favicon 적용

타이틀은 배달의민족 도현체, 내용은 IBM Plex Sans를 사용했다.
추가로 favicon도 간단하게 적용해서 만족스러웠다.

- - + + \ No newline at end of file diff --git a/tecochat-retrospective-2.html b/tecochat-retrospective-2.html index bd21113e2..7e88f82cf 100644 --- a/tecochat-retrospective-2.html +++ b/tecochat-retrospective-2.html @@ -13,12 +13,12 @@ - - + +
-

[테코챗] 2. 배포

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
+

[테코챗] 2. 배포

· 약 5분

프론트엔트

닉네임을 입력하여 간단히 로그인하는 화면, 채팅 목록을 보여주는 화면도 만들었고 단일 채팅을 확인할 수 있는 화면도 만들었다.
추가로 채팅을 이어나갈 수 있게 하는 기능도 추가했다.
자잘하게 신경 쓸 부분이 많아서, 프론트엔드 하는 사람들이 대단하다고 생각되었다.
여유가 된다면 자신의 채팅을 볼 수 있는 기능이나, 채팅을 이어서 할 수 있는 기능, 댓글 기능도 추가할 예정이다.

백엔드

최대한 빨리 서비스를 크루들에게 제공하기로 정해서, 백엔드는 말랑이 일단 다 만들고 있다.
@@ -37,7 +37,7 @@ 오늘 적용해 보니 램이 부족하여 중간에 잘 안되기도 하고 그래서 그냥 "Pipeline만 사용할 걸 그랬나?" 라는 생각이 든다.

참고 자료

Elastic Beanstalk, AWS
EC2 AWS Graviton, AWS
Default Memory Settings, AWS

- - + + \ No newline at end of file diff --git a/tecochat-retrospective-3.html b/tecochat-retrospective-3.html index 6a9c0cb76..22d0c7b24 100644 --- a/tecochat-retrospective-3.html +++ b/tecochat-retrospective-3.html @@ -13,12 +13,12 @@ - - + +
-

[테코챗] 3. 기능 구현

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
+

[테코챗] 3. 기능 구현

· 약 5분

개요

원래 목적인 크루들의 학습에 도움을 주기 위해 어떤 기능을 추가해야 할지 고민을 많이 했다.
레벨 2가 거의 끝나가는 시점, 그동안 했던 것을 정리해 보려고 한다.

나의 채팅 확인하고 이어하는 기능

GPT에도 있는 기능인데, 내가 이전에 했던 채팅을 이어할 수 있는 기능을 추가했다.
예전에 어떤 질문을 남겼는지, 또한 해당 채팅을 이어서 할 수 있다.

chat1

좋아요와 댓글 기능

다른 사람들이 질문한 내용에 반응할 수 있는 무언가가 있었으면 좋겠다는 의견들이 많았다.
누가 좋아요를 눌렀는지, 어떤 채팅이 좋아요를 가장 많이 받았는지 확인할 수 있는 기능을 추가했다.
@@ -32,7 +32,7 @@ 제일 하고 싶은 것은 실제 GPT를 사용하는 것처럼 stream/text 값을 처리하고 싶은데 이 부분은 방학 때 기회가 되면 도전해 봐야겠다.

향후 계획

실제 크루들이 사용해 주는 서비스를 직접 만들어보면서 사용자의 입장에서 고민도 하게 되는 것 같다.
크루들이 직접 사용해 주니까 너무 고맙고, 한편으로는 신기하다.
일단 방학 때 stream/text 관련된 부분 동작되도록 구현해보려고 하고, 그 외의 부분은 조금 더 고민해야될 것 같다.

- - + + \ No newline at end of file diff --git a/test-double.html b/test-double.html index a172a23c8..449a271cc 100644 --- a/test-double.html +++ b/test-double.html @@ -13,12 +13,12 @@ - - + +
-

테스트 대역

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
+

테스트 대역

· 약 5분

테스트 대역이란?

모든 유형의 테스트를 위한 가짜 의존성을 의미하고, 테스트가 실행될 때 다른 객체를 대신한다.
Gerard Meszaros의 xUnit Test Patterns라는 책에서는 테스트 대역을 다섯 가지(더미, 스텁, 스파이, 목, 페이크)로 구분한다.

테스트 대역의 기본 메커니즘은 다형성을 이용하는 방법이다.
외부 서비스를 사용하는 코드를 테스트 하는 경우, 인터페이스를 정의하고 외부 서비스 대신 테스트 용도의 구현체를 생성하는 것이다.

테스트 대역의 타입 계층 구조

더미(Dummy)

가장 단순하고, 원시적인 유형의 테스트 대역이다.
기본적으로 아무 일도 하지 않는 구현체로 인스턴스화가 필요한 경우 사용한다.
@@ -36,7 +36,7 @@ 테스트 더블, Martin Fowler
테스트 관련 용어 정리, Johngrib
Test Double, Gerard Meszaros

- - + + \ No newline at end of file diff --git a/the-essence-of-object-orientation.html b/the-essence-of-object-orientation.html index 7ef016a8e..0f5d79673 100644 --- a/the-essence-of-object-orientation.html +++ b/the-essence-of-object-orientation.html @@ -13,12 +13,12 @@ - - + +
-

[책] 객체지향의 사실과 오해

· 약 6분

책 정보

객체지향의 사실과 오해
+

[책] 객체지향의 사실과 오해

· 약 6분

책 정보

객체지향의 사실과 오해
조영호

읽고 나서

조영호님의 오브젝트를 읽고 나서 다시 한 번 읽어보았다.
아직 이해가 안되는 부분이 많지만, 그래도 항상 새로움을 느낀다.
더할 나위 없이 휼륭한 객체지향 책이고, 조금 더 공부하고 다시 읽어봐야될 것 같다.

커피 전문점, 지하철 노선도, 이상한 나라의 엘리스를 예시로 든 설명이 너무 좋았고
@@ -38,7 +38,7 @@ ’어떤 행위(What)’를 수행할 것인지 결정한 후 ‘누가(who)’ 그 행위를 수행할 것인지 결정해야 한다. 여기서 ‘어떤 행위’가 바로 메시지다. p.158

- - + + \ No newline at end of file diff --git a/tomcat-retrospective.html b/tomcat-retrospective.html index f752bab82..b4c7ec7ad 100644 --- a/tomcat-retrospective.html +++ b/tomcat-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

톰캣 구현 미션 회고

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
+

톰캣 구현 미션 회고

· 약 13분

톰캣 구현

우아한테크코스를 지원할 때 객체지향과 관련된 미션도 기대를 많이 했지만 레벨 4에 진행하는 미션이 정말 하고 싶었다.
그래서 미션을 할 수 있을까라는 걱정 반, 미션에 대한 기대 반으로 부푼 마음을 가지고 미션을 시작했던 것 같다.

이번 미션에서는 적절하게 추상화하고, 미션의 본질을 이해하려고 노력했다.
톰캣 구현 미션은 RFC 2616에 명시된 스펙(완벽하지 않지만 미션에서 주어진 요구사항만 만족하도록)으로 요청을 받아 처리 후 반환하는데 집중했다.

다이어그램

Catalina는 Tomcat의 서블릿 컨테이너, Coyote는 HTTP 1.1 웹 서버를 지원하는 구성 요소라고 생각하고 아래와 같이 구성했다.
사실 내부 구조를 깊게 공부할 시간을 가지지 못해서 각 구성 요소가 왜 해당 위치에 있는지 완벽하게 설명하지는 못하지만 미션을 진행하면서 이건 여기에 있으면 좋을 것 같은데? 라는 생각이 들면 적절한 패키지에 위치시키는 방향으로 진행을 했다.
@@ -46,8 +46,8 @@ ETag, mdn
Apache Tomcat 8 Configuration Reference
Apache Tomcat Tuning, Terry Cho
-maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

- - +maxThreads, maxConnections, acceptCount로 Tomcat 튜닝하기

+ + \ No newline at end of file diff --git a/transaction-and-isolation.html b/transaction-and-isolation.html index f2e681b35..85e4a65f1 100644 --- a/transaction-and-isolation.html +++ b/transaction-and-isolation.html @@ -13,12 +13,12 @@ - - + +
-

트랜잭션과 격리수준

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
+

트랜잭션과 격리수준

· 약 10분

트랜잭션(Transaction)

데이터베이스에서 논리적 기능을 수행하기 위한 작업의 단위를 말한다.
트랜잭션은 작업의 완전성과 데이터의 정합성을 보장해 준다.
논리적인 작업 셋을 완벽하게 처리하거나, 오류 시 작업의 일부만 적용되는 현상을 막아준다.

트랜잭션의 속성(ACID)

원자성(Atomicity): 트랜잭션 내에서 실행된 작업들은 모두 성공하거나, 실패해야 한다.
일관성(Consistency): 트랜잭션이 수행되기 전과 후에 데이터베이스가 일관된 상태를 유지해야 한다.
@@ -42,7 +42,7 @@ 예) A가 레코드를 여러 번 조회하던 중 B가 레코드를 변경하여 A가 조회한 값이 달라지는 경우

팬텀 리드(Phantom read, Phantom row)

한 트랜잭션 내에서 동일한 쿼리 수행시, 수행 결과가 다른 현상
예) A가 레코드를 조회하고 B가 레코드를 추가하여 A가 다시 조회할 때 존재하지 않은 레코드가 조회되는 경우

참고 자료

Real My SQL 8.0 - 5장 트랜잭션과 잠금, 백은빈, 이성욱
Isolation Level, MySQL

- - + + \ No newline at end of file diff --git a/web-racing-car-retrospective.html b/web-racing-car-retrospective.html index d58b3b426..2d4bd8f10 100644 --- a/web-racing-car-retrospective.html +++ b/web-racing-car-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

웹 자동차 미션 회고

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
+

웹 자동차 미션 회고

· 약 4분

웹 자동차 미션

사이드 프로젝트를 한다고 시간이 많이 없어서 회고가 늦어졌다.
웹 자동차 미션에서는 비버와 페어가 매칭되었다.
레벨 2에서 진행하는 첫 미션이라 많이 긴장되었지만, 그래도 비버랑 초반에 맛있는 것도 많이 먹으면서 빨리 친해져서 재밌게 할 수 있었다.

스프링을 조금 사용할 줄 알아서, 비버랑 같이 학습하면서 미션을 진행했다.
첫 미션이라 그런지 특별한 부분은 없었고, 최대한 깔끔하게 작성하려고 노력했다.
@@ -37,7 +37,7 @@ 추가적으로 알고 싶은 부분을 따로 학습하는 열정이 좋다고 생각했다.
비버와 스프링에 대해 알아가는 시간을 많이 가진 부분이 매우 좋았다.
나도 5월부터 조금 더 화이팅 해야겠다.

- - + + \ No newline at end of file diff --git a/websocket.html b/websocket.html index c39f9c68e..a459c0656 100644 --- a/websocket.html +++ b/websocket.html @@ -13,12 +13,12 @@ - - + +
-

웹소켓

· 약 5분

웹소켓

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
+

웹소켓

· 약 5분

웹소켓

단일 TCP 연결을 통해 클라이언트와 서버 간 전이중 양방향 통신을 지원하는 프로토콜
웹 환경에서 연속된 데이터를 실시간으로 처리할 수 있다.

웹소켓은 HTTP의 포트를 그대로 사용하고 각각 포트 80과 포트 443을 사용하여 HTTP(ws://) 및 HTTPS(wss://)로 서버에 연결한다.

웹소켓 등장 배경

웹소켓이 등장하기 이전, 실시간성을 보장하기 위해 Polling, Long polling, Streaming 같은 기술을 사용했어야 했다.
이는 실시간성이나 양방향성을 만족시키지 못했고, HTTP를 이용하기 때문에 과도한 오버헤드가 발생했다.

polling, long polling, streaming

Polling: 주기적으로 서버에 요청을 보내 수신할 정보가 있는지 확인하는 방법

  • 서버에서 보낼 내용이 없어도 클라이언트는 알 수 없다.
  • 계속해서 요청을 보내 확인을 해야하기 때문에 서버에 불필요한 부하를 주어야 한다.

Long Polling: 클라이언트의 요청에 대해 응답을 보내지 않고 있다가 이벤트가 발생했을때 응답하는 방법

  • 폴링 방식보다 서버에 적은 부하를 줄 수 있지만, 요청의 주기가 짧으면 폴링과 차이가 없어진다.

Streaming: 클라이언트가 request를 보내면 커넥션을 맺고, 이 커넥션을 유지하면서 서버가 계속 데이터를 보내는 방법

  • 클라이언트가 서버에 요청을 하고 싶다면 새로운 커넥션을 맺어야 한다.

웹소켓의 동작

1. Upgrade 요청

WebSocket 프로토콜로 전환하는 HTTP 요청을 보낸다.
이는 HTTP와 같이 80, 443 포트를 사용한다.
@@ -32,7 +32,7 @@ https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
https://developer.mozilla.org/ko/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
https://docs.spring.io/spring-framework/reference/web/websocket.html

- - + + \ No newline at end of file diff --git a/woowacourse-level1-retrospective.html b/woowacourse-level1-retrospective.html index 38713bba8..59e56ebe7 100644 --- a/woowacourse-level1-retrospective.html +++ b/woowacourse-level1-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

우아한테크코스 레벨 1 회고

· 약 8분

레벨 1이 끝났다.
+

우아한테크코스 레벨 1 회고

· 약 8분

레벨 1이 끝났다.
우테코를 시작하기 전 내가 정해두었던 목표 이상으로 달성했기 때문에 매우 만족스럽다.
혼자 독학을 할 땐 이 방향으로 공부하는 게 맞는지 계속 반추하다 결국 무기력함에 빠져들었다.
하지만 이제는 같이 공부할 사람도 있고, 이야기할 사람도 있기 때문에 즐기는 일만 남은 것 같다.

Keep

나만의 루틴 만들기

스스로가 외부의 영향을 많이 받는다고 생각한다.
@@ -50,7 +50,7 @@ 블로그에 기술적인 부분을 많이 정리하지 않았는데, 조금 더 깊게 공부하고 정리하는 시간도 가져야겠다.

레벨 1을 마무리하며

시간이 빠르게 흘러갔다.
타인에게 좋은 영향을 주기위해, 방학동안 나를 챙기는 시간을 가져야겠다.
또한 함께 일하고 싶은 사람을 목표로 앞으로도 꾸준히 의식적 노력을 해야겠다.

- - + + \ No newline at end of file diff --git a/woowacourse-level2-retrospective.html b/woowacourse-level2-retrospective.html index 6e2316a0f..c2589c0cd 100644 --- a/woowacourse-level2-retrospective.html +++ b/woowacourse-level2-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

우아한테크코스 레벨 2 회고

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
+

우아한테크코스 레벨 2 회고

· 약 3분

23년의 6월이 오고, 레벨 2가 끝났다.
빠르게 지나가서 조금 아쉽다.

학습

회고를 작성하기 전에 레벨 2 동안 보냈던 PR과 회고를 쭉 읽어봤다.
항상 아쉬운 곳은 있기 마련이지만, 잘 학습한 것 같다.
미션을 하면서 기술을 어떻게 선택하고, 적용할 것인지 고민하는 과정에서 꽤나 많은 성장을 한 것 같다.

고민은 깊었지만 이론적인 학습이 부족한 레벨 2였다.
@@ -29,7 +29,7 @@ 이번에는 프런트엔드 크루와 협업을 했다. 소통은 잘 된 것 같지만 API 명세를 정하는 부분이 아직 미숙한 것 같다.

레벨 3 때부터 본격적으로 프로젝트가 시작된다.
팀을 위해 어떤 것을 할 수 있을지 고민을 많이 해봐야겠다.

레벨 2를 마무리하며

회고 작성하면서 레벨 2에서 했던 것들을 반추해 봤는데 부족한 점은 많았어도 좋은 방향으로 가고 있는 것 같다. 읽고 싶은 책도 읽고, 부족한 부분 채우면서 쉬어야겠다.

- - + + \ No newline at end of file diff --git a/woowacourse-level3-retrospective.html b/woowacourse-level3-retrospective.html index 5af019860..c7f1c20b0 100644 --- a/woowacourse-level3-retrospective.html +++ b/woowacourse-level3-retrospective.html @@ -13,12 +13,12 @@ - - + +
-

우아한테크코스 레벨 3 회고

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
+

우아한테크코스 레벨 3 회고

· 약 4분

회고

지난 8주는 레벨 1, 2 때보다 5배 정도 빠르게 지나간 것 같은 느낌이 들었다.
레벨 3에는 기술적인 부분에서도, 기술 외적인 부분에서도 부족함이 많이 보였던 것 같다.
부족한 부분을 알았기에, 앞으로 더욱 성장할 수 있을 것 같다.
내가 부족했던 부분을 팀원들이 잘 보충해 줘서 든든했다.

아쉬운 점

문서화

개인적으로는 기술 외적으로 학습한 부분을 잘 정리하지 못했다.
@@ -33,7 +33,7 @@ 아래의 D 부분은 유튜브 강의 들으면서 직접 만들어서 뿌듯하다.

기술 선택의 이유

기술의 학습 비용, 현재 구조에 적합한지, 실제 가지고 있는 리소스를 고려해서 기술 선택을 하고, 도입했던 부분이 좋았다.
100% 좋은 선택일 순 없지만, 그래도 선택에 대한 근거가 존재한다면 확률을 높혀주는 것 같다.

마치며

플레이스토어에 앱이 올라가 있는 거 너무 신기하다.
안드로이드 브레멘 음악대(멧돼지, 수달, 핑구), 그리고 백엔드 팀원들(체인저, 후추, 리오) 너무 고생이 많았다.

- - + + \ No newline at end of file