오늘 뭐했냐/함께했던 작업들

23.08.26 회원 탈퇴 만들기2 (서버 상태 확인 모듈 만들기)

스스로에게 2023. 9. 3. 21:16

서버 상태를 확인해야 하는 한다는 게 여러 방법이 있었는데 

  • cpu나 메모리 등을 확인하는 방법
  • 응답 시간을 확인하는 방법
  • 처리 중인 요청의 수에 따라 처리하는 방법

 

이런 방법들이 하나만 사용되진 않고 각각의 장단점이 있기에 보완적으로 같이 사용된다고 한다. 그래서 나도 같이 적용시키고 싶지만 하나라도 제대로 만들자는 생각으로 하나만 선택해서 사용하기로 하고 요청 수에 따라 처리하는 방법을 찾아봤다. 

 

처리 중인 요청의 수에 따라 처리하는 방법을 선택을 한 이유는 회원 탈퇴 뿐 아니라 처리가 제대로 이루어지고 있나 확인하는 용도로 사용할 수도 있으며 세부적으로 조정하기 쉽다는 장점이 있어 이런 시도를 처음 해보는 입장에서 테스트를 하기 쉬울 것이라고 생각이 되었다.

 

그럼 이것을 이제 어떻게 만들고 적용을 시킬지에 대해서 다시 찾아보니 요청이 들어왔을 때 숫자를 올리고 요청이 끝나면 숫자가 다시 내려가는 방식으로 구현을 할 수 있었다. 그리고 이를 모듈화 시켜서 따로 분리를 했다. 

 

const { EventEmitter } = require('events');
const { Mutex } = require('async-mutex');

class ConfirmRequest extends EventEmitter {
    constructor() {
        super();
        this.currentRequests = 0;
        this.mutex = new Mutex();  // 뮤텍스 인스턴스 생성
    }

    async increment() {
        const release = await this.mutex.acquire(); // 뮤텍스 획득

        try {
            this.currentRequests++;
            this.emit('requestIncremented');
        } finally {
            release();  // 뮤텍스 반환
        }
    }

    async decrement() {
        const release = await this.mutex.acquire(); // 뮤텍스 획득

        try {
            this.currentRequests--;
            if (this.currentRequests === 0) {
                this.emit('requestCompleted');
            }
        } finally {
            release();  // 뮤텍스 반환
        }
    }

    getCurrentRequests() {
        return this.currentRequests;  // 이 메서드는 동기적이므로 뮤텍스가 필요하지 않습니다.
    }
}

module.exports = ConfirmRequest;

 

이것은 완성된 코드라서 이벤트나 뮤텍스가 적용이 되어있는데 처음엔 증가와 감소에 관한 것만 있었다. 

 

뮤텍스를 적용 시킨 이유 : 동시에 여러 요청이 들어갈 경우에 증감함수가 제대로 작동을 안 할 수가 있다. 그래서 비동기 함수가 하나씩만 자원에 접근할 수 있게 처리하였다. 당연히 속도적으로는 조금 느려지더라도 안정성을 위해 이렇게 결정을 했다.

 

전역 미들어로 만듦 : 처음에는 필요한 부분에서 불러와서 인스턴스를 만들어서 사용하려 했는데 그렇게 하면 각 요청별로 인스턴스가 만들어져서 서버 전체에서 처리하는 요청의 수를 파악해야 하는 목적이었던 결과가 나오지 않는다. 그래서 방법을 찾다가 전역 미들웨어로 만들고 요청 수를 req에 담아서 전역에서 사용할 수 있게 했다.

 

이벤트 상속 : 회원 정보를 완전히 지울 때 이벤트를 사용해서 처리한다. 

 

app.use(async (req, res, next) => {
    req.confirmRequest = confirmRequest;

    await req.confirmRequest.increment();
    res.on('finish', async () => {
        await req.confirmRequest.decrement();
    });
    next();
});

 

이제 다 끝난 줄 알았지만 아니었다. 처음에 가볍게 시작한 게 커졌다. 생각할 부분도 많고 그에 따라서 추가되거나 수정하는 부분이 많았다. 그리고 그 때마다 다시 생각을 전체적인 조율이 필요하다. 위에처럼 전역 미들웨어로 만드는 것 뿐 아니라 에러가 발생했다면 finish 이벤트가 발생하지 않는 문제가 있었다. 그래서 이것을 위해 에러 처리 미들 웨어에도 요청 수를 감소시키는 로직을 추가했다. 그나마 기존에 하위 라우터에서 발생한 에러를 상위 라우터로 전달해서 전역 미들웨어에서 처리하게 설계해놨기에 전역 에러처리 미들웨어에만 추가를 해주는 것으로 해결했다.