[Nest.js] JWT๋ฅผ ์ด์šฉํ•œ ์ธ์ฆ, ์ธ๊ฐ€ ๊ทธ๋ฆฌ๊ณ  Multi part ์ด์•ผ๊ธฐ - โ‘ข Multer๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

2024. 1. 21. 00:59ใ†Back-End ์ž‘์—…์‹ค/Nest.js

728x90
๋ฐ˜์‘ํ˜•

 

 

 

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค

์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

qr.kakaopay.com

 

 

 

 

 

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."

 




๐Ÿ—‚ ๋ชฉ์ฐจ

โœ… [Nest.js] JWT๋ฅผ ์ด์šฉํ•œ ์ธ์ฆ, ์ธ๊ฐ€ ๊ทธ๋ฆฌ๊ณ  Multi part ์ด์•ผ๊ธฐ - โ‘  ์ดˆ๊ธฐ๊ตฌ์„ฑ
โœ… [Nest.js] JWT๋ฅผ ์ด์šฉํ•œ ์ธ์ฆ, ์ธ๊ฐ€ ๊ทธ๋ฆฌ๊ณ  Multi part ์ด์•ผ๊ธฐ - โ‘ก ํšŒ์›๊ฐ€์ž…๊ณผ ์ธ์ฆ(feat. Access Token & Refresh Token)
โœ… [Nest.js] JWT๋ฅผ ์ด์šฉํ•œ ์ธ์ฆ, ์ธ๊ฐ€ ๊ทธ๋ฆฌ๊ณ  Multi part ์ด์•ผ๊ธฐ - โ‘ข Multer๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
โœ… 

 

 

 

GitHub - junyharang/nestTs-jwt-multer: Nest.ts๋ฅผ ์ด์šฉํ•œ JWT ์ธ์ฆ, ์ธ๊ฐ€์™€ ํŒŒ์ผ ์ฒ˜๋ฆฌ ์—ฐ์Šต

Nest.ts๋ฅผ ์ด์šฉํ•œ JWT ์ธ์ฆ, ์ธ๊ฐ€์™€ ํŒŒ์ผ ์ฒ˜๋ฆฌ ์—ฐ์Šต. Contribute to junyharang/nestTs-jwt-multer development by creating an account on GitHub.

github.com

 

 

 

๐Ÿš€ Multi part๋ฅผ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

    ๐Ÿ”ฝ ๊ฐœ์š”

        ๐Ÿ“ฆ ์†Œ๊ฐœ

Multi part(๋ฉ€ํ‹ฐ ํŒŒํŠธ)๋Š” Client(ํด๋ผ์ด์–ธํŠธ)์™€ Server(์„œ๋ฒ„) ์‚ฌ์ด์— ์ „์†ก๋˜๋Š” HTTP Request(์š”์ฒญ) ๋˜๋Š” Response(์‘๋‹ต)์—์„œ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ Data(๋ฐ์ดํ„ฐ)๋ฅผ ๋™์‹œ์— ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ์‹์„ ์ด์•ผ๊ธฐํ•ด์š”.

์ผ๋ฐ˜์ ์œผ๋กœ File Upload(ํŒŒ์ผ ์—…๋กœ๋“œ)์™€ ๊ด€๋ จ๋œ ๋ฐ์ดํ„ฐ ์ „์†ก ๋•Œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์š”.

HTTP Protocol(ํ”„๋กœํ† ์ฝœ)์€ ๊ธฐ๋ณธ์ ์œผ๋กœ Text(๊ธ€์ž) ๊ธฐ๋ฐ˜์˜ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•ด์š”.
ํ•˜์ง€๋งŒ, ํŒŒ์ผ๊ณผ ๊ฐ™์€ Binary(์ด์ง„) ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์•ผ ํ•  ๋•Œ ์ด์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธ€์ž ํ˜•์‹์œผ๋กœ Encoding(์ธ์ฝ”๋”ฉ)ํ•˜๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ด๊ณ , ์ œํ•œ ์‚ฌํ•ญ์ด ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

๋ฉ€ํ‹ฐ ํŒŒํŠธ ์š”์ฒญ์€ Content-Type Header(ํ—ค๋”)์— multipart/form-data ๊ฐ’์„ ๊ฐ€์ง€๋ฉฐ, ์—ฌ๋Ÿฌ๊ฐœ์˜ Part(ํŒŒํŠธ)๋กœ ๊ตฌ์„ฑ๋ผ์š”.
๊ฐ ํŒŒํŠธ๋Š” ๊ฐœ๋ณ„์ ์ธ ๋ฐ์ดํ„ฐ ์กฐ๊ฐ์œผ๋กœ ํŒŒ์ผ์ด๋‚˜, ๊ธ€์ž ๋ฐ์ดํ„ฐ ๋“ฑ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์–ด์š”.
๋˜ํ•œ, ๊ฐ ํŒŒํŠธ๋Š” ํ—ค๋”์™€ Body(๋ณธ๋ฌธ)์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ, ํ—ค๋”์—๋Š” ํŒŒํŠธ์˜ Meta data(๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ)๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ณ , ๋ณธ๋ฌธ์—๋Š” ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๋ฐฉ์‹์ด์—์š”.

