/Runnect-Server

Server team repository of Runnect (Node.js) πŸƒπŸ»β€β™€οΈπŸƒπŸ»β€β™‚οΈπŸƒπŸ»

Primary LanguageTypeScript

πŸƒβ€β™€οΈ Runnect_Server

[32st SOPT APPJAM] Server team repository of Runnect

점과 점으둜, μ½”μŠ€μ™€ μ½”μŠ€λ‘œ μ—°κ²°λ˜λŠ” λ„ˆμ™€ λ‚˜μ˜ λŸ¬λ‹ κ²½ν—˜

ν‘œμ§€
A333



☝ μ„œλΉ„μŠ€ 핡심 κΈ°λŠ₯

1. μ½”μŠ€ 그리기

μ½”μŠ€ 그리기둜 달리기 μ „ λͺ©ν‘œλ₯Ό μ„€μ •ν•˜κ³  μ‹€μ‹œκ°„ νŠΈλž˜ν‚ΉμœΌλ‘œ μ½”μŠ€λ₯΄ 따라 잘 달리고 μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.

2. μ½”μŠ€ 발견

μ½”μŠ€ λ°œκ²¬μ„ 톡해 λ‚˜μ—κ²Œ λ§žλŠ” μ½”μŠ€λ₯Ό μΆ”μ²œ λ°›κ±°λ‚˜ λ‹€λ₯Έ μœ μ €κ°€ κ³΅μœ ν•œ μ½”μŠ€λ₯Ό κ²€μƒ‰ν•˜κ³  μŠ€ν¬λž©ν•©λ‹ˆλ‹€. μ½”μŠ€λ₯Ό 직접 μ—…λ‘œλ“œν•  수 도 μžˆμŠ΅λ‹ˆλ‹€.

3. μ½”μŠ€ 보관함

μ½”μŠ€ λ³΄κ΄€ν•¨μ—μ„œ λ‚΄κ°€ κ·Έλ¦° μ½”μŠ€μ™€ 슀크랩 μ½”μŠ€λ₯Ό κ΄€λ¦¬ν•©λ‹ˆλ‹€.

4. λ§ˆμ΄νŽ˜μ΄μ§€

λ§ˆμ΄νŽ˜μ΄μ§€μ—μ„œ ν”„λ‘œν•„κ³Ό ν™œλ™ 기둝, μ—…λ‘œλ“œν•œ μ½”μŠ€λ₯Ό ν™•μΈν•˜κ³  λͺ©ν‘œ λ³΄μƒμœΌλ‘œ 동기λ₯Ό κ°•ν™”ν•©λ‹ˆλ‹€.



πŸ”¨ Dependencies Module ( package.json )

{
  "name": "Runnect_Server",
  "version": "1.0.0",
  "main": "index.js",
  "repository": "https://github.com/Runnect/Runnect_Server.git",
  "author": "YuSuhwa-ve <dhfhfkzjxms@sookmyung.ac.kr>",
  "license": "MIT",
  "scripts": {
    "dev": "nodemon",
    "build": "tsc && node dist",
    "db:pull": "npx prisma db pull",
    "db:push": "npx prisma db push",
    "generate": "npx prisma generate",
    "prepare": "chmod ug+x .husky/* && husky install",
    "greet": "hello husky!",
    "test": "mocha ./test/ -r ts-node/register"
  },
  "dependencies": {
    "@prisma/client": "^4.8.0",
    "aws-sdk": "^2.1281.0",
    "bcryptjs": "^2.4.3",
    "dayjs": "^1.11.7",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "express-validator": "^6.14.2",
    "jsonwebtoken": "^9.0.0",
    "multer": "^1.4.5-lts.1",
    "multer-s3": "^3.0.1",
    "prisma": "^4.8.0"
  },
  "devDependencies": {
    "@types/bcryptjs": "^2.4.2",
    "@types/chai": "^4.3.4",
    "@types/express": "^4.17.15",
    "@types/express-validator": "^3.0.0",
    "@types/jsonwebtoken": "^8.5.9",
    "@types/mocha": "^10.0.1",
    "@types/multer": "^1.4.7",
    "@types/multer-s3": "^3.0.0",
    "@types/node": "^18.11.17",
    "@types/supertest": "^2.0.12",
    "chai": "^4.3.7",
    "commitizen": "^4.2.6",
    "cz-conventional-changelog": "3.3.0",
    "cz-emoji-conventional": "^1.0.1",
    "husky": "^8.0.0",
    "mocha": "^10.2.0",
    "nodemon": "^2.0.20",
    "supertest": "^6.3.3",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-emoji-conventional"
    }
  }
}


