티스토리 뷰
1. 프로젝트 소개
제목: 천씨네
간단 설명: 25년 장인 미스타천의 손길이 닿은 수제(?) 빨래방에 어서오세요
핵심 기능
- 계정 관리: 회원가입, 로그인, 마이페이지
- 세탁 서비스 이용: 서비스 신청 및 상태 파악(손님), 서비스 진행 및 상태 업데이트(사장님)
- 리뷰: 이용한 서비스에 대한 리뷰 CRUD
배포 URL ( AWS EC2 이용, ~2023.01.08. )
개발 GitHub
팀 노션
시연 영상
로고
2. 개발 인원 및 역할
- 천준기(팀장): 회원가입 및 로그인 페이지, 사장님 메인 페이지, 리뷰 조회 페이지
- 이설인: 리뷰 작성 페이지, 프론트엔드 총괄
- 육준호: 손님 메인 페이지
- 김재원: 리뷰 작성 페이지
- 김희서: 손님 및 사장님 마이페이지
3. 사용 기술
테스트 도구
Jest
프로젝트 구조
3계층 (Controller, Service, Repository) 아키텍처 패턴을 적용함.
4. 초안과 와이어 프레임
5. API 명세
- 사장님만 접근 가능할 서비스:
- 세탁 서비스 목록 조회,
- 마이 페이지 중 빨래 현황 업데이트 가능하도록
- 손님이 접근 가능할 서비스:
- 세탁 서비스 신청 페이지,
- 마이 페이지 중 내가 신청한 서비스 조회,
- 세탁 사장님에 대한 리뷰 작성 페이지
- 로그인한 모든 유저가 접근 가능할 서비스:
- 마이 페이지(?),
- 세탁 사장님에 대한 리뷰 조회 페이지
- 로그인 안 한 채로 접근 가능할 서비스:
- 메인 페이지, - 대문 배너와 로고 간단히, 회원 가입/로그인 버튼
- 회원 가입 페이지 - nickname, password, (password 확인), phone_number, address, user_type 입력 폼
- 로그인 페이지 - nickname, password 입력 폼
구체적인 예외처리는 각자에게 맡긴다.
- 서비스 수정 및 삭제, 리뷰 삭제를 제외한 모든 API를 구현하였다.
- 개발하면서 경로명이 수정된 경우가 몇 있었다.
- ⇒ 예를 들어 Services의 3가지 GET의 경우 처음 예상과 다르게 customerId를 params로 받는 게 적절치 않다는 것을 알게 되었고, 그로 인한 수정이 연쇄적으로 다른 GET들의 경로와 중복되게 되었다. customerId를 req.params로 받지 않고 대신 userId를 res.locals.user로 받는 등 적절한 변수를 적절한 방식으로 가져오는 것과, 의미상으로 적절한 경로명을 부여하는 것을 고민해 본 시간이었다.
6. 데이터베이스 스키마
- 데이터베이스는 초기 설계가 매우 잘 되었고, sequelize를 이용하여 테이블을 쉽게 생성할 수 있었다.
- Amazon RDS를 MySQL 서버로 이용하였다.
7. 잘 한 점
- DB 설계를 잘 한 것 같다. 개발하면서 크게 수정할 부분이 없었다.
- API 설계는 개발하면서 새롭게 추가하거나 수정한 부분이 있었으나 전체적으로 Restful한 설계였다고 생각한다.
- 깃의 브랜치를 나눠 작업하는 방식을 프로젝트에 처음 사용하는 팀원이 많았는데, 팀장의 주도 하에 다들 서투르면서도 큰 문제 없이 개발이 진행되었다. Push, Pull, 풀 리퀘스트 후 머지 등 Git과 Github 사용법을 반복 연습하며 손에 익히게 되어 좋았다.
- 처음에 코드를 통으로 짠 후에 Layered Architecture 패턴을 적용하여 3계층 구조로 만드는 방식을 취하길 잘했다. ⇒ 계층을 다 분리하고 코드를 찬찬히 보니 새삼 이게 결국 메소드와 클래스로 이루어진 객체 지향적 프로그램이라는 것을 알 수 있었다. 열심히 쪼개고 쪼개었을 뿐인데 추상화가 이루어지게 되고, 객체 지향 프로그래밍의 맛을 보게 되어 좋았다. 처음부터 계층을 나눈 채로 작업하기 시작했다면 어렵기도 어려웠겠거니와 지금처럼 이전과 이후를 비교하여 장단점과 차이점을 깨닫기도 힘들었을 것이다.
8. 해결한 내용
💨💨💨
- 천준기님이 시연을 해보면서 찾은 오류! 리뷰 조회 버튼을 눌렀는데 아무것도 나오지 않아서 에러를 찾느라 오래 걸렸는데 결국 if 문에서 = 3개를 썼어야 하는데 2개만 쓴 자바스크립트 문법 오류를 찾아내셨다! 이건 어렵진 않았지만 치명적인 오류였어서 해결이 더 뿌듯한 내용
- “프론트에서 보내는 PUT body가 백에 전달되지 않는 에러”⇒ 해결책을 찾고 생각해보니 전에 배웠던 기초 내용이었던 것 같아 혼자 부끄러웠다.해결된 ajax 콜 예시:
- $.ajax({ ... type: 'PUT', url: `/api/services/${serviceId}/mypage`, data: JSON.stringify({ status: status }), contentType: 'application/json; charset=UTF-8', headers: { authorizat~~ion: `Bearer ${localSt~~orage.getItem('token')}`, }, success: function (response) { customAlert(response.message); }, error: function (xhr, status, error) { console.log(xhr.responseJSON.errorMessage); }, });
- data:JSON.stringify(jsondata), contentType:'application/json;charset=UTF-8',
- ⇒ ajax 폼에 다음 데이터를 추가하여 해결하였다.
9. 아쉬웠던 점, 해결하지 못한 부분
- 이미지 파일을 올리고 DB에 저장하는 것은 됐지만, 그 이후의 처리와 DB에서 꺼내오는 것을 구현하지 못해 아쉬웠다. multer 모듈을 공부하면 이를 해결할 수 있을 것이다.
- 단위 테스트를 시도해보았으나 시간이 없어 더 도입하지 못한 것이 아쉽다. 다음엔 통합 테스트까지 진행해보고 싶다.
- 모달창을 활용해 여러 예외 처리를 구현 하였으나, 모든 케이스를 고려하지는 못했다. 테스트를 진행해보면서 더 충분한 예외 처리가 되면 좋을 것 같다.
- 마감이 다가올수록, 중복되는 코드나 작은 에러 등 개선점이 눈에 보이는데도 잘못 건드렸다가 잘 돌아가던 기능에 구멍날까봐 불안해서 건드리지 못한 부분이 많았다. 깃은 여러 명의 작업물을 합치기 위한 협업 도구로써만 역할을 했을 뿐, 또 다른 핵심 기능인 버전 저장이나 되돌리기 기능을 활용하지 못한 반쪽짜리 사용이었다.
- ⇒ 깃의 이 부분을 좀 더 연습해서, 다음부턴 지금같이 ‘함부로 건드렸다가 잘못되면 이제 고칠 시간 여유도 없고 큰일이다’ 같은 부담을 줄이고, 마감이 다가와도 리팩토링에 손 댈 수 있는 여유를 가질 수 있도록 해야겠다.
- 이설인: 백을 건드리지 않아서 할 말이 없지만! 열심히 만들어본 프론트가 백과 연결했을때 에러때문에 깨지고, 만들어둔 구성을 적용하지 못한건 조금 가슴 아픈일이라 역시 백을 잘 알아야 프론트도 잘 나오겠다는 생각이 들었다.
10. 각자 마음에 드는 코드
- 김희서
Users 테이블의 userId 컬럼에 Service 테이블 쪽의 사장님과 손님 ID, 이렇게 두 개의 외래키가 붙어 있는 상황에서, 사장님과 손님 정보를 각각 조인해 가져오기에 성공한 것이 기억에 남는다.
Users와 Services 테이블 관계도
models.service.js
repositories/services.repository.js ( “include”로 조인해올 때 테이블 별명을 호출하는 것이 핵심이다. )
- 천준기
그 동안의 route 파일과는 달리 계층화되어 깔끔해진 코드가 제일 마음에 듭니다!
// ./routes/reviews.routes.js
const express = require('express');
const router = express.Router();
const authMiddleware = require('../middlewares/auth-middleware');
const ReviewsController = require('../controllers/reviews.controller');
const reviewsController = new ReviewsController();
router.get('/', authMiddleware, reviewsController.getReviews);
router.get('/owner/:userId', authMiddleware, reviewsController.getReviewByOwnerId);
router.get('/customer', authMiddleware, reviewsController.getReviewByCustomerId);
router.get('/customer/:serviceId', authMiddleware, reviewsController.getReviewByServiceId);
router.put('/customer/:serviceId', authMiddleware, reviewsController.updateReview);
router.post('/create', authMiddleware, reviewsController.createReview);
module.exports = router;
팀원 블로그
천준기: https://interrobang.tistory.com
이설인: https://velog.io/@lee129you
육준호: https://velog.io/@yuk1479
'What I Learned > SpartaCodingClub' 카테고리의 다른 글
[내일배움캠프] 2023-01-09 TIL (0) | 2023.01.09 |
---|---|
[내일배움캠프] 2023.01.02. ~ 2023.01.08. WIL (0) | 2023.01.09 |
[내일배움캠프] 천씨네: KPT 회고 (0) | 2023.01.06 |
[내일배움캠프] 2023-01-06 TIL (0) | 2023.01.06 |
[내일배움캠프] 2023-01-05 TIL (0) | 2023.01.06 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 24723
- 25501
- 벡준
- 2738
- 24060
- 백준
- Programmers
- 2053
- 항해+
- MySQL
- Python
- 1269
- 5597
- Wil
- 13909
- 25192
- 10807
- 2587
- SQL
- 17103
- 13241
- 26069
- 20920
- programmer
- 항해 플러스
- 4134
- 코육대
- til
- 2903
- 24313
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함