Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Team-Teamble/Teamble-Server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

256 Commits

Repository files navigation


μ„œλ‘œ λ‹€λ₯Έ μƒ‰μ˜ μš°λ¦¬κ°€ λ§Œλ‚˜λŠ” 곡간, νŒ€λΈ” πŸ’œ


# 우리_νŒ€λΈ”ν•˜μž!

KakaoTalk_20220107_191904466

22.01.02 ~ 22.01.22 - SOPT 29th APPJAM



Main Service

1. ν˜‘μ—… μ„±ν–₯ ν…ŒμŠ€νŠΈ

image πŸ‘‰ ν˜‘μ—… μ„±ν–₯ ν…ŒμŠ€νŠΈλ₯Ό 톡해 λ‚˜μ˜ ν˜‘μ—… μœ ν˜•μ„ μ•Œμ•„λ³΄κ³ , νƒœκ·Έμ— λ“±λ‘ν•˜μ—¬ λ‚˜μ™€ 잘 λ§žλŠ” νŒ€μ›λ“€μ„ μ°Ύμ•„λ³΄μž

2. 마이 ν”„λ‘œν•„ μ„€μ •

image πŸ‘‰ ν˜‘μ—… μ„±ν–₯ νƒœκ·Έμ™€ 관심 ν”„λ‘œμ νŠΈ λΆ„μ•Ό, ν˜‘μ—… ν¬μ§€μ…˜ μ„€μ •κ³Ό μžκΈ°μ†Œκ°œ 글을 톡해 λ‚˜λ₯Ό ν‘œν˜„ν•˜μž

3. ν”„λ‘œμ νŠΈ νŒ€ λ§Œλ“€κΈ°

image πŸ‘‰ λͺ¨μ§‘ ν¬μ§€μ…˜, μ„ ν˜Έ ν˜‘μ—… μ„±ν–₯ 및 ν”„λ‘œμ νŠΈ λΆ„μ•Ό νƒœκ·Έ 등을 선택해 λ‚˜μ™€ 잘 λ§žλŠ” νŒ€μ›λ“€μ„ κ΅¬ν•΄λ³΄μž

4. ν‚€μ›Œλ“œ νƒœκ·Έ ν•„ν„° 검색 (ν”„λ‘œμ νŠΈ & νŒ€μ›)

image image πŸ‘‰ ν‚€μ›Œλ“œ νƒœκ·Έ ν•„ν„° 검색을 톡해 λ‚˜μ™€ 잘 λ§žλŠ” ν”„λ‘œμ νŠΈμ™€ νŒ€μ›μ„ μ°Ύμ•„λ³΄μž

5. 콕 찌λ₯΄κΈ°

image πŸ‘‰ 콕 찌λ₯΄κΈ°λ₯Ό 톡해 ν•¨κ»˜ ν•˜κ³  싢은 ν”„λ‘œμ νŠΈ νŒ€μ›μ—κ²Œ 관심을 ν‘œν˜„ν•΄ 보자




Developers

λ°•ν˜„μ§€ λ¬Έκ·œμ›
dingding-21 MoonGyu1

Role

이름 μ—­ν• 
λ°•ν˜„μ§€ 초기 ν™˜κ²½ μ„ΈνŒ…, λ°μ΄ν„°λ² μ΄μŠ€ 섀계, API λͺ…μ„Έμ„œ μž‘μ„± 및 κ΅¬ν˜„
λ¬Έκ·œμ› README μž‘μ„±, λ°μ΄ν„°λ² μ΄μŠ€ 섀계, API λͺ…μ„Έμ„œ μž‘μ„± 및 κ΅¬ν˜„

IA

μ›Œλ„ˆλΉ„νŒ€ IA


Git Workflow

main ← develop ← name_feature/#issue

Click!

main은 λͺ¨λ“  μž‘μ—…μ΄ λλ‚œ ν›„ developμ—μ„œ Merge μ‹œν‚¨λ‹€.

β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”

  • main - 초기 μ„ΈνŒ… 쑴재

  • develop - local μž‘μ—… μ™„λ£Œ ν›„ Merge 브랜치

  • name_feature/#issue - 각자의 κΈ°λŠ₯ μΆ”κ°€ 브랜치

    ex) gyuwon_login/#1

