ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

Version 1.

SpringMVC

Build: Maven

Java: 1.8

JSP

Mybatis

๐Ÿ”ฝ Upgrade

Version 2.

SpringBoot: 3.1.3

Build: Gradle

Java: 17

React:18.2

Spring data JPA

๋ชฉํ‘œ

์•ฝ 1๋…„ ์ „ ์ฆˆ์Œ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ์˜ ์—…๋ฐ์ดํŠธ ์ œ์•ˆ์„ ๋ฐ›์•˜๋‹ค.

SpringMvc ๋ณต์Šต, Spring JPA, data JPA, React.js์˜ ๋ชฉ์ ์œผ๋กœ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰

→ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋“ฑ ์šด์˜ ๋•Œ์— ๋ถˆํŽธํ–ˆ๋˜ ์  ๊ฐœ์„ 

→ ๋ถ„ํŽธํ–ˆ๋˜ Work UI ๊ฐœ์„ 


BACK ๋‹จ(์†Œ์Šคํ™•์ธ)

์˜ˆ์™ธ์ฒ˜๋ฆฌ ๊ณตํ†ต ๊ธฐ๋Šฅ

batch size์ฒ˜๋ฆฌ, ์ฟผ๋ฆฌ ์š”์ฒญ ํšŸ์ˆ˜ ์ค„์ž„์œผ๋กœ ์†๋„๊ฐœ์„ 

1. ์˜ˆ์™ธ์ฒ˜๋ฆฌ

์˜ˆ์™ธ์ฒ˜๋ฆฌ๋Š” ํฌ๊ฒŒ ๋ฐ”๋€ ๋ถ€๋ถ„์œผ๋กœ ๊ณ ๋ฏผ์ด ๋งŽ์ด ๋˜์—ˆ๋‹ค. ์‹ค๋ฌด์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋ ๊นŒ๋ฅผ ๊ณ ๋ฏผํ•˜๋ฉฐ ์ง„ํ–‰ํ–ˆ๋‹ค. ๊ณตํ†ต์œผ๋กœ ์žก๊ณ  ์˜ค๋ฅ˜์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ง์ ‘ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด front์—์„œ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋•Œ ๊ณตํ†ต์œผ๋กœ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

 
GlobalExceptionHandler
  1. ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์ง€๋ฉด ๋ชจ๋‘ GlobalExceptionHandler์„ ํ†ตํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.
RestApiException

@RestControllerAdvice

RestControllerAdvice, ControllerAdivce๋Š” ์ „์—ญ์œผ๋กœ ExceptionHandler๋ฅผ ์ ์šฉํ•ด ์ค€๋‹ค. ์Šคํ”„๋ง์€ 4๊ฐœ์˜ ์šฐ์„ ์ˆœ์œ„๋กœ ์šฐ์„ ์ฒ˜๋ฆฌ ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค. ๊ทธ์ค‘์— @ExceptionHandler๋Š” ์›ํ•˜๋Š” Exception ํด๋ž˜์Šค๋“ค์„ ์†์„ฑ์œผ๋กœ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•  ์˜ˆ์™ธ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 
UserErrorCode
  1. ์˜ˆ์™ธ๋ฅผ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„๋“ค์€ ๋ชจ๋‘ RestApiException์„ ์˜ˆ์™ธ๋กœ ๋˜์ง€๋ฉฐ ์˜ˆ์™ธ๋ฉ”์„ธ์ง€๋ฅผ Enum์œผ๋กœ ๋งŒ๋“ค์–ด ๋ณด๋‚ด์ค€๋‹ค.

front์—์„œ๋Š” ์˜ˆ์™ธ๊ฐ€ ํ„ฐ์งˆ ๊ฒฝ์šฐ result.data ์•ˆ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , status๊ฐ€ 200์ด ์•„๋‹Œ ๊ฒฝ์šฐ๋กœ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ ํ•ด์„œ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

2. ์•„์‰ฌ์šด ์ 

