Skip to content

기술 기획서

HG.Seo edited this page Nov 11, 2022 · 35 revisions

기술 기획서

기술 스택

언어 - TypeScript

  • 팀원들 모두가 TypeScript를 사용해본 경험이 있어서 별도 학습이 많이 요구되지 않았습니다.
  • 프론트와 백에 같은 언어를 사용함으로써, 기본적인 문법을 통일함으로써 더욱 원활한 소통을 할 수 있습니다.
  • 코드 작성 시 매번 타입을 결정해야 하기 때문에 번거롭고 코드량이 증가하지만, 정적 타입 언어로 코드 작성 단계에서 에러를 체크할 수 있습니다. 이 장점으로 버그를 발견하고, 해결하는 시간을 단축시킬 수 있습니다.
  • any 는 최대한 사용하지 않습니다.

패키지 매니저

npm

FE

React

  • 프로젝트 기간이 짧아, 팀원들이 모두 이미 잘 알고 있는 React를 사용하는 것이 생산성을 높일 수 있다고 생각했습니다.
  • 커뮤니티가 큽니다.
    • Best practice 를 찾기가 쉽다고 생각합니다.
    • 상용화된 라이브러리가 많습니다.
  • Angular, Vue 와 달리 React 는 라이브러리기 때문에, JavaScript 언어를 알고 있다면 프론트엔드 지식이 부족해도 이해하기 수월합니다. -> 풀스택 작업이 더 수월해집니다.
    • JSX 문법 덕분에 HTML 과 JS 코드 작성이 효율적입니다.
  • Why use react

redux toolkit or recoil(고민 중)

emotion css

  • HTML 태그를 직관적으로 인지하기 쉽습니다. 따라서 Semantic 하게 태그를 작성할 수 좋습니다.
  • Javascript (또는 Typescript) 파일 내에 CSS를 작성할 수 있어 편리합니다

BE

Nest.js

  • 백엔드 서버를 구현하기 위한 기능이 Nest.js 프레임워크 자체에 포함되어 있습니다. -> 짧은 기간에 서버를 만들기 수월하다고 생각했습니다.
  • Nest.js 는 구조가 정해져 있어서 협업을 진행할 때 일관성을 유지할 수 있습니다.
  • 새로운 학습을 해야되서 시간적 손해가 있을 수 있지만, 공식 문서가 잘 정리되어있는 편이기 때문에 그 부분에 대한 부담을 해소할 수 있다고 생각합니다.
  • Why use Nest.js
  • Nest.js DOCS

Jest + Cypress

DB

  • MySQL
  • TypeORM

Production

  • Gihub Action
  • 배포하는 클라우드(NCloud)

ERD

image

디자인 및 기능 상세

Figma

API 명세

API 주소 API 유형 기능 그룹 비고
/auth/logout GET 로그아웃 회원관리 (auth)  
/auth/check GET 로그인 여부 확인 회원관리 (auth) 현재 로그인이 되어 있는지 여부를 쿠키를 통해 확인
/auth/validate?id=ABC GET 아이디 중복 및 유효성 확인 회원관리 (auth) 아이디는 쿼리스트링으로 전송, 아이디 유효성 및 중복 체크
/auth/register POST 회원가입 회원관리 (auth)  
/auth/withdraw DELETE 회원 탈퇴 회원관리 (auth) DB에서도 데이터 아예 삭제
/detail/edit PUT 상세프로필 수정 프로필  
/detail?id=ABC GET 상세프로필 열람 프로필 아이디나 고유값은 쿼리스트링으로 전송
/profile?stack=frontend&filter1=A&filter2=B&filter3=C&liked=true&pages=1 GET 간략한 프로필 리스트 열람 프로필 리스트 쿼리가 있으면 쿼리 내용에 맞춰 필터링, 쿼리가 없을 경우 전체 리스트 가져오기, 페이지네이션 적용
/like POST 좋아요 추가 좋아요 새로운 좋아요 정보가 DB에 저장되므로, POST
/like DELETE 좋아요 삭제 좋아요 기존의 좋아요 정보가 DB에서 삭제되므로 DELETE

데이터 명세

Github, Google 로그인

  • client 에서 바로 OAuth 인증 서버로 a 태그 이용
  • 리디렉션이 깃허브 또는 구글에서 오므로, 데이터를 보낼 수 없어 쿠키만을 전달
  • 성공 시
res.cookie(token).redirect('localhost:3000');
  • 실패 시
res.status(401).redirect('localhost:3000').error(400);

/auth/logout

  • 아이디와 같은 내용물은 쿠키 안에 들어있는 토큰에서 읽어들이기

  • 성공 시

res.status(200);
  • 실패 시
res.status(400);

/auth/check

  • 성공 시
