본문으로 바로가기

유효성 검사는 백에서? 프론트에서?

category Frontend 2021. 2. 28. 13:20

이번에 리액트와 노드를 사용해서 간단한 블로그를 구현했는데 하면서 한 가지 의문점을 느꼈다

서버쪽 개발을 할 때 분명히 로그인이나 회원가입 폼에서 들어오는 입력에 유효성 검사를 해서 올바르지 않은 데이터 형식을 걸러냈는데

프론트에서 입력 폼을 구현할 때 또 유효성 검사를 하다가 '아니 서버에서 검사하는데 왜 이걸 또 구현해야 하지?'

서버에서의 유효성 구현은 익숙하지 않은데다가 postman같은 걸로 테스트해야하니 자바스크립트로만 구현하면 편한데 대체 왜?

여기저기 찾아본 결과 정답은 백과 프론트 양쪽에서 다 해주어야 한다 였다

프론트에서만 검사

    const onSubmit = (e)=>{
        e.preventDefault();
        const {username, password, passwordConfirm} = form;

        if([username,password,passwordConfirm].includes('')){
            setError('빈 칸을 모두 입력하세요');
            return ;
        }
        if(username.length<=3){
            setError('아이디가 너무 짧습니다');
            return ;
        }
        if(password!==passwordConfirm){
            setError('비밀번호가 일치하지 않습니다');
            return ;
        }
        dispatch(register({username, password}));
    };

     useEffect(()=>{
        if(authError){
            if(authError){
                if(authError.response.status === 409){
                    setError('이미 존재하는 계정입니다');
                    return ;
                }
                setError('회원가입 실패');
            }
        }

        if(auth) {
            console.group('success');
            console.log(auth);
            console.groupEnd();
            dispatch(check());
        }
    }, [auth, authError, dispatch]);

리액트에서 입력 폼에서 유저 아이디, 비밀번호, 비밀번호 재확인에서 데이터를 받아와 유효성 검사하는 코드이다

submit이벤트에서는 서버에 api를 요청하기 전에 걸러내는 것이고

useEffect의 코드는 api 요청을 한 뒤 응답 값을 받아서 성공, 실패를 알려준다

유저에게 잘못된 정보도 다 알려주고 데이터가 잘 못 들어갈 일도 없어보인다

문제점

브라우저의 개발자 도구로 손쉽게 뚫을 수 있다

왼쪽을 보면 정상적으로 입력된 로그인 폼이 있고 오른쪽에선 소스를 연 뒤 입력 폼의 유효성 검사들이 다 지나고 난 후 api를 날리기 전에 브레이크 포인트를 걸어놓았다

이대로 회원가입을 누르면 서버에 데이터를 날리기 전에 동작이 멈추는데 그 때 콘솔 창으로 데이터를 수정하면 프론트의 유효성 검사를 피해서 얼마든지 내가 원하는 데이터를 넣을 수 있다

 

 

1414로 유효성 검사를 통과시킨 뒤 브레이크 포인트에서 계정명을 '하나'로 바꾼 뒤 회원가입이 된 모습 (계정명은 4글자 이상이어야한다)

사실상 프론트에서의 유효성 검사는 UI/UX를 위한 것이지 다른 용도로는 쓸 수 없다

디비에도 정상?적으로 들어간 계정들을 볼 수 있다

해결 방안

그렇다면 서버에서만 검사하는 것은 어떨까?

UX/UI를 위해서 굳이 프론트에서 검사할 필요가 있을까 입력 폼을 검사하지않고 api를 날린 뒤 서버 검증에서 실패하고 받아온 에러 코드들로 사용자에게 정보를 주면 되지 않을까

아래는 node.js의 데이터 검증 코드다

export const register = async ctx=>{
    const schema = Joi.object().keys({
        username : Joi.string()
            .alphanum()
            .min(3)
            .max(20)
            .required(),
        password : Joi.string().required(),
    });
    const result = schema.validate(ctx.request.body);


    if(result.error){
        ctx.status = 400;
        ctx.body = result.error;
        console.log(ctx.body);
        return;
    }

    const {username, password} = ctx.request.body;
    try{
        const exists = await User.findByUsername(username);
        if(exists) {
            ctx.status = 409;
            return;
        }

문제점

근데 저기서 계정 길이, 암호 일치, 빈 칸 유무 등의 에러 상태를 표현할 새 변수를 만들어서 프론트로 보내려고 머리를 쓰고있는데

에러가 날 데이터를 거르지않고 서버에 요청을 해서 리소스를 잡아먹는 것이 과연 옳은 개발 방법일까? 요청에 걸리는 시간 동안 사용자는 기다림이 생기면서 불편할텐데..

해결 방안

서로 상호보완적이 가능하게 결국 처음에 했던대로 양쪽 다에서 해주는 것이 맞았다

데이터 변조로 서버에 들이밀었을 때 거를 수 있게 해주는 백 검증,

사용자에게 빠른 응답을 줄 수 있게, 서버에 리소스를 덜 먹게하기 위한 프론트 검증

'Frontend' 카테고리의 다른 글

프론트엔드 개발환경의 이해 : Webpack (2)  (0) 2021.03.14
프론트엔드 개발환경의 이해 : Webpack  (0) 2021.03.10
프론트엔드 개발환경의 이해 : NPM  (0) 2021.03.09
MVC 패턴  (0) 2021.03.06
SPA, MPA, SSR, CSR  (0) 2021.01.31