모던 자바스크립트로 HTTP request 모듈 만들기

둘러봐 기술블로그·2023년 9월 26일

Toy Project 🪀

목록 보기
3/4

결과물

const CONTEXT = "";   // context 기입
                // 예를 들어 http://localhost:8080/test 라면,
                //  "/test"로 초기화
if (window.location.hostname==='localhost'){
    const host = "http://localhost:8080"
}

class HTTP {
    static async request(api, method, data , contentType = "application/json"){
        let options = {};
            options.headers = new Headers({"Content-Type" : contentType});
            options.url = this.backendHost + api;
            options.method = method;
          
        if (data && contentType == "application/json"){
            options.body = JSON.stringify(data);
        }
          
        return fetch(options.url, options)
              .then(response => {return response.json()})
              .catch(error => console.log(error));
    }
}

Object.defineProperty(HTTP, "backendHost", {
        value : host + CONTEXT
});

export default HTTP;

개발 동기

1. 풀스택 토이 프로젝트를 진행할 때 편하려고

이제 슬슬 토이 프로젝트에서 AJAX를 적용해야 할 일이 늘어난다. AJAX를 위해서는 HTTP Request 수행 코드를 작성해야 하는데, 앞으로 진행할 모든 토이 프로젝트에서 일일히 작성하고 싶지는 않다. 그래서 그냥 계속 사용할 HTTP 모듈을 구현하기로 했다.

구현

이번에는 다른 사람의 코드를 기반으로 구현했기 때문에 필자가 따로 설계한 부분이 적다. 따라서 설계 보다는 '왜 이렇게 구현했는지'에 대해 적어두었다.

1. 호스트와 context 파악하기

const CONTEXT = "";   // context 기입
                // 예를 들어 http://localhost:8080/test 라면,
                //  "/test"로 초기화
if (window.location.hostname==='localhost'){
    const host = "http://localhost:8080"
}
// else if 추가

먼저 HTTP Request를 할 웹 서버 url을 파악한다. 로컬 환경에서도 굳이 const host = "http://localhost:8080" 로 값을 지정하여 초기화를 하는 이유는 프론트 서버를 따로 굴리는 경우 때문이다.(CORS)

2. Fetch API로 HTTP Request 구현하기

class HTTP {
    static async request(api, method, data , contentType = "application/json"){
        let options = {};
            options.headers = new Headers({"Content-Type" : contentType});
            options.url = this.backendHost + api;
            options.method = method;
          
        if (data && contentType == "application/json"){
            options.body = JSON.stringify(data);
        }
          
        return fetch(options.url, options)
              .then(response => {return response.json()})
              .catch(error => console.log(error));
    }
}

위의 코드는 과거 참고하면서 괜찮다고 생각했던 HTTP 모듈 코드 두 개를 참고해서 작성했다. 하나는 여기에서 참고했고, 나머지 하나는 여기에서 참고했다.

두 코드는 함수로 구현했는데, 나는 HTTP 클래스를 만들어서 구현했다. 이유는 두 가지인데, 첫 번째는 클래스로 만들면 나중에 메소드를 추가해도 따로 import 구문을 수정할 필요가 없기 때문이고, 두 번째는 밑에 있는 Object.defineProperty을 통해 static이면서 const인 멤버 변수를 만들기 위해서이다.(static 성질이 없을 경우, HTTP.request를 쓰기 위해 늘 객체를 먼저 생성해야 하고, const 성질이 없을 경우 backendHost 값이 변경될 수 있다.)

fetch? XMLHttpRequest는 어디가고?

fetch와 그 리턴형인 Promise는 ES6에 추가된 API와 객체이다. Fetch API는 기존의 XMLHttpRequest의 불편함 점들을 개선한 API로 callback 함수를 Promise:then으로 설정한다. 이는 기존의 XMLHttpRequest보다 직관적인데, 단어 fetch의 뜻이 물어오다 라는 뜻이기 때문이다(밑의 그림을 보자).

XMLHttpRequest.onload 보다는 '물어와(fetch)! 그리고(then) ... 해!'가 더 직관적이다.

3. Object.defineProperty로 static이면서 const인 멤버 변수를 만들기

Object.defineProperty(HTTP, "backendHost", {
        value : host + CONTEXT
});

export default HTTP;

Java에서는 static이면서 const인 멤버 변수를 그냥 직접 선언하면 되지만, 자바스크립트에서는 두 가지 성질을 모두 갖는 멤버 변수를 직접 선언할 수 없다. 간접적으로 선언하는 방법이 Object.defineProperty를 통해 선언하는 방법으로, 이 방법으로 선언된 멤버 변수는 클래스 인스턴스가 아닌 프로토타입에 선언되기 때문에 static이고, writable 값을 설정하지 않으면 defualt 로 writable 하지 않다. 즉, static이며 const인 것이다. (import를 이용한 다른 방법도 있다.) (출처, 출처2)

개발 후기

이제 더 재밌는 토이 프로젝트를 할 수 있을 거 같아 두근거린다

profile
move out to : https://lobster-tech.com?utm_source=velog

0개의 댓글