๋ฉ€ํ‹ฐ ํŒŒํŠธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„œ๋ฒ„ ์ธก์—์„œ ๋ฉ€ํ‹ฐ ํŒŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ Parsing(ํŒŒ์‹ฑ)ํ•˜๋Š” Logic(๋กœ์ง)์ด ํ•„์š”ํ•ด์š”.
์ผ๋ฐ˜์ ์œผ๋กœ ๋ฉ€ํ‹ฐ ํŒŒํŠธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” Library(๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)๋‚˜, Framework(ํ”„๋ ˆ์ž„์›Œํฌ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ€ํ‹ฐ ํŒŒํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๊ณ , ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ต๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ Spring MVC์—์„œ๋Š” MultipartResolver๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ€ํ‹ฐ ํŒŒํŠธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์–ด์š”.

์ฃผ๋‹ˆ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•ด์„œ ๋ฉ€ํ‹ฐ ํŒŒํŠธ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.
์ตœ์ดˆ ๋‹จ์ผ ํŒŒ์ผ ์ฒ˜๋ฆฌ๋Š” Router(๋ผ์šฐํ„ฐ) Handler(ํ•ธ๋“ค๋Ÿฌ)์— Decorator(๋ฐ์ฝ”๋ ˆ์ดํ„ฐ)๋ฅผ ์ด์šฉํ•ด์„œ Option(์˜ต์…˜)์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ๋ณผ ๊ฒƒ์ด๊ณ ,

๋‘๋ฒˆ์งธ ๋‹ค์ˆ˜์˜ ํŒŒ์ผ ์ฒ˜๋ฆฌ๋Š” multer.options ๋ผ๋Š” ์˜ต์…˜ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๊ณตํ†ต์ ์œผ๋กœ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.

 

 

 

NestJS๋กœ ๋ฐฐ์šฐ๋Š” ๋ฐฑ์—”๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ:ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์˜ ์ฐจ์„ธ๋Œ€ ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋‚˜๋‹ค

COUPANG

www.coupang.com

 

 

 

 

    ๐Ÿ”ฝ ๋‹จ์ผ ํŒŒ์ผ ์ฒ˜๋ฆฌ

        ๐Ÿ“ฆ Entity

src/api/common/file/model/entity/file.entity.ts
src/api/common/file/model/entity/file.entity.ts


Entity๋Š” ๋ชจ๋“  ๋ฉ€ํ‹ฐ ํŒŒํŠธ๋ฅผ ํ†ตํ•ด ๋“ค์–ด์˜ค๋Š” File(ํŒŒ์ผ) ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.
์‚ฌ์‹ค ์ด๋ ‡๊ฒŒ ๋‹ค Database(๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค)์— ์ €์žฅํ•  ํ•„์š”๋Š” ์—†๊ณ , ๊ณ ์œ  ๋ฒˆํ˜ธ(ID)์™€ image url๋งŒ ์ฒ˜๋ฆฌํ•ด๋„ ๋˜๋ฉฐ, ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์›๋ณธ ํŒŒ์ผ ์ด๋ฆ„๊ณผ ์žฌ ๊ตฌ์„ฑ๋œ ํŒŒ์ผ ์ด๋ฆ„ ์ •๋ณด๋งŒ ์ฒ˜๋ฆฌํ•ด๋„ ๋ฌด๋ฐฉํ•˜์ง€๋งŒ, ์ฃผ๋‹ˆ๋Š” ์‹ค์Šต์„ ์œ„ํ•ด ์œ„์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

 

 

 

        ๐Ÿ“ฆ Controller

src/api/common/file/controller/file.controller.ts
src/api/common/file/controller/file.controller.ts


๋ผ์šฐํ„ฐ ํ•ธ๋“ค๋Ÿฌ์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด ๋ณผ๊ฒŒ์š”.
์ตœ์ดˆ ํ•ด๋‹น ํด๋ž˜์Šค์˜ URN Prifix๋Š” file๋กœ ์ •์˜ํ•ด ์ฃผ์—ˆ์–ด์š”.


๊ทธ๋ ‡๋‹ค๋ฉด http://localhost:8181/file ๋กœ ์ •์˜๊ฐ€ ๋  ๊ฑฐ์—์š”.

16๋ฒˆ์งธ ์ค„์— ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด FileService๋ฅผ ์ฃผ์ž… ๋ฐ›๋Š”๋ฐ, ์ฃผ๋‹ˆ๋Š” SOLID 5์›์น™ ์ค€์ˆ˜๋ฅผ ์œ„ํ•ด Interface(์ธํ„ฐํŽ˜์ด์Šค)์™€ Implementation(๊ตฌํ˜„์ฒด)๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ๋งŒ๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์ด ์ฃผ์ž…ํ•˜์—ฌ ์ฃผ์—ˆ์–ด์š”.

18, 21๋ฒˆ์งธ ์ค„์€ Swagger(์Šค์›จ๊ฑฐ) ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋กœ 18 ~ 20๋ฒˆ์งธ ์ค„ ๋‚ด์šฉ์€ ์Šค์›จ๊ฑฐ ๋ฌธ์„œ์—์„œ API์˜ ์š”์•ฝ ์ •๋ณด ์ œ๊ณต์„ ์œ„ํ•˜์—ฌ ์ž‘์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋ฆฌ๊ณ , 21 ~ 24๋ฒˆ์งธ ์ค„์— ๋‚ด์šฉ์€ ๋กœ์ง์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๋˜์—ˆ์„ ๋•Œ, ์„ฑ๊ณต์— ๋Œ€ํ•œ Response(์‘๋‹ต)์„ ์–ด๋–ป๊ฒŒ ๋‚ด๋ ค์ค„ ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๋Š” ๋ถ€๋ถ„์ด๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ํŒŒ์ผ ์—…๋กœ๋“œ ์„ฑ๊ณต์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ์‘๋‹ต ํ˜•์‹์„ ์ •์˜ํ•ด ์ฃผ์—ˆ์–ด์š”.

25๋ฒˆ์งธ ์ค„์€ REST API ํ˜•์‹์„ ์œ„ํ•ด HTTP POST Method๋กœ Endpoint URN์„ /uploads/image๋กœ ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.
์ด๋ ‡๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” http://localhost:8181/file/uploads/image๋ผ๋Š” URL๋กœ POST ์š”์ฒญ์„ ๋ณด๋‚ด์ค˜์•ผ ํ•ด์š”.

26 ~ 39๋ฒˆ์งธ ์ค„ ๊นŒ์ง€๊ฐ€ ๋ฉ€ํ‹ฐ ํŒŒํŠธ๋ฅผ ์œ„ํ•œ ์„ค์ • ๋ถ€๋ถ„์ด์—์š”.
26๋ฒˆ์งธ ์ค„์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” NestJS์—์„œ Interceptor(์ธํ„ฐ์…‰ํ„ฐ)๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ์ ์šฉํ•˜๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์—์š”.
์—ฌ๊ธฐ์„œ๋Š” FileInterceptor๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Image File(์ด๋ฏธ์ง€ ํŒŒ์ผ)์„ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ, ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด diskStorage๋ฅผ ๊ตฌ์„ฑํ•˜๋„๋ก ๋งŒ๋“  ๋ถ€๋ถ„์ด์—์š”.

27 ~ 38๋ฒˆ์งธ ์ค„์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด ๋ณด๋ฉด FileInterceptor๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์ •์˜ํ•œ ๋ถ€๋ถ„์ด๊ณ , fieldName ์ฆ‰, ์ฒซ๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์˜ Field(ํ•„๋“œ) ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด ์ฃผ๋Š” ๋ถ€๋ถ„์ด์—์š”.

๋‘๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜ localOptions์— storage ์†์„ฑ์€ ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์˜ ์ €์žฅ์†Œ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ถ€๋ถ„์ด๊ณ , ์ฃผ๋‹ˆ๋Š” Disk Storage(๋””์Šคํฌ ์Šคํ† ๋ฆฌ์ง€)๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๊ณ  ์ •์˜ํ•ด ์ฃผ์—ˆ๊ณ , ํŒŒ์ผ์€ ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ๋‚ด์— ./local/storage/images ๊ฒฝ๋กœ๋กœ ์ง€์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.

30๋ฒˆ์งธ ์ค„ filename()์€ ๊ฐ ํŒŒ์ผ์— ๋Œ€ํ•œ ๊ณ ์œ  ์ด๋ฆ„์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋ถ€๋ถ„์ด๊ณ , ์ฃผ๋‹ˆ๋Š” Random(๋žœ๋ค)์œผ๋กœ 32์ž์˜ ์ž„์˜์˜ ๋ฌธ์ž์—ด๊ณผ ์—…๋กœ๋“œ๋œ ํŒŒ์ผ ์›๋ณธ ์ด๋ฆ„์˜ ํ™•์žฅ์ž๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๋งŒ๋“ค๋„๋ก ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

40 ~ 42๋ฒˆ์งธ ์ค„์ด ๋ณธ๊ฒฉ์ ์ธ ํ•ธ๋“ค๋Ÿฌ ์ •์˜ ๋ถ€๋ถ„์ธ๋ฐ, ์—ฌ๊ธฐ์„œ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ @UploadedFile()์€ ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์ •์˜ํ•œ ๋ถ€๋ถ„์ด๊ณ , Express.Multer.File์€ ์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ์ •์˜ํ•ด ์ค€ ๋ถ€๋ถ„์ด์—์š”.

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ํ•ธ๋“ค๋Ÿฌ๋Š” fileService.uploadImage()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฒฐ๊ณผ๋กœ Promise๋กœ Wrapping(๋ž˜ํ•‘)๋œ DefaultResponse ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

์ •๋ฆฌํ•˜๋ฉด ํ•ด๋‹น ํ•ธ๋“ค๋Ÿฌ๋Š” ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ง„ ํ•ธ๋“ค๋Ÿฌ์ด๊ณ , ๋žœ๋คํ•œ ํŒŒ์ผ ์ด๋ฆ„ ์ƒ์„ฑ, ๋””์Šคํฌ ์Šคํ† ๋ฆฌ์ง€ ์„ค์ •, ์Šค์›จ๊ฑฐ ๋ฌธ์„œํ™” ๋“ฑ์„ ํ†ตํ•ด ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ €์žฅ์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ์„ ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ์—์š”.

 

 

        ๐Ÿ“ฆ Service

Service ๋กœ์ง์˜ ์ธํ„ฐํŽ˜์ด์Šค ์ฝ”๋“œ ๋ถ€๋ถ„์€ ์บก์ณํ•˜์ง€ ์•Š์„๊ฒŒ์š”.
์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ฃผ๋‹ˆ์˜ ๊นƒํ—™์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์–ด์š”.

 

GitHub - junyharang/nestTs-jwt-multer: Nest.ts๋ฅผ ์ด์šฉํ•œ JWT ์ธ์ฆ, ์ธ๊ฐ€์™€ ํŒŒ์ผ ์ฒ˜๋ฆฌ ์—ฐ์Šต

Nest.ts๋ฅผ ์ด์šฉํ•œ JWT ์ธ์ฆ, ์ธ๊ฐ€์™€ ํŒŒ์ผ ์ฒ˜๋ฆฌ ์—ฐ์Šต. Contribute to junyharang/nestTs-jwt-multer development by creating an account on GitHub.

github.com

 

src/api/common/file/service/file.service-impl.ts


Business Logic(๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง)์€ ์œ„์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

์ตœ์ดˆ 13๋ฒˆ์งธ ์ค„ ์ƒ์„ฑ์ž์—์„œ TypeORM์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด fileRepository๋ฅผ ์ฃผ์ž… ์‹œ์ผœ ์ฃผ์—ˆ์–ด์š”.

uploadImage()๋Š” ๋ฉ€ํ‹ฐ ํŒŒํŠธ๋ฅผ ์ด์šฉํ•ด ์ „๋‹ฌ๋œ ํŒŒ์ผ์„ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ๋ฐ›๊ฒŒ ๋˜๊ณ , ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚œ ๋’ค DefaultResponse ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜๋˜๋Š”๋ฐ, ์ด ๋•Œ, data Type์œผ๋กœ ์ €์žฅ๋œ ์ด๋ฏธ์ง€์˜ ๊ณ ์œ ๋ฒˆํ˜ธ์™€ URL์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•ด ์ฃผ์—ˆ์–ด์š”.

๋™๊ธฐ์‹ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— async - await์ด ์‚ฌ์šฉ๋˜์—ˆ๊ณ , ์ด ๋•Œ๋ฌธ์— Promise<>๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ด์ฃผ์—ˆ์–ด์š”.

16๋ฒˆ์งธ ์ค„์€ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋œ ํŒŒ์ผ์ด Null์ธ์ง€ ํ™•์ธํ•˜๊ณ  ์žˆ์–ด์š”.

Null์ด ์•„๋‹ˆ๋ผ๋ฉด TypeORM์˜ save()๋ฅผ ์ด์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š”๋ฐ, ๋ฉ€ํ‹ฐ ํŒŒํŠธ๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ชจ๋“  ๋‚ด์šฉ์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•ด ์ฃผ์—ˆ์–ด์š”.

์ฐธ๊ณ ๋กœ 30๋ฒˆ์งธ ์ค„์— URL์€ configuration()์„ ์ด์šฉํ•˜์—ฌ .env.yml์— ์„œ๋ฒ„ URL ๊ฐ’๊ณผ PORT ๋ฒˆํ˜ธ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์ €์žฅ ์ „ ์ „๋‹ฌ๋œ ํŒŒ์ผ ์ •๋ณด๋ฅผ Entity๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด 21๋ฒˆ์งธ ์ค„๊ณผ ๊ฐ™์ด ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ฐ๊ฐ์˜ ๋‚ด์šฉ์„ ๋„ฃ๊ณ , ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ค€ ๋’ค ์ด Entity๋ฅผ save()์—๊ฒŒ ์ „๋‹ฌํ•˜์—ฌ ์ €์žฅ๋  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•ด ์ค€ ๋ถ€๋ถ„์ด์—์š”.

๊ทธ๋Ÿฐ๋’ค 34 ~ 37๋ฒˆ์งธ์™€ ๊ฐ™์ด ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด imageContent๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ์•ˆ์— ์ด๋ฏธ์ง€ ๊ณ ์œ ๋ฒˆํ˜ธ์™€ URL์ด ์‹๋ณ„ ๊ฐ€๋Šฅํ•˜๊ฒŒ Key - Value ํ˜•ํƒœ๋กœ ๋„ฃ์–ด์ฃผ๊ณ , ์ด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

 

 

 

        ๐Ÿ“ฆ Module

src/api/common/file/module/file.module.ts


Module(๋ชจ๋“ˆ)์€ ์œ„์™€ ๊ฐ™์ด ์ปจํŠธ๋กค๋Ÿฌ์™€ ์„œ๋น„์Šค๋ฅผ ์ •์˜ํ•ด ์ฃผ์—ˆ๊ณ ,
TypeORM์— Entity๋ฅผ File๋กœ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.

src/app.module.ts


๊ทธ๋ฆฌ๊ณ  app.module์— ์œ„์™€ ๊ฐ™์ด FileModule์„ ์ •์˜ํ•ด ์ฃผ์—ˆ์–ด์š”.

 

 

 

 

    ๐Ÿ”ฝ ์ž˜ ๋งŒ๋“ค์—ˆ๋‚˜? ๐Ÿค”

        ๐Ÿ“ฆ Postman

์œ„์˜ ๋กœ์ง์ด ์ •์ƒ ๊ตฌ๋™๋˜๋Š”์ง€ Postman์„ ์ด์šฉํ•˜์—ฌ ํ™•์ธํ•ด ๋ณผ๊ฒŒ์š”.

Postman


์œ„์™€ ๊ฐ™์ด HTTP Request Body์— image๋ผ๋Š” Key๋กœ Value๋ฅผ ์ด๋ฏธ์ง€ ํŒŒ์ผ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

Disk Storage

์‹ค์ œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์€ ์ง€์ •ํ•ด ์ค€ ๊ฒฝ๋กœ์— ์ž˜ ์ €์žฅ๋œ ๊ฒƒ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


Database


๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๋„ ๊ฐ’์ด ์ž˜ ์ €์žฅ๋œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


 

 

 

 

    ๐Ÿ”ฝ  ๋‹ค์ค‘ ํŒŒ์ผ ์ฒ˜๋ฆฌ

        ๐Ÿ“ฆ Controller

์ด๋ฒˆ์—๋Š” ์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ํ•œ๋ฒˆ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์–ด ๋ณผ๊ฒŒ์š”.
์œ„์—์„œ๋„ ์ด์•ผ๊ธฐ ํ–ˆ๋“ฏ ์ด๋ฒˆ์—๋Š” ์˜ต์…˜ ์ฒ˜๋ฆฌ๋ฅผ ๊ณตํ†ต์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๊ตฌ์„ฑํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.

src/api/common/file/controller/file.controller.ts


๋‹จ์ผ ํŒŒ์ผ ์ฒ˜๋ฆฌ ํ•ธ๋“ค๋Ÿฌ๋ณด๋‹ค ์ฝ”๋“œ ๊ธธ์ด๊ฐ€ ๋งŽ์ด ์งง์€๊ฑธ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.
๊ทธ ์ด์œ ๋Š” ๋ฐ”๋กœ 52๋ฒˆ์งธ ์ค„์— multerDiskOptions ๋•๋ถ„์ด์—์š”.

๋‹จ์ผ ํŒŒ์ผ ์ฒ˜๋ฆฌ์™€ ๋‹ค๋ฅธ์ ์€ 52๋ฒˆ์งธ ์ค„์— FilesInterceptor์˜ fieldName์ด images ์ด๊ธฐ ๋•Œ๋ฌธ์— HTTP Request Body์— Key ์ด๋ฆ„์„ image๊ฐ€ ์•„๋‹Œ images๋กœ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด์—์š”.

๋˜ํ•œ, ์ด ํ•ธ๋“ค๋Ÿฌ๋Š” ์—ฌ๋Ÿฌ๊ฑด์˜ ํŒŒ์ผ์„ ๋ฐ›์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค๊ฐœ ๋ณ€์ˆ˜ ์ž๋ฃŒํ˜• ํƒ€์ž…์ด Array๋กœ ๊ฐ์‹ธ์ ธ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

52๋ฒˆ์งธ ์ค„์—์„œ FilesInterceptor(...)๋Š” ๋‹ค์ค‘ ํŒŒ์ผ ์—…๋กœ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์ •์˜ํ•œ ๋ถ€๋ถ„์œผ๋กœ images ๋ฌธ์ž์—ด์€ ์—…๋กœ๋“œ๋œ ํŒŒ์ผ๋“ค์˜ ํ•„๋“œ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถ€๋ถ„์ด๊ณ , multerDiskOptions๋Š” ๋ฐ‘์—์„œ ์ด์•ผ๊ธฐํ•  Options ์—์„œ ๋งŒ๋“  multerDiskOptions ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ •์˜ํ•ด ์ค€ ๋ถ€๋ถ„์ด์—์š”.

๊ทธ๋ฆฌ๊ณ , 53๋ฒˆ์งธ ์ค„ ๋‚ด์šฉ์€ uploadImages()์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ํŒŒ์ผ ์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€๋“ค์„ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ ์œ„ํ•ด ๋ช…์‹œํ•œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์—์š”.

54๋ฒˆ์งธ ์ค„ ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋‚ด์šฉ์€ ์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€ ํŒŒ์ผ๋“ค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด ์ค€ ๋ถ€๋ถ„์ด์—์š”.

 

 

        ๐Ÿ“ฆ Options

src/api/common/file/config/multer.options.ts

728x90

src/api/common/file/config/multer.options.ts


์ด ๋ถ€๋ถ„์ด ํŒŒ์ผ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•ด ๊ณตํ†ต์œผ๋กœ ์ •์˜ํ•  ์‚ฌํ•ญ์„ ๋ชจ์•„๋‘๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ์ด์—์š”.
multerDiskOptions{}๋Š” ๋ฉ€ํ‹ฐ ํŒŒํŠธ๋ฅผ ์ด์šฉํ• ๋•Œ, ๋””์Šคํฌ์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์˜ต์…˜์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ผ์š”.

ํ•ด๋‹น ์˜ต์…˜์€ MemoryOption๋„ ์กด์žฌํ•˜๋Š”๋ฐ, ์ด๋Š” ํŒŒ์ผ์„ ๋””์Šคํฌ ์ฆ‰, ๋ณด์กฐ ๊ธฐ์–ต ์žฅ์น˜๊ฐ€ ์•„๋‹Œ RAM(๋žจ) ์ฃผ ๊ธฐ์–ต ์žฅ์น˜์— ์ €์žฅํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”.

์ฃผ ๊ธฐ์–ต ์žฅ์น˜์— ์ด๋ฏธ์ง€ ์ €์žฅํ•  ์ผ์ด ์žˆ์„๊นŒ ์‹ถ์–ด ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋Š” ์‹ค์Šตํ•˜์ง€ ์•Š๋„๋ก ํ• ๊ฒŒ์š”.

๋ณธ๊ฒฉ์ ์œผ๋กœ ์œ„ ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.

์ด ์ฝ”๋“œ๋Š” multer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ ์—…๋กœ๋“œ ์‹œ ํ•„์š”ํ•œ ๋‹ค์–‘ํ•œ ์„ค์ •์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์ฃผ๋กœ File filter(ํŒŒ์ผ ํ•„ํ„ฐ), ์ €์žฅ์†Œ(destination ๋ฐ ํŒŒ์ผ ์ด๋ฆ„ ์„ค์ •), ์—…๋กœ๋“œ ์ œํ•œ ์‚ฌํ•ญ(limits)๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด์—์š”.

์ตœ์ดˆ 7๋ฒˆ์งธ ์ค„์— fileFilter()๋Š” ์—…๋กœ๋“œ ๋˜๋Š” ํŒŒ์ผ์˜ ํ•„ํ„ฐ๋ง์„ ๋‹ด๋‹นํ•˜๋Š” ํ•จ์ˆ˜์—์š”.
์ด ์ฝ”๋“œ์—์„œ๋Š” ์ด๋ฏธ์ง€ ํ™•์žฅ์ž๋กœ .jpg, .jpeg, .png ํ™•์žฅ์ž๋งŒ ํ—ˆ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.
๋งŒ์•ฝ ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ํŒŒ์ผ ํ˜•์‹์ด ์—…๋กœ๋“œ ์š”์ฒญ์ด ์˜ค๋ฉด HttpException์„ ํ„ฐํŠธ๋ ค Client(ํด๋ผ์ด์–ธํŠธ)์—๊ฒŒ ๋ฐ˜ํ™˜๋  ๊ฑฐ์—์š”.

25๋ฒˆ์งธ ์ค„ storage๋Š” diskStorage()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒ์ผ์˜ ์ €์žฅ์†Œ(destination)์™€ ํŒŒ์ผ ์ด๋ฆ„(filename)์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”.

destination()์€ ํŒŒ์ผ์ด ์ €์žฅ๋  ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•˜๋Š”๋ฐ, 29๋ฒˆ์งธ ์ค„์— ํ•ด๋‹น ๊ฒฝ๋กœ์— ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ํ˜„์žฌ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์—†์œผ๋ฉด 31๋ฒˆ์งธ ์ค„์„ ํ†ตํ•ด ๊ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ๋“ค์„ ์ƒ์„ฑํ•ด ์ฃผ๋„๋ก ์„ค์ •ํ•ด ์ฃผ์—ˆ์–ด์š”.

filename()์€ ์—…๋กœ๋“œ ์š”์ฒญ์— ๋Œ€ํ•œ ํŒŒ์ผ์˜ ์ด๋ฆ„์„ ์„ค์ •ํ•˜๋Š” ๋ถ€๋ถ„์ด์—์š”. ์—ฌ๊ธฐ์„œ๋Š” ํ˜„์žฌ ์‹œ๊ฐ„(timestamp)๊ณผ ์—…๋กœ๋“œ ์š”์ฒญ๋œ ํŒŒ์ผ์˜ ์›๋ณธ ์ด๋ฆ„์˜ ํ™•์žฅ์ž๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ด๋ฆ„์„ ๋งŒ๋“ค๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

limits ๊ฐ์ฒด๋Š” ์—…๋กœ๋“œ๋  ํŒŒ์ผ ๊ด€๋ จ ์ œํ•œ ์‚ฌํ•ญ์„ ์„ค์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด์—์š”.

์ด      ๋ฆ„ ์„ค       ๋ช…
fieldNameSize Field ์ด๋ฆ„์˜ ์ตœ๋Œ€ ํฌ๊ธฐ ์„ค์ • (๊ธฐ๋ณธ๊ฐ’ 100 bytes)
fieldSize Field Size ์ตœ๋Œ€๊ฐ’ (๊ธฐ๋ณธ๊ฐ’ 1MB)
fields File ํ˜•์‹์ด ์•„๋‹Œ Field์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’ ๋ฌด์ œํ•œ)
fileSize Multipart ํ˜•์‹ Form์˜ ์ตœ๋Œ€ ์šฉ๋Ÿ‰. (๊ธฐ๋ณธ๊ฐ’ ๋ฌด์ œํ•œ) ์ฆ‰, ํŒŒ์ผ์˜ ํ—ˆ์šฉ ํฌ๊ธฐ ์„ค์ •.
files Multipart ํ˜•์‹ Form์˜ File Field ์ตœ๋Œ€ ํ—ˆ์šฉ ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’ ๋ฌด์ œํ•œ)
๋ฐ˜์‘ํ˜•