🏠 server architecture

μ„œλ²„μ•„ν‚€ν…μ³



πŸ“ Folder ꡬ쑰

πŸ“ src
|_ πŸ“ config
|_ πŸ“ constant
|_ πŸ“ controller
|_ πŸ“ interface
|_ πŸ“ middleware
|_ πŸ“ module
|_ πŸ“ prisma
|_ πŸ“ router
|_ πŸ“ service
|_ index.ts

πŸ“ test


πŸ’½ DB ERD

image



πŸ“„ API(+ Non - API) Docs

image



πŸ™†β€β™€οΈ μ—­ν• λΆ„λ‹΄ & κ΅¬ν˜„ 진척도

λ‹΄λ‹Ήμž λ‹΄λ‹Ή λ‚΄μš© κ΅¬ν˜„ 진척도
μœ μˆ˜ν™” EC2, publicCourse & stamp κ΄€λ ¨ api 100%
전선희 RDS, course & user κ΄€λ ¨ api 100%
λ°•μˆ˜λ¦° S3, record & scrap κ΄€λ ¨ api 100%


πŸ—£οΈοΈ μ»¨λ²€μ…˜

πŸ’‘ λ™λ£Œλ“€κ³Ό 말투λ₯Ό ν†΅μΌν•˜κΈ° μœ„ν•΄ μ»¨λ²€μ…˜μ„ μ§€μ •ν•©λ‹ˆλ‹€. μ˜€ν•©μ§€μ‘Έμ˜ μ½”λ“œκ°€ μ•„λ‹Œ, ν•œ μ‚¬λžŒμ΄ μ§  것같은 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” 것이 μΆ”ν›„ μœ μ§€λ³΄μˆ˜λ‚˜ ν˜‘μ—…μ—μ„œ 도움이 λ©λ‹ˆλ‹€. λ‚΄κ°€ μ½”λ“œλ₯Ό μƒκ°ν•˜λ©΄μ„œ 지 수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” 룰이라고 생각해도 μ’‹μŠ΅λ‹ˆλ‹€!

πŸ‘©β€πŸ’» Coding Conventions

λͺ…λͺ…κ·œμΉ™(Naming Conventions)
  1. μ΄λ¦„μœΌλ‘œλΆ€ν„° μ˜λ„κ°€ μ½ν˜€μ§ˆ 수 있게 μ“΄λ‹€.
  • ex)

    // bad
    function q() {
      // ...stuff...
    }
    
    // good
    function query() {
      // ..stuff..
    }
  1. 였브젝트, ν•¨μˆ˜, 그리고 μΈμŠ€ν„΄μŠ€μ—λŠ” camelCaseλ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    // bad
    const OBJEcttsssss = {};
    const this_is_my_object = {};
    function c() {}
    
    // good
    const thisIsMyObject = {};
    function thisIsMyFunction() {}
  1. ν΄λž˜μŠ€λ‚˜ constructorμ—λŠ” PascalCaseλ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    // bad
    function user(options) {
      this.name = options.name;
    }
    
    const bad = new user({
      name: "nope",
    });
    
    // good
    class User {
      constructor(options) {
        this.name = options.name;
      }
    }
    
    const good = new User({
      name: "yup",
    });
  1. ν•¨μˆ˜ 이름은 동사 + λͺ…사 ν˜•νƒœλ‘œ μž‘μ„±ν•œλ‹€. ex) postUserInformation( )
  2. μ•½μ–΄ μ‚¬μš©μ€ μ΅œλŒ€ν•œ μ§€μ–‘ν•œλ‹€.
  3. 이름에 λ„€ 단어 이상이 λ“€μ–΄κ°€λ©΄ νŒ€μ›κ³Ό μƒμ˜λ₯Ό 거친 ν›„ μ‚¬μš©ν•œλ‹€
