WECODE/Project

2차 프로젝트 회고

HEY_WOO 2023. 10. 10. 20:56

23.09.18 ~ 23.10.06 총 2주의 2차 프로젝트

 

 이번 2차 프로젝트는 클론 코딩을 통해 회원가입 - 로그인 - 제품페이지 - 장바구니 - 주문페이지 전체의 유저 플로우를 직접 구현해 보는 것을 목표하는 프로젝트였다. 2주 간 진행하였기에 디자인/기획 부분은 기존 웹 서비스를 클론 하였지만 추가로 구현하고자 논의한 내용은 직접 개발하였다.

 

 

 

🎯 나의 목표

 

1) 해보고 싶었던 결제 부분을 구현하며 제품 - 장바구니 - 결제 프로세스에 대해 이해하고 필요한 쿼리문을 직접 작성하고자 하였다.

 

2) 위 내용과 더불어 전체 로직의 흐름을 잘 이해하고자 데이터베이스 생성을 맡고자 하였다. 또한 dbmate 작성법을 익히고  

 

3) 2차 프로젝트에서는 2차 프로젝트에서 부족했던 문서화 작업에 더 신경 쓰고자 하였다.  - api 명세서 작성, 에러 공유, 커밋 메시지(이모지까지)

 

 

💻 내가 구현한 것

 

1. 주문페이지 api

 장바구니 정보, 주문자 정보, 배송지 정보, 결제(포인트) 정보를 하나의 api로 호출하였다.

 

2. 주문하기 api

주문하기 api 호출 시 order 관련 정보를 저장함과 동시에 cart에 담긴 제품의 상태를 주문 완료로 변경, 결제 시 사용하고자 입력한 포인트만큼 삭감하며 이를 트랜잭션으로 관리한다.

 

3. 배송지 api

배송지 추가 api 호출 시 새로운 배송지 정보를 저장, 배송지 삭제 api 호출 시 기존 저장한 주소 정보를 삭제한다.

 

🔐 내가 고민한 것

 

1) 쿼리문

get으로 여러 가지 데이터를 가져올 때 join 문과 서브쿼리를 써서  한 번에 가져오고 싶었으나 충분히 고려하지 못하여 결국 dao에서 구한 각각의 값을 서비스에서 합쳤다. 이후 속도적인 측면에서 쿼리로 처리해야 했다는 피드백을 얻었다.

 

