/saladit

main project team project

Primary LanguageJava

๐Ÿ“Œ Saladit!

๊ฑด๊ฐ•์‹ ํ’ˆ๋ชฉ๋ณ„ ํŒ๋งค ์›น ์‚ฌ์ดํŠธ


0. ๋ชฉ์ฐจ

  1. ์ œ์ž‘ ๊ธฐ๊ฐ„ & ์ฐธ์—ฌ ์ธ์›
  2. ์‚ฌ์šฉ ๊ธฐ์ˆ 
  3. ํ•ต์‹ฌ ERD
  4. ํ•ต์‹ฌ ๊ธฐ๋Šฅ
  5. ํ•ต์‹ฌ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…
  6. ๊ทธ ์™ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

1. ์ œ์ž‘ ๊ธฐ๊ฐ„ & ์ฐธ์—ฌ ์ธ์› (๊ฐœ๋ฐœ 4๊ฐœ์›”์ฐจ)

  • 2022.2.18 ~ 2022.3.30 (40์ผ)
  • ๊ตฌ์„ฑ ์ธ์› : Back-end 6๋ช…

2. ์‚ฌ์šฉ ๊ธฐ์ˆ 

Back-end

  • Java 8
  • Spring Framework
  • Spring MVC
  • Mybatis

Front-end

  • HTML
  • CSS
  • JS
  • JQuery
  • BootStrap

DevOps

  • MySQL 5.7
  • AWS - EC2, S3, RDS

3. ํ•ต์‹ฌ ERD

์‚ฌ์ง„์„ ํด๋ฆญํ•˜์—ฌ ํฌ๊ฒŒ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ฒซ๋ฒˆ์งธ ์‚ฌ์ง„์˜ payment_item_mapping ํ…Œ์ด๋ธ”์˜ payment_item_mapping_item_code(๊ฒฐ์ œ ์ƒํ’ˆ ๊ณ ์œ  ๋ฒˆํ˜ธ) ์ปฌ๋Ÿผ๊ณผ
  • ๋‘๋ฒˆ์งธ ์‚ฌ์ง„์˜ item, subscribe ํ…Œ์ด๋ธ”์˜ ๊ฐ๊ฐ์˜ Primary key์ธ ๊ณ ์œ ๋ฒˆํ˜ธ ์ปฌ๋Ÿผ๋“ค์ด ์™ธ๋ž˜ํ‚ค๋กœ ๋ฌถ์—ฌ์žˆ์ง€๋งŒ ํ•œ ์ด๋ฏธ์ง€์— ์ „๋ถ€ ๋„ฃ์„ ์ˆ˜ ์—†์–ด ๋ถˆ๊ฐ€ํ”ผํ•˜๊ฒŒ ๋‘ ๊ฐœ์˜ ์ด๋ฏธ์ง€๋กœ ๋‚˜๋ˆ ๋†“์•˜์Šต๋‹ˆ๋‹ค.

4. ํ•ต์‹ฌ ๊ธฐ๋Šฅ

์ด ์„œ๋น„์Šค์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์€ '๊ณ ๊ฐ์˜ ์ƒํ’ˆ ์ฃผ๋ฌธ / ๊ฒฐ์ œ' ์™€ '๊ด€๋ฆฌ์ž์˜ ํ†ต๊ณ„ ์‹œ์Šคํ…œ' ์ž…๋‹ˆ๋‹ค.

  • (1) ๊ณ ๊ฐ์€ ์ƒํ’ˆ์˜ ์ฃผ๋ฌธ ๋ฐ ๊ฒฐ์ œ๋ฅผ ํ•˜๊ณ , ๊ฒฐ์ œํ•œ ์ƒํ’ˆ์— ํ•œํ•ด์„œ ์ด๋ฏธ์ง€ ์ฒจ๋ถ€๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋ฆฌ๋ทฐ๋ฅผ ๋Œ“๊ธ€ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • (2) ๊ด€๋ฆฌ์ž๋Š” ๋งค์ถœ ํ†ต๊ณ„ ํ‘œ์‹œ ๋ฐ ํŒŒ์ผ๋กœ ๋‹ค์šด๋กœ๋“œ(PDF, Excel) ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ , ํšŒ์› ๊ด€๋ฆฌ์™€ ์ฟ ํฐ ๊ด€๋ฆฌ ๋“ฑ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์„ค๋ช…์„ ํŽผ์ณ์„œ ๊ธฐ๋Šฅ์˜ ํ๋ฆ„์„ ๋ณด๋ฉด, ์„œ๋น„์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์„ค๋ช… ํŽผ์น˜๊ธฐ

4.1. ์ „์ฒด ํ๋ฆ„

