Skip to content

9oormthon-univ/2024_BEOTKKOTTHON_TEAM_10_BE_EXPRESS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

35 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽ“ CEN โ€“ ๋งž์ถคํ˜• ์žฅํ•™๊ธˆ ์ •๋ณด ์ œ๊ณต ์•ฑ (Express ๋ฐฑ์—”๋“œ)

์†Œ๋“๋ถ„์œ„ยท๊ฑฐ์ฃผ์ง€ยท์ „๊ณต ๊ธฐ๋ฐ˜ ์žฅํ•™๊ธˆ ์ž๋™ ์ถ”์ฒœ + D-day ์•Œ๋ฆผ ์„œ๋น„์Šค์˜ Node.js API ์„œ๋ฒ„

Node.js Express MySQL PM2 License


๐Ÿ“Œ ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

์ฃผ๋ณ€ ํ•™์ƒ๋“ค์ด ์กฐ๊ฑด์— ๋งž๋Š” ์žฅํ•™๊ธˆ ๊ณต๊ณ ๋ฅผ ๋†“์น˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ž์ฃผ ๋ชฉ๊ฒฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ •๋ณด๋Š” ์กด์žฌํ•˜์ง€๋งŒ ์ ‘๊ทผ์ด ๋ถˆํŽธํ•˜๊ณ , ๋งˆ๊ฐ์ผ์„ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•ด ํ˜œํƒ์„ ๋ฐ›์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค.

CEN์€ ํ•™์ƒ ๊ฐœ์ธ ์ •๋ณด(์†Œ๋“๋ถ„์œ„ยท๊ฑฐ์ฃผ์ง€ยท์ „๊ณตยทํ•™์ )๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งž์ถค ์žฅํ•™๊ธˆ์„ ์ž๋™ ์ถ”์ฒœํ•˜๊ณ , ๋งˆ๊ฐ D-day๋ฅผ ์•ฑ ํ‘ธ์‹œ๋กœ ์•Œ๋ ค์ฃผ๋Š” ์›์Šคํ†ฑ ์žฅํ•™๊ธˆ ์ •๋ณด ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.

๊ณต๊ณต๋ฐ์ดํ„ฐ API โ†’ ์žฅํ•™๊ธˆ DB ์ ์žฌ โ†’ ์‚ฌ์šฉ์ž ์กฐ๊ฑด ํ•„ํ„ฐ๋ง โ†’ ๋งž์ถค ์ถ”์ฒœ + ํ‘ธ์‹œ ์•Œ๋ฆผ

2024 ๋ฒš๊ฝƒํ†ค ํ•ด์ปคํ†ค ์ถœํ’ˆ์ž‘ (ํŒ€์› 6์ธ / Backend Developer ์—ญํ• )


โœจ ์ฃผ์š” ๊ธฐ๋Šฅ

๐Ÿ” ์‚ฌ์šฉ์ž ์ธ์ฆ

  • ํšŒ์›๊ฐ€์ž… / ๋กœ๊ทธ์ธ โ€” bcrypt ํ•ด์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ + JWT Access Token (7์ผ ์œ ํšจ)
  • ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ โ€” ์ด๋ฆ„ + ์•„์ด๋”” ๊ฒ€์ฆ ํ›„ ์žฌ๋ฐœ๊ธ‰
  • JWT ๋ฏธ๋“ค์›จ์–ด โ€” ๋ชจ๋“  ์ธ์ฆ ํ•„์š” API์—์„œ ํ† ํฐ ๊ฒ€์ฆ

๐ŸŽฏ ์˜จ๋ณด๋”ฉ & ๋งž์ถค ์ถ”์ฒœ

  • ์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ ์†Œ๋“๋ถ„์œ„ยทํ•™์ ยท๊ฑฐ์ฃผ์ง€ยท์ „๊ณต ์ž…๋ ฅ (์˜จ๋ณด๋”ฉ)
  • ์˜จ๋ณด๋”ฉ ์™„๋ฃŒ ์—ฌ๋ถ€ ์ฒดํฌ API ์ œ๊ณต
  • ํ•ด์‹œํƒœ๊ทธ(์กฐ๊ฑด ํ•„ํ„ฐ) ์กฐํšŒ API

๐Ÿ“… ์žฅํ•™๊ธˆ ์บ˜๋ฆฐ๋”

  • ์Šคํฌ๋žฉํ•œ ์žฅํ•™๊ธˆ์˜ ๋งˆ๊ฐ์ผ์„ ์›”๋ณ„ / ์ผ๋ณ„ ์บ˜๋ฆฐ๋”๋กœ ์กฐํšŒ
  • D-day ์ž๋™ ๊ณ„์‚ฐ (D-1, D-day, D+1 ํ˜•์‹)
  • ์‹ ์ฒญ ์ƒํƒœ(status) ํ•จ๊ป˜ ๋ฐ˜ํ™˜

๐Ÿ”” iOS ํ‘ธ์‹œ ์•Œ๋ฆผ (APN)

  • 10์ดˆ๋งˆ๋‹ค ์ƒˆ ์žฅํ•™๊ธˆ ๊ณต๊ณ  ๊ฐ์ง€
  • ์‹ ๊ทœ ๊ณต๊ณ  ๋“ฑ๋ก ์‹œ ๋“ฑ๋ก๋œ ๋ชจ๋“  iOS ๋””๋ฐ”์ด์Šค์— ํ‘ธ์‹œ ๋ฐœ์†ก
  • Apple Push Notification ์„œ๋น„์Šค(APN) ์—ฐ๋™

๐Ÿ”€ API Gateway (Spring Boot ํ”„๋ก์‹œ)

  • Express + Spring Boot ํ˜ผ์žฌ ํ™˜๊ฒฝ์—์„œ ์ธ์ฆ ๋‹จ์ผํ™”
  • JWT ๊ฒ€์ฆ ํ›„ Spring ๋ฐฑ์—”๋“œ๋กœ ์š”์ฒญ ํ”„๋ก์‹œ
  • ์ธ์ฆ ๋ณต์žก๋„๋ฅผ Express Gateway์—์„œ ํ†ตํ•ฉ ์ฒ˜๋ฆฌ

๐Ÿ—๏ธ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜

[iOS ์•ฑ (Swift)]
       โ”‚
       โ–ผ
[Express.js API Gateway :8001]
  โ”œโ”€โ”€ JWT ์ธ์ฆ ๋ฏธ๋“ค์›จ์–ด
  โ”œโ”€โ”€ ์ง์ ‘ ์ฒ˜๋ฆฌ (User, Calendar, Scholarship)
  โ”‚       โ”‚
  โ”‚       โ–ผ
  โ”‚   [MySQL DB]
  โ”‚   โ”œโ”€โ”€ users
  โ”‚   โ”œโ”€โ”€ scholarships
  โ”‚   โ”œโ”€โ”€ saves (์Šคํฌ๋žฉ)
  โ”‚   โ””โ”€โ”€ Userdevice (ํ‘ธ์‹œ ํ† ํฐ)
  โ”‚
  โ””โ”€โ”€ ํ”„๋ก์‹œ (Spring Boot :?)
          โ”‚
          โ–ผ
      [Spring Boot API]
      (์žฅํ•™๊ธˆ ์ถ”์ฒœ ๋กœ์ง, ์ƒํƒœ๊ด€๋ฆฌ ๋“ฑ)

[node-cron / setInterval]
  โ””โ”€โ”€ 10์ดˆ๋งˆ๋‹ค ์‹ ๊ทœ ์žฅํ•™๊ธˆ ๊ฐ์ง€ โ†’ APN ํ‘ธ์‹œ

ํ•ต์‹ฌ ์„ค๊ณ„ ๊ฒฐ์ • โ€” API Gateway ํŒจํ„ด: Express์™€ Spring Boot๊ฐ€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋Š” ํ™˜๊ฒฝ์—์„œ, ๋ชจ๋“  ์š”์ฒญ์„ Express๊ฐ€ ๋จผ์ € ๋ฐ›์•„ JWT๋ฅผ ๊ฒ€์ฆํ•œ ๋’ค Spring์œผ๋กœ ํ”„๋ก์‹œํ•ฉ๋‹ˆ๋‹ค. โ†’ ์ธ์ฆ ๋กœ์ง ์ค‘๋ณต ์ œ๊ฑฐ, ๊ฐœ๋ฐœ ๋ณต์žก๋„ ๊ฐ์†Œ, ๋ฐฐํฌ ๊ตฌ์กฐ ๋ช…ํ™•ํ™”


๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ

๋ถ„๋ฅ˜ ๊ธฐ์ˆ 
Runtime Node.js
Framework Express.js 4.18
Auth JWT (jsonwebtoken), bcrypt
DB MySQL + Sequelize ORM
Push Apple APNs (apn ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)
Proxy express-http-proxy, http-proxy-middleware
Scheduler node-cron, setInterval
Process PM2 (ํ”„๋กœ์„ธ์Šค ๊ด€๋ฆฌ)
Dev nodemon

๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

.
โ”œโ”€โ”€ server.js                    # ์ง„์ž…์  (Express ์•ฑ ์„ค์ • + ํ‘ธ์‹œ ์Šค์ผ€์ค„๋Ÿฌ)
โ”œโ”€โ”€ routes/
โ”‚   โ”œโ”€โ”€ user.js                  # ํšŒ์›๊ฐ€์ž…/๋กœ๊ทธ์ธ/์˜จ๋ณด๋”ฉ/๋””๋ฐ”์ด์Šคํ† ํฐ
โ”‚   โ”œโ”€โ”€ scholarship.js           # ์žฅํ•™๊ธˆ ๋ฐ์ดํ„ฐ ์ ์žฌ
โ”‚   โ”œโ”€โ”€ calendar.js              # ์›”๋ณ„ยท์ผ๋ณ„ ์บ˜๋ฆฐ๋” ์กฐํšŒ
โ”‚   โ”œโ”€โ”€ count.js                 # ์›”๋ณ„ ๋งˆ๊ฐ์ผ ์นด์šดํŠธ
โ”‚   โ””โ”€โ”€ proxy.js                 # Spring Boot ํ”„๋ก์‹œ ๋ผ์šฐํ„ฐ
โ”œโ”€โ”€ controller/
โ”‚   โ”œโ”€โ”€ user.js                  # ์‚ฌ์šฉ์ž CRUD + JWT ๋ฐœ๊ธ‰
โ”‚   โ”œโ”€โ”€ scholarship.js           # ์žฅํ•™๊ธˆ DB ์ƒ์„ฑ
โ”‚   โ””โ”€โ”€ calendar.js              # ์บ˜๋ฆฐ๋” ๋กœ์ง + D-day ๊ณ„์‚ฐ
โ”œโ”€โ”€ middleware/
โ”‚   โ””โ”€โ”€ auth.js                  # JWT verifyToken ๋ฏธ๋“ค์›จ์–ด
โ”œโ”€โ”€ proxy/
โ”‚   โ””โ”€โ”€ proxy.js                 # Spring ๋ฐฑ์—”๋“œ ํ”„๋ก์‹œ ํ•จ์ˆ˜
โ”œโ”€โ”€ services/
โ”‚   โ””โ”€โ”€ notification.js          # APN ํ‘ธ์‹œ ์•Œ๋ฆผ ์„œ๋น„์Šค
โ”œโ”€โ”€ models/
โ”‚   โ”œโ”€โ”€ user.js
โ”‚   โ”œโ”€โ”€ scholarship.js
โ”‚   โ”œโ”€โ”€ scrapped.js              # ์Šคํฌ๋žฉ (saves ํ…Œ์ด๋ธ”)
โ”‚   โ”œโ”€โ”€ userdevice.js            # iOS ๋””๋ฐ”์ด์Šค ํ† ํฐ
โ”‚   โ””โ”€โ”€ count.js                 # ์žฅํ•™๊ธˆ ์นด์šดํŠธ (์‹ ๊ทœ ๊ฐ์ง€์šฉ)
โ”œโ”€โ”€ migrations/                  # Sequelize ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
โ””โ”€โ”€ config/
    โ””โ”€โ”€ config.json              # DB ์—ฐ๊ฒฐ ์„ค์ •

๐Ÿ—„๏ธ DB ์Šคํ‚ค๋งˆ

users
โ”œโ”€โ”€ userid (PK, STRING)
โ”œโ”€โ”€ password (STRING, bcrypt ํ•ด์‹œ)
โ”œโ”€โ”€ name (STRING)
โ”œโ”€โ”€ ranking (STRING)        โ† ์†Œ๋“๋ถ„์œ„
โ”œโ”€โ”€ grade (STRING)          โ† ํ•™์ 
โ”œโ”€โ”€ region_city_province (STRING)
โ”œโ”€โ”€ region_city_country_district (STRING)
โ”œโ”€โ”€ major (STRING)
โ””โ”€โ”€ onboard (BOOLEAN)