์œ„์™€ ๊ฐ™์ด ์„ค์ •๋œ multerDiskOptions ๊ฐ์ฒด๋Š” NestJS์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ํ•ธ๋“ค๋Ÿฌ์—์„œ FileInterceptor ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋ช…์‹œํ•ด ์ฃผ๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋Ÿฌํ•œ ์„ค์ •์„ ํ†ตํ•ด ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์˜ ํ˜•์‹, ๊ฒฝ๋กœ, ์ด๋ฆ„ ๋ฐ ์ œํ•œ ์‚ฌํ•ญ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

 

 

        ๐Ÿ“ฆ Service

src/api/common/file/service/file.service-impl.ts


๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด ๋ณผ๊ฒŒ์š”.

์ตœ์ดˆ 43๋ฒˆ์งธ ์ค„์—์„œ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋œ ํŒŒ์ผ์˜ ๋ฐฐ์—ด์ด Null์ด๊ฑฐ๋‚˜, ๊ธธ์ด๊ฐ€ 0์ธ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  ์žˆ์–ด์š”.
์•„๋‹ˆ๋ผ๋ฉด result๋ผ๋Š” ๋ฐฐ์—ด์„ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ์ค€ ๋’ค ํ–ฅ์ƒ๋œ For ๋ฌธ์„ ํ†ตํ•ด images์˜ ์š”์†Œ ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด๋ฉด์„œ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๊ฒŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.

