Node.js 애플리케이션을 위한 간단한 라우터를 구축하는 방법

며칠 전에 저는 Node.Js backend without any 3rd party dependencies을 구축하기 시작했으며 오늘은 해당 애플리케이션용 라우터를 어떻게 개발했는지 설명하겠습니다.

더 진행하기 전에 제가 이런 유형의 프로젝트를 수행하는 것은 이번이 처음이며 라우터 이면의 논리가 가장 효율적이거나 최상의 솔루션이 아닐 수도 있음을 말씀드리고 싶습니다. 그래서 저와 다른 사람들과 생각을 공유하도록 여러분을 초대하고 싶습니다.

따라서 기본적으로 경로를 고려할 때 몇 가지 구성 요소로 나눌 수 있습니다.
  • 서브루트 및 경로 매개변수
  • 쿼리 매개변수

  • 먼저 서브루트 및 경로 매개변수에 대한 논리를 개발할 수 있는 방법을 살펴보겠습니다.

    경로는 각 경로에 와일드 카드(경로 매개변수)가 있거나 없는 하위 경로 집합이 있는 트리 데이터 구조로 생각할 수 있습니다.



    경로 구성



    처음에는 쿼리 매개변수와 경로를 다음과 같이 분리해야 합니다.

    let endpoint;
    if (req.url.includes('?')) {
        endpoint = req.url.split('?')[0];
    } else endpoint = req.url;
    


    이제 끝점을 추가/구성하기 전에 '/'를 사용하여 각 하위 경로를 구분해야 합니다.

    if (endpoint[endpoint.length - 1] != '/') endpoint += '/';
    let path = endpoint.split('/');
    


    위의 알고리즘을 사용하여 경로 '/someroute/another'를 연결하면 다음과 같은 출력을 얻습니다.
    ['', 'someroute', 'another', '']
    모든 경로에 대해 처음에 '' 경로를 가져옵니다. 따라서 모든 경로에 대해 무시할 수 있습니다.

    let adjPath = path.slice(1, path.length);
    


    다음으로 반복자를 adjPath 배열로 설정하고 각 수준에서 다음 수준으로 이동하여 경로의 각 부분을 트리에 추가할 수 있습니다.

    앞에 ':'를 사용하여 와일드카드를 식별할 수 있습니다. 따라서 해당 경로를 와일드 카드로 설정할 수 있습니다.

    static constructPath(path, currIndex, head) {
            if (currIndex === path.length) {
                return;
            }
            const newObj = new Router(path[currIndex]);
            if (path[currIndex][0] === ':') {
                head.wildCard = newObj;
                this.constructPath(path, currIndex + 1, head.wildCard);
            } else {
                const childrenAvailable = head.children.find(
                    (c) => c.path === path[currIndex]
                );
                if (childrenAvailable) {
                    const childrenIndex = head.children.findIndex(
                        (c) => c.path === path[currIndex]
                    );
                    this.constructPath(
                        path,
                        currIndex + 1,
                        head.children[childrenIndex]
                    );
                } else {
                    head.addChildren(newObj);
                    this.constructPath(
                        path,
                        currIndex + 1,
                        head.children[head.children.length - 1]
                    );
                }
            }
        }
    


    주어진 경로를 구성하는 동안 현재 하위 경로가 이미 구성되어 있는지 확인해야 합니다. 이미 구성되어 있으면 경로의 다음 섹션으로 계속 진행할 수 있습니다.

    위의 단계를 반복하여 애플리케이션의 경로에 대한 트리 데이터 구조를 설정할 수 있습니다.

    요청 시 컨트롤러 실행



    위 섹션에서 트리를 구성하는 것을 제외하고는 어떤 엔드포인트가 어떤 경로에서 실행되는지 추적해야 합니다. adjPath 변수를 키로 하는 객체를 설정하기만 하면 됩니다.

    컨트롤러를 실행하기 전에 요청된 경로가 유효한지 여부를 확인하고 해당 형식(경로 매개변수 포함)을 찾아야 합니다. 트리 데이터 구조를 검색하여 간단히 수행할 수 있습니다.

    그 전에 다시 위와 같이 요청된 경로를 배열로 변환해야 합니다.

    그런 다음 각 하위 경로에 대해 트리에 포함되는지 또는 와일드카드가 존재하는지 확인할 수 있습니다. 둘 다 거짓이면 요청한 경로를 사용할 수 없다는 404 응답을 보낼 수 있습니다.

    static getPath(path, currIndex, head) {
            if (currIndex === path.length) {
                return [];
            }
            const pathExists = head.children.find(
                (p) => p.path === path[currIndex]
            );
            let res;
            if (pathExists) {
                const tempRes = this.getPath(path, currIndex + 1, pathExists);
                if (!tempRes) return null;
                res = [pathExists.path, ...tempRes];
            } else if (head.wildCard) {
                const tempRes = this.getPath(path, currIndex + 1, head.wildCard);
                if (!tempRes) return null;
                res = [head.wildCard.path, ...tempRes];
            } else return null;
    
            return res;
        }
    


    그런 다음 getPath 함수에서 반환된 값과 경로를 포함하는 배열 간의 차이점을 비교하고 이러한 서로 다른 항목을 경로 ​​매개 변수로 지정할 수 있습니다.

    예: configuredPath = ['someroute', ':param', 'end', ''] 요청 경로 = ['someroute', 'paramValue', 'end', '']
    let params = {};
    for (let i = 0; i < constructedPath.length; i++) {
        if (reqPath[i] !== constructedPath[i]) {
            params = {...params,[constructedPath[i].substring(1,constructedPath[i].length)]: reqPath[i],};
        }
    }
    


    여기에서 경로 매개변수 'param'의 값을 찾을 수 있으며 이는 'paramValue'입니다.

    마지막으로 '?'에서 분할하여 URL에서 쿼리 매개변수를 찾을 수 있습니다. 다음 알고리즘을 구현합니다.

    let query = {};
    const splittedQuery = req.url.split('?');
    if (splittedQuery.length == 2) {
        const queryParams = splittedQuery[1].split('&');
        queryParams.forEach((q) => {
        const n = q.split('=');
            query = { ...query, [n[0]]: n[1] };
        });
    }
    


    이것이 제가 제3자 종속성 없는 node.js 애플리케이션용 라우터를 구현하는 방법입니다.

    자세한 내용 및 위의 라우팅 전략을 구현한 방법은 체크아웃here

    감사합니다!

    좋은 웹페이지 즐겨찾기