β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”

  1. 각 κΈ°λŠ₯이 좔가될 λ•Œλ§ˆλ‹€ Issue 및 Branch 생성
  2. local - name_feature/#issue μ—μ„œ 각자 κΈ°λŠ₯ μž‘μ—…
  3. μž‘μ—… μ™„λ£Œ ν›„ remote - develop 에 Pull Request
  4. μ½”λ“œ 리뷰 ν›„ Confirm λ°›κ³  Merge
  5. remote - develop 에 Merge 될 λ•Œ λ§ˆλ‹€ λͺ¨λ“  νŒ€μ› remote - develop pull λ°›μ•„ μ΅œμ‹  μƒνƒœ μœ μ§€

Commit Message Convention

Click!

νƒœκ·Έ μ„€λͺ…
[CHORE] μ½”λ“œ μˆ˜μ •, λ‚΄λΆ€ 파일 μˆ˜μ •
[FEAT] μƒˆλ‘œμš΄ κΈ°λŠ₯ κ΅¬ν˜„
[ADD] Feat μ΄μ™Έμ˜ λΆ€μˆ˜μ μΈ μ½”λ“œ μΆ”κ°€, 라이브러리 μΆ”κ°€, μƒˆλ‘œμš΄ 파일 생성 μ‹œ
[HOTFIX] issueλ‚˜, QAμ—μ„œ κΈ‰ν•œ 버그 μˆ˜μ •μ— μ‚¬μš©
[FIX] 버그, 였λ₯˜ ν•΄κ²°
[DEL] μ“Έλͺ¨μ—†λŠ” μ½”λ“œ μ‚­μ œ
[DOCS] READMEλ‚˜ WIKI λ“±μ˜ λ¬Έμ„œ κ°œμ •
[CORRECT] 주둜 λ¬Έλ²•μ˜ 였λ₯˜λ‚˜ νƒ€μž…μ˜ λ³€κ²½, 이름 λ³€κ²½ 등에 μ‚¬μš©
[MOVE] ν”„λ‘œμ νŠΈ λ‚΄ νŒŒμΌμ΄λ‚˜ μ½”λ“œμ˜ 이동
[RENAME] 파일 이름 변경이 μžˆμ„ λ•Œ μ‚¬μš©
[IMPROVE] ν–₯상이 μžˆμ„ λ•Œ μ‚¬μš©
[REFACTOR] μ „λ©΄ μˆ˜μ •μ΄ μžˆμ„ λ•Œ μ‚¬μš©
[MERGE] λ‹€λ₯Έ 브랜치λ₯Ό Merge ν•  λ•Œ μ‚¬μš©

Coding Convention

Click!

λͺ…λͺ…κ·œμΉ™(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. μ•½μ–΄ μ‚¬μš©μ€ μ΅œλŒ€ν•œ μ§€μ–‘ν•œλ‹€.

μ°Έμ‘°(References)


  1. λͺ¨λ“  μ°Έμ‘°λŠ” constλ₯Ό μ‚¬μš©ν•˜κ³ , varλŠ” μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.

  2. μ°Έμ‘°λ₯Ό μž¬ν• λ‹Ή ν•΄μ•Όν•œλ‹€λ©΄ varλŒ€μ‹  let을 μ‚¬μš©ν•œλ‹€.

    μ΄λ•Œ, const와 let은 λΈ”λ‘μŠ€μ½”ν”„μž„μ„ 유의


블둝(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)

    // 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)

    // 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;
    }