res.status(200).send({
  code: 200,
  message: '인증 성공',
  data: {
    id: '123' // DB상의 식별자
    username: 'limited-hyeon' // 회원가입 시 입력했던 ID
  },
}
  • 실패 시
res.status(401).send({
  code: 401, // custom code
  message: '로그인 실패'
});

/auth/validate

  • 성공 시
res.status(200).send({
  code: 200,
  message: '유효한 ID'
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '유효하지 않은 ID'
});

/auth/register

  • 보내는 데이터
{
  username: 'limited-hyeon', // 입력한 유저 이름
  interest: INTERESTS.FRONTEND, // 관심 분야, 상수값 => 프론트엔드, 백엔드에서 공용으로 사용
  skills: [SKILLS.REACT, SKILLS.VUE] // 기술 스택, 상수값 => 프론트엔드, 백엔드에서 공용으로 사용
}
  • 성공 시
res.status(200).send({
  code: 200,
  message: '회원가입 성공'
});
// 회원가입 성공 후 리디렉션 처리는 프론트엔드에서 분기를 나누어 진행
  • 실패 시
res.status(400).send({
  code: 400,
  message: '회원가입 실패'
});

/auth/withdraw

  • 아이디와 같은 내용물은 쿠키 안에 들어있는 토큰에서 읽어들이기

  • 성공 시

res.status(200).send({
  code: 200,
  message: '탈퇴 성공'
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '탈퇴 실패'
});

/detail/edit

  • 보내는 데이터
{
  username: 'limited-hyeon',
  code: `console.log('hello world');\nreturn(0);`,
  interest: INTERESTS.FRONTEND,
  skills: [SKILLS.REACT, SKILLS.TYPESCRIPT],
  worktype: '페어 프로그래밍, 잠실역 근처'
  worktime: '새벽은 타협 가능하고 오후 1시부터 항상 비어있어요'
  email: '[email protected]'
  requirements: ['잠실사는사람만', '소통좋아해요'],
}
  • 성공 시
res.status(200).send({
  code: 200,
  message: '정보 변경 성공'
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '정보 변경 실패'
});
// 정보 변경 실패할 경우 프론트엔드에서 alert 띄워주기

/detail?id=ABC

  • 성공 시
res.status(200).send({
  code: 200,
  message: '정보 변경 성공',
  data: {
    username: 'limited-hyeon',
    code: `console.log('hello world');\nreturn(0);`,
    interest: INTERESTS.FRONTEND,
    skills: [SKILLS.REACT, SKILLS.TYPESCRIPT],
    worktype: '페어 프로그래밍, 잠실역 근처'
    worktime: '새벽은 타협 가능하고 오후 1시부터 항상 비어있어요'
    email: '[email protected]'
    requirements: ['잠실사는사람만', '소통좋아해요'],
    liked: true
  }
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '정보 수신 실패'
})
// 정보 수신 실패할 경우 프론트엔드에서 alert 띄워주고, 리스트 화면으로 리디렉션

/profile?stack=frontend&filter1=A&filter2=B&filter3=C&liked=true&pages=1

  • 성공 시
res.status(200).send({
  code: 200,
  message: '정보 변경 성공',
  data: {
    lists: [
      {
        id: '', // 상세 페이지 조회 및 좋아요 용도
        code: `console.log('hello world');\nreturn(0);`, // 프론트엔드에서 잘라서 사용
        skills: [SKILLS.REACT, SKILLS.TYPESCRIPT],
        requirements: ['잠실사는사람만', '소통좋아해요'],
        liked: true
      },
      {
        id: '',
        code: `console.log('hello world');\nreturn(0);`,
        skills: [SKILLS.REACT, SKILLS.TYPESCRIPT],
        requirements: ['잠실사는사람만', '소통좋아해요'],
        liked: true
      },
      ...
    ]
  }
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '정보 수신 실패'
})
// 정보 수신 실패할 경우 프론트엔드에서 alert 띄워주기

/like (POST)

  • 보내는 데이터
{
  likedId: '' // 좋아요한 상대방의 아이디
}
  • 성공 시
res.status(200).send({
  code: 200,
  message: '좋아요 성공'
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '좋아요 실패'
});
// 좋아요 실패할 경우 프론트엔드에서 alert 띄워주기?

/like (DELETE)

  • 보내는 데이터
{
  likedId: '' // 좋아요한 상대방의 아이디
}
  • 성공 시
res.status(200).send({
  code: 200,
  message: '좋아요 취소 성공'
});
  • 실패 시
res.status(400).send({
  code: 400,
  message: '좋아요 취소 실패'
});
// 좋아요 실패할 경우 프론트엔드에서 alert 띄워주기?

페이지 라우팅

페이지 주소 기능 비고
/ 메인 페이지 /main 으로 리디렉션
/?stack=frontend&filter1=A&filter2=B&filter3=C&liked=true 메인 페이지 (필터와 함께) 쿼리가 있으면 쿼리 내용에 맞춰 필터링, 쿼리가 없을 경우 전체 리스트 렌더링
/login 로그인 페이지  
/detail/ABC 유저의 상세페이지 열람 id는 주소에 붙이기
/mypage 유저 자신의 페이지 열람  

얼리버드

프로젝트

개발일지

스프린트 계획

멘토링

데일리 스크럼

데일리 개인 회고

위클리 그룹 회고

스터디

Clone this wiki locally