4.2. ์‚ฌ์šฉ์ž ์š”์ฒญ (JSP < - > Controller)

  • ํšŒ์›๊ฐ€์ž…

    • ์ด๋ฉ”์ผ ์ •๊ทœ์‹, ์ด๋ฏธ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€ ์ฒดํฌ (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ์ด๋ฏธ ์กด์žฌํ•œ๋‹ค๋ฉด ์นด์นด์˜ค, ๊ตฌ๊ธ€, ์ƒ๋Ÿฌ๋”ง ์ค‘ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ ๊ฐ€์ž…๋˜์–ด์žˆ๋Š”์ง€ ๋ชจ๋‹ฌ์ฐฝ์„ ๋„์›Œ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
    • ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ ์ธ์ฆ

      • ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ ์ •๊ทœ์‹ ์ฒดํฌ (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ๋ฌธ์ž ์ธ์ฆ ๊ณผ์ •
        • (1) ์ธ์ฆ๋ฒˆํ˜ธ ๋ฌธ์ž๋ฅผ ๋ณด๋‚ด๋Š” ๊ณผ์ • (๋„ค์ด๋ฒ„ SMS API) (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
          • ๋žœ๋ค ์ˆซ์ž 6์ž๋ฆฌ๋ฅผ ๋ฝ‘๊ณ  ์„ธ์…˜์— ๋“ค์–ด๊ฐ€์žˆ๋Š” MemberVO์— ์ €์žฅํ•ด์ค๋‹ˆ๋‹ค.
          • ๋„ค์ด๋ฒ„ SMS API ๋ฅผ ์ด์šฉํ•ด ๋žœ๋ค ์ˆซ์ž 6์ž๋ฆฌ๋ฅผ ํฌํ•จํ•œ ๋ฌธ์ž๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
        • (2) ์„ธ์…˜์— ์ €์žฅ๋œ 6์ž๋ฆฌ ์ˆซ์ž์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ ์€ ์ˆซ์ž๋ฅผ ๋น„๊ต (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

  • ๋กœ๊ทธ์ธ

    • ์นด์นด์˜ค ๋กœ๊ทธ์ธ API (ํ™”๋ฉด๋‹จ : JavaScript) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ์นด์นด์˜ค ๋กœ๊ทธ์ธ ํŒ์—…์ฐฝ์„ ๋„์›Œ์„œ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๋กœ๊ทธ์ธ ํƒ€์ž… ์ฒดํฌ ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ
    • ๋กœ๊ทธ์ธ ํƒ€์ž… ์ฒดํฌ (Controller) - ์นด์นด์˜ค๋กœ ๋กœ๊ทธ์ธ ์‹œ ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ์ด๋ฉ”์ผ์ด ๊ตฌ๊ธ€์ด๊ฑฐ๋‚˜ ์ƒ๋Ÿฌ๋”ง ์ „์šฉ ์ด๋ฉ”์ผ์ด๋ผ๋ฉด ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ๋Œ๋ ค๋ณด๋‚ด๋ฉฐ ๊ฒฝ๊ณ ์ฐฝ์„ ๋„์›๋‹ˆ๋‹ค.

      • ์นด์นด์˜ค ์ด๋ฉ”์ผ์ด ๋งž๋‹ค๋ฉด, ์„ธ์…˜์— ํšŒ์› ์ •๋ณด๋ฅผ DB์—์„œ ๊ฐ€์ ธ์™€์„œ ๋„ฃ๊ณ  ๋ฉ”์ธํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.


  • ์ฃผ๋ฌธ ํŽ˜์ด์ง€๋กœ ์ด๋™ (3๊ฐ€์ง€ ๋ฃจํŠธ๋ฅผ ์ „๋ถ€ ๊ฐ์•ˆํ•˜์—ฌ ๋งŒ๋“  ๋ฉ”์„œ๋“œ) (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

    • (1) ์ƒํ’ˆ ์ƒ์„ธํŽ˜์ด์ง€์—์„œ ๊ตฌ๋งค ๋ฒ„ํŠผ ํด๋ฆญ
    • (2) ์žฅ๋ฐ”๊ตฌ๋‹ˆ์—์„œ ๊ตฌ๋งค ๋ฒ„ํŠผ ํด๋ฆญ
    • (3) ๋ฐ”๋กœ์ฃผ๋ฌธํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ
      • 3๊ฐ€์ง€ ๋ฃจํŠธ๋ฅผ ์ปค๋ฒ„ํ•˜๊ธฐ ์œ„ํ•ด, ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋“ค์€ ์ „๋ถ€ ๋ฐฐ์—ด ํ˜•์‹์œผ๋กœ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌ.

  • ์ฃผ๋ฌธ ํŽ˜์ด์ง€ (์ฃผ๋ฌธํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ ํ›„) -> ๊ฒฐ์ œ ํŽ˜์ด์ง€๋กœ ์ด๋™

    • ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋‚˜์˜ค๋Š” ๋ฐ์ดํ„ฐ ์ข…๋ฅ˜๋“ค์€ List VO์—, ํ•˜๋‚˜์”ฉ ๋‚˜์˜ค๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋‹จ์ผ ๋ฐ์ดํ„ฐ VO์— ๋„ฃ์–ด์„œ ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌ (ํ™”๋ฉด๋‹จ : Javascript) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
    • ๋ฆฌ์ŠคํŠธ VO(PaymentSingleListVO), ๋‹จ์ผ ๋ฐ์ดํ„ฐ VO(PaymentSingleSideInfoVO) ๋ฅผ ํ†ตํ•ด ๊ฒฐ์ œ ํŽ˜์ด์ง€์— ๋ฐ์ดํ„ฐ ์ „๋‹ฌ (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ๋ฆฌ์ŠคํŠธ ํ˜•์‹์œผ๋กœ ๋ฐ›๋Š” ํด๋ž˜์Šค ์ฝ”๋“œ (PaymentSingleListVO) (Java) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ


  • ๊ฒฐ์ œ ํŽ˜์ด์ง€ -> ๊ฒฐ์ œ ์™„๋ฃŒ ํŽ˜์ด์ง€

    • (1) ๊ฒฐ์ œํ•˜๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ
      • ๊ฐ€๊ฒฉ์ด 0์› ์ด์ƒ์ผ ๋•Œ (iamport API ๋ฅผ ์ด์šฉํ•ด์„œ ๊ฒฐ์ œ ์ง„ํ–‰ ํ›„ ๋ฐ์ดํ„ฐ ๋„˜๊ธฐ๊ธฐ) (ํ™”๋ฉด๋‹จ : Javascript) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ํฌ์ธํŠธ, ์ฟ ํฐ์œผ๋กœ ์ธํ•ด ๊ฐ€๊ฒฉ์ด 0์›์ผ ๋•Œ (API ๋Š” ์ง„ํ–‰ํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋ฐ์ดํ„ฐ ๋„˜๊ธฐ๊ธฐ) (ํ™”๋ฉด๋‹จ : Javascript) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
    • (2) ๊ฒฐ์ œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ, ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ชฉ๋ก ๊ฐฑ์‹ , ์ฟ ํฐ ๊ฐฑ์‹ , ํฌ์ธํŠธ ๊ฐฑ์‹ ์˜ ์—ญํ• ์„ ๋‹ด๋‹นํ•˜๋Š” ๋ฉ”์„œ๋“œ (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

  • ๊ตฌ๋งคํ•œ ์ƒํ’ˆ ๋ฆฌ๋ทฐ ์ž‘์„ฑ (๋Œ“๊ธ€) - AWS S3์— ์ด๋ฏธ์ง€ ํŒŒ์ผ ์—…๋กœ๋“œ ํฌํ•จ

    • ๋ฆฌ๋ทฐ ์ •๋ณด (๋ณ„์ , ๋‚ด์šฉ, ์ด๋ฏธ์ง€ ํŒŒ์ผ ์—…๋กœ๋“œ, ํ•ด๋‹น ์ƒํ’ˆ ์ •๋ณด ๋“ฑ๋“ฑ) ๋ฅผ DB์— ์ €์žฅ ํ›„, ๋ฆฌ๋ทฐ ์ž‘์„ฑ ํ˜œํƒ์ธ ํฌ์ธํŠธ ์ ๋ฆฝํ•˜๋Š” ๋ฉ”์„œ๋“œ (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
    • ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ AWS S3 ์— ์—…๋กœ๋“œํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” AwsS3 ํด๋ž˜์Šค ์ฝ”๋“œ
      • createS3Client() ๋ฉ”์„œ๋“œ๋กœ AmazonS3 ๊ฐ์ฒด ์ƒ์„ฑ ํ›„ (Service) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

      • upload(InputStream is, String key, String contentType, long contentLength) ๋ฉ”์„œ๋“œ๋กœ S3 ์— ์ด๋ฏธ์ง€ ํŒŒ์ผ ์—…๋กœ๋“œ ์‹คํ–‰ (Service) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ


  • ์นด์นด์˜ค ์šฐํŽธ๋ฒˆํ˜ธ (์ฃผ์†Œ) ์„œ๋น„์Šค API

    • ๋จผ์ € ์นด์นด์˜ค ์ฃผ์†Œ ์„œ๋น„์Šค API ์˜ iframe ์„ ๋‹ด๊ธฐ ์œ„ํ•œ ๋ชจ๋‹ฌ์ฐฝ์„ ๋„์›๋‹ˆ๋‹ค. (ํ™”๋ฉด๋‹จ : JavaScript) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
    • ๋„์›Œ์ง„ ๋ชจ๋‹ฌ์ฐฝ ์•ˆ์— API iframe ์„ ๊ปด๋งž์ถฐ ๋„ฃ์–ด์„œ ๋„์›๋‹ˆ๋‹ค. (ํ™”๋ฉด๋‹จ : JavaScript) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

4.3. Controller < - > Service

  • ์ƒํ’ˆ(๋ฐ์ดํ„ฐ) ๋ชฉ๋ก ์š”์ฒญ (๋Œ€๋ถ€๋ถ„์˜ Controller < - > Service ๊ณ„์ธต์€ ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.)
    • ์š”์ฒญ ํ™•์ธ (Controller) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • ํ™”๋ฉด๋‹จ์—์„œ ํƒœ๊ทธ ์ •๋ณด(DetailVO.item_tag_main)์™€ ๋ชจ๋‹ฌ์ฐฝ ์ƒํ’ˆ ๋ชฉ๋ก ์š”์ฒญ์„ ํ•จ๊ป˜ ๋ฐ›๊ณ , ๊ทธ ์ •๋ณด๋“ค์„ Service ๋กœ ๋„˜๊น๋‹ˆ๋‹ค.
    • ๊ฒฐ๊ณผ ์‘๋‹ต (Service) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
      • Service ๊ณ„์ธต์—์„œ Controller์—์„œ ๋„˜์–ด์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•ด ๋‹จํ’ˆ, ๊ตฌ๋… ์ƒํ’ˆ๊ฐ„์˜ ๋ถ„๋ฅ˜๋ฅผ ๊ฑฐ์น˜๊ณ  Repository ๋กœ ๋„˜๊ฒจ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค.

4.4. Repository (DAO) - 4.3 ๊ณผ ์ด์–ด์ง„ ๊ตฌ์กฐ๋กœ ์„ค๋ช…

  • Service ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌ (Repository) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

    • Service๋กœ๋ถ€ํ„ฐ ๋„˜์–ด์˜จ ๋ฐ์ดํ„ฐ๋ฅผ SqlSessionTemplate ์„ ํ†ตํ•ด Mybatis๋กœ ๋„˜๊น๋‹ˆ๋‹ค.

    • Mybatis์—์„œ ๋ฐ˜ํ™˜ ๋œ ์ƒํ’ˆ ๋ฆฌ์ŠคํŠธ(๋ฐ์ดํ„ฐ) ๋ฅผ ๋ฐ›์•„์„œ ์ž์‹ ์„ ํ˜ธ์ถœํ•œ Service๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.


4.5. MyBatis (MySQL)

  • Repository -> MyBatis - 4.4 ์™€ ์ด์–ด์ง„ ๊ตฌ์กฐ๋กœ ์„ค๋ช…
    • (1) applicationContext.xml ์—์„œ sqlSessionTemplate ์˜ bean ๊ฐ์ฒด ์ƒ์„ฑ (xml ์„ค์ •ํŒŒ์ผ) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

    • (2) mybatis ํ™˜๊ฒฝ์„ค์ • ํŒŒ์ผ(mybatis-config.xml) ์— SQL ๋งคํผํŒŒ์ผ ๋“ฑ๋ก (xml ์„ค์ • ํŒŒ์ผ) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ

    • (3) ๋งคํผํŒŒ์ผ์—์„œ SQL ๋ฌธ์„ ํ†ตํ•ด ์ƒํ’ˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ (xml ๋งคํผ ํŒŒ์ผ) ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ


  • ์ƒํ’ˆ ๊ฒ€์ƒ‰ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต SQL๋ฌธ ๐Ÿ“Œ ์ฝ”๋“œ ํ™•์ธ
    • ๋‘ ํ…Œ์ด๋ธ”์„ left join์œผ๋กœ ํ•ฉ์ณ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณต ๋ฐ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜
      • (์ƒํ’ˆ ์ด๋ฏธ์ง€, ์ด๋ฆ„, ๊ฐ€๊ฒฉ) + (์ƒํ’ˆ์˜ ๋ฆฌ๋ทฐ ํ‰๊ท  ๋ณ„์ , ๋ฆฌ๋ทฐ ์ด ๊ฐœ์ˆ˜)

5. ํ•ต์‹ฌ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

5.1. ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ PDF ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ์ฒ˜๋ฆฌ ๋ฌธ์ œ ํ•ด๊ฒฐ

1) ๋ฌธ์ œ ์ƒํ™ฉ

  • ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€์˜ ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ๋ฅผ PDF๋กœ ๋‹ค์šด ๋ฐ›์œผ๋ ค ํ•  ๋•Œ, ํด๋ผ์ด์–ธํŠธ ๊ฒฝ๋กœ๋กœ ๋‹ค์šด๋กœ๋“œ ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

2) ์›์ธ ๋ถ„์„

  • PDF ๋‹ค์šด๋กœ๋“œ ๊ฒฝ๋กœ๊ฐ€ "C:\๊ธˆ์ฃผ ๋งค์ถœ.pdf" ๋กœ ์žกํ˜€์žˆ๋Š”๋ฐ, warํŒŒ์ผ๋กœ ๋ฐฐํฌ ํ›„ warํŒŒ์ผ ์•ˆ์˜ ํด๋”๋กœ ๊ฒฝ๋กœ๊ฐ€ ์žกํ˜€๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค. (ํด๋ผ์ด์–ธํŠธ๋กœ ๋‹ค์šด์ด ์•ˆ๋ฐ›์•„์ง)
  • ๋•Œ๋ฌธ์— ํด๋ผ์ด์–ธํŠธ ๊ฒฝ๋กœ๊ฐ€ ์•„๋‹Œ ์„œ๋ฒ„ ๊ฒฝ๋กœ๋กœ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
๊ธฐ์กด ์ฝ”๋“œ(ํด๋ฆญ)
@RequestMapping("/pdfDown.mdo")
public void pdfDown(HttpServletRequest request)throws Exception{

    try {
        Document document = new Document(); // pdf๋ฌธ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด

        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\๊ธˆ์ฃผ ๋งค์ถœ.pdf"));
        // pdfํŒŒ์ผ์˜ ์ €์žฅ๊ฒฝ๋กœ๋ฅผ C๋“œ๋ผ์ด๋ธŒ์— '๊ธˆ์ฃผ ๋งค์ถœ.pdf'๋กœ ์ €์žฅํ•œ๋‹ค๋Š” ๋œป

        document.open(); // ์›นํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์—ฐ๋‹ค
        String path =request.getSession().getServletContext().getRealPath("/");

        /* ์ค‘๊ฐ„ ์ฝ”๋“œ ์ƒ๋žต */

        document.add(table); // ์›น์ ‘๊ทผ ๊ฐ์ฒด์— table๋ฅผ ์ €์žฅํ•œ๋‹ค.
        document.close(); // ์ €์žฅ์ด ๋๋‚ฌ์œผ๋ฉด document๊ฐ์ฒด๋ฅผ ๋‹ซ๋Š”๋‹ค.
        System.out.println("์„ฑ๊ณต");

    }catch (Exception e) {
        System.out.println("์‹คํŒจ");
        e.printStackTrace();
    }
}

3) ๋ฌธ์ œ ํ•ด๊ฒฐ

  • ๋‚ด์šฉ์„ ์ง‘์–ด๋„ฃ์€ pdf ํŒŒ์ผ์„ ์•„์˜ˆ ์ƒˆ ํƒญ์œผ๋กœ ๋„์›Œ์„œ, ํด๋ผ์ด์–ธํŠธ์—์„œ ์ƒˆ ํƒญ์„ ํ†ตํ•ด ์ธ์‡„์™€ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ€ ์ „๋ถ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ณผ์ •
    • pom.xml์— itext์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • application.xml ์„ค์ • ํŒŒ์ผ์— pdf๋ฅผ ์ถœ๋ ฅํ•  ํด๋ž˜์Šค๋ฅผ ๋นˆ ๊ฐ์ฒด๋กœ ์ƒ์„ฑํ•œ ๋’ค, ํ•ด๋‹น ๋นˆ ๊ฐ์ฒด๋ฅผ pdf๋ผ๋Š” ๋ทฐ ์ด๋ฆ„์ด ์™”์„ ๋•Œ ๋™์ž‘ ํ•  ํด๋ž˜์Šค๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฆฌ์ŠคํŠธ๋กœ pdf์— ์ฐ์„ ๊ฐ’์„ ์ •์ œํ•ด์„œ pdf ๋ž€ ์ด๋ฆ„์œผ๋กœ ๋ทฐ ์ด๋ฆ„์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
    • ์ตœ์ข…์ ์œผ๋กœ pdf ๋‚ด์šฉ์„ ๋งŒ๋“ค๊ณ  ์ถœ๋ ฅํ•  ๋นˆ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด, ์ž๋ฐ” ์ฝ”๋“œ๋กœ ๋ฌธ์„œ์— ์“ฐ์ผ ํ‘œ๋ฅผ ๋งŒ๋“ค์–ด ๊ทธ ํ‘œ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ์ƒˆ ํƒญ์— PDF๋ฅผ ์ถœ๋ ฅํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ฐœ์„ ๋œ ์ฝ”๋“œ (ํด๋ฆญ)
// 1๋ฒˆ
// pom.xml ์— ์˜์กด์„ฑ ์ถ”๊ฐ€
// PDF ์ถœ๋ ฅ์„ ์œ„ํ•œ ์˜์กด์„ฑ ์„ค์ •
<dependency>
	<groupId>com.lowagie</groupId>
	<artifactId>itext</artifactId>
	<version>2.1.7</version>
</dependency>
    
    
// 2๋ฒˆ
// application.xml ๋ถ€๋ชจ ์„ค์ •ํŒŒ์ผ์— pdf ์ถœ๋ ฅํ•  ํด๋ž˜์Šค๋ฅผ ๋นˆ๊ฐ์ฒด๋กœ ์ƒ์„ฑ
// ๋นˆ๊ฐ์ฒด ์ƒ์„ฑ
<context:component-scan base-package="com.pdf.*" />
    
// Controller์—์„œ 'pdf' ๋กœ ๋ทฐ ์ด๋ฆ„ ์ „์†ก ์‹œ ๋ฐ‘์˜ com.pdf.web.PdfDownView ํด๋ž˜์Šค๊ฐ€ ์ฒ˜๋ฆฌ ํ›„ ํ™”๋ฉด์ถœ๋ ฅ
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <property name="order" value="0" />
</bean>
    
// pdf๋ผ๋Š” ๋ทฐ ์ด๋ฆ„์ด ์™”์„ ๋•Œ ์ถœ๋ ฅํ•  ๋ทฐ๋ฅผ ์„ค์ •
<bean id="pdf" class="com.pdf.web.PdfDownView"/>
    
    
// 3๋ฒˆ
// ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฆฌ์ŠคํŠธ๋กœ pdf์— ์ฐ์„ ๊ฐ’์„ ๋„˜๊ธด ํ›„ pdf ๋ž€ ์ด๋ฆ„์œผ๋กœ ๋ทฐ ์ด๋ฆ„ ๋ณด๋‚ด๊ธฐ
@RequestMapping("/pdfDown.mdo")
public String pdfDownload(Model model){
    //๋‚ ์งœ์šฉ ๋ฉ”์„œ๋“œ
    LocalDate now = LocalDate.now();
    DecimalFormat df = new DecimalFormat("00");
    Calendar currentCalendar = Calendar.getInstance();
    // ์ด๋ฒˆ ๋…„๋„	--> 2022
    int year = now.getYear();
    //์ด๋ฒˆ๋‹ฌ		--> 03
    String month  = df.format(currentCalendar.get(Calendar.MONTH) + 1);
    // ์ด๋ฒˆ๋‹ฌ ์‹œ์ž‘์ผ
    String startDay = year+"-"+month+"-"+"01";
    // ์ด๋ฒˆ๋‹ฌ ๋งˆ์ง€๋ง‰์ผ
    int str = currentCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    String endDay = year+"-"+month+"-"+str;
    AdminReportDayVO vo = new AdminReportDayVO();
    vo.setDate(startDay);
    vo.setImpl(endDay);
    List<AdminReportDayVO> list2 = adminReportDayService.reportMonth(vo);
    //์ถœ๋ ฅํ•  ๋ทฐ ์ด๋ฆ„ ๋ฆฌํ„ด
    model.addAttribute("list", list2);
    return "pdf";
}
// 4๋ฒˆ
// com.pdf.web.PdfDownView ํด๋ž˜์Šค์˜ pdf๋ฅผ ์ƒˆ์ฐฝ์œผ๋กœ ๋„์›Œ์„œ ์ถœ๋ ฅํ•˜๋Š” ๋ฉ”์„œ๋“œ
	//์ฒซ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ Controller๊ฐ€ ๋„˜๊ฒจ์ค€ ๋ฐ์ดํ„ฐ 
    //๋‘๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ถœ๋ ฅํ•  ๋ฌธ์„œ
@Override
protected void buildPdfDocument(Map<String, Object> model, Document doc, PdfWriter writer, HttpServletRequest request,HttpServletResponse response) throws Exception {
    List<String> list = (List<String>)model.get("list");
    XMLWorkerHelper helper = XMLWorkerHelper.getInstance();
    //ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑ
    //1์—ด list.size()+1 ํ–‰์œผ๋กœ ์ƒ์„ฑ
    Table table = new Table(1,list.size()+1);
    
    /* ์ค‘๊ฐ„ ์ฝ”๋“œ ์ƒ๋žต */
    
    String path =request.getSession().getServletContext().getRealPath("/");
    BaseFont baseFont= BaseFont.createFont(path +"/resources/pdfFresh/fresh.ttf".replace('/', File.separatorChar), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    Font font = new Font(baseFont);
    Cell cell = new Cell(new Paragraph("๊ฒฐ์ œ ์˜์ˆ˜์ฆ",font));
    cell.setHeader(true);
    table.addCell(cell);
    table.endHeaders();
    //๋ฐ์ดํ„ฐ๋ฅผ ํ…Œ์ด๋ธ”์˜ ์…€์— ์ถœ๋ ฅ
    for(String language : list){
        Cell imsi = new Cell(new Paragraph(language,font));
        table.addCell(imsi);
    }
    //๋ฌธ์„œ์— ํ…Œ์ด๋ธ” ์ถ”๊ฐ€
    doc.add(table);
}

(3) ์‹œ์—ฐ

PDF ํŒŒ์ผ ๋‹ค์šด ์‹œ์—ฐ ์˜์ƒ (10์ดˆ)
default.mp4

5.2. DB์—์„œ ํ•œ ์ปฌ๋Ÿผ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ด๋ฏธ์ง€ URL์„ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

1) ๋ฌธ์ œ ์ƒํ™ฉ

  • ๊ฐ ์ƒํ’ˆ์˜ ์†Œ๊ฐœ๋ฅผ ์œ„ํ•œ ์ด๋ฏธ์ง€ URL ์ปฌ๋Ÿผ ๊ฐœ์ˆ˜๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„์„œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๊ฐ€ ์‰ฝ์ง€ ์•Š์€ ํ˜„์ƒ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

2) ์›์ธ ๋ถ„์„

  • ๊ฐ ์ƒํ’ˆ์˜ ์†Œ๊ฐœ ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜๊ฐ€ ํ‰๊ท ์ ์œผ๋กœ 10๊ฐœ ์ด์ƒ์ž…๋‹ˆ๋‹ค.
  • ์ƒํ’ˆ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ๊ณ  ๊ฐ ์ƒํ’ˆ์˜ ์†Œ๊ฐœ์—์„œ ์“ฐ์ด๋Š” ์ด๋ฏธ์ง€์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ „๋ถ€ ๋‹ค ๋‹ฌ๋ผ์„œ, ๊ณตํ†ต์œผ๋กœ ์ด๋ฏธ์ง€ URL์„ ๊ด€๋ฆฌํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

3) ๋ฌธ์ œ ํ•ด๊ฒฐ - ๊ณ ์œ ํ•œ ๊ตฌ๋ถ„์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ปฌ๋Ÿผ์œผ๋กœ ์ด๋ฏธ์ง€ URL ๊ด€๋ฆฌ

  • URL์—์„œ ์“ฐ์ด์ง€ ์•Š์„๋งŒํ•œ ๊ณ ์œ ํ•œ ๊ตฌ๋ถ„์ž๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ ์ƒํ’ˆ์˜ ์†Œ๊ฐœ ์ด๋ฏธ์ง€ URL๋“ค์„ ํ•ด๋‹น ๊ตฌ๋ถ„์ž๋ฅผ ์‚ฌ์ด์— ๋ผ์›Œ ๋„ฃ์–ด์„œ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด๋กœ ๋ถ™์ž…๋‹ˆ๋‹ค.
  • ๊ทธ ๋ฌธ์ž์—ด์„ ํ•˜๋‚˜์˜ ์ปฌ๋Ÿผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ ์ƒํ’ˆ ์†Œ๊ฐœ ํŽ˜์ด์ง€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ, ๊ทธ ๋ฌธ์ž์—ด์„ ๊ตฌ๋ถ„์ž๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ List๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • ๊ทธ ๋ฆฌ์ŠคํŠธ ์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  ์ด๋ฏธ์ง€ URL์„ ์ˆœ์ฐจ์ ์œผ๋กœ ๋ฝ‘์•„๋ƒ…๋‹ˆ๋‹ค.

4) ํ˜„์žฌ ์ €์˜ ์ƒ๊ฐ - ๋” ์ข‹์€ ๋ฌธ์ œ ํ•ด๊ฒฐ๋ฒ• (์ž‘์„ฑ ๋‚ ์งœ : 2023๋…„ 11์›”)

  • ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ•  ๋‹น์‹œ์— URL์„ ๊ตฌ๋ถ„์ž๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ปฌ๋Ÿผ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์ง€๊ธˆ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๋ฉด, ์ฐจ๋ผ๋ฆฌ ์ƒํ’ˆ ํ…Œ์ด๋ธ”๊ณผ 1๋Œ€N ๊ด€๊ณ„์ธ ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜ ๋” ๋งŒ๋“ค์–ด์„œ ๊ฐ ์ƒํ’ˆ๋งˆ๋‹ค ์—ฌ๋Ÿฌ๊ฐœ์˜ Image URL์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ์œผ๋ฉด ๋” ์ข‹์•˜๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.

5.3. ๋‹ฌ๋ ฅ ์ฒ˜๋ฆฌ ๋ฌธ์ œ (๋‹ฌ๋ ฅ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ง์ ‘ ๊ตฌํ˜„)

1) ๋ฌธ์ œ ์ƒํ™ฉ

  • ์ƒํ’ˆ ์„ ํƒ ํ›„, ๋ฐฐ์†ก ์˜ˆ์ •์ผ์„ ์„ ํƒํ•  ๋•Œ ๋‹ฌ๋ ฅ์„ ๋„์šฐ๊ธฐ ์œ„ํ•ด DatePicker API ๋ฅผ ์ด์šฉํ•ด ๊ฐ€์ ธ์™”์ง€๋งŒ ํ•ด๋‹น ํŽ˜์ด์ง€์™€์˜ CSS ๊ฐ€ ๋„ˆ๋ฌด ์—‡๋‚˜๊ฐ€๋Š” ๋Š๋‚Œ์ด ๋“œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ (CSS ์˜ ์กฐ์ ˆ์ด ๋ถˆ๊ฐ€๋Šฅ)

2) ๋ฌธ์ œ ํ•ด๊ฒฐ

  • ํ˜„์žฌ ๋‹ฌ๋ ฅ ๋ชจ๋‹ฌ์ฐฝ์˜ CSS๋ฅผ ํŽ˜์ด์ง€์— ๋งž๊ฒŒ ์ˆ˜์ • ํ›„ ๋‹ฌ๋ ฅ์˜ ๋‚ ์งœ๊ฐ€ ๋งค์ผ ๊ฐฑ์‹ ๋˜๋„๋ก ๋‹ฌ๋ ฅ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ง์ ‘ ๊ตฌํ˜„
  • ๊ฐœ์„ ๋œ ์ฝ”๋“œ ์ฐธ์กฐ