50๋ฒˆ์งธ ์ค„์—์„œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด TypeORM์˜ save()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ new ์—ฐ์‚ฐ์ž๋กœ File ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•œ ๋‹ค์Œ ์ €์žฅํ•  ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ ๊ฐ๊ฐ ๋„ฃ์–ด ๊ฐ์ฒดํ™” ํ•ด ์ฃผ๊ณ , Entity ๊ฐ์ฒด๋ฅผ save()์— ๋„ฃ์–ด ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๊ฒŒ ํ•ด ์ค€ ๋’ค ์ €์žฅ๋œ ๊ฒฐ๊ณผ๋ฅผ saveFile์— ๋‹ด๊ธฐ๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋Ÿฐ ๋’ค 64๋ฒˆ์งธ ์ค„์—์„œ ํ•ด๋‹น saveFile ๊ฐ์ฒด์— ๋‹ด๊ธด Entity๊ฐ€ Null์ธ์ง€ ํ™•์ธํ•ด ์ฃผ๊ณ , ์•„๋‹ˆ๋ผ๋ฉด imageContent๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ด๋ฏธ์ง€ ๊ณ ์œ ๋ฒˆํ˜ธ์™€ URL์„ ์‹๋ณ„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ •์˜ํ•˜์—ฌ ๋„ฃ์–ด์ค€ ๋’ค imageContent ๊ฐ์ฒด๋ฅผ result ๋ฐฐ์—ด์— ๋„ฃ์–ด ์ฃผ๋„๋ก ํ•˜์˜€๊ณ , ์ด๋ฅผ ๊ณ„์† ๋ฐ˜๋ณตํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