FRONT์—์„œ API๋ฅผ ํ˜ธ์ถœ ํ–ˆ์„ ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค๊ณ  ํ•ด๋„ ์—๋Ÿฌ๋ฅผ ๊ทธ๋Œ€๋กœ ํ‘œ์ถœํ•  ์ˆ˜๋Š” ์—†์—ˆ๋‹ค.

๋‘ ๊ฐ€์ง€์˜ ์ค‘ ํ•˜๋‚˜์˜ ์„ ํƒ์„ ๊ณ ๋ฏผํ–ˆ๋‹ค.

  1. ์˜ˆ์™ธ ์ด์œ ์— ๋Œ€ํ•œ status์™€ Message ์‘๋‹ต (ex. ๊ฐ’์ด ์ž˜ ๋ชป ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.)
  2. ์˜ˆ์™ธ ์ด์œ ๊ฐ€ ์•„๋‹Œ status์™€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ณตํ†ต์œผ๋กœ ๋งŒ๋“  ์—๋Ÿฌ์ฝ”๋“œ ์‘๋‹ต (ex. W01, W02.. ๋“ฑ )

→ 1๋ฒˆ์œผ๋กœ ์ง„ํ–‰ํ–ˆ๋‹ค. React.js ์—์„œ Alert์œผ๋กœ ๋„์šฐ๋Š” ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹๋‹ค๊ณ  ์ƒ๊ฐ → ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ํ•ด๋‹น API๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ์—๋Š” ์˜ค๋ฅ˜์˜ ์ด์œ ๋Š” ์™ธ๋ถ€์—์„œ ์•Œ๊ฒŒ ๋˜๋ฉด ์•ˆ๋œ๋‹ค. ์˜ค์ง ๊ฐœ๋ฐœ์ž๋งŒ ๊ทธ ๋‚ด์šฉ์„ ํŒŒ์•…ํ•ด์•ผ ํ•œ๋‹ค → ๊ฐœ๋ฐœ์„ ๋‹คํ•˜๊ณ  ๋‚˜์„œ ์„ ๋ฐฐ์—๊ฒŒ ํ”ผ๋“œ๋ฐฑ ๋ฐ›์•˜๋˜ ๋ถ€๋ถ„ → ์  ์žฅ ์•„์‰ฝ๋‹ค. ๋ฉ”์„ธ์ง€๋ฅผ ์—๋Ÿฌ์ฝ”๋“œ๋กœ ๋ณ€๊ฒฝ ์ง„ํ–‰ ํ•„์š”


FRONT ๋‹จ( ์†Œ์Šคํ™•์ธ)

ํ–ฅ์ƒ๋œ ์ 

๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ์†๋„ ํ–ฅ์ƒ

๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ๊ฐ„ํŽธํ•œ UI ์ธํ„ฐํŽ˜์ด์Šค ์ œ๊ณต

 

์ฒซ React.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋งŽ์ด ํ—ค๋งธ๋‹ค. ์ด ์‹œ๊ฐ„์— ๋ฐฑ์—”๋“œ ๊ณต๋ถ€๋ฅผ ๋” ํ• ๊นŒ ์‹ถ์—ˆ์ง€๋งŒ, ํ”„๋ก ํŠธ ๊ฐœ๋ฐœ๋„ ์•Œ์•„์•ผ ์‹ค๋ฌด์—์„œ ์†Œํ†ต์ด ์ž˜ ๋  ๊ฑฐ๋ผ๋Š” ์ƒ๊ฐ์— ๊ณ„์†ํ–ˆ๋‹ค. ๊ธฐ๊ฐ„์ด ์งง์•˜๊ธฐ์— ๊นŠ์ด ๊ณต๋ถ€ํ•˜์ง„ ๋ชปํ–ˆ๊ณ , chatGPT์˜ ๋„์›€์„ ๋งŽ์ด ๋ฐ›์œผ๋ฉฐ ํ”„๋ก ํŠธ ์ „๋ฐ˜์„ ์ง„ํ–‰ํ–ˆ๋‹ค.