๊ฐœ์„ ๋œ ์ฝ”๋“œ 1๋ฒˆ (ํด๋ฆญ)
// 1๋ฒˆ
// ํ™”๋ฉด๋‹จ์—์„œ ์—ฐ, ์›”, ์ผ์„ ๋ฐ›์•„์„œ ์œค๋…„, ์›”์„ ๋ถ„๋ฅ˜ํ•ด์„œ ๊ทธ์— ๋งž๋Š” ๋ฐฐ์—ด ๊ธธ์ด๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.
// ํ™”๋ฉด๋‹จ์—์„œ ๋ฐ›์€ getDay (ํ˜„์žฌ ๋‚ ์งœ๊ฐ€ ์ผ์ฃผ์ผ ์ค‘ ๋ช‡๋ฒˆ์งธ ์š”์ผ์ธ์ง€) ์ •๋ณด๋ฅผ ๋‹ฌ๋ ฅ ๋ชจ๋‹ฌ์ฐฝ์— ๋„˜๊ฒจ์„œ 
	// ์›”๋งˆ๋‹ค ์–ด๋–ค ์š”์ผ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š”์ง€ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

@RequestMapping("/orderDateCalendar.do")
public ModelAndView orderDateCalendarDo(ModelAndView mav, String year, String month, String day, String getDay) {
    System.out.println(Integer.parseInt(month));
    String[] dateNum;
    if(Integer.parseInt(month) == 1 || Integer.parseInt(month) == 3 || Integer.parseInt(month) == 5 || Integer.parseInt(month) == 7
       || Integer.parseInt(month) == 8 || Integer.parseInt(month) == 10 || Integer.parseInt(month) == 12) {
        dateNum = new String[38];
    }else if(Integer.parseInt(month) == 2) {
        if(Integer.parseInt(year) % 4 == 0){
            if(Integer.parseInt(year) % 400 != 0 && Integer.parseInt(year) % 100 == 0) {
                dateNum = new String[35];
            }else {
                dateNum = new String[36];
            }
        }else {
            dateNum = new String[35];
        }
    }else {
        dateNum = new String[37];
    }
    int getDayNum = Integer.parseInt(getDay);
    String[] getD = new String[getDayNum];
    int mon = Integer.parseInt(month);

    mav.addObject("remainSu", getDayNum);
    mav.addObject("remainCheck", getD);
    mav.addObject("year", year);
    mav.addObject("check", day);
    mav.addObject("month", mon);
    mav.addObject("list", dateNum);
    mav.setViewName("orderDateCalendar");
    return mav;
}
๊ฐœ์„ ๋œ ์ฝ”๋“œ 2๋ฒˆ (ํด๋ฆญ)
<!-- 2๋ฒˆ -->