곡백(Whitespace)


  1. μ£Όμš” μ€‘κ΄„ν˜Έ({}) μ•žμ—λŠ” 슀페이슀 1개λ₯Ό λ„£λŠ”λ‹€.
  • ex)

    // bad
    function test() {
     console.log('test');
    }
    // good
    function test() {
     console.log('test');
    }

  1. μ œμ–΄κ΅¬λ¬Έ (if λ¬Έμ΄λ‚˜ while λ¬Έ λ“±) 의 μ†Œκ΄„ν˜Έ (()) μ•žμ—λŠ” 슀페이슀λ₯Ό 1개 λ„£κ³  ν•¨μˆ˜ μ„ μ–Έμ΄λ‚˜ ν•¨μˆ˜ ν˜ΈμΆœμ‹œ 인수 리슀트의 μ•žμ—λŠ” 슀페이슀λ₯Ό λ„£μ§€ μ•ŠλŠ”λ‹€.
  • ex)

    // bad
    if (isJedi) {
     fight();
    }
    // good
    if (isJedi) {
     fight();
    }
    // bad
    function fight() {
     console.log('Swooosh!');
    }
    // good
    function fight() {
     console.log('Swooosh!');
    }

  1. μ—°μ‚°μž μ‚¬μ΄μ—λŠ” 슀페이슀λ₯Ό λ„£λŠ”λ‹€.
  • ex)

    // bad
    const x = y + 5;
    // good
    const x = y + 5;

콀마(Commas)


  1. μ„ λ‘μ˜ 콀마 BAD
  • ex)

    // bad
    const story = [once, upon, aTime];
    // good
    const story = [once, upon, aTime];

  1. 끝의 콀마 GOOD
  • ex)

    // bad
    const hero = {
     firstName: 'Dana',
     lastName: 'Scully',
    };
    // good
    const hero = {
     firstName: 'Dana',
     lastName: 'Scully',
    };

μ„Έλ―Έμ½œλ‘ (Seminolons)


  1. μ„Έλ―Έμ½œλ‘ μ„ μ‚¬μš©ν•œλ‹€.
  • ex)
    // bad
    (function () {
     const name = 'Skywalker';
     return name;
    })()(
     // good
     () => {
     const name = 'Skywalker';
     return name;
     }
    )();

λ¬Έμžμ—΄(Strings)


  1. λ¬Έμžμ—΄μ—λŠ” μ‹±ν¬μΏΌνŠΈ '' λ₯Ό μ‚¬μš©ν•œλ‹€.
  • ex)

    ```jsx
    // bad
    const name = "Capt. Janeway";
    // good
    const name = 'Capt. Janeway';
    ```
    

  1. ν”„λ‘œκ·Έλž¨μ—μ„œ λ¬Έμžμ—΄μ„ μƒμ„±ν•˜λŠ” κ²½μš°λŠ” λ¬Έμžμ—΄ 연결이 μ•„λ‹Œ 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}?`;
    }

ν•¨μˆ˜(Functions)


  1. ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€.
  • 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
     ```
    

  1. ν•¨μˆ˜μ‹λ³΄λ‹€ ν•¨μˆ˜ 선언을 μ΄μš©ν•œλ‹€.
  • ex)

     ```jsx
     // bad
     const foo = function () {
     };
     // good
     function foo() {
     }
     ```
    

쑰건식과 등가식(Comparison Operators & Equality)


  1. == μ΄λ‚˜ != 보닀 === 와 !== 을 μ‚¬μš©ν•œλ‹€.

  1. λ‹¨μΆ•ν˜•μ„ μ‚¬μš©ν•œλ‹€.
  • ex)

    // bad
    if (name !== '') {
     // ...stuff...
    }
    // good
    if (name) {
     // ...stuff...
    }
    // bad
    if (collection.length > 0) {
     // ...stuff...
    }
    // good
    if (collection.length) {
     // ...stuff...
    }

  1. 비동기 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œ Promiseν•¨μˆ˜μ˜ μ‚¬μš©μ€ μ§€μ–‘ν•˜κ³  async, awaitλ₯Ό 쓰도둝 ν•œλ‹€.


API

πŸ‘‰ λͺ…μ„Έμ„œ λ³΄λŸ¬κ°€κΈ°!

κΈ°λŠ₯ 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 λ‚΄ ν”„λ‘œμ νŠΈμ— μ§€μ›ν•œ μ‚¬λžŒ μ‚­μ œ ν˜„μ§€ πŸ’œ

ERD

ERD


Foldering

|-πŸ“‹ 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

Dependencies Module

{
 "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
}

About

πŸ’›πŸ’›λŸ¬λΈ”λ¦¬ν•œ μ„œλ²„ νŒ€λΈ”λŸ¬πŸ’›πŸ’›

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /