위코드-1차 프로젝트 회고

kmjmarine·2023년 8월 20일
1

wecode

목록 보기
8/8

프로젝트 소개

  • Text 중심의 새로운 sns 'Treads'의 프로토타입격인 'Wereads'(Wecode + Threads) 개발 프로젝트이다.
    • 필수와 추가 구현사항으로 나뉘어 회원가입, 로그인(인증/인가), 글쓰기/수정/삭제, 좋아요, 댓글기능이 개발 범위에 포함되었다.
  • 작업 기간은 단 5일, 그 사이 휴일이 껴있어서 실제적으로는 4일 뿐이었다.
    그래서 프로젝트 시작 전 주말에 trello 카드 작성을 공동으로 하였고 사전 initial setting를 팀원 각자 진행했다.

  • 사용 기술 스택
    • node.js, express, Mysql, react.js, npm, dbmate

  • 나의 역할
    • ERD 작성, 인증/인가 개발

구글캘린더 일정 상 3일 뒤 front end와 fusion이 예정되어 있어 늦어도 수요일까지는 웬만한 backend 작업이 되어 있어야 했다.

초기셋팅 및 작업 시작 단계

  • 웹서버 구축에 필요한 의존성 모듈 정의(package.json) 및 샘플 코드는 github repository에서 제공이 되었었기 때문에 'git clone'를 먼저 진행했고 나머지 개발자간 상이하게 정의 되었던 .env와 .gitignore는 일치 시켰다.

  • 각 개발자에게 기능 개발을 할당하고 각기 개발을 하여 개발 기간을 줄이기 보다는 최대한 공통 부분 즉 Layered Pattern 설계, ERD, dbmate 스키마 작성등은 하나의 pc에서 페어 코딩 방식으로 진행을 해서 추후 수정이 적게하여 개발 기간을 줄이기로 팀원간 협의를 했다.

이때부터 팀원간 협업이 무리없이 잘되고 있음을 느끼게 되었다. 매일 오전에 시행한 stand up 미팅에서도 초기 일정보다 크게 지연되는 ticket는 거의 없었다.

ERD 작성하기

  • ERD 작성은 온라인 기반인 dbdiagram.io 를 사용했다. 각자 ERD를 작성 후 서로 놓쳤던 부분과 미흡한 부분을 공유 후 하나의 ERD를 도출해 냈다.
  • 총 4개의 테이블이 나왔고 추후 확인 결과 모범 답안과 크게 다르지 않았다.
    다만 실제 Mysql DBMS에 스키마를 적용하기 위해 DBmate 마이그레이션을 Mysql용으로 DDL 문을 export 받아서 진행 했지만 일부 컬럼 속성들이 정상 반영되지 않아 콘솔에서 별도 속성 부여를 진행해야 했다.
  • 최종적으로 한 pc에서 dbmate up 후 원하는대로 마이그레이션이 됐음을 확인하고 DDL *.sql 문을 배포하여 각 pc에서 마이그레이션 작업을 완료했다.

위와 같은 순서로 작업을 진행하고 나니 예상대로 다시 이전 이나 처음으로 돌아가는 일은 없었다.

회원가입 / 로그인 구현

  • 회원가입 api, 로그인 api 부분은 이전 과정에서 한번 해봤기 때문에 크게 어렵지 않았다.

    특히 비지니스 로직(auth.controller.js)에서 다른팀과 다르게 유저가 닉네임과 프로필 이미지를 등록하지 않았을 경우 즉, req.body에 해당 데이터가 없을 경우 .env에 선언한 기본 데이터가 저장되도록 했다.
//.env
NONAME = "게스트"
NOIMAGE = "https://ssl.pstatic.net/static/cafe/cafe_pc/default/cafe_profile_70.png"
//auth.contorller.js 
  if (!userName) {
    defalutUserName = process.env.NONAME;
  }else{
    defalutUserName = userName;
  }
  if (!profileImage) {
    defalutProfileImage = process.env.NOIMAGE;
  }else {
    defalutProfileImage = profileImage;
  }

(삼항식이나 더 간소화를 하려 했으나 다른 팀원이 이해하기 쉽도록 일단은 if else 로 표현)

  • password는 bcrypt 10번 hash로 지정했다. 이렇게 하면 테스트 결과 암호화된 데이터는 60자로 되기 때문에 해당 db 컬럼 속성을 char(60)으로 지정하여 그 외의 길이의 데이터가 들어오면 정상적인 프로세스를 거친것이 아닌것으로 간주하려 했으나 다른 의견에 의해 char(100)으로 변경 했다.

정상적으로 token 값이 추출이 되었고 postman POST 시 정상적으로 회원가입 및 로그인이 되었다. 샘플코드에는 이메일과 password를 토큰값으로 인코딩 했으나 현재 필요한 데이터는 user_id뿐이라 user_id값만 인코딩 하도록 수정이 필요했다.