<!-- ์กฐ๊ฑด 4๊ฐ€์ง€๋ฅผ if๋ฌธ์œผ๋กœ ๋‚˜๋ˆ ์„œ, ์œ„์น˜๋ฅผ ์ง€์ •ํ•ด์ฃผ๋Š” style์˜ grid-area ์†์„ฑ์„ ํ†ตํ•ด ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„ -->
<!-- 1. ์ €๋ฒˆ ๋‹ฌ์— ์†ํ•œ ๋‚ ์งœ (๋นˆ์นธ ๋น„์›Œ๋‘๋Š” ์šฉ๋„)-->
<!-- 2. ์ด๋ฒˆ ๋‹ฌ์— ์†ํ–ˆ์ง€๋งŒ ์˜ค๋Š˜ ๋‚ ์งœ๋ณด๋‹ค ์ „์ธ ๋‚ (์˜ค๋Š˜๋‚ ์งœ ํฌํ•จ) -->
<!-- 3. ์ด๋ฒˆ ๋‹ฌ์— ์†ํ•˜๋ฉด์„œ ์˜ค๋Š˜ ๋‚ ์งœ๋ณด๋‹ค ํ›„์˜ ๋‚  -->
<!-- 4. ๋‹ฌ๋ ฅ์„ 5์ค„๋กœ ๋งž์ถฐ์•ผ ํ•˜๊ธฐ์— 4์ค„๋กœ ๋๋‚˜๋Š” ๋‹ฌ์€ ๊ณต๋ฐฑ ๋‚ ์งœ ์ผ์ฃผ์ผ์„ ๋” ์ถ”๊ฐ€ -->