๋ฐ˜๋ณต๋ฌธ์ด ๋ชจ๋‘ ๋๋‚˜๋ฉด ์ •์ƒ ์ฒ˜๋ฆฌ ๋˜์—ˆ๋‹ค๊ณ  ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— result[]์™€ ํ•จ๊ป˜ ์ •์ƒ ์ฒ˜๋ฆฌ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

 

 

 

    ๐Ÿ”ฝ ์ž˜ ๋งŒ๋“ค์—ˆ๋‚˜? ๐Ÿค”

        ๐Ÿ“ฆ Postman

Postman


Postman์„ ํ†ตํ•ด HTTP Request Body์— form-data ํ˜•์‹์œผ๋กœ images๋ผ๋Š” Key๋กœ ๋‘ ์žฅ์˜ ์ด๋ฏธ์ง€๊ฐ€ ์ „์†ก๋  ์ˆ˜ ์žˆ๋„๋ก ํ•œ ๋’ค ์š”์ฒญ์„ ๋ณด๋‚ด๋‹ˆ ์ •์ƒ ์ฒ˜๋ฆฌ ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

Disk Storage


ํŒŒ์ผ๋„ ๋””์Šคํฌ์— ์ž˜ ์ €์žฅ๋œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


Database

 

Database


์œ„์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์—๋„ ์ •์ƒ์ ์œผ๋กœ ์ž˜ ์ €์žฅ๋œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

 

 

