22.01.02 ~ 22.01.22 - SOPT 29th APPJAM
π νμ
μ±ν₯ ν
μ€νΈλ₯Ό ν΅ν΄ λμ νμ
μ νμ μμλ³΄κ³ , νκ·Έμ λ±λ‘νμ¬ λμ μ λ§λ νμλ€μ μ°Ύμ보μ
π νμ
μ±ν₯ νκ·Έμ κ΄μ¬ νλ‘μ νΈ λΆμΌ, νμ
ν¬μ§μ
μ€μ κ³Ό μκΈ°μκ° κΈμ ν΅ν΄ λλ₯Ό νννμ
π λͺ¨μ§ ν¬μ§μ
, μ νΈ νμ
μ±ν₯ λ° νλ‘μ νΈ λΆμΌ νκ·Έ λ±μ μ νν΄ λμ μ λ§λ νμλ€μ ꡬν΄λ³΄μ
π ν€μλ νκ·Έ νν° κ²μμ ν΅ν΄ λμ μ λ§λ νλ‘μ νΈμ νμμ μ°Ύμ보μ
π μ½ μ°λ₯΄κΈ°λ₯Ό ν΅ν΄ ν¨κ» νκ³ μΆμ νλ‘μ νΈ νμμκ² κ΄μ¬μ ννν΄ λ³΄μ
λ°νμ§ | λ¬Έκ·μ |
---|---|
dingding-21 | MoonGyu1 |
μ΄λ¦ | μν |
---|---|
λ°νμ§ | μ΄κΈ° νκ²½ μΈν , λ°μ΄ν°λ² μ΄μ€ μ€κ³, API λͺ μΈμ μμ± λ° κ΅¬ν |
λ¬Έκ·μ | README μμ±, λ°μ΄ν°λ² μ΄μ€ μ€κ³, API λͺ μΈμ μμ± λ° κ΅¬ν |
Click!
mainμ λͺ¨λ μμ μ΄ λλ ν developμμ Merge μν¨λ€.
βββββββββββββββββββββββββ
-
main
- μ΄κΈ° μΈν μ‘΄μ¬ -
develop
- local μμ μλ£ ν Merge λΈλμΉ -
name_feature/#issue
- κ°μμ κΈ°λ₯ μΆκ° λΈλμΉex)
gyuwon_login/#1
βββββββββββββββββββββββββ
- κ° κΈ°λ₯μ΄ μΆκ°λ λλ§λ€ Issue λ° Branch μμ±
local - name_feature/#issue
μμ κ°μ κΈ°λ₯ μμ- μμ
μλ£ ν
remote - develop
μ Pull Request - μ½λ 리뷰 ν Confirm λ°κ³ Merge
remote - develop
μ Merge λ λ λ§λ€ λͺ¨λ νμremote - develop pull
λ°μ μ΅μ μν μ μ§
Click!
νκ·Έ | μ€λͺ |
---|---|
[CHORE] | μ½λ μμ , λ΄λΆ νμΌ μμ |
[FEAT] | μλ‘μ΄ κΈ°λ₯ ꡬν |
[ADD] | Feat μ΄μΈμ λΆμμ μΈ μ½λ μΆκ°, λΌμ΄λΈλ¬λ¦¬ μΆκ°, μλ‘μ΄ νμΌ μμ± μ |
[HOTFIX] | issueλ, QAμμ κΈν λ²κ·Έ μμ μ μ¬μ© |
[FIX] | λ²κ·Έ, μ€λ₯ ν΄κ²° |
[DEL] | μΈλͺ¨μλ μ½λ μμ |
[DOCS] | READMEλ WIKI λ±μ λ¬Έμ κ°μ |
[CORRECT] | μ£Όλ‘ λ¬Έλ²μ μ€λ₯λ νμ μ λ³κ²½, μ΄λ¦ λ³κ²½ λ±μ μ¬μ© |
[MOVE] | νλ‘μ νΈ λ΄ νμΌμ΄λ μ½λμ μ΄λ |
[RENAME] | νμΌ μ΄λ¦ λ³κ²½μ΄ μμ λ μ¬μ© |
[IMPROVE] | ν₯μμ΄ μμ λ μ¬μ© |
[REFACTOR] | μ λ©΄ μμ μ΄ μμ λ μ¬μ© |
[MERGE] | λ€λ₯Έ λΈλμΉλ₯Ό Merge ν λ μ¬μ© |
Click!
- μ΄λ¦μΌλ‘λΆν° μλκ° μ½νμ§ μ μκ² μ΄λ€.
-
ex)
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. }
- μ€λΈμ νΈ, ν¨μ, κ·Έλ¦¬κ³ μΈμ€ν΄μ€μλ
camelCase
λ₯Ό μ¬μ©νλ€.
-
ex)
// bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {}
- ν΄λμ€λ 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', });
- ν¨μ μ΄λ¦μ λμ¬ - λͺ
μ¬ ννλ‘ μμ±νλ€.
ex)
postUserInformation( )
- μ½μ΄ μ¬μ©μ μ΅λν μ§μνλ€.
-
λͺ¨λ μ°Έμ‘°λ
const
λ₯Ό μ¬μ©νκ³ ,var
λ μ¬μ©νμ§ μλλ€. -
μ°Έμ‘°λ₯Ό μ¬ν λΉ ν΄μΌνλ€λ©΄
var
λμlet
μ μ¬μ©νλ€.μ΄λ,
const
μlet
μ λΈλ‘μ€μ½νμμ μ μ
- 볡μνμ λΈλ‘μλ μ€κ΄νΈ({})λ₯Ό μ¬μ©νλ€.
-
ex)
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
- 볡μν λΈλ‘μ
if
μelse
λ₯Ό μ΄μ©νλ κ²½μ°else
λif
λΈλ‘ λμ μ€κ΄νΈ(})μ κ°μ νμ μμΉμν¨λ€.
-
ex)
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
- 볡μνμ μ½λ©νΈλ
/** ... */
λ₯Ό μ¬μ©νλ€.
-
ex)
// good /** * @param {String} tag * @return {Element} element */ function make(tag) { // ...stuff... return element; }
- λ¨μΌνμ μ½λ©νΈμλ
//
μ μ¬μ©νκ³ μ½λ©νΈλ₯Ό μΆκ°νκ³ μΆμ μ½λμ μλΆμ λ°°μΉνλ€. κ·Έλ¦¬κ³ μ½λ©νΈμ μμ λΉνμ λ£λλ€.
-
ex)
// 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; }
- μ£Όμ μ€κ΄νΈ({}) μμλ μ€νμ΄μ€ 1κ°λ₯Ό λ£λλ€.
-
ex)
// bad function test() { console.log('test'); } // good function test() { console.log('test'); }
- μ μ΄κ΅¬λ¬Έ (
if
λ¬Έμ΄λwhile
λ¬Έ λ±) μ μκ΄νΈ (()) μμλ μ€νμ΄μ€λ₯Ό 1κ° λ£κ³ ν¨μ μ μΈμ΄λ ν¨μ νΈμΆμ μΈμ 리μ€νΈμ μμλ μ€νμ΄μ€λ₯Ό λ£μ§ μλλ€.
-
ex)
// bad if (isJedi) { fight(); } // good if (isJedi) { fight(); } // bad function fight() { console.log('Swooosh!'); } // good function fight() { console.log('Swooosh!'); }
- μ°μ°μ μ¬μ΄μλ μ€νμ΄μ€λ₯Ό λ£λλ€.
-
ex)
// bad const x = y + 5; // good const x = y + 5;
- μ λμ μ½€λ§ BAD
-
ex)
// bad const story = [once, upon, aTime]; // good const story = [once, upon, aTime];
- λμ μ½€λ§ GOOD
-
ex)
// bad const hero = { firstName: 'Dana', lastName: 'Scully', }; // good const hero = { firstName: 'Dana', lastName: 'Scully', };
- μΈλ―Έμ½λ‘ μ μ¬μ©νλ€.
- ex)
// bad (function () { const name = 'Skywalker'; return name; })()( // good () => { const name = 'Skywalker'; return name; } )();
- λ¬Έμμ΄μλ μ±ν¬μΏΌνΈ
''
λ₯Ό μ¬μ©νλ€.
-
ex)
```jsx // bad const name = "Capt. Janeway"; // good const name = 'Capt. Janeway'; ```
- νλ‘κ·Έλ¨μμ λ¬Έμμ΄μ μμ±νλ κ²½μ°λ λ¬Έμμ΄ μ°κ²°μ΄ μλ
template strings
λ₯Ό μ΄μ©νλ€.
-
ex)
// 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}?`; }
- νμ΄ν ν¨μλ₯Ό μ¬μ©νλ€.
-
ex)
```jsx 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 ```
- ν¨μμλ³΄λ€ ν¨μ μ μΈμ μ΄μ©νλ€.
-
ex)
```jsx // bad const foo = function () { }; // good function foo() { } ```
==
μ΄λ!=
보λ€===
μ!==
μ μ¬μ©νλ€.
- λ¨μΆνμ μ¬μ©νλ€.
-
ex)
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
- λΉλκΈ° ν¨μλ₯Ό μ¬μ©ν λ
Promise
ν¨μμ μ¬μ©μ μ§μνκ³async
,await
λ₯Ό μ°λλ‘ νλ€.
κΈ°λ₯ | URI | HTTP λ©μλ |
μ€λͺ | λ΄λΉ | μλ£ |
---|---|---|---|---|---|
νμκ°μ
/ λ‘κ·ΈμΈ |
/auth/signup | POST | μ μ νμκ°μ | κ·μ | π |
/auth/login | POST | μ μ λ‘κ·ΈμΈ | νμ§ | π | |
/auth/login | GET | μ μ μλ λ‘κ·ΈμΈ | νμ§ | π | |
λλ© νμ΄μ§ | /project/top | GET | μ£Όλͺ©ν λ§ν νλ‘μ νΈ μ‘°ν | κ·μ | π |
νλ‘μ νΈ | /project/metadata | GET | νλ‘μ νΈ μμ± - λλ―Έ λ°μ΄ν° λ°κΈ° | νμ§ | π |
/project | POST | νλ‘μ νΈ μμ± | νμ§ | π | |
/project/photo/:projectId | POST | νλ‘μ νΈ μμ± - μ¬μ§ μΆκ° | νμ§ | π | |
/project/member | POST | νλ‘μ νΈ μμ± - ν ꡬμ±μ μΆκ° | νμ§ | π | |
/project/search/metadata | GET | νλ‘μ νΈ μ°ΎκΈ° - λλ―Έ λ°μ΄ν° λ°κΈ° | νμ§ | π | |
/project/search | POST | νλ‘μ νΈ μ°ΎκΈ° - μ‘°ν | νμ§ | π | |
/project/:projectId | GET | νλ‘μ νΈ μμΈλ·° μ‘°ν | νμ§ | π | |
/project/:projectId | DELETE | νλ‘μ νΈ λͺ¨μ§ μλ£ | νμ§ | π | |
νμ μ°ΎκΈ° | /member/metadata | GET | νμ μ°ΎκΈ° λ·° λλ―Έ λ°μ΄ν° λ°κΈ° | κ·μ | π |
/member | POST | νμ μ°ΎκΈ° μ‘°ν | κ·μ | π | |
λ§μ΄νμ΄μ§/ νμ μμΈλ·° |
/user/profile/:userId | GET | μ μ νλ‘ν κ°μ Έμ€κΈ° | κ·μ | π |
/user/profile/metadata | GET | μ μ νλ‘ν μμ λλ―Έ λ°μ΄ν° λ°κΈ° | κ·μ | π | |
/user/profile/:userId | GET | μ μ νλ‘ν μμ | κ·μ | π | |
/user/profile/photo /:userId |
POST | μ μ νλ‘ν μ¬μ§ λ³κ²½ | κ·μ | π | |
μ½ μ°λ₯΄κΈ°/ ν μ§μνκΈ° |
/user/poke-user | POST | μ½μ°λ₯΄κΈ° | κ·μ | π |
/user/poke-project | POST | ν μ§μνκΈ° | νμ§ | π | |
/user/poke-user/:userId | GET | λλ₯Ό μ°λ¬λ³Έ μ¬λ | κ·μ | π | |
/user/poke-project/:userId | GET | λ΄ νλ‘μ νΈμ μ§μν μ¬λ | νμ§ | π | |
/user/poke-user /:userId/:pokingUserId |
DELETE | λλ₯Ό μ°λ¬λ³Έ μ¬λ μμ | κ·μ | π | |
/user/poke-project /:projectId/:pokingUserId |
DELETE | λ΄ νλ‘μ νΈμ μ§μν μ¬λ μμ | νμ§ | π |
|-π firebaserc
|-π firebase.json
|-π .gitignore
|-π db*query
|-π functions*
|- π index.js
|- π package.json
|- π .gitignore
|- π .env
|- π api*
| |- π index.js
| |- π routes*
| |- π index.js
| |- π auth
| |- π member
| |- π project
| |- π user
|
|- π config*
| |- π dbConfig.js
| |- π firebaseClient.js
|
|- π constants*
| |- π jwt.js
| |- π responseMessage.js
| |- π statusCode.js
|
|- π db*
| |- π db.js
| |- π index.js
|
|- π lib*
| |- π convertSnakeToCamel.js
| |- π jwtHandlers.js
| |- π util.js
|
|- π middlewares\_
|- π auth.js
|- π uploadImage.js
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "cross-env NODE_ENV=development firebase emulators:start --only functions --project dev",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "cross-env NODE_ENV=production firebase deploy --only functions --project prod",
"logs": "firebase functions:log"
},
"engines": {
"node": "16"
},
"main": "index.js",
"dependencies": {
"axios": "^0.25.0",
"busboy": "^0.3.1",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"dayjs": "^1.10.7",
"dotenv": "^11.0.0",
"eslint-config-prettier": "^8.3.0",
"express": "^4.17.2",
"firebase": "^9.6.2",
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.14.1",
"helmet": "^5.0.1",
"hpp": "^0.2.3",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"pg": "^8.7.1"
},
"devDependencies": {
"eslint": "^7.32.0",
"eslint-config-google": "^0.14.0",
"firebase-functions-test": "^0.2.0"
},
"private": true
}