<!-- span ํƒœ๊ทธ id์†์„ฑ, text์— ๋‚ ์งœ ์ž…๋ ฅ -->
<!-- ๋ณด๊ธฐ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด class ์†์„ฑ์€ ์ „๋ถ€ ์ง€์› ์Šต๋‹ˆ๋‹ค. -->



<!-- 1. ์ €๋ฒˆ ๋‹ฌ์— ์†ํ•œ ๋‚ ์งœ (๋นˆ์นธ ๋น„์›Œ๋‘๋Š” ์šฉ๋„)-->
<c:forEach var="remain" items="${remainCheck }" varStatus="i">
	
    <!-- grid-area ์†์„ฑ์— ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ ์šฉ -->
    <div data-v-3ca35a05="" style="grid-area: 2/${i.count}/auto/auto;">
        <div data-v-2aac4f42="" data-v-4a5f2beb="" attributes="[object Object]" data-v-3ca35a05="">
            <div data-v-2aac4f42="">
                <span data-v-2aac4f42=""></span>
            </div>
        </div>
    </div>
</c:forEach>



<c:forEach var="list1" items="${list }" varStatus="i">
    <c:if test="${fn:length(list) == 38}">
        <c:if test="${i.count <= 31}">
		
	    <!-- grid-area ์†์„ฑ์— ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ ์šฉ -->
            <div data-v-3ca35a05="" style="grid-area: ${(i.count + remainSu - 1) / 7 + 2}/${(i.count + remainSu - 1) % 7 + 1}/auto/auto;">
                <div data-v-2aac4f42="" data-v-4a5f2beb="" data-v-3ca35a05="">
                    
                    
                    <!-- 2. ์ด๋ฒˆ ๋‹ฌ์— ์†ํ–ˆ์ง€๋งŒ ์˜ค๋Š˜ ๋‚ ์งœ๋ณด๋‹ค ์ „์ธ ๋‚ (์˜ค๋Š˜๋‚ ์งœ ํฌํ•จ) -->
                    <c:if test="${i.count <= check }">
                        <div data-v-2aac4f42="" class="vc-h-full">
                            <span data-v-2aac4f42="" tabindex="-1" id="${year}/${month}/${i.count}">${i.count }</span>
                        </div>
                    </c:if>
                    
                    
                    <!-- 3. ์ด๋ฒˆ ๋‹ฌ์— ์†ํ•˜๋ฉด์„œ ์˜ค๋Š˜ ๋‚ ์งœ๋ณด๋‹ค ํ›„์˜ ๋‚  -->
                    <c:if test="${i.count > check }">
                        <div data-v-2aac4f42="" class="vc-h-full">
                            <span data-v-2aac4f42="" tabindex="-1" id="${year}/${month}/${i.count}">${i.count }</span>
                        </div>
                    </c:if>
                </div>
            </div>
        </c:if>
        
        
        <!-- 4. ๋‹ฌ๋ ฅ์„ 5์ค„๋กœ ๋งž์ถฐ์•ผ ํ•˜๊ธฐ์— 4์ค„๋กœ ๋๋‚˜๋Š” ๋‹ฌ์€ ๊ณต๋ฐฑ ๋‚ ์งœ ์ผ์ฃผ์ผ์„ ๋” ์ถ”๊ฐ€ -->
        <c:if test="${i.count > 31 && remainSu < 5}">
		
	    <!-- grid-area ์†์„ฑ์— ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ ์šฉ -->
            <div data-v-3ca35a05="" style="grid-area: ${(i.count + remainSu - 1) / 7 + 2}/${(i.count + remainSu - 1) % 7 + 1}/auto/auto;">
                <div data-v-2aac4f42="" data-v-4a5f2beb="" data-v-3ca35a05="">
                    <div data-v-2aac4f42="" >
                        <span data-v-2aac4f42="" id="${year}/${month}/${i.count}">27</span>
                    </div>
                </div>
            </div>
        </c:if>
    </c:if>
    
    
    <!-- ์ด ์ดํ›„๋ก  ๋„˜์–ด์˜จ ๋ฐฐ์—ด์˜ ๊ธธ์ด๋งˆ๋‹ค ์กฐ๊ฑด๋งŒ ๋‹ค๋ฅด๊ฒŒ ์ฃผ๋ฉด์„œ ์œ„์˜ ํ˜•์‹๊ณผ ๋™์ผํ•˜๊ฒŒ 3๋ฒˆ ๋” ๋ฐ˜๋ณตํ•˜๊ธฐ์— ์ƒ๋žต -->
    
    
    <c:if test="${fn:length(list) == 37}">
        <c:if test="${i.count <= 30}">
            <div data-v-3ca35a05="" style="grid-area: ${(i.count + remainSu - 1) / 7 + 2}/${(i.count + remainSu - 1) % 7 + 1}/auto/auto;">
                
                			<!-- ์ƒ๋žต -->
    </c:if>
