BackEnd/Node.js

[Node.js] Request 객체의 IP Address 확인

꼽파 2024. 8. 26. 12:01

프로젝트에서 클라이언트 Request의 IP 주소를 서버에 저장해야하는 일이 생겼다.

그래서 node.js 환경에서는 어떻게 해야하는지 알아보았다.

 

https://stackoverflow.com/questions/8107856/how-to-determine-a-users-ip-address-in-node

 

How to determine a user's IP address in node

How can I determine the IP address of a given request from within a controller? For example (in express): app.post('/get/ip/address', function (req, res) { // need access to IP address here })

stackoverflow.com

https://riverblue.tistory.com/22

 

Node.js 클라이언트 IP 가져오기 request-ip

로그에 ip를 넣기위해 클라이언트 ip를 가져와야 하는 이슈가 생겼다. request-ip 미들웨어가 있어서 사용하기로 한다. npm install request-ip --save 사용법은 매우 간단하다. var requestIp = require('request-ip');

riverblue.tistory.com

 

 

클라이언트 IP 주소 추출방법 요약

1. 클라이언트 IP 주소 직접 추출 (remoteAddress)

  • request.socket.remoteAddress : net.Socket 객체의 속성, 클라이언트 ip를 직접 반환
  • req.connection.remoteAddress (node.js 버전 13 미만, 권장되지 않음.)

2. 프록시 서버 환경에서 클라이언트 IP 주소 추출

  • 프록시 서버 : 클라이언트와 서버 사이에서 중개 역할을 하는 서버 (예: Nginx)
  • 클라이언트가 프록시 서버를 통해 서버에 요청을 보낼 때 원래 클라이언트의 IP 주소를 포함함.
  • 여러 가지 IP 주소 목록을 포함할 수 있으며 맨 첫번째 것이 원래 클라이언트의 IP임.
  • X-Forwarded-For 헤더: 프록시 서버를 통해 요청이 전달될 때, 원래 클라이언트의 IP 주소를 포함하는 헤더
  • app.set('trust proxy', true) 설정으로 프록시 서버를 신뢰하도록 설정해줘야 함.
  • request.headers['x-forwarded-for'] 혹은 request.ip에서 추출 가능함.
  • request.ip는 x-forwared-for 헤더를 사용하여 IP 주소를 반환함.

3. request-ip 미들웨어 사용

  • npm i request-ip : request-ip 모듈 설치
  • const requestIp = require('request-ip'); 로 불러와서 requestIp.getClientIp(req); 로 ip 주소 추출 가능함.
  • 이때 app.listen(port, '0.0.0.0') 추가하면 IPv4로 변경 가능

IP 주소 직접 출력해보기

순서

  1. express 서버를 생성하여 실행한다.
  2. 브라우저에서 요청을 보낸다.
  3. express 서버의 출력 결과를 확인한다.

서버 생성

프로젝트를 초기화해준다.

-y 플래그로 기본값으로 package.json 파일이 자동 생성된다.

npm init -y

 

express를 설치한다.

npm i express

 

express가 설치된 서버 파일을 시작한다.

node server.js

 

클라이언트 생성

Chrome 브라우저에 직접 스크립트를 입력하니 에러가 났다.

 

html 파일을 하나 만들어서 간단하게 요청을 보내본다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fetch Request Example</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const url = 'http://localhost:3001';

            fetch(url)
                .then(response => response.json())
                .then(data => {
                    console.log('Response Data:', data);
                })
                .catch(error => {
                    console.error('Fetch Error:', error);
                });
        });
    </script>
</head>
<body>
    <h1>Request IP 확인</h1>
</body>
</html>

 

cors 오류가 나서 express에서 CORS 설정을 해주었다.

 

express 코드는 다음과 같다.

const express = require('express');
const app = express();
const cors = require('cors');

app.use(cors());

app.use((req, res, next) => {
  console.log("★★★★★★★★★리퀘스트의 IP★★★★★★★★★")
  console.log("request.ip", req.ip)
  console.log("request.socket.remoteAddress", req.socket.remoteAddress);
  next();
})

app.get('/', (req,res) => {
  res.send("IP 확인되었습니다.")
})

const port = 3001;

app.listen(port, () => {
  console.log(`${port}포트로 express 서버 시작!`)
})

::1 이 출력되는 것으로 보아 잘 작동하는 것을 확인할 수 있다.

IPv6 주소로 '::1'은 IPv4 주소로 '127.0.0.1'과 같은 것이다.

 

ip6 패키지를 사용하려고 보니까 에러가 났다.

 

Error [ERR_REQUIRE_ESM]: require() of ES Module C:\Users\airyt\express-test\node_modules\ip6\ip6.js from C:\Users\airyt\express-test\server.js not supported.
Instead change the require of ip6.js in C:\Users\airyt\express-test\server.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (C:\Users\airyt\express-test\server.js:4:13) {
  code: 'ERR_REQUIRE_ESM'
}

위와 같은 에러는 해당 패키지가 ES 모듈로 작성되어 있는데 현재 CommonJS 모듈에서 에러가 났기 때문에 발생한다.

파일 확장자를 mjs로 바꿔주고, package.json에 "type":"module"을 추가해주면 된다.

왼쪽에 server.js로 확장자를 mjs로 바꿔주자.

 

또 에러가 났는데 귀찮아서 스킵했다.

원래 하려던건 IPv6과 IPv4를 모두 출력하는 것이었다. 지금 다른 개발을 위해서 잠시 확인한 것이므로 일단 스킵하자.

 

만약 애초에 IPv4 주소로 출력되게 하고 싶으면 아래처럼 쓰면 된다.

const express = require('express');
const app = express();
const cors = require('cors');
const ip = require('ip'); 

app.use(cors());

app.use((req, res, next) => {
  const requestIp = req.socket.remoteAddress // 127.0.0.1

  console.log("★★★★★★★★★리퀘스트의 IP★★★★★★★★★")
  console.log("requestIp", requestIp)
  
  next();
})

app.get('/', (req,res) => {
  res.send("IP 확인되었습니다.")
})

const port = 3001;

app.listen(port, '0.0.0.0', () => {
  console.log(`${port}포트로 express 서버 시작!`, )
})

 

아래 터미널 결과를 보면 알 수 있다.

728x90