NestJS๋กœ ๋ฐฐ์šฐ๋Š” ๋ฐฑ์—”๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ:ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์˜ ์ฐจ์„ธ๋Œ€ ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋‚˜๋‹ค

COUPANG

www.coupang.com

 

 

 

 

    ๐Ÿ”ฝ ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ์ด์šฉํ•˜๊ธฐ - URL์„ ์ด์šฉํ•œ ์ด๋ฏธ์ง€ ๋ฐ”๋กœ ์ถœ๋ ฅ

        ๐Ÿ“ฆ ๊ฐœ์š”

์ด๋ฒˆ์—๋Š” ์ €์žฅ๋œ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”๋กœ ์ถœ๋ ฅํ•ด ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.
HTTP Method GET์„ ์ด์šฉํ•˜์—ฌ Parameter(ํŒŒ๋ผ๋ฏธํ„ฐ)๋กœ ์ด๋ฏธ์ง€ ์ด๋ฆ„์„ ๋ณด๋‚ด๋ฉด ์ถœ๋ ฅ๋  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด์—์š”.


 

        ๐Ÿ“ฆ Controller

src/api/common/file/controller/file.controller.ts


์œ„ ์ฝ”๋“œ๋Š” ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€ ์ด๋ฆ„(ํ™•์žฅ์ž ํฌํ•จ)์„ ๋ณด๋‚ด์ฃผ๋ฉด ๋ฐ”๋กœ ํ•ด๋‹น ์‚ฌ์ง„์„ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ํ•ธ๋“ค๋Ÿฌ์—์š”.
๋งŒ์•ฝ ์—ฌ๋Ÿฌ ๊ฑด์˜ ์ด๋ฏธ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๋ฆ„์„ ๋ฐฐ์—ด๋กœ ๋ฐ›๋˜์ง€ ํ•ด๋ณด๋ฉด ๋  ๊ฑฐ ๊ฐ™์•„์š”.

์ฃผ๋‹ˆ๋Š” ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋งŒ ์ฒ˜๋ฆฌํ•ด ๋ณผ๊ฒŒ์š”.