</c:forEach>

  • (3) ์‹œ์—ฐ

๋‹ฌ๋ ฅ ๋ชจ๋‹ฌ์ฐฝ ์‹œ์—ฐ ์˜์ƒ (10์ดˆ)
default.mp4

6. ๊ทธ ์™ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

1) aws s3 ์—‘์„ธ์Šค ํ‚ค, ์‹œํฌ๋ฆฟ ํ‚ค ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

  • ์‹ค์ˆ˜๋กœ ๊นƒํ—ˆ๋ธŒ์— AWS S3์˜ ์—‘์„ธ์Šค, ์‹œํฌ๋ฆฟ ํ‚ค๋ฅผ ์˜ฌ๋ฆฌ๊ฒŒ ๋ผ์„œ AWS ๊ณ„์ • ํ์‡„ ์œ„๊ธฐ ์ง๋ฉด

  • ํ•ด๊ฒฐ
    • (1) AWS ๋ฃจํŠธ ๊ณ„์ • ์•”ํ˜ธ์™€ IAM(Identity and Access Management) ์‚ฌ์šฉ์ž์˜ ์•”ํ˜ธ ๋ณ€๊ฒฝ

    • (2) AWS Management ์ฝ˜์†”์„ ํ™•์ธํ•˜์—ฌ ๋ชจ๋“  ์‚ฌ์šฉ์ด ์Šน์ธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ

    • (3) ์ž๋ฐ” ํŒŒ์ผ์ด ์•„๋‹Œ DB์— ์—‘์„ธ์Šค ํ‚ค, ์‹œํฌ๋ฆฟ ํ‚ค๋ฅผ ์ €์žฅํ•˜๊ณ , ํ•„์š” ์‹œ ๊บผ๋‚ด์„œ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
