๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend

    [Redis] M1 MacOS์—์„œ Docker Redis Cluster ์„ค์ •ํ•˜๊ธฐ + SpringBoot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํด๋Ÿฌ์Šคํ„ฐ ์—ฐ๊ฒฐํ•˜๊ธฐ

    [Redis] M1 MacOS์—์„œ Docker Redis Cluster ์„ค์ •ํ•˜๊ธฐ + SpringBoot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํด๋Ÿฌ์Šคํ„ฐ ์—ฐ๊ฒฐํ•˜๊ธฐ

    ๐Ÿค” ๊ฐœ์š” [Redis] Redis์˜ ๋ฐฑ์—…๊ณผ HA๋ฅผ ์œ„ํ•œ ์ „๋žต (RDB, AOF, Replication, Sentinel, Sharding, Cluster)๐Ÿ0. ์„œ๋ก  ํŒ€ ํ”„๋กœ์ ํŠธ์—์„œ Redis๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€, ์‹ ๊ธฐํ•œ ํ˜„์ƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค. ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋„์ปค๋ฅผ ํ†ตํ•ด ๋ ˆ๋””์Šค ์„œ๋ฒ„๋ฅผ ๋Œ๋ฆฌ๊ณ  ์žˆ์—ˆ๊ณ , JWT Refresh Token์„ ๋ ˆ๋””์Šค ์„œ๋ฒ„์— ์ €์žฅํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๋„hoons-dev.tistory.com ์ด์ „ ๊ธ€์„ ๋ณด๋ฉด, ๋ ˆ๋””์Šค์˜ ๋ฐฑ์—…๊ณผ ๊ณ ๊ฐ€์šฉ์„ฑ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ด์•ผ๊ธฐ๊ฐ€ ๋‹ด๊ฒจ์žˆ์Šต๋‹ˆ๋‹ค.Redis์˜ ๊ณ ๊ฐ€์šฉ์„ฑ์„ ์œ„ํ•ด์„œ Cluster๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘์—์„œ๋„ Docker Desktop for Mac์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ Redis-Cluster๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋„๋ก Docker-Compose ํŒŒ์ผ ๊ตฌ์„ฑ๊ณผ Sprin..

    [QueryDSL] QueryDSL-JPA : DTO Projection๊ณผ Transform

    [QueryDSL] QueryDSL-JPA : DTO Projection๊ณผ Transform

    QueryDSL์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์กฐํšŒ Query ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ• ์ค‘์— ํ•˜๋‚˜๋Š”, ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์•„๋‹Œ DTO๋กœ ๊ฐ’์„ ๋ฐ›์œผ๋ฉด ์†๋„ ํ–ฅ์ƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๊ทธ ์ด์œ ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€๋ฐ์š”. 1. ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์กฐํšŒํ•˜๋ฏ€๋กœ ๋‹น์—ฐํ•˜๊ฒŒ๋„ ์กฐํšŒ ์†๋„๊ฐ€ ์ฆ๊ฐ€ํ•œ๋‹ค.SQL์˜ SELECT๋ฌธ์„ ๋ณด๋ฉด, ํ•„์š”ํ•œ ์ปฌ๋Ÿผ๋งŒ ์–ป์–ด์˜ค๋Š” ๊ฒƒ์ด ํ…Œ์ด๋ธ” ์ „์ฒด๋ฅผ ์–ป์–ด์˜ค๋Š” ๊ฒƒ๋ณด๋‹ค ๋‹น์—ฐํ•˜๊ฒŒ๋„ ๋น ๋ฆ…๋‹ˆ๋‹ค. DTO๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์กฐํšŒํ•˜๋ ค๋Š” ์˜๋„๊ฐ€ ๋‚ดํฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ์•Š์Œ์œผ๋กœ์จ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 2. JPA์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๊ด€๋ฆฌ๋Œ€์ƒ์ด ์•„๋‹ˆ๋‹ค.์—”ํ‹ฐํ‹ฐ๋Š” JPA์˜ ๊ด€๋ฆฌ ๋Œ€์ƒ์ด๋ฏ€๋กœ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์˜ํ•ด ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ƒ๋Œ€์ ์œผ๋กœ ๋” ๋งŽ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๋ฐ˜๋ฉด DTO๋Š” ์ˆœ์ˆ˜ํ•œ..

    [QueryDSL] QueryDSL-JPA : JOIN ํ•˜๊ธฐ

    [QueryDSL] QueryDSL-JPA : JOIN ํ•˜๊ธฐ

    ๐Ÿ ํ™˜๊ฒฝ- QueryDSL 5.0.0- Spring Data JPA 3.1.2  ๐Ÿ’œ JOIN ์ข…๋ฅ˜1. INNER JOINJOIN ๋‹นํ•˜๋Š” ํ…Œ์ด๋ธ”์„ A, JOIN์„ ๊ฑฐ๋Š” ํ…Œ์ด๋ธ”์„ B๋ผ๊ณ  ํ•  ๋•Œ, A์™€ B ํ…Œ์ด๋ธ” ๋ชจ๋‘ JOIN์„ ํ•˜๋ ค๋Š” ๋Œ€์ƒ Key ์ปฌ๋Ÿผ์— ๋Œ€ํ•ด ๊ฐ’์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ๋งŒ JOIN์„ ํ•˜๋Š” ๊ฒƒ์„ INNER JOIN์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. queryDSL์—์„œ Inner join์„ ์“ฐ๋Š” ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.queryFactory์—์„œ select์™€ from์ ˆ ์ดํ›„์— join ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์ฝ”๋“œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. @Entity@Getter@Table(name = "neo_starpage")public class StarPage { @EmbeddedId @AttributeOverride(na..

    [QueryDSL] QueryDSL-JPA : @ElementCollection VO์— ๋Œ€ํ•œ JOIN

    [QueryDSL] QueryDSL-JPA : @ElementCollection VO์— ๋Œ€ํ•œ JOIN

    ๐Ÿ ํ™˜๊ฒฝ - QueryDSL 5.0.0 - Spring Data JPA 3.1.2 ๐Ÿค” ์‚ฌ์šฉ๋œ ๋„๋ฉ”์ธ ์ฝ”๋“œ ๐Ÿ’œ StarPage Aggregate Root @Entity @Getter @Table(name = "neo_starpage") public class StarPage { @EmbeddedId @AttributeOverride(name = "value", column = @Column(name = "star_page_id")) private StarPageId starPageId; @Embedded private StarPageInfo information; @ElementCollection @CollectionTable(name = "neo_starpage_admin", joinColumns = @..

    [Spring] Spring Security + OAuth2.0 + JWT Token์„ ํ™œ์šฉํ•œ ์†Œ์…œ๋กœ๊ทธ์ธ ์ด์ •๋ฆฌ - (1) ๋ฐฐ๊ฒฝ ์ง€์‹ ์ดํ•ดํ•˜๊ธฐ, ์ „์ฒด ๊ทธ๋ฆผ ์‚ดํŽด๋ณด๊ธฐ

    [Spring] Spring Security + OAuth2.0 + JWT Token์„ ํ™œ์šฉํ•œ ์†Œ์…œ๋กœ๊ทธ์ธ ์ด์ •๋ฆฌ - (1) ๋ฐฐ๊ฒฝ ์ง€์‹ ์ดํ•ดํ•˜๊ธฐ, ์ „์ฒด ๊ทธ๋ฆผ ์‚ดํŽด๋ณด๊ธฐ

    ๐Ÿ™‹๐Ÿป ์„œ๋ก  NEO ํ† ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์†Œ์…œ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐ๋„ท ์ƒ์˜ ๋งŽ์€ ๊ธ€์„ ์ฝ๊ณ , ๋„์›€์„ ๋งŽ์ด ๋ฐ›์•˜์œผ๋‚˜ ์ •๋ณด๊ฐ€ ํ•œ๋ฐ ๋ชจ์—ฌ์žˆ์ง€ ์•Š๊ณ  ๋ณธ์ธ์ด ๊ฐœ์ธ์ ์œผ๋กœ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„์ด ๋งŽ์•„ ๋‚˜์ค‘์— ๋‹ค์‹œ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•ด ๊ธ€๋กœ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ๋งˆ์Œ์„ ๋จน์—ˆ์Šต๋‹ˆ๋‹ค. ๋ถ€์กฑํ•œ ๋‚ด์šฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๋” ์ข‹์€ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€๋กœ ๋‹ฌ์•„์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ข‹์€ ํ”ผ๋“œ๋ฐฑ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜์ด๋ฉฐ, ์ œ ๊ธ€์ด ์†Œ์…œ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•˜๋ ค๋Š” ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ์ข‹์€ ๋„์›€์ด ๋˜์—ˆ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค. ๊ธ€์˜ ์ง„ํ–‰์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์ด์–ด์งˆ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. 1. ๋ฐฐ๊ฒฝ์ง€์‹ ์ดํ•ดํ•˜๊ธฐ, ์ „์ฒด ๊ทธ๋ฆผ ์‚ดํŽด๋ณด๊ธฐ (OAuth2, JWT Token, ํ”„๋กœ์ ํŠธ ์ „์ฒด ๋„์‹ํ™”) 2. Naver, Kakao, Google์— ํ”„๋กœ์ ํŠธ๋ฅผ OAuth2 Client๋กœ..

    [Spring] API ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Swagger ๋„์ž…ํ•˜๊ธฐ (gradle ๊ธฐ์ค€)

    [Spring] API ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Swagger ๋„์ž…ํ•˜๊ธฐ (gradle ๊ธฐ์ค€)

    ๋ณธ ๊ธ€์€, ํ•„์ž๊ฐ€ Swagger๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๊ณ„์†๋˜์–ด ์‚ฌ์šฉ๋ฒ•์ด ์—…๋ฐ์ดํŠธ ๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. - 2023.03.24 : Tag / Operation / ApiResponses / ApiResponse / Parameter - 2023.03.25 : @ControllerAdvice์—์„œ์˜ ์‚ฌ์šฉ, @Schema, @Schema์˜ hidden ์˜ต์…˜๊ณผ ๋ฌธ์ œ ํ•ด๊ฒฐ ๐Ÿ 0. ์„œ๋ก  ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ REST API๋ฅผ ์ž˜ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์€ ํ‰์ƒ์˜ ์ˆ™์›์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ž˜ ๋งŒ๋“  API์— ๋Œ€ํ•ด ์ž˜ ์ •๋ฆฌํ•œ ๋ฌธ์„œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ๊ฐœ๋ฐœ์ž์™€, ์ธ์ˆ˜์ธ๊ณ„๋ฅผ ๋ฐ›๊ฑฐ๋‚˜, ์‚ฌ๋‚ด API๋ฅผ ํ˜ธ์ถœํ•  EndPoint์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•ดํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๊ต‰์žฅํžˆ ์œ ํšจํ•œ ์ž์›์œผ๋กœ ๋‚จ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ํ•™์ƒ ๋•Œ๋Š”, API ๋ฌธ์„œ๋ฅผ ๋”ฐ๋กœ ์™ธ๋ถ€ ๋ฌธ์„œ๋กœ ์ž‘..

    [Spring] @Transactional๊ณผ DB Lock์— DeepDive - (1) DB ํŠธ๋žœ์žญ์…˜, ์‚ฌ์šฉ๋ฐฉ๋ฒ•, ๊ฒฉ๋ฆฌ์ˆ˜์ค€, ์ „ํŒŒ ๋‹จ๊ณ„ ํ›‘์–ด๋ณด๊ธฐ

    [Spring] @Transactional๊ณผ DB Lock์— DeepDive - (1) DB ํŠธ๋žœ์žญ์…˜, ์‚ฌ์šฉ๋ฐฉ๋ฒ•, ๊ฒฉ๋ฆฌ์ˆ˜์ค€, ์ „ํŒŒ ๋‹จ๊ณ„ ํ›‘์–ด๋ณด๊ธฐ

    ๐Ÿค” 0. DB ํŠธ๋žœ์žญ์…˜ ๋” ์ด์ƒ ์ชผ๊ฐค ์ˆ˜ ์—†๋Š” ์ตœ์†Œ ๋‹จ์œ„์˜ ์ž‘์—…์ด๋ผ๋Š” ๊ฐœ๋…์œผ๋กœ, commit()์„ ํ†ตํ•ด ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๋“ ์ง€ ์•„๋‹ˆ๋ฉด rollback()์„ ํ†ตํ•ด ๋ชจ๋‘ ์ทจ์†Œ๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—… ๋‹จ์œ„. ํŠธ๋žœ์žญ์…˜์€ DB์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ•˜๋‚˜์˜ ์ž‘์—… ๋‹จ์œ„์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ INSERT, UPDATE, DELETE ๋“ฑ์˜ SQL๋ฌธ์„ ์‹คํ–‰ํ•˜๋ฉด, ์ž๋™์œผ๋กœ ํ•œ ๋ผ์ธ๋งˆ๋‹ค ํŠธ๋žœ์žญ์…˜์ด ์ ์šฉ๋˜์–ด Commit์„ ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŠธ๋žœ์žญ์…˜์˜ ์˜์—ญ์„ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•ด, ํ•œ ํŠธ๋žœ์žญ์…˜ ์•ˆ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ช…๋ น๋ฌธ์„ ๋„ฃ๋„๋ก ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. START TRANSACTION; .... COMMIT; ํŠธ๋žœ์žญ์…˜์€ ์šฐ๋ฆฌ๋ง๋กœ '๊ฑฐ๋ž˜'๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, A์™€ B๊ฐ€ ๊ฑฐ๋ž˜๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ A๊ฐ€ B์—๊ฒŒ ๋ˆ์„ ์ž…๊ธˆ ํ–ˆ์œผ๋‚˜, B์—๊ฒŒ ์‚ฌ์ •์ด ์ƒ๊ฒจ ๋ฌผ๊ฑด์„ ๋ณด๋‚ด์ง€..

    [Spring] @ControllerAdvice์™€ @ExceptionHandler

    ๐Ÿค” 0. ๊ธฐ์กด์˜ Exception์„ ํ•ธ๋“ค๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ• Java Application์„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ, ๋งŽ์€ Exception์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ Exception์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ๋Œ€๋ถ€๋ถ„ ์•„์‹œ๋‹ค์‹œํ”ผ try-catch ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. try ๊ตฌ๋ฌธ ๋‚ด๋ถ€์—์„œ Exception์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๋ฌธ์žฅ์„ ์‹คํ–‰ํ•˜๊ณ , ํ•ด๋‹น try๋ฌธ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ Exception์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ๊ฐœ์˜ catch ๋ฌธ์„ ๋ถ™์—ฌ ํ•ธ๋“ค๋ง ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก , Exception์„ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, SpringBoot์—์„œ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ๋ช‡ ๊ฐ€์ง€ ๋ถˆํŽธํ•œ ์ ์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์—†๊ณ , ํ•ญ์ƒ try-catch ๋ธ”๋ก์œผ๋กœ ๋ฌถ์–ด์„œ ๊ฐœ๋ฐœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ •ํ™•ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํŒŒ์•…ํ•˜๋ ค๋ฉด, ์ด๋Ÿฌ..