블둝(Blocks)
  1. λ³΅μˆ˜ν–‰μ˜ λΈ”λ‘μ—λŠ” μ€‘κ΄„ν˜Έ({})λ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    // bad
    if (test)
      return false;
    
    // good
    if (test) return false;
    
    // good
    if (test) {
      return false;
    }
    
    // bad
    function() { return false; }
    
    // good
    function() {
      return false;
    }
  1. λ³΅μˆ˜ν–‰ λΈ”λ‘μ˜ if 와 else λ₯Ό μ΄μš©ν•˜λŠ” 경우 else λŠ” if 블둝 끝의 μ€‘κ΄„ν˜Έ( } )와 같은 행에 μœ„μΉ˜μ‹œν‚¨λ‹€.
  • ex) java // bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
μ½”λ©˜νŠΈ(Comments)
  1. λ³΅μˆ˜ν˜•μ˜ μ½”λ©˜νŠΈλŠ” /** ... */ λ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    // good
    /**
     * @param {String} tag
     * @return {Element} element
     */
    function make(tag) {
      // ...stuff...
    
      return element;
    }
  1. 단일 ν–‰μ˜ μ½”λ©˜νŠΈμ—λŠ” // 을 μ‚¬μš©ν•˜κ³  μ½”λ©˜νŠΈλ₯Ό μΆ”κ°€ν•˜κ³  싢은 μ½”λ“œμ˜ 상뢀에 λ°°μΉ˜ν•œλ‹€. 그리고 μ½”λ©˜νŠΈμ˜ μ•žμ— 빈 행을 λ„£λŠ”λ‹€.
  • ex) jsx // bad const active = true; // is current tab // good // is current tab const active = true; // good function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; }
λ¬Έμžμ—΄(Strings)
  1. λ¬Έμžμ—΄μ—λŠ” μ‹±ν¬μΏΌνŠΈ '' λ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    // bad
    const name = "Capt. Janeway";
    
    // good
    const name = "Capt. Janeway";
  1. ν”„λ‘œκ·Έλž¨μ—μ„œ λ¬Έμžμ—΄μ„ μƒμ„±ν•˜λŠ” κ²½μš°λŠ” λ¬Έμžμ—΄ 연결이 μ•„λ‹Œ template stringsλ₯Ό μ΄μš©ν•œλ‹€.
  • ex) jsx // bad function sayHi(name) { return 'How are you, ' + name + '?'; } // bad function sayHi(name) { return ['How are you, ', name, '?'].join(); } // good function sayHi(name) { return `How are you, ${name}?`; }
ν•¨μˆ˜(Functions)
  1. ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    var arr1 = [1, 2, 3];
    var pow1 = arr.map(function(x) {
      // ES5 Not Good
      return x * x;
    });
    
    const arr2 = [1, 2, 3];
    const pow2 = arr.map((x) => x * x); // ES6 Good
쑰건식과 등가식(Comparison Operators & Equality)
  1. == μ΄λ‚˜ != 보닀 === 와 !== 을 μ‚¬μš©ν•œλ‹€.
  2. λ‹¨μΆ•ν˜•μ„ μ‚¬μš©ν•œλ‹€.
  • ex)

    // bad
    if (name !== "") {
      // ...stuff...
    }
    
    // good
    if (name) {
      // ...stuff...
    }
  1. 비동기 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œ Promiseν•¨μˆ˜μ˜ μ‚¬μš©μ€ μ§€μ–‘ν•˜κ³  async, awaitλ₯Ό 쓰도둝 ν•œλ‹€


🌳 Branch

🌱 git branch μ „λž΅

main branch : 배포 λ‹¨μœ„ branch

dev branch : μ£Όμš” 개발 branch, main merge μ „ κ±°μΉ˜λŠ” branch

feat branch: 각자 개발 branch

  • ν•  일 issue 등둝 ν›„ issue λ²ˆν˜Έμ™€ isuue μ΄λ¦„μœΌλ‘œ branch 생성 ν›„ μž‘μ—…
    • ex) feat/#issue num-isuue name(κΈ°λŠ₯μš”μ•½)
  • ν•΄λ‹Ή branch μž‘μ—… μ™„λ£Œ ν›„ PR 보내기
    • 항상 localμ—μ„œ 좩돌 ν•΄κ²° ν›„ β†’ remote에 올리기
    • reviewer에 μ„œλ‘œ tagν›„ code-review
    • comment μ „ merge λΆˆκ°€!
    • review반영 ν›„, 본인이 merge.

branch ꡬ쑰

- main
- dev
- feat
   β”œβ”€β”€ #1-isuue name1
   └── #2-isuue name2


🧡 Commit Convention

πŸ“ git commit message convention

ex) feat(λ³€κ²½ν•œ 파일) : λ³€κ²½ λ‚΄μš© (/#issue num)

- ✨ feat:      μƒˆλ‘œμš΄ κΈ°λŠ₯ κ΅¬ν˜„
- πŸ› fix:       버그, 였λ₯˜ ν•΄κ²°
- 🧹 chore:     src λ˜λŠ” test νŒŒμΌμ„ μˆ˜μ •ν•˜μ§€ μ•ŠλŠ” 기타 λ³€κ²½ 사항 ( μƒˆλ‘œμš΄ 파일 생성, 파일 이동, 이름 λ³€κ²½ λ“± )
- ♻️ refactor:  버그 μˆ˜μ •μ΄λ‚˜ κΈ°λŠ₯ μΆ”κ°€κ°€ μ—†λŠ” μ½”λ“œ λ³€κ²½ ( μ½”λ“œ ꡬ쑰 λ³€κ²½ λ“±μ˜ λ¦¬νŒ©ν† λ§ )
- πŸ’Ž style:     μ½”λ“œμ˜ μ˜λ―Έμ— 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ” λ³€κ²½ 사항 ( μ½”λ“œ ν˜•μ‹, μ„Έλ―Έμ½œλ‘  μΆ”κ°€: λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— λ³€κ²½ μ—†μŒ )
- πŸ—οΈ build:    λΉŒλ“œ μ‹œμŠ€ν…œ λ˜λŠ” 외뢀에 영ν–₯을 λ―ΈμΉ˜λŠ” λ³€κ²½ 사항 쒅속성 ( 라이브러리 μΆ”κ°€ λ“± )
- πŸ“ˆ perf:      μ„±λŠ₯을 ν–₯상 μ‹œν‚€κΈ° μœ„ν•œ μ½”λ“œ λ³€κ²½
- πŸ§ͺ test:      ν…ŒμŠ€νŠΈ μΆ”κ°€ λ˜λŠ” 이전 ν…ŒμŠ€νŠΈ μˆ˜μ •
- πŸ“ docs:      READMEλ‚˜ WIKI λ“±μ˜ λ¬Έμ„œ κ°œμ •
- βͺ️ revert:    이전 컀밋을 λ˜λŒλ¦¬λŠ” 경우
- πŸ“¦ ci:      CI ꡬ성 파일 및 슀크립트 λ³€κ²½
- Merge: λ‹€λ₯ΈλΈŒλ ŒμΉ˜λ₯Ό mergeν•˜λŠ” 경우
- Init : Initial commit을 ν•˜λŠ” 경우