๊ฐœ์„ ๋œ ์ฝ”๋“œ (ํด๋ฆญ)
// ๊ด€๋ฆฌ์ž์˜ ์ƒํ’ˆ ๋“ฑ๋ก ์ฝ”๋“œ ์ค‘...
    
// ๋ฉ”์ธ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
try {
        AwsS3 awsS3 = new AwsS3();
        
        // awsS3Service ์„œ๋น„์Šค ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด DB์—์„œ ํ‚ค ๊บผ๋‚ด์˜ค๊ธฐ
        AwsS3VO avo = awsS3Service.getKey();
        awsS3.setAccessKey(avo.getA_key());
        awsS3.setSecretKey(avo.getS_key());
        
        // ๋ฐ›์•„์˜จ ํ‚ค๋ฅผ ํ†ตํ•ด AmazonS3 ๊ฐ์ฒด ์ƒ์„ฑ
        awsS3.createS3Client();
        String key = "menu/" + uploadFile.getOriginalFilename();
        InputStream is = uploadFile.getInputStream();
        String contentType = uploadFile.getContentType();
        long contentLength = uploadFile.getSize();
        
        // ์ด๋ฏธ์ง€ ํŒŒ์ผ S3์— ์—…๋กœ๋“œ
        awsS3.upload(is, key, contentType, contentLength);
    
        // DB์— S3 ์ด๋ฏธ์ง€ ํŒŒ์ผ URL ์ €์žฅ
        vo.setItem_image(url + key);
	adminItemService.itemInsert(vo);
} catch (IOException e) {
	System.out.println("๋ฉ”์ธ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์‹คํŒจ");
}

