Skip to content

TeamHappic/happic-Server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

337 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation


happic: ํ•ดํ”ฝ

Be happy, take a happic:

๋งค์ผ์˜ ์ถ”์–ต์ด ๋‚˜์˜ ํ–‰๋ณต์ด ๋˜์–ด, ํ•ดํ”ฝ
์ €ํฌ๋Š” ํ•ดํ”ฝ์ž…๋‹ˆ๋‹ค

SOPT 30th APP JAM
ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„ : 2022.07.02 ~ 2022.07.23

์ถ”ํ›„ ๋ฆด๋ฆฌ์ฆˆ ์˜ˆ์ •

์ฃผ์š” ๊ธฐ๋Šฅ ์†Œ๊ฐœ

KakaoTalk_20220722_234934351

KakaoTalk_20220722_234934351_01

KakaoTalk_20220722_234934351_02

KakaoTalk_20220722_234934351_03


Service workflow

IA-FLOW@3x

Team happic SERVER Developers

์ด์„œ์šฐ ๊น€๋™์žฌ ์œ ์†ก๊ฒฝ
dltjdn ehdwoKIM ssong915

๐ŸŒฒ Git Branch Convention

  • main: ๋ฐฐํฌ๋ฅผ ์œ„ํ•œ ๋ธŒ๋žœ์น˜ ( ์ตœ์ข…๋ณธ )

  • develop: ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์ด ์™„๋ฃŒ๋œ ์ฝ”๋“œ๋“ค์ด ๋ชจ์ด๋Š” ๊ณณ ( ๊ฒ€์ฆ๋œ ๊ณณ์ด์ž ๊ฒ€์ฆํ•  ๊ณณ )

  • feature: ๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ๋ธŒ๋žœ์น˜ ( feature/๋ณธ์ธ์ด๋ฆ„/๊ธฐ๋Šฅ๋ช… )


๐Ÿ’Œ Commit Convention

- [ADD] : ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๊ตฌํ˜„
- [FEAT] : ADD ์ด์™ธ์˜ ๋ถ€์ˆ˜์ ์ธ ์ฝ”๋“œ ์ถ”๊ฐ€, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€, ์ƒˆ๋กœ์šด ํŒŒ์ผ ์ƒ์„ฑ ์‹œ
- [CHORE]: ์ฝ”๋“œ ์ˆ˜์ •, ๋‚ด๋ถ€ ํŒŒ์ผ ์ˆ˜์ •
- [FIX] : ๋ฒ„๊ทธ, ์˜ค๋ฅ˜ ํ•ด๊ฒฐ
- [DEL] : ์“ธ๋ชจ์—†๋Š” ์ฝ”๋“œ ์‚ญ์ œ
- [DOCS] : README๋‚˜ WIKI ๋“ฑ์˜ ๋ฌธ์„œ ๊ฐœ์ •
- [MOVE] : ํ”„๋กœ์ ํŠธ ๋‚ด ํŒŒ์ผ์ด๋‚˜ ์ฝ”๋“œ์˜ ์ด๋™
- [RENAME] : ํŒŒ์ผ ์ด๋ฆ„์˜ ๋ณ€๊ฒฝ
- [STYLE] : ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ์„ ํ•˜๋Š” ๊ฒฝ์šฐ

โœจ Coding Convention

๋ช…๋ช…๊ทœ์น™ (Naming Conventions)
  1. ์ด๋ฆ„์œผ๋กœ๋ถ€ํ„ฐ ์˜๋„๊ฐ€ ์ฝํ˜€์งˆ ์ˆ˜ ์žˆ๊ฒŒ ์“ด๋‹ค.
  2. ์˜ค๋ธŒ์ ํŠธ, ํ•จ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  ์ธ์Šคํ„ด์Šค์—๋Š” camelCase๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  3. ํด๋ž˜์Šค๋‚˜ constructor์—๋Š” PascalCase๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  4. ํ•จ์ˆ˜ ์ด๋ฆ„์€ ๋™์‚ฌ + ๋ช…์‚ฌ ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ•œ๋‹ค.
    ex) postUserInformation()
  5. ์•ฝ์–ด ์‚ฌ์šฉ์€ ์ตœ๋Œ€ํ•œ ์ง€์–‘ํ•œ๋‹ค.
  6. ์ด๋ฆ„์— ๋„ค ๋‹จ์–ด ์ด์ƒ์ด ๋“ค์–ด๊ฐ€๋ฉด ํŒ€์›๊ณผ ์ƒ์˜๋ฅผ ๊ฑฐ์นœ ํ›„ ์‚ฌ์šฉํ•œ๋‹ค.
  7. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ช…์€ ์˜์–ด ์†Œ๋ฌธ์ž๋กœ ๊ตฌ์„ฑํ•œ๋‹ค.