1. React.js ์—ฌ๋Ÿฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ

    return(
        <div class="wrapper">
            <UserHead />
            <Header />
            <Routes>
					<Route path="/" element={<Main />  } />            
					<Route path="/work/view/:id" element={<WorkView />  } />
                    <Route path="/work/init" element={<WorkList />  } />
                    <Route path="/about/init" element={<About />  } />
                    <Route path="/contact/init" element={<Contact />  } />
			</Routes>
            <Footer />
        </div>
    )

๊ด€๋ฆฌ์ž์™€ ์‚ฌ์šฉ์ž ํ™”๋ฉด์„ ๋‚˜๋ˆ„๊ธฐ ๋•Œ๋ฌธ์— Route,Helmet๋„ ์ฐพ์•„๋ณด๋ฉฐ ๊ณต๋ถ€ํ•˜๋ฉฐ ํ•œ ๋•€ ํ•œ ๋•€ ์ง„ํ–‰ → Route๋กœ url path์„ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๊ณ , Helmet์œผ๋กœ url path์— ๋”ฐ๋ฅธ html head์˜ ์กฐ์ •์„ ๋ฐฐ์› ๋‹ค.

์ด๋ฏธ์ง€ ํ•œ๊ฐœ ๋‹น ImageUploadBox ํ•œ ๊ฐœ

ํŠนํžˆ Work ๊ฒŒ์‹œํŒ์˜ ๋“ฑ๋กํผ์„ ๋‚˜๋ˆ„๊ธฐ ์–ด๋ ค์› ๋‹ค.

→ ์œ ํ˜• ๋ณ„๋กœ ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋ชจ์–‘์„ ๋„ฃ์–ด์•ผ ํ–ˆ๊ธฐ์— ๋„์ €ํžˆ ๊ณตํ†ต์œผ๋กœ ์žก์„ ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค(ImageUpload1,2 ๋“ฑ)

→ ๊ทธ๋ž˜์„œ ๊ฐ๊ฐ ํ…œํ”Œ๋ฆฟ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰

→ ๋‹ค๋งŒ ์ด๋ฏธ์ง€์— ๋Œ€ํ•ด์„œ๋Š” ImageUploadBox๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์ง„ 1๊ฐœ์— ๋Œ€ํ•ด์„œ๋งŒ ๋“ฑ๋ก, ์‚ญ์ œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

2. Work ๋“ฑ๋ก UI ๊ฐœ์„ 

OLD

NEW

  • OLD : ์ œ๊ณตํ•ด ์ค€ ๋งค๋‰ด์–ผ pdf๋ฅผ ๋ณด๊ณ  ์˜ฌ๋ฆผ
  • NEW : ํ…œํ”Œ๋ฆฟ ๋ชจ์–‘๋Œ€๋กœ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ œ๊ณต

์ด์–ด์ง€๋Š” ๋‚ด์šฉ์œผ๋กœ ๊ณ ๊ฐ์€ Work ๊ฒŒ์‹œ๊ธ€์„ ์˜ฌ๋ฆฌ๊ธฐ ํž˜๋“ค๋‹ค๊ณ  ํ–ˆ๋‹ค.. OLD์˜ ์‚ฌ์ง„์ฒ˜๋Ÿผ ํ…œํ”Œ๋ฆฟ์„ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ํž˜๋“ค์—ˆ๋‹ค. ๋ณ€๊ฒฝ๋œ UI์™€ ๊ธฐ๋Šฅ์œผ๋กœ ์ธํ•ด ๋” ์ด์ƒ ๋งค๋‰ด์–ผ pdf๊ฐ€ ํ•„์š” ์—†์–ด์กŒ๋‹ค. ๊ณ ๊ฐ๋„ ํฌ๊ฒŒ ๋งŒ์กฑํ–ˆ๋‹ค.

