ํญํด99 6์ฃผ์ฐจ ํ๊ณ (WIL)
Q. ์ธ์๊น์๋ ์ฃผ์ ๋ ๋ฌด์์ด์๋์? ๋ถ์ฐ๋ฝ๊ณผ ์บ์ ์ ๋ต์ค ์ด๋ค ์ฃผ์ ๊ฐ ๋ ์ธ์๊น์๋์? ํญํด๋ฅผ ํ๊ธฐ์ ๋ ๋์ค๋ฅผ ์ฌ์ฉํด์์๋๋ JWT ํ ํฐ์ ๋๋ก๋ง ํด์์ต๋๋ค. Key value ๊ธฐ๋ฐ NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ธ ๋ ๋์ค๊ฐ ๋จ์ํ ์บ์ฑ์ ์ญํ ์ ํ์ง ์๊ณ Lock์ผ๋ก์์ ์ญํ ์ ํ ์ ์๋ค๋๊ฑธ ์ด๋ฒ๊ณผ์ ๋ฅผ ํตํด ์๋ก์๊ฒ๋์ต๋๋ค. ๋ํ ์ฝ๊ธฐ์ ์ฐ๊ธฐ์์์ ์บ์ฑ์ ๋ต์ด ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค๋๊ฑธ ์ฒ์์๊ฒ๋์ต๋๋ค. ํด๋น ๊ฐ๋ ์ ํตํด ์ด๋ค ๊ตฌ์กฐ์ /์ฑ๋ฅ์ ๋ฌธ์ ํด๊ฒฐ์ ๊ฐ๋ฅ์ฑ์ ๋๊ผ๋์? ์์ง๊น์ง๋ ๊ณผ์ ๋ฅผ ์ํํด๋ณด๋ฉด์ ์ด๋์ ์ด ๋ฌธ์ ์ธ์ง, ๊ทธ์ ๋ํ ํด๊ฒฐ์ ๋ฌด์์ธ์ง์ ๋ํ ๋ต๋ณ์ด ๋ช ํํ์ง ์์์ต๋๋ค. ๊ทธ๋๋ ๋ ์ค๋ฅด๋ ํ๊ฐ์ง๋ ์บ์ฑ์ชฝ์์๋ ํธ๋์ญ์ ์ ์ ๊ทผํ๊ธฐ์ ์ ์บ์์ ์ฅ์(redis)์์ ์บ์ํํธ๊ฐ๋๋ฉด ๋น ๋ฅธ ์๋ต์ ํด์ค ์ ์๋ค๋ ์ ์ ๋๋ค....
RDBMS ๋ฝ์ ์ฌ์ฉํ ๋์์ฑ๋ฌธ์ ํด๊ฒฐ
๋์์ฑ ๋ฌธ์ (RaceCondition) ์ฌ๋ฌ๊ฐ์ ์ค๋ ๋๊ฐ ๊ฐ์ ๊ณต์ ์์์ ๋ํด์ ๋์์ ์ฝ๊ธฐ/์ฐ๊ธฐ ์ ๊ทผ ์์ฒญํ ๋ ๊ณต์ ์์์ ๋ฐ์ดํฐ์ ์ ํฉ์ฑ์ด ๊นจ์ง๋ ํ์. ๋ฐ๋๋ฝ (DeadLock) 1 2 3 4 ํ์ฅํ๊ฐ๊ฒ ์๋ ๋ฆฝ๋ฐค 1๊ฐ, ์คํจ๋ก์ 1๊ฐ ๋ฅผ ํ๋งคํ๊ณ ์๋ค. - ์๋ A๊ฐ ๋ฆฝ๋ฐค 1๊ฐ๋ฅผ ์ง์๋ค. - ์๋ B๊ฐ ์คํจ๋ก์ 1๊ฐ๋ฅผ ์ง์๋ค. ์๋ A ๋ (B๊ฐ ์ง์) ์คํจ๋ก์ ์ ์ํ๊ณ , ์๋ B ๋ (A๊ฐ ์ง์) ๋ฆฝ๋ฐค์ ์ํ๋ค. ์๋ A์ ์ ์ฅ์์๋ ์๋B๊ฐ ์คํจ๋ก์ ์ ๋ด๋ ค๋์ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผํ๊ณ ์๋ B์ ์ ์ฅ์์๋ ์๋A๊ฐ ๋ฆฝ๋ฐค์ ๋ด๋ ค๋์ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผํ๋ค....
RDBMS(Mysql)์์์ ์ธ๋ฑ์ค ๊ฐ๋ ์ ๋ฆฌ
๋ง๋ฅ์ ์๋ค. TradeOff๋ ์๋ค. ์ฝ๊ธฐ ์ฑ๋ฅ์ด ์ข์ผ๋ฉด ์ฐ๊ธฐ์ฑ๋ฅ์ด ๊ตฌ๋ฆฌ๊ณ , ์ฐ๊ธฐ์ฑ๋ฅ์ด ์ข์ผ๋ฉด ์ฝ๊ธฐ์ฑ๋ฅ์ ๊ตฌ๋ ค์ง๋ค. ์ ๊ทํ ์ฐ๊ธฐ์ฑ๋ฅ์ ๋์์ผ๋ก์จ ๋ฐ์ดํฐ ์ค๋ณต์ ์ค์ด๊ณ ์ผ๊ด์ฑ์ ๋์ธ๋ค. ๋ฐ์ ๊ทํ ์ฝ๊ธฐ์ฑ๋ฅ์ ๋์์ผ๋ก์จ ์ผ๋ถ ์ค๋ณต์ ํ์ฉํ๋ค. ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ์์ค Uncommitted Read - ์ปค๋ฐ๋์ง ์์ ์ฝ๊ธฐ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ์ปค๋ฐ๋์ง ์์ ๋ฐ์ดํฐ์๋ ์ ๊ทผํ๊ฒ ํ ์ ์๋ ๊ฒฉ๋ฆฌ์์ค DirtyRead: ์ปค๋ฐ๋์ง ์์ ํธ๋์ญ์ ์ ์ ๊ทผํด์ ์์ง ์ ์๋ฐ์๋์ง ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ํ์ (ํด๋น ๋ฐ์ดํฐ๋ ๋กค๋ฐฑ๋์ด ์์ด์ง ์๋ ์๋ค) Committed Read - ์ปค๋ฐ๋ ์ฝ๊ธฐ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ์ปค๋ฐ๋ ๋ฐ์ดํฐ์๋ง ์ ๊ทผํ ์ ์๊ฒ ํ๋ ๊ฒฉ๋ฆฌ์์ค Non-Repeatable Read: ํ๋์ ํธ๋์ญ์ ์์ ๋์ผํ SELECT ์ฟผ๋ฆฌ๋ฌธ์ ์คํํ์ ๋ ์ปค๋ฐ์ ์ ๋ฐ์ดํฐ์ ์ปค๋ฐํ์ ๋ฐ์ดํฐ๊ฐ ์ฝํ๋ฉด์ ๋ค๋ฅธ๊ฒฐ๊ณผ๊ฐ ์๊ธฐ๋ ํ์ Repeatable Read - ๋ฐ๋ณต๊ฐ๋ฅํ ์ฝ๊ธฐ ์ปค๋ฐ๋ ๋ฐ์ดํฐ๋ง ์ฝ์ ์ ์์ผ๋ฉฐ, ์์ ๋ณด๋ค ๋นจ๋ฆฌ ์ํ๋ ํธ๋์ญ์ ์์ ์ปค๋ฐํ ๋ฐ์ดํฐ๋ง ์ฝ์ ์ ์๋ ๊ฒฉ๋ฆฌ ์์ค...
์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋
์๋ก ๋จ์ํ ์คํธ์ ๋ชฉ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค๋ ์์ฑ์๋ฅผ ํธ์ถํ๊ฒ๋์ด ์ฐ๊ด๊ด๊ณ๋ฅผ ๊ฐ๋ ๋๋ฉ์ธ์ setter๋ก ์ค์ ์์ผ์ ๋ชฉ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋๋ฐ ์ ์ ๋ฌด๊ฑฐ์์ง๋ ๋ถํธํจ์ ๊ฒช์์ต๋๋ค. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Test void ์ ๊ท_์์์์ฝ์ํ์_์์ฝ๋๋ฉ์ธ_์์ฑ์_์ฑ๊ณต๋๋ค() { // given long userId = 1L; long concertSeatId = 1L; User user = new User(userId, "์๊ฐ"); Concert concert = new Concert(1L, "ํญํด์ ํจ๊ปํ๋ TDD ๋จ์ํ ์คํธ ์ฝ์ํธ", "ํญํดํ๋ฌ์ค"); // ๐ ๋๋ฉ์ธ ์ํฐํฐ ์์ฑ์๋ฅผ ์ง์ ํธ์ถ!...
์ํคํ ์ณ ๊ณ ๋ฏผํ๊ธฐ
ERD ๊ฐ์ ํ๊ธฐ ๋ณด์ํผ๋๋ฐฑ1: ์ ์ ์ ํ ํฐ ํ ์ด๋ธ ๋ถ๋ฆฌํ๊ธฐ ๋ณด์ํผ๋๋ฐฑ2: ํ ์ด๋ธ์ ์ญํ ์ ๊ณ ๋ฏผํด์ ๋ง๋ค๊ธฐ payments ๋ผ๋ ์ํฐํฐ์ ๊ธ์ก์ ๋ณด๊ฐ ์์ด์ ์ฑ ์์ ๋คํ์ง ๋ชปํ ์ ์์. As-Is (1์ฐจ ์ค๊ณ) To-Be (2์ฐจ ์ค๊ณ) ํ ์ด๋ธ๊ฐ์๋ฅผ 6๊ฐ -> 8๊ฐ ๋ก ํ์ฅํ์ต๋๋ค. ํ ํฐ(tokens) ํ ์ด๋ธ ์ถ๊ฐ ํฌ์ธํธ ๋ด์ญ(point_histories) ํ ์ด๋ธ ์ถ๊ฐ payments ํ ์ด๋ธ์ ๊ฒฐ์ ๊ธ์ก(price) ๋ฅผ ์ถ๊ฐํ์ฌ ๊ฒฐ์ ์ ๋ํ ์ฑ ์์ ๋ถ์ฌํ์ต๋๋ค. 2์ฐจ ์ค๊ณ์ ๊ณ ๋ฏผํฌ์ธํธ 1๋ฒ์ ์ฐธ๊ณ ํ์ฌ, ๋ ์ง์์ ์์ฝ๊ฐ๋ฅ์ฌ๋ถ(is_available)์ ์ถ๊ฐํ์ต๋๋ค. ERD 2์ฐจ ์ค๊ณ์ ๊ณ ๋ฏผํฌ์ธํธ ๋๊ธฐ์ดํ ํฐ์ ๋๊ธฐ์์๋ฅผ ๋ํ๋ด๋ ค๋ฉด, ํ ํฐํ ์ด๋ธ์ ๋๊ธฐ์์๋ฅผ ๊ธฐ์ฌํ๋๊ฒ ์ข์๊น์ ์๋๋ฉด ๋๊ธฐ์ดํ๋ฅผ ํ๋์ ํ ์ด๋ธ๋ก ๋ํ๋ด์ด ๋๊ธฐ์์๋ฅผ ๊ธฐ์ฌํ๋๊ฒ ์ข์๊น์?...
ํญํด99 2์ฃผ์ฐจ ํ๊ณ (WIL)
๋ฉํ ๋งํ๋ฉด์ ๊นจ๋ฌ์ ์ ๊ฐ์ฒด์๊ฒ ์ฑ ์์ ๋ถ์ฌ์์ผ์ ๋ถ๋ฆฌ๋ฅผ ํ๋ค๋ฉด TDD ๋ ๊ฐ๋ฅํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๋์ ์ฝ๋ฉ์ํ๋ฉด์ API๋ฅผ ์ค๊ณํ๊ณ ๊ฐ๋ฐํ๋ค. ์ฝ๋ฉ์ผ๋ก ์ค๊ณ๋ฅผ ํ ์ ์๋ค ํ์ง๋ง ๊ฒฌ๊ณ ํ๊ฑฐ๋ ๋ช ํํ์ง ์์ ์ ์์ต๋๋ค. ๋ช ํํ ์ค๊ณ๊ฐ ๋ท๋ฐ์นจ๋๋ค๋ฉด ์ฝ๋ฉ์ ๋จ์ํ ๋ช ํํ ์ค๊ณ๋ฅผ ๊ตฌ์ฒดํํ๋ ์๋จ์ด ๋ ์ ์์ต๋๋ค. ๊ณผ์ ๋ฐ์ ์๊ฐ์ ๋ฐ์ ์ฝ์น์ธ ํ์ฌ๋์ด ๋ง์ํ์ ๋ถ๋ถ์ด ๊ธฐ์ต์ด ๋จ์ต๋๋ค. ์ค๊ณ๊ฐ ๋ช ํํ๋ฉด, โ์ฝ๋๋ฅผ ์น๋ ํ์โ ๋ ๋ชฉํ๋ฅผ ๋ฌ์ฑํ๋ โ์๋จโ ์ด ๋๋ค. ์ค๊ณ๊ฐ ๋ช ํํ์ง ์์ผ๋ฉด, โ์ฝ๋๋ฅผ ์น๋ ํ์โ ๋ ๋ถํ์ํ โ๋ ธ๋โ ์ด ๋๋ค....
SpringBoot์์ Swagger ๋์ ๋ถํฐ ํธ๋ฌ๋ธ์ํ ์ ๋ฐฐํฌ๊น์ง...(?)
์๋ก API๋ช ์ธ์๋ ํ๋ก ํธ์๋์ ๋ฐฑ์๋๊ฐ์ ํ์ ์ ์ํด์ ๊ฐ์ฅ ํ์ํ ๋๊ตฌ์ ๋๋ค. ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ API๋ฅผ ์ค๊ณํ๊ณ ๊ณต์ ํ ๋ API๋ช ์ธ์๋ฅผ ๋ง๋ญ๋๋ค. API ๋ช ์ธ์๋ฅผ ๋ค๋ฃจ๋ ๋ํ์ ์ธ ํด๋ก๋ Swagger๊ฐ ์์ต๋๋ค. ์ด๋ฒ์๋ Swagger ์ ๋์ ํ๋ ๊ณผ์ ๊ณผ ์ค๊ฐ์ ๊ฒช์ ํธ๋ฌ๋ธ์ํ ํด๊ฒฐ๊ณผ์ ๊ทธ๋ฆฌ๊ณ ๋๋์๊ฐ์ ์ง์ github-action์ผ๋ก ๋ฐฐํฌํ๋ ๊ณผ์ ์ ๊ณต์ ํด๋ณด๋๋กํ๊ฒ ์ต๋๋ค. ์คํ๋ง๋ถํธ์ ์ค์จ๊ฑฐ ๋์ ํ๊ธฐ Java: 17 SpringBoot: 3.4.4 build.gradle ์ ์ถ๊ฐํ๊ธฐ 1 2 3 4 5 6 7 dependencies { // Swagger UI implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' ...์๋ต... } application.yaml ์ ์ถ๊ฐํ๊ธฐ 1 2 3 4 5 6 7 8 9 10 11 spring: application: name: hhplus-concert ....
ํญํด99 1์ฃผ์ฐจ ํ๊ณ (WIL)
๋ฉํ ๋งํ๋ฉด์ ๊นจ๋ฌ์ ์ ํตํฉํ ์คํธ/์ ๋ํ ์คํธ ์ ๋ฒ์๋ ์ ํด์ ธ์์ง ์๋ค. ํตํฉํ ์คํธ์ ๋ํ ์ต์ ๊ธฐ์ค์ ๋ด๊ฐ ํธ์ถํ ์น๊ตฌ๊ฐ ํตํฉํ ์คํธ๋ก ๊ฒ์ฆ๋์ด์๋์ง ํ์ธ์ ํฉ๋๋ค. ๋จ์ํจ์๊ฐ ์๋ 2๊ฐ์ด์์ ํจ์๋ ์ธ๋ถ์์กด์ฑ์ด ์๋์ง e2e ๊ด์ ์ผ๋ก๋ ํตํฉํ ์คํธ๋ฅผ ํ ์ ์๋ค. ๋น๊ฐ๋ฐ์ ๋ฅผ ๋์์ผ๋ก ๋ด๋ถ๋์๋ณด๋ค๋ ํธ์ถํ์๋ ์ค์ง์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ํ ์คํธ๋ ๊ด์ฐฎ์ ํธ. ๊ฐ๊น์ด ๋์์ ํ ์คํธํ๋๊ฒ ์ข๋ค DTO์ ์ฅ์์๋ ์๋น์ค ๋ฉ์๋ํจ์ ํ๊ฐ๊ฐ ํตํฉํ ์คํธ๊ฐ ๋ ์๋ ์๋ค. ๋จ์ํ ์คํธ๋ ํ ์คํธ ๋์์ธ์๊ฒ๋ค์ (์๋น์ค์ ์์กด์ฑ์ ๋น๋กฏํ ํ ์คํธ ๋์์๋ ํด๋น๋์ง์์ง๋ง ์๋น์ค์ ์ฐ๊ฒฐ๋์ด์๋ ๋์๋ค์) Mocking ์ ํด์ผํ๋ค. ๊ฐ์ฒด์๊ฒ ์ฑ ์์ ๋ถ์ฌํ๋ฉด ๋ถํ์ํ ์ฝ๋๋ฅผ ์ ์ธํ ์ ์๋ค....
synchronized ์ ReentrantLock ์ ์ด๋ค ์ฐจ์ด์ ์ด ์์๊น?
๋์์ฑ์ ์ด๋ฅผ ํ ์คํธํ๋ ๊ฒ์ ๋จ์ํ ์คํธ์ ์ ํฉํ ๊น? ํตํฉํ ์คํธ์ ์ ํฉํ ๊น? JVM ๋ด์์ ๋์์ฑํ ์คํธ๋ฅผ ํ๋ ค๊ณ ํ๋ค๋ฉด, synchornized, ReentrantLock, JVM ๋ด ํ(queue)๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋์์ฑ์ ์ด๋ฅผ ํ ์คํธํ ๋ ํตํฉํ ์คํธ์์ ์คํํด์ผ๋๋๊ฑด์ง ์๋๋ฉด ์ ๋ํ ์คํธ์์ ํ ์คํธ๋ฅผ ํด์ผ๋ ์ง ์ ๋งคํ ๊ฒ๋๋ค. ๋จ์ํ ์คํธ๋ ๊ฐ์ฅ ์์ ํ ์คํธ์ธ๋งํผ 1๊ฐ ๋ฉ์๋/ํจ์ ๋จ์๋ก ๋ ๋ฆฝ์ ์ธ ๊ธฐ๋ฅ์ ๋น ๋ฅด๊ฒ ๊ฒ์ฆํ๊ธฐ ์ํ ํ ์คํธ์ ๋๋ค. ๋์์์ฒญ์ด ๋ฐ์ํ ๋ ํ๋ฅผ ์ด์ฉํด์ ์์๋ฅผ ์ ๊ณตํด์ฃผ๊ฑฐ๋ ์ ๊ธ(locking)์ฐ์ฐ์ ์ํํ์ฌ ๋ค๋ฅธ์์ฒญ์ด ์ ๊ทผํ์ง ๋ชปํ๋๋ก ๋ง๊ฑฐ๋, ํ๋ฅผ ์ด์ฉํด์ ์์๋ฅผ ๋ณด์ฅํด์ค์ผํ๋ ์ญํ ๊น์ง ๊ฒ์ฆ์ ํด์ผ๋๊ธฐ ๋๋ฌธ์ ๋จ์ํ ์คํธ๋ง์ผ๋ก๋ ์ด๋ ค์ธ๊ฑฐ๊ฐ์ต๋๋ค. ์ฆ, ๋์์ฑ์ ์ฌ๋ฌ๊ฐ์ ์ค๋ ๋๊ฐ ๋์์ ์ ๊ทผํ๊ฑฐ๋ ์คํ๋ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๊ฒ์ฆํด์ผํ๋ฏ๋ก, ๋จ์ผ ์ค๋ ๋ ํ๊ฒฝ์์ ์คํ๋๋ ๋จ์ํ ์คํธ๋ง์ผ๋ก๋ ๋์์ ์ธ ์ํฉ์ ์ฌํํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค....
๊ฐ์ฒด์ ์ฑ ์(๋๋ฉ์ธ ์ฃผ๋)
๋ชฉ์ UserPointService ์ ์ถฉ์ /์ฌ์ฉ ๋ฉ์๋๋ฅผ ๋ฆฌํฉํฐ๋งํ๋ค ์ ์ฐจ์งํฅ์ ์ธ ์ฝ๋๋ฅผ ๊ฐ์ฒด์งํฅ์ ์ผ๋ก ๋ณ๊ฒฝํด๋ณด์ ๋์๋๋ ์ฝ๋? ํฌ์ธํธ ์ถฉ์ ๋ก์ง ๊ฐ์ ์ํค๊ธฐ ์์ ์ด์ (์ ์ฐจ์งํฅ์ ) ํฌ์ธํธ ์ถฉ์ ๋ด๋ถ๋ก์ง ํ๋ก์ฐ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // PointServiceImpl.java @Service @RequiredArgsConstructor public class PointServiceImpl implements PointService { @Override public ChargeResponse charge(ChargeRequest request) { long id = request.id(); long amount = request.amount(); UserPoint userPoint = this....