๋ธ”๋ก (Blocks)
  1. ๋ณต์ˆ˜ํ–‰์˜ ๋ธ”๋ก์—๋Š” ์ค‘๊ด„ํ˜ธ({})๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ๋ณต์ˆ˜ํ–‰ ๋ธ”๋ก์˜ if ์™€ else ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒฝ์šฐ else ๋Š” if ๋ธ”๋ก ๋์˜ ์ค‘๊ด„ํ˜ธ( } )์™€ ๊ฐ™์€ ํ–‰์— ์œ„์น˜์‹œํ‚จ๋‹ค.
์ฝ”๋ฉ˜ํŠธ (Comments)
  1. ๋ณต์ˆ˜ํ˜•์˜ ์ฝ”๋ฉ˜ํŠธ๋Š” /** ... */ ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ๋‹จ์ผ ํ–‰์˜ ์ฝ”๋ฉ˜ํŠธ์—๋Š” // ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์€ ์ฝ”๋“œ์˜ ์ƒ๋ถ€์— ๋ฐฐ์น˜ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋ฉ˜ํŠธ์˜ ์•ž์— ๋นˆ ํ–‰์„ ๋„ฃ๋Š”๋‹ค.
๋ฌธ์ž์—ด (Strings)
  1. ๋ฌธ์ž์—ด์—๋Š” ์‹ฑํฌ์ฟผํŠธ '' ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค..
  2. ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฌธ์ž์—ด์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋ฌธ์ž์—ด ์—ฐ๊ฒฐ์ด ์•„๋‹Œ template strings๋ฅผ ์ด์šฉํ•œ๋‹ค.
ํ•จ์ˆ˜ (Functions)
  1. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
 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
  1. ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ์‚ฌ์šฉ ์‹œ Promiseํ•จ์ˆ˜์˜ ์‚ฌ์šฉ์€ ์ง€์–‘ํ•˜๊ณ  async, await ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค.
์กฐ๊ฑด์‹๊ณผ ๋“ฑ๊ฐ€์‹ (Comparsion Operators & Equality)
  1. ==์ด๋‚˜ !=๋ณด๋‹ค === ์™€ !==์„ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ๋‹จ์ถ•ํ˜•์„ ์‚ฌ์šฉํ•œ๋‹ค.
  3. ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Promiseํ•จ์ˆ˜์˜ ์‚ฌ์šฉ์€ ์ง€์–‘ํ•˜๊ณ  async, await๋ฅผ ์“ฐ๋„๋ก ํ•œ๋‹ค.

๐Ÿ—‚ Project Foldering

๐Ÿ“ฆ config                   
 โ”— ๐Ÿ“œ index.ts

๐Ÿ“ฆ controllers               
 โ”ฃ ๐Ÿ“œ index.ts

๐Ÿ“ฆ interfaces                
 โ”— ๐Ÿ“‚ film
 โ”ƒ โ”— ๐Ÿ“œ FilmInfo.ts
 โ”— ๐Ÿ“‚ keyword
   โ”— ๐Ÿ“œ KeywordInfo.ts
 โ”— ๐Ÿ“‚ user
   โ”— ๐Ÿ“œ UserInfo.ts

๐Ÿ“ฆ loaders
 โ”— ๐Ÿ“œ db.ts

๐Ÿ“ฆ middlewares
 โ”— ๐Ÿ“œ auth.ts

๐Ÿ“ฆ models                    
 โ”ฃ ๐Ÿ“œ Film.ts
 โ”ฃ ๐Ÿ“œ Keyword.ts
 โ”— ๐Ÿ“œ User.ts

๐Ÿ“ฆ modules
 โ”— ๐Ÿ“œ util.ts
 โ”— ๐Ÿ“œ statusCode.ts
 โ”— ๐Ÿ“œ responseMessage.ts

๐Ÿ“ฆ routes                    
 โ”ฃ ๐Ÿ“œ index.ts

๐Ÿ“ฆ services                  
 โ”ฃ ๐Ÿ“œ index.ts

๐Ÿ—’ DB Schema