scholarships (scholarships ํ…Œ์ด๋ธ”)
โ”œโ”€โ”€ id (PK, AUTO_INCREMENT)
โ”œโ”€โ”€ title, provider
โ”œโ”€โ”€ start_date, end_date
โ”œโ”€โ”€ amount, amount2
โ”œโ”€โ”€ support_ranking, support_grade, support_major
โ”œโ”€โ”€ support_city_province
โ”œโ”€โ”€ support_target, support_target2, support_target3
โ”œโ”€โ”€ description ~ description4
โ”œโ”€โ”€ required_documents
โ””โ”€โ”€ site

saves  (์Šคํฌ๋žฉ = Scrapped ๋ชจ๋ธ)
โ”œโ”€โ”€ userid (STRING)
โ”œโ”€โ”€ scholarship_id (INTEGER)
โ””โ”€โ”€ status (STRING)

Userdevice
โ”œโ”€โ”€ userid (PK, STRING)
โ””โ”€โ”€ devicetoken (STRING)

CountScholarship  (Count ๋ชจ๋ธ โ€” ์‹ ๊ทœ ์žฅํ•™๊ธˆ ๊ฐ์ง€์šฉ)
โ”œโ”€โ”€ id (PK, AUTO_INCREMENT)
โ””โ”€โ”€ count (INTEGER)

๐Ÿ”” ํ‘ธ์‹œ ์•Œ๋ฆผ ๋™์ž‘ ๋ฐฉ์‹

[server.js] setInterval(sendPushNotification, 10 * 1000)
                โ”‚
                โ–ผ
[services/notification.js]
  1. DB์—์„œ ์ „์ฒด ์žฅํ•™๊ธˆ ์ˆ˜(scholarships.length) ์กฐํšŒ
  2. CountScholarship ํ…Œ์ด๋ธ”์˜ ๋งˆ์ง€๋ง‰ count์™€ ๋น„๊ต
  3. ์‹ ๊ทœ ์žฅํ•™๊ธˆ ์žˆ์œผ๋ฉด โ†’ count ์—…๋ฐ์ดํŠธ
  4. Userdevice ํ…Œ์ด๋ธ”์—์„œ ๋ชจ๋“  iOS ๋””๋ฐ”์ด์Šค ํ† ํฐ ์กฐํšŒ
  5. ๊ฐ ์‚ฌ์šฉ์ž์—๊ฒŒ APN ํ‘ธ์‹œ ๋ฐœ์†ก
     โ†’ "{name}๋‹˜ ์ƒˆ๋กœ์šด ๊ณต๊ณ ๊ฐ€ ์˜ฌ๋ผ์™”์Šต๋‹ˆ๋‹ค."

APN ์„ค์ •๊ฐ’ (.env ํ•„์š”):

  • APN_KEY_PATH โ€” Apple์—์„œ ๋ฐœ๊ธ‰ํ•œ .p8 ํ‚ค ํŒŒ์ผ ๊ฒฝ๋กœ
  • APN_KEY_ID โ€” Key ID (10์ž๋ฆฌ)
  • APN_TEAM_ID โ€” Apple Developer Team ID
  • APN_TOPIC โ€” ์•ฑ Bundle ID (์˜ˆ: com.yourcompany.CenApp)

๐Ÿ”„ JWT ์ธ์ฆ ํ๋ฆ„

ํด๋ผ์ด์–ธํŠธ                    Express ์„œ๋ฒ„
    โ”‚                             โ”‚
    โ”‚โ”€โ”€ POST /user/login โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚
    โ”‚                             โ”‚ bcrypt.compare(password, hash)
    โ”‚                             โ”‚ jwt.sign({ name, userid }, SECRET, { expiresIn: '7d' })
    โ”‚โ—€โ”€โ”€ { accesstoken } โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
    โ”‚                             โ”‚
    โ”‚โ”€โ”€ GET /user/hashtag โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚
    โ”‚   Header: accesstoken: xxx  โ”‚ jwt.verify(token, SECRET)
    โ”‚                             โ”‚ โ†’ decoded.userid โ†’ req.headers.userid
    โ”‚โ—€โ”€โ”€ { ranking, grade, ... } โ”€โ”‚