์ด๋ฏธ์ง€ ์ €์žฅ๋กœ์ง ๋ณ€๊ฒฝ

  • form ์ž‘์„ฑ ํ›„ ๋“ฑ๋ก ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ ์ €์žฅ → ์šฉ๋Ÿ‰์ด ํฐ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋‹ค๋Ÿ‰์œผ๋กœ ์ €์žฅํ•˜๊ธฐ์— ์†๋„๊ฐ€ ๋А๋ ค ๋“ฑ๋ก ๋ฒ„ํŠผ ํด๋ฆญ ํ›„ ํ•œ์ฐธ์„ ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค. → → ์ด๋ฏธ์ง€๋ฅผ ๋“œ๋ž˜๊ทธํ•˜์—ฌ ๋„ฃ์œผ๋ฉด 1์žฅ์”ฉ ์ €์žฅ์œผ๋กœ ๊ฐœ์„  → ๊ธฐ๋‹ค๋ฆด ํ•„์š” ์—†์ด back์—์„œ ์ˆœ์„œ๋Œ€๋กœ ์ฒ˜๋ฆฌ๋˜์–ด ์†๋„ ๊ฐœ์„ 

์•„์‰ฌ์šด ์ 

  1. ์—ฌ์ „ํžˆ gif๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์†๋„๊ฐ€ ๋А๋ฆฌ๋‹ค. ์†๋„ ๊ฐœ์„ ์„ ์œ„ํ•ด AWS S3 ๋„์ž…์ด ์‹œ๊ธ‰ํ•จ์œผ๋กœ ๊ณ ๊ฐ๊ณผ ํ˜‘์˜๊ฐ€ ํ•„์š”
  2. React.js์— ๋Œ€ํ•œ ์„ค๊ณ„๊ฐ€ ์กฐ๊ธˆ ์•„์‰ฝ๋‹ค. ํด๋” ๊ตฌ์กฐ๋ฅผ url์— ๋งž์ถ”๋Š” ๊ฒŒ ์ข‹์€ ๊ฐœ๋ฐœ์ด๋ผ๊ณ  ํ•œ๋‹ค. ๋‹ค์Œ์— ์ฐธ๊ณ ํ•˜์ž
  3. ๊ธฐ์กด DB ๊ตฌ์กฐ๋กœ ํŒŒ์ผ์ฒจ๋ถ€๋Š” ํ•œ ๊ฐœ์˜ ํ…Œ์ด๋ธ”์—์„œ ์ฒ˜๋ฆฌ

→ ํฐ ํ”„๋กœ์ ํŠธ๊ฐ€ ๋  ์ผ์€ ์—†์ง€๋งŒ, ๋‚˜์ค‘์— ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ์— ๊ทœ๋ชจ๋ฅผ ๋ณด๊ณ  ์„ ํƒ์„ ์ž˜ํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค.

ํŒŒ์ผ ํ…Œ์ด๋ธ”์„ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์—์„œ ์“ฐ๋‹ค ๋ณด๋‹ˆ, ํŠธ๋ž˜ํ”ฝ ์ฆ๊ฐ€์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๊ณ , entity๋ฅผ ์‚ฌ์šฉํ•˜๋Š” JPA๋ฅผ ์‚ฌ์šฉํ•˜๋‹ˆ ์ฝ”๋“œ๋ณต์žก์„ฑ์ด ์˜ฌ๋ผ๊ฐ„๋‹ค.

→ ๋งŒ์•ฝ ์ •๋ง ํฐ ๊ทœ๋ชจ์—์„œ CQRS ๊ธฐ๋ฒ• ๊ฐ™์€ ๊ฒƒ์„ ์“ธ ๊ฒฝ์šฐ ํ…Œ์ด๋ธ” ๋ถ„๋ฆฌ์—๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ์•„์˜ˆ ๋”ฐ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์—ฌ๋Ÿฌ๋ชจ๋กœ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋๋‚ด๋ฉด์„œ JPA์™€ Spring์„ ๋” ์ดํ•ดํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ณผ์ˆ˜๋ก ๊ณต๋ถ€ํ•ด์•ผ ํ•  ์ ๋„ ๋งŽ๊ณ  ์‚ฌ์šฉํ•ด๋ณด๊ณ  ์‹ถ์€ ๊ธฐ์ˆ ์ด ๋Š˜์–ด๋‚œ๋‹ค.