ํ•ด๋‹น ํ•ธ๋“ค๋Ÿฌ๋Š” URL ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ด๋ฏธ์ง€์˜ ์ด๋ฆ„์„ ๋ฐ›๊ณ , ์‘๋‹ต ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.
์‘๋‹ต ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š” ์ด์œ ๋Š” ์ด ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด์„œ ๋ณด๋‚ผ ์‘๋‹ต์„ Customizing (๋ชฉ์ ์— ๋งž๊ฒŒ ๋ณ€๊ฒฝ)ํ•˜๊ธฐ ์œ„ํ•จ์ด์—์š”.

 

 

 

 

        ๐Ÿ“ฆ Service

src/api/common/file/service/file.service-impl.ts


๋กœ์ง์€ ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•ด์š”.

๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋œ ์ด๋ฏธ์ง€ ์ด๋ฆ„์ด Null์ธ์ง€ ํ™•์ธํ•˜๊ณ , Null์ด ์•„๋‹ˆ๋ฉด ๋กœ์ง์ด ์ฒ˜๋ฆฌ๋˜๋Š”๋ฐ,
์ด ๋•Œ, Express ์‘๋‹ต ๊ฐ์ฒด response์˜ sendFile()์„ ํ˜ธ์ถœํ•˜์—ฌ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ํŒŒ์ผ ์ด๋ฆ„๊ณผ options(ํŒŒ์ผ ์ „์†ก๊ณผ ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ ์˜ต์…˜ ์„ค์ •ํ•˜๋Š” ๊ฐ์ฒด)๋กœ root Key ๊ฐ’์˜ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•ด ์ฃผ๋Š”๋ฐ, ์ด๋Š” ํŒŒ์ผ์„ ์ฐพ์„ ๊ธฐ์ค€ ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•ด ์ค€ ๊ฒƒ์œผ๋กœ ./local/storage/images์—์„œ ํŒŒ์ผ์„ ์ฐพ์œผ๋ผ๋Š” ์˜๋ฏธ์—์š”.

sendFile()์€ Server(์„œ๋ฒ„) ์ธก์—์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ „์†ก ์‹œ ์‚ฌ์šฉ๋˜๋Š”๋ฐ, ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์—๊ฒŒ ํŒŒ์ผ ์ด๋ฆ„์„ ํฌํ•จํ•œ ์ด๋ฏธ์ง€ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด ์„œ๋ฒ„๋Š” ํ•ด๋‹น ํŒŒ์ผ์„ ์ฐพ์•„ response.sendFile()์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์•„ ์ „์†กํ•˜๋Š” ๊ฒƒ์ด์—์š”.

ํด๋ผ์ด์–ธํŠธ๋Š” ์ด๋ฅผ ๋ฐ›์•„ ์ด๋ฏธ์ง€๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ต๋‹ˆ๋‹ค.

 

 

 

 

    ๐Ÿ”ฝ ์ž˜ ๋งŒ๋“ค์—ˆ๋‚˜? ๐Ÿค”

        ๐Ÿ“ฆ Postman

Postman


๊ทธ๋ž˜์„œ ์œ„์™€ ๊ฐ™์ด Postman์„ ์ด์šฉํ•˜์—ฌ ํŒŒ์ผ ์ด๋ฆ„์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณด๋‚ด๋ณด๋ฉด ํ•ด๋‹น ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ”๋กœ ์ถœ๋ ฅ๋˜๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.

 

 

 

NestJS๋กœ ๋ฐฐ์šฐ๋Š” ๋ฐฑ์—”๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ:ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์˜ ์ฐจ์„ธ๋Œ€ ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋‚˜๋‹ค

COUPANG

www.coupang.com

 

 

 

    ๐Ÿ”ฝ ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ์ด์šฉํ•˜๊ธฐ - image ๊ณ ์œ  ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ์ •๋ณด ์–ป์–ด ์˜ค๊ธฐ

        ๐Ÿ“ฆ ๊ฐœ์š”

์ด๋ฒˆ์—๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ GET ์š”์ฒญ์œผ๋กœ image ๊ณ ์œ  ๋ฒˆํ˜ธ๋ฅผ ๋ณด๋ƒˆ์„ ๋•Œ, ํ•ด๋‹น ์ด๋ฏธ์ง€ URL์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.

์ด ๋˜ํ•œ, ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์™€ ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ๋กœ ๋‚˜๋ˆ„์–ด์„œ ์ด์•ผ๊ธฐ ํ•ด ๋ณผ๊ฒŒ์š”.

 

 

        ๐Ÿ“ฆ Controller - ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

src/api/common/file/controller/file.controller.ts


์œ„ ํ•ธ๋“ค๋Ÿฌ๋Š” imageId๋ฅผ URL ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„ ๋™์ž‘ํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ์—์š”.
๋ฐ˜ํ™˜๋˜๋Š” ์ •๋ณด๋Š” ์ด๋ฏธ์ง€ URL์„ ๋ฐ˜ํ™˜ํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.

 

 

        ๐Ÿ“ฆ Service - ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

src/api/common/file/service/file.service-impl.ts


๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์ตœ์ดˆ 87๋ฒˆ์งธ ์ค„์—์„œ imageId๊ฐ€ 0๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ˜น์€ Null์ธ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ  ์žˆ์–ด์š”.
๋‘˜ ๋‹ค ๋ชจ๋‘ True๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด 91๋ฒˆ์งธ ์ค„์„ ํ†ตํ•ด imageId๋ฅผ id ๋ณ€์ˆ˜๋ช…์œผ๋กœ ๋ฐ”๊พธ๊ณ , ๊ทธ๊ฑธ TypeORM findOne()์„ ํ†ตํ•ด ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ํ•ด๋‹น ์ด๋ฏธ์ง€ ๊ณ ์œ ๋ฒˆํ˜ธ๋กœ ์ €์žฅ๋œ ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ–ˆ์–ด์š”.

๋งŒ์•ฝ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด (95๋ฒˆ์งธ ์ค„) ์กด์žฌ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ํ•ด์ฃผ๊ณ , ์กด์žฌ ํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์ด๋ฏธ์ง€ URL์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.



 

 

 

    ๐Ÿ”ฝ ์ž˜ ๋งŒ๋“ค์—ˆ๋‚˜? ๐Ÿค”

        ๐Ÿ“ฆ Postman

Postman