2) 반복문 시 무한 반복 문제

 주문번호를 생성할 때 랜덤값이 포함되도록 로직을 작성하고 postman으로 요청을 보냈더니 계속 요청 시간이 오버되었다. 원인을 찾아보니 반복문에서 무한루프에 걸릴 수 있다고 해서 해결 방법을 찾아서 수정했다.

 

        //orderNumber가 중복되지 않을 때까지 반복
        while (true) {
            // 현재 날짜 포맷 (20231002)
            const currentDate = new Date().toISOString().slice(0, 10).replace(/-/g, "");
            // 2자리 랜덤 숫자 생성
            const randomDigits = Math.floor(Math.random() * 100).toString().padStart(2, "0");

            const orderNumber = parseInt(`${currentDate}${id}${randomDigits}`);

            // 주문번호 중복 확인
            const isOrderNumberDuplicate = await findByOrderNumber(orderNumber)

            if (!isOrderNumberDuplicate) {
    
                return await createOrderData(...

 

🔺 위 코드가 기존 코드이다. 항상 참인  while (true) 문 안에 break없이 if (!isOrderNumberDuplicate)가 있기에 계속 주문정보를 생성하며 무한 루프에 빠지게 된 것이다.

 

        let orderNumber = null;
        let isOrderNumberDuplicate = true;
        
        // 주문번호가 중복되지 않을 때까지 반복
        while (isOrderNumberDuplicate) {
            // 현재 날짜 포맷 (20231002)
            const currentDate = new Date().toISOString().slice(0, 10).replace(/-/g, "");
            // 2자리 랜덤 숫자 생성
            const randomDigits = Math.floor(Math.random() * 100).toString().padStart(2, "0");
            orderNumber = parseInt(`${currentDate}${id}${randomDigits}`);

            // 주문번호 중복 확인
            isOrderNumberDuplicate = await findByOrderNumber(orderNumber);
        }

           return await createOrderData(...

 

🔺 따라서 위와 같이 while 루프의 종료 조건을 수정하였고, 코드가 정상 작동하였다.

 

 

 

3) 트랜젝션 

 이번 과제의 미션 중 하나로 트랜젝션 처리를 생각했다. 단순히 데이터를 select 하는 것이 아닌 insert나 update같이 변화가 생길 때 제대로 처리되지 않으면 rollback 되는 것이 중요하며, 내가 맡은 부분이 결제 부분이라 더욱 신경이 쓰였다. 간단하게 적용해서 큰 어려움이 있었던 것은 아니었지만, 테스트할 때 rollback 되는 것을 직접 보면서 트랜젝션의 중요성을 몸소 깨달았다.

 

📌 내가 배운 것

 

1) 정해진 기간이 있으므로 블로커에 대해 적극적을 공유하여 정체 기간을 줄여야 한다. 

 

2) 기획 단계와 ERD 작성, API 명세서 작성부터 프론트와의 소통이 중요하다. url 공유에서부터 주고받는 데이터에 대해 모두가 같은 내용을 이해하고 있어야 개발이 원활히 이뤄진다는 것을 깨달았다.

 

3) 데이터베이스 공유가 잘 되어야 한다. 내가 서버를 돌릴 때도 user 테이블에 수정사항을 제때 업데이트하지 않아서 쓸데없이 시간을 날리기도 하였다. 가데이터인 products 데이터가 있는 노트북을 최종 서버로 하여 프론트와 연결했는데 해당 노트북에 그동안 수정된 데이터베이스가 업데이트가 되어 있지 않아서 추가적으로 수정을 하는 일이 있었다. 그전에 products 데이터 정보를 모두가 미리 공유했다면 수정사항이 반영된 데이터베이스를 서버로 할 수 있었다. 

 

4) api 명세서 : 코드를 작성하는 시간보다 고민하는 시간이 길었다. 문서화로 미리 작성해서 프론트와 공유하진 못했지만 구현하고자 하는 api에 필요한 데이터, 쿼리, 로직을 구상하고 간략히 정리한 후 코드를 작성하니 하루, 이틀 만에 완성하기도 하였다. 물론 제대로 된 완성은 아니었지만, 확실히 추가 사항이 계속 생겨서 코드를 수정하고 추가 테스트를 하던 때보다 훨씬 효율적이었다. 따라서 api 명세서가 작성된다면 프론트와의 통신 과정도 훨씬 원활해질 것 같다는 생각을 하였다.

 

5) http 상태 코드 코드

2XX - Success 4XX - Client Error 
200 - Success 400 - Bad Request
201 - create 401 - Unauthorized
204 - delete 403 - Forbidden

 

 

 

 

[웹 프로그래밍] HTTP 상태 코드 표(100 ~ 500) 전체 요약 정리

서버에서의 처리 결과는 응답 메시지의 상태 라인에 있는 상태 코드(status code)를 보고 파악할 수 있습니다. 상태 코드는 세 자리 숫자로 되어 있는데 첫 번째 숫자는 HTTP 응답의 종류를 구분하는

hongong.hanbit.co.kr

 

6) 코드 리뷰

  • 사용하지 않는 라이브러리는 제거한다. 코드의 가독성을 향상시키고, 보안 및 성능 측면에서 이점이 있다.
  • 미들웨어는 코드 상 순서대로 정의되어 작동한다. 이러한 미들웨어는 라우터보다 앞에 위치하기 때문에 router()는 마지막에 작성해야 한다.
  • dao 변수명은 보통 crudTable 로 작성한다. createUser , deleteOrder
  • select 문에서 *은 잘 사용하지 않는다. 대량의 데이터를 다뤄야 하는 경우에는 불필요한 데이터를 가져오는 것은 성능에 부정적인 영향을 준다.  테이블을 생성할 때부터 WHERE 절에 있는 컬럼을 unique key로 걸어두었다면, 그 조건만으로도 충분하긴 하다.
  • select 시 찾은 결과를 제한하기 위해 LIMIT 또는 TOP 등의 키워드를 사용하면 더 효율적이다.