2024.01.15(월)

📍MariaDB SQL_CALC_FOUND_ROWS, FOUND_ROWS()

  • SQL_CALC_FOUND_ROWS 🔗
    • 이 option이 사용되면 MariaDB는 LIMIT 절이 없었을 때 몇 개의 행이 결과에 있을지를 계산한다.
    • 다음 sql 문에서 FOUND_ROWS() 함수를 호출하면 앞서 계산한 결과를 찾을 수 있다!
  • FOUND_ROWS() 🔗
    • SELECT 문은 서버가 클라이언트에게 반환하는 행의 개수를 제한하기 위해 LIMIT 절을 포함할 수 있다.
    • 경우에 따라 LIMIT 절이 없었을 때 몇 개의 행이 반환되었을지를 문(statement)을 다시 실행하지 않고 아는 것이 바람직하다.
    • 이 행 수를 얻기 위해서는 SELECT 문에 SQL_CALC_FOUND_ROWS option을 포함하고 이후에 FOUND_ROWS()를 호출한다.
    • LIMIT 절이 포함되지 않은 SELECT에서 반환되는 행의 수를 구하는데에도 FOUND_ROWS()를 사용할 수 있으며 이 경우 SQL_CALC_FOUND_ROWS option을 사용할 필요가 없다.

MariaDB의 모체인 MySQL에서 "SQL_CALC_FOUND_ROWSFOUND_ROWS() 함수는 MySQL 8.0.17에서 더 이상 사용되지 않으며, 이후 MySQL의 후속 버전에서 제거될 것으로 예상한다."고 나와있다. 대체 방법으로 첫번째 query에서 LIMIT을 사용한 다음, 두번째 query에서 COUNT(*)를 사용한다.

SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();

⬇️ 대체 방법

SELECT * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT COUNT(*) FROM tbl_name WHERE id > 100;

🔗WL#12615: Deprecate SQL_CALC_FOUND_ROWS and FOUND_ROWS

그래서 나는 대체 방법으로 구현했다.

🚫errorHandler 수정

  • mariadb-error-code-reference를 참고하여 외래키 제약 조건 위배와 관련된 4가지 error case를 추가했다.
  • 다음과 같이 현재 errorHandler로 넘어온 error가 외래키 제약 조건 위배에 관련된 것인지 확인한다.
  • 왜래키 제약 조건 위배 error는 클라이언트에서 잘못된 값을 보내서 발생하기 때문에 400(Bad Request)를 보냈다.
[
    "ER_NO_REFERENCED_ROW",
    "ER_ROW_IS_REFERENCED",
    "ER_ROW_IS_REFERENCED_2",
    "ER_NO_REFERENCED_ROW_2"
].includes(err.code)

코드 리뷰를 하면서 해당 부분을 간단하게 err.code.startsWith("ER_")로 수정했다. sql에서 나온 error는 보통 클라이언트에서 보낸 값에 문제가 있어서 발생하기 때문에 그냥 크게 묶어서 처리해도 될 것 같다.

🧐유효성 검사 구현

  • express-validator를 사용하여 구현했다.

  • 나무위키를 참고하여 비밀번호 길이는 일단 최소 8자, 길이 제한은 두지 않기로 결정했다.

  • 각 endpoint에 맞는 grouped validation chain을 만들고 object로 만들어 property로 접근할 수 있도록 했다.

    const validator = {
        signUp: emailPasswordValidation,
        logIn: emailPasswordValidation,
        passwordResetRequest: emailValidation,
        resetPassword: emailPasswordValidation,
    
        getBooks: pagingValidation,
        getBookById: bookIdParamValidation,
    
        addToLikes: bookIdParamValidation,
        removeFromLikes: bookIdParamValidation,
    
        addToCart: addToCartValidation,
        getCartItems: selectedValidation,
        removeFromCart: itemIdValidation,
    
        submitOrder: orderRequestValidation,
        getOrderDetails: orderIdValidation
    };
    
    module.exports = validator;
  • 이런 식으로 각 endpoint handler 전에 실행되도록 앞에 넣어준다.

    router.post('/:bookId', validator.addToLikes, addToLikes);
    router.delete('/:bookId', validator.removeFromLikes, removeFromLikes);

이름 짓는 일이 제일 어려운 것 같다. 러프하게 짜본 것이고 이름과 중복 코드 제거는 내일 마저 해볼 예정이다.

profile
이것저것 관심 많은 개발자👩‍💻

0개의 댓글