Postman์„ ์ด์šฉํ•˜์—ฌ URL ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ฐพ์„ ์ด๋ฏธ์ง€์˜ ๊ณ ์œ ๋ฒˆํ˜ธ๋ฅผ ๋„ฃ๊ณ , GET ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์œ„์™€ ๊ฐ™์ด ์ด๋ฏธ์ง€ URL์„ ๋ฐ˜ํ™˜๋ฐ›๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

 

 

 

        ๐Ÿ“ฆ Controller - ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

์ด๋ฒˆ์—๋Š” ์—ฌ๋Ÿฌ ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด ๋ณผ๊ฒŒ์š”.

src/api/common/file/controller/file.controller.ts


์ด ํ•ธ๋“ค๋Ÿฌ๋Š” ์ด๋ฏธ์ง€ ๊ณ ์œ  ๋ฒˆํ˜ธ๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋ฐฐ์—ด์„ ๋ฐ›๋„๋ก ํ•ด ์ฃผ์—ˆ๋Š”๋ฐ, ๋‹จ์ผ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ์™€๋Š” ๋‹ฌ๋ฆฌ Query String์œผ๋กœ GET ์š”์ฒญ์„ ๋ฐ›๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋ฆฌ๊ณ , ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒƒ๋„ ์ด๋ฏธ์ง€ URL์ด ์—ฌ๋Ÿฌ๊ฐœ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ๋„๋ก ๋ฐฐ์—ด์— ๋‹ด๊ฒจ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.





        ๐Ÿ“ฆ Service - ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ

src/api/common/file/service/file.service-impl.ts


๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์ตœ์ดˆ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋œ ์ด๋ฏธ์ง€ ๊ณ ์œ  ๋ฒˆํ˜ธ๊ฐ€ ๋‹ด๊ธด ๋ฐฐ์—ด์ด Null์ด๊ฑฐ๋‚˜, ๊ธธ์ด๊ฐ€ 0์ธ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ , ์•„๋‹ˆ๋ผ๋ฉด ์‘๋‹ต๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•  ๊ฐ์ฒด images๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ, ์ด ๊ฐ์ฒด๋Š” ์ด๋ฏธ์ง€ URL์„ ๋ฌธ์ž์—ด๋กœ ๋‹ด์„ ๋ฐฐ์—ด ๊ฐ์ฒด๋กœ ์„ ์–ธํ•ด ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋Ÿฐ ๋’ค 109 ~ 116๋ฒˆ์งธ ์ค„๊นŒ์ง€ ํ–ฅ์ƒ๋œ For๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ๊ณ ์œ  ๋ฒˆํ˜ธ ์š”์†Œ ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๊ฒŒ ํ•˜๋Š”๋ฐ, 110๋ฒˆ์งธ ์ค„์—์„œ ํ•œ ๊ฐœ์˜ ์ด๋ฏธ์ง€ ๊ณ ์œ ๋ฒˆํ˜ธ๋ฅผ ๊บผ๋‚ด ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒ๋˜๋„๋ก TypeORM์˜ findOne()์„ ์ด์šฉํ•˜์—ฌ ์ฐพ๊ฒŒ ํ•˜๊ณ , ์ฐพ์€ ์ด๋ฏธ์ง€ ์ •๋ณด๋ฅผ image ์ƒ์ˆ˜ ๋ณ€์ˆ˜์— ๋‹ด๊ธฐ๋„๋ก ํ•˜์˜€์–ด์š”.

๊ทธ๋Ÿฐ ๋’ค ๊ทธ ๊ฐ์ฒด๊ฐ€ Null์ด ์•„๋‹Œ์ง€ ํ™•์ธ(111๋ฒˆ์งธ ์ค„)ํ•˜๊ณ , ์•„๋‹ˆ๋ผ๋ฉด images ๊ฐ์ฒด ๋ฐฐ์—ด์— ๋‹ด์•„ ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋Ÿฐ ๋’ค ๋ฐ˜๋ณต๋ฌธ์ด ๋๋‚˜๋ฉด ์ •์ƒ ์ฒ˜๋ฆฌ๋œ ์ •๋ณด์™€ ํ•จ๊ป˜ images ๊ฐ์ฒด ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ด ์ฃผ๋Š” ๋กœ์ง์ด์—์š”.

 

 

 

    ๐Ÿ”ฝ ์ž˜ ๋งŒ๋“ค์—ˆ๋‚˜? ๐Ÿค”

        ๐Ÿ“ฆ Postman

Postman


์œ„์™€ ๊ฐ™์ด GET ์š”์ฒญ์‹œ Query String์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์„ imagesId๋กœ ํ•œ ๋’ค
,(์‰ผํ‘œ)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ด๋ฏธ์ง€ ๊ณ ์œ  ๋ฒˆํ˜ธ๋ฅผ ๊ฐ’์œผ๋กœ ๋„ฃ์–ด ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์ •์ƒ ์ฒ˜๋ฆฌ ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

 

 

 

์—ฌ๊ธฐ๊นŒ์ง€ NestJS์˜ Multer๋ฅผ ์ด์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๊ณ , ์‹ค์Šตํ•ด ๋ณด์•˜์–ด์š”.
๋‹ค์Œ ๊ธ€์—์„  ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ฒŒ์‹œํŒ ํ˜•์‹์˜ ๊ธฐ๋Šฅ ๋‘ ๊ฐœ๋ฅผ ๋งŒ๋“ค๊ณ , JWT ์ธ๊ฐ€๋ฅผ ์ด์šฉํ•ด ๊ถŒํ•œ์„ ํ™•์ธํ•˜๊ณ ,
๊ธ€์ž์™€ ์ด๋ฏธ์ง€ ๋“ฑ์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ตฌํ˜„ํ•˜๊ณ , ์‹ค์Šตํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.

 

 

 

 

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."

 

 

 

GitHub - junyharang/nestTs-jwt-multer: Nest.ts๋ฅผ ์ด์šฉํ•œ JWT ์ธ์ฆ, ์ธ๊ฐ€์™€ ํŒŒ์ผ ์ฒ˜๋ฆฌ ์—ฐ์Šต

Nest.ts๋ฅผ ์ด์šฉํ•œ JWT ์ธ์ฆ, ์ธ๊ฐ€์™€ ํŒŒ์ผ ์ฒ˜๋ฆฌ ์—ฐ์Šต. Contribute to junyharang/nestTs-jwt-multer development by creating an account on GitHub.

github.com

 

 

 

 

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค

์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

qr.kakaopay.com

 

 

 

728x90
๋ฐ˜์‘ํ˜•