๐Ÿ› ๏ธ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… โ€” API Gateway ํŒจํ„ด์œผ๋กœ ์ธ์ฆ ๋ณต์žก๋„ ํ•ด๊ฒฐ

๋ฌธ์ œ

Express.js์™€ Spring Boot๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉํ•˜๋Š” ํŒ€ ๊ตฌ์„ฑ์—์„œ ๊ฐ ์„œ๋ฒ„๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ JWT ์ธ์ฆ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. โ†’ ์ธ์ฆ ๋กœ์ง ์ค‘๋ณต, ์ฝ”๋“œ ๋ณต์žก๋„ ์ฆ๊ฐ€, ํ† ํฐ ๋ถˆ์ผ์น˜ ์˜ค๋ฅ˜ ๋นˆ๋ฐœ

์›์ธ

์„œ๋กœ ๋‹ค๋ฅธ ๊ธฐ์ˆ  ์Šคํƒ(Node.js vs Java)์—์„œ JWT ๋ฐœ๊ธ‰ยท๊ฒ€์ฆ ๋กœ์ง์„ ๊ฐ์ž ๊ตฌํ˜„ํ•˜๋‹ค ๋ณด๋‹ˆ ํ‘œ์ค€์ด ๋‹ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ

Express๋ฅผ API Gateway๋กœ ์ง€์ •, ๋ชจ๋“  ์š”์ฒญ์„ Express๊ฐ€ ๋จผ์ € ์ˆ˜์‹ ํ•˜์—ฌ JWT๋ฅผ ๊ฒ€์ฆํ•œ ํ›„ Spring์œผ๋กœ ํ”„๋ก์‹œํ•˜๋Š” ๊ตฌ์กฐ๋ฅผ ์ฑ„ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Before:
  ํด๋ผ์ด์–ธํŠธ โ†’ Express (JWT ๊ฒ€์ฆ) โ†’ Express API
  ํด๋ผ์ด์–ธํŠธ โ†’ Spring (JWT ๊ฒ€์ฆ) โ†’ Spring API

After:
  ํด๋ผ์ด์–ธํŠธ โ†’ Express (JWT ๊ฒ€์ฆ 1ํšŒ) โ†’ Express API
                                      โ†’ Spring API (ํ”„๋ก์‹œ)

๊ฒฐ๊ณผ

  • ์ธ์ฆ ๋กœ์ง ๋‹จ์ผํ™” โ†’ ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐ
  • JWT ๊ด€๋ จ ์˜ค๋ฅ˜ ๊ฐ์†Œ
  • ๋ฐฐํฌ ๊ตฌ์กฐ ๋ช…ํ™•ํ™” โ†’ ํŒ€ ๊ฐœ๋ฐœ ์†๋„ ํ–ฅ์ƒ

๐Ÿ‘จโ€๐Ÿ’ป ๊ฐœ๋ฐœ์ž

์ด๋ฆ„ ์žฅ์„ฑ์›
์ด๋ฉ”์ผ [email protected]
GitHub github.com/jjang6251
๊ธฐ๊ฐ„ 2024.03 (ํ•ด์ปคํ†ค)
์—ญํ•  Backend Developer (6์ธ ํŒ€)

๋‹ด๋‹น ๊ตฌํ˜„:

  • middleware/auth.js โ€” JWT Access/Refresh Token ์„ค๊ณ„ ๋ฐ ๋ฏธ๋“ค์›จ์–ด
  • proxy/proxy.js + routes/proxy.js โ€” API Gateway ํŒจํ„ด ๊ตฌํ˜„
  • services/notification.js โ€” APN ํ‘ธ์‹œ ์•Œ๋ฆผ ์„œ๋น„์Šค
  • DB ์Šคํ‚ค๋งˆ ์„ค๊ณ„ ๋ฐ Sequelize ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
  • GCP ์ธํ”„๋ผ ๊ตฌ์„ฑ ๋ฐ ๋ฐฐํฌ

๐Ÿ“„ ๋ผ์ด์„ ์Šค

ISC License

About

CEN EXPRESS SERVER

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

โšก