2) WAS(tomcat ์„œ๋ฒ„)๋ฅผ ํ†ตํ•ด war ํŒŒ์ผ๋กœ ๋ฐฐํฌ ํ›„ ๊ตฌ๊ธ€ ๋กœ๊ทธ์ธ API๊ฐ€ "popup_closed_by_user" ๊ฒฝ๊ณ ์ฐฝ์ด ๋œจ๋ฉด์„œ ๋กœ๊ทธ์ธ์ด ์•ˆ๋˜๋Š” ๋ฌธ์ œ

  • ํ•ด๊ฒฐ : ํฌ๋กฌ ์šฐ์ธก ์ƒ๋‹จ ๋”๋ณด๊ธฐ -> ๋„๊ตฌ ๋”๋ณด๊ธฐ -> ์ธํ„ฐ๋„ท ์‚ฌ์šฉ ๊ธฐ๋ก ์‚ญ์ œ -> ์บ์‹œ๋œ ์ด๋ฏธ์ง€ ๋ฐ ํŒŒ์ผ๋งŒ ์ฒดํฌ -> ์ธํ„ฐ๋„ท ์‚ฌ์šฉ ๊ธฐ๋ก ์‚ญ์ œ ๋ฒ„ํŠผ ํด๋ฆญ

3) ์นด์นด์˜ค ๋กœ๊ทธ์ธ API ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ ๋‘๋ฒˆ์งธ ๋กœ๊ทธ์ธ๋ถ€ํ„ฐ ์ •๋ณด ์ œ๊ณต ๋™์˜ ํ™”๋ฉด์ด ๋„์›Œ์ง€์ง€ ์•Š๋Š” ๋ฌธ์ œ

  • ํ•ด๊ฒฐ : https://accounts.kakao.com/weblogin/account/info ๋งํฌ(๊ณ„์ •๊ด€๋ฆฌ ์‚ฌ์ดํŠธ)์— ๋“ค์–ด๊ฐ€์„œ ์ƒ๋‹จ์— ๊ณ„์ • ์ด์šฉ ํƒญ -> ์™ธ๋ถ€ ์„œ๋น„์Šค ์ „์ฒด๋ณด๊ธฐ -> ํ•ด๋‹น ์„œ๋น„์Šค(์•ฑ) ์—ฐ๊ฒฐ ๋Š๊ธฐ

4) ์ด๋ฏธ์ง€ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ฒ˜๋ฆฌ ๋ฌธ์ œ

  • ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ ๋ฒ„ํŠผ ํด๋ฆญ -> ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์„ ํƒ ํ›„, ์„ ํƒํ•œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋ฒ„ํŠผ ์˜†์— ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ 
๊ฐœ์„ ๋œ ์ฝ”๋“œ (ํด๋ฆญ)
function readURL1(input) {
    
    // ์ธํ’‹ ํƒœ๊ทธ์— ํŒŒ์ผ์ด ์žˆ๋Š” ๊ฒฝ์šฐ
    if (input.files && input.files[0]) {
        
        // FileReader ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        var reader = new FileReader();
        
        // ์ด๋ฏธ์ง€๊ฐ€ ๋กœ๋“œ ๋œ ๊ฒฝ์šฐ
        reader.onload = function (e) {
            // ์ด๋ฏธ์ง€ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋„์šฐ๊ธฐ
            $(".preview-images1").css({"background":"url(" + e.target.result + ")"});
        }
        
        // reader ๊ฐ€ ์ด๋ฏธ์ง€ ์ฝ๋„๋ก ํ•˜๊ธฐ
        reader.readAsDataURL(input.files[0]);
    }

    $('#image-file-button1').parent().css('display', 'none');
    $('#image-file-button2').parent().css('display', '');
}