쓰레드 기능 구현

  • 쓰래드 기능 구현 시 예상치 못한 난제를 맞닥드렸다. 인가에 대한 프로세스를 생각하지 못했다. thread, comment, 좋아요에서 회원 pk값(user_id)이 필요한데 frontend에서 req.header로 보내오는 token 값을 해석해야 했다.

  • 이 부분은 이전 세션에서 배운적이 없어서 어떻게 구현해야 할지 팀원들과 고민의 시간이 길어졌다. 다행히 예전에 개인적으로 했던 프로젝트에서 해당 기능이 구현이 되어 있어 이를 참고해서 ./utils 안에 token.verify.js 파일을 작성했다.
const checkVerify = async (req, res, next) => {
  checkVerifyPromise(req, res, next).then(
    (user) => {
      res.user = user;
      next();
    },
    (error) => {
      res.user = {};
      console.log('토큰값 불일치');
      //res.render("user/signin");
    }
  );
};
const moveLogin = (req, res, next) => {
  if (res?.user?.user_id) {
    next();
  } else {
    console.log('로그인 페이지 이동');
    //res.render("user/signin");
  }
};
// router역할하는 코드에서 인가가 필요한 경우 삽입해 준다.
threadsRouter.get(
  "/set",
  [checkVerify, moveLogin],
  threadsController.threadSet
);
const commentList = async (req, res) => {
	//checkVerify를 통해 디코딩한 user_id 값
    const user_id = res.user.user_id; 
    try {
        const commendListShow = await commentsService.commentList(user_id);
        res.status(200).json(commendListShow);
    } catch (err) {
        res.status(err.statusCode || 400).json({ message: err.message });
    }
};

res.render method가 오류 시 페이지 이동의 역할을 하는 것으로 보이는데 해당 기능은 .ejs환경에서 작동하는것으로 파악이 되고 본 프로젝트에서의 페이지 이동은 frontend에서 하는것으로 했기때문에 res.render 메소드에 대해서는 별도로 스터디 및 테스트가 필요하다.

스레드 글 리스트 영역의 쿼리

  • 스레드 글 리스트를 구현하기 위해서는 threads, users, likes, comments 즉 wereads DB의 모든 테이블에 필요했다.
USE wereads;
SELECT t.id AS postId, 
u.id AS userId, 
u.nickname AS userName, 
u.profile_image AS profileImage, 
t.content,
CASE
	WHEN (l.id IS NOT NULL) THEN 'true' 
    ELSE 'false'
END
AS likeId,
ifnull(c.likeCount,0) AS likeCount,
t.created_At,
cmt.comments
FROM threads t LEFT JOIN users u ON t.user_id = u.id
LEFT JOIN likes l ON l.thread_id = t.id AND l.user_id = 1
LEFT JOIN (SELECT COUNT(thread_id) AS likeCount, thread_id FROM likes GROUP BY thread_id) c ON c.thread_id = t.id 
LEFT JOIN (
	SELECT 
		thread_id,
		JSON_ARRAYAGG(
			JSON_OBJECT(
				"commentId",id, 
				"userName", user_id, 
                "comment", content, 
                "createAt", created_at  
			)  
		) AS comments
	FROM comments GROUP BY thread_id) cmt ON t.id = cmt.thread_id 
ORDER BY t.id DESC
// 내가 작성한 쿼리와 멘토님이 작성한 쿼리를 비교 분석 해보자. (좋아요 여부, 좋아요 수)
EXISTS (SELECT 1 FROM likes l WHERE l.user_id = 1 AND 
l.thread_id = t.id) AS isLiked,
COALESCE(c.likeCount, 0) AS likeCount,

해당 글의 comments를 가져와야 하는 부분은 조언을 받아 json형태 2차배열로 가져오도록 했다. 이는 MS-SQL에서는 dataset 객체 반환이 주이고 json으로의 반환이 거의 없어 경험하지 못한 부분인데 새로운 것을 배운 좋은 기회가 되었다.

잘된점과 아쉬웠던 점

  • 그간 세션에서 배운 점과 개인적으로 스터디 한 부분을 한 싸이클을 돌려 보는 좋은 경험이 되었다. 개발 스펙은 작았지만 다른 프로젝트도 이 프로젝트에서 보안적인 측면에 대한 코드 추가, 에러 페이지로의 이동등과 같이 기능과 살을 더 붙이는 수준일 것 이다.

    팀간 협업이 잘되었고 PM의 스케쥴 관리및 문서 정리가 특히 잘되었다.
    다만 아쉬웠던 부분은 frontend와 fusion시 완벽하게 화면에서 모든 기능테스트가 되었으면 했는데 페이지별 단위 테스트로 진행이 되어 아쉬운 부분이 있었다.

    다음 프로젝트에서는 좀 더 다양한 기능 구현과 화면에서의 테스트가 완벽하게 이뤄질수 있도록 잘 준비해야겠다.
profile
shared knowledge is long, life is short

0개의 댓글