Char
const CharSchema = new mongoose.Schema({
  characterId: {
    type: Number,
    required: true,
  },
  characterName: {
    type: String,
    required: true,
  },
});
File
const FileSchema = new mongoose.Schema(
  {
    link: {
      type: String,
      required: true,
    },
    fileName: {
      type: String,
      required: true,
    },
  },
  {
    timestamps: true, // createdAt, updatedAt ์ž๋™๊ธฐ๋ก
  }
);
User
const UserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  social: {
    type: String,
    required: true,
    unique: true,
  },
  socialId: {
    type: String,
    required: true,
    unique: true,
  },
  email: {
    type: String,
    required: true,
    unique: true,
  },
  characterId: {
    type: Number,
    required: true,
  },
  characterName: {
    type: String,
    required: true,
  },
  growthRate: {
    type: Number,
    required: true,
    default: 0,
  },
  level: {
    type: Number,
    required: true,
    default: 1,
  },
  film: [
    {
      type: mongoose.Types.ObjectId,
      ref: 'Film',
    },
  ],
  count: {
    type: Number,
    required: true,
    default: 0,
  },
  fcmToken: {
    type: String,
    required: true,
    unique: true,
  },
  refreshToken: {
    type: String,
    required: true,
    unique: true,
  },
});
Film
const FilmSchema = new mongoose.Schema(
  {
    writer: {
      type: mongoose.Types.ObjectId,
      required: true,
      ref: 'User',
    },
    photo: {
      type: String,
      required: true,
    },
    thumbnail: {
      type: String,
    },
    keyword: [
      {
        type: mongoose.Types.ObjectId,
        required: true,
        ref: 'Keyword',
      },
    ],
    year: {
      type: Number,
      required: true,
    },
    month: {
      type: Number,
      required: true,
    },
  },
  {
    timestamps: true, // createdAt, updatedAt ์ž๋™๊ธฐ๋ก
  }
);
Keyword
const KeywordSchema = new mongoose.Schema(
  {
    writer: {
      type: mongoose.Types.ObjectId,
      required: true,
      ref: 'User',
    },
    category: {
      type: String,
      required: true,
    },
    content: {
      type: String,
      required: true,
    },
    year: {
      type: Number,
      required: true,
    },
    month: {
      type: Number,
      required: true,
    },
    count: {
      type: Number,
      required: true,
      default: 0,
    },
  },
  {
    timestamps: true, // createdAt, updatedAt ์ž๋™๊ธฐ๋ก
  }
);

๐Ÿ›  API


๐Ÿ›  Dependencies module (package.json)

{
  "name": "node-typescript-init",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon",
    "build": "tsc",
    "start:dev": "node dist/index.js",
    "test": "mocha -r ts-node/register src/test/daily.spec.ts"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/chai": "^4.3.1",
    "@types/express": "^4.17.13",
    "@types/jsonwebtoken": "^8.5.8",
    "@types/mocha": "^9.1.1",
    "@types/mongoose": "^5.11.97",
    "@types/multer": "^1.4.7",
    "@types/multer-s3": "^2.7.12",
    "@types/node": "^17.0.25",
    "@types/supertest": "^2.0.12",
    "@typescript-eslint/eslint-plugin": "^5.30.5",
    "@typescript-eslint/parser": "^5.30.5",
    "chai": "^4.3.6",
    "eslint": "^8.19.0",
    "mocha": "^10.0.0",
    "nodemon": "^2.0.15",
    "prettier": "^2.7.1",
    "supertest": "^6.2.4",
    "ts-node": "^10.7.0",
    "typescript": "^4.6.3"
  },
  "dependencies": {
    "aws-sdk": "^2.1143.0",
    "axios": "^0.27.2",
    "bcryptjs": "^2.4.3",
    "bucket": "^0.0.1",
    "dayjs": "^1.11.3",
    "dotenv": "^16.0.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.2.1",
    "express": "^4.18.1",
    "express-validator": "^6.14.2",
    "firebase-admin": "^11.0.0",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^6.3.1",
    "multer": "^1.4.4",
    "multer-s3": "^2.10.0",
    "node-schedule": "^2.1.0",
    "winston": "^3.8.1"
  }
}

๐Ÿ›  Server Architecture

  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ : Typescript, Express(Node.js)
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค : MongoDB, AWS S3
  • ์„œ๋ฒ„ ํ™˜๊ฒฝ : AWS EC2, PM2 180420764-1afac15d-1ef5-4c47-b68e-90cb128c3d7c


About

Be happy, take a happic: ๐Ÿ“ธ

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors