맥미니 홈서버 구축하기 (2) - 포트 포워딩과 DDNS 설정

jinvicky·2025년 1월 11일

개발 환경 셋팅

목록 보기
2/6

Intro


이번에는 도메인을 연결하기 이전에 포트포워딩과 DDNS 설정을 먼저 해보는 과정을 적었다. 그리고 공인 ip로 접속함으로써 몰랐던 CORS 이슈도 해결해보자.

공인 IP와 사설 IP

이전 포스팅(맥미니에서 로컬 프로젝트 환경)에서 192.168.0.28:8082로 접속했었다. 하지만 이걸로는 사람들이 내가 만든 웹사이트에 접속할 수 없다. 이것은 언제까지고 사설(private) IP 이기 때문이다.

Private IP

  • 우리 집 와이파이 공유기가 할당해주는 local IP다. (내부 네트워크 안에서만 유효하다)
  • DHCP나 수동 설정으로 할당할 수 있다.
  • 192.168.~ 형식이다.
  • 공유기를 껐다 키면 ip 주소가 바뀐다.

Public IP

  • 네이버에 내 ip 주소라고 검색하면 뜨는 ip 주소다. 친구가 내 웹사이트에 접속하고 싶으면 이 ip 주소로 접속해야 한다.
  • 공인 ip 주소도 평생 고정이 아니라 계속해서 바뀐다.
  • 전세계적으로 접근 가능, 주로 ISP 같은 곳이 할당해줌

공인 ip로 접속해야 하는데 공인 ip가 새로운 연결 등으로 계속 바뀐다면 매번 ip 주소를 검색해서 도메인과 연결해주어야 한다.
이것의 불편함을 막기 위해 DDNS 설정이 등장한다.

DDNS 설정

iptime 관리자에 들어가서 로그인을 해준다. (192.168.0.1)

고급 설정 > 특수 기능 > DDNS 설정에 들어가서 호스트 이름과 사용자 ID를 설정한다.

  • 호스트 ID: 편하게 적는다.
  • 사용자 ID: 난 이메일을 적었다.

DDNS를 등록하면 위 사진처럼 호스트 이름과 정보를 볼 수 있다.
👉 DDNS 설정 참고 https://blog.naver.com/cjs0308cjs/2232585759=49

이제 호스트이름.iptime.org로 접속하면 내 웹사이트를 볼 수 있다.

저 뒤에 붙은 :8080은 포트포워딩 설정인데 그냥 호스트명.iptime.org로만 접속하면 내 사이트를 못 찾고 빙글빙글 계속 돌기만 한다;;

222.112.27.63를 외우는 것보다 호스트명를 외우는 것이 당연 더 쉽다. 또한 공인 ip가 변경되든지 말든지 나는 호스트명만 알고 있으면 되니 도메인을 구입했을 때 DDNS 설정을 해두고 이와 연결하는 것이 관리하기 더 편하다.

포트포워딩

외부에서 들어온 요청을 내 웹사이트의 nginx 웹 서버로 가도록 포워딩 작업을 해줬다.

아까의 ip 관리자 페이지에 가서 고급 설정 > NAT/라우터 관리 > 포트포워드 설정에 들어가서 아래처럼 설정했다. 나는 8080 포트로 접속 시 내 웹 서버의 8082 포트로 연결되도록 했다. (내 사설 ip도 고정으로 바꿨다)

포트포워딩을 써야 하는 이유

  • 가정이나 회사에서는 여러 장치가 동일한 공인 IP를 공유하고 있는 경우가 많다. 이때 특정 요청을 특정 네트워크 장치로 연결하는 작업이 필요한데 그것이 포트포워딩이다.
    결과적으로 외부에서 접속한 포트에 따라서 올바른 내부 장치로 트래픽을 설정한다.
  • 또한 포트포워딩을 사용하면 외부에서 웹 서버에만 접속하고 다른 서버는 외부로부터 보호할 수 있어서 보안적인 장점이 있다.

CORS 이슈

공인 ip.iptime.org로 접속하면 프론트에서 백엔드 api를 호출할 때 CORS 이슈가 발생했다. 에러는 대략 줄여서 백엔드에서는 jvk(중략).iptime.org:8080에 대한 cors 처리가 되어 있지 않다는 내용이다.

해결 시도

  1. 백엔드 프로젝트에서 cors 설정 경로에 jvk(중략).iptime.org:8080을 추가한다. 결과적으로 실패 ❌

  2. nginx.conf를 변경한다.
    /api 경로로 location 블록을 추가해서 프록시 설정을 해보기도 하고, 웹서버 포트를 백엔드 경로로 설정해 보기도 했다. 결과적으로 전부 실패 ❌

실마리

내가 본 에러가 아래 블로그 내용처럼이었는데, origin보다 접근 수준이 낮은 네트워크에 액세스 요청을 할 때 CORS가 발생한다고 한다.

👉 https://velog.io/@tjdals9638/The-request-client-is-not-a-secure-context-and-the-resource-is-in-more-private-address-space

그렇다면 외부에서 웹서버에 요청을 보내더라도 프론트단에서 백단으로는 localhost로 내부 통신을 하도록 뭔가를 감싸줘야 하는 거 아닌가...? 생각을 했다.

그 감싸다? 다시 쓰다? 생각해보다가 기존 vue 프로젝트의 /api 경로에 대한 target 설정이 기억났다. + next.js cors 이슈로 검색하면서 답을 찾았다.

Next.js rewrites()

문제는 클라이언트와 서버가 다른 도메인이었던 것이 원인이었고, 외부 요청이 내부 로컬 서버로 전달되도록 설정하는 방법이다.

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false,
  async rewrites() {
    const apiUrl = process.env.NEXT_PUBLIC_URL || 'http://localhost:8080'; // 로컬 기본 값

    return  [{
      source: '/api/:path*',
      destination: `${apiUrl}/api/:path*`,
    },]
  }, 
  images: {
    domains: ['res.cloudinary.com'],
  },
};

export default nextConfig;

무조건 localhost:8080을 하드코딩하면 render.com 등에 배포할 때 위험이 생기니까 환경변수로부터 읽도록 한다.

호출부는 아래처럼 바뀐다. 앞에 매번 붙였던 환경변수 경로가 사라진다.

export const fetchChatRoomsBySrch = async ({ queryKey }: { queryKey: string[] }) => {

    const userEmail = queryKey[1];

    // const response = await fetch(process.env.NEXT_PUBLIC_DOMAIN_URL + '/api/chat/search/room?userEmail=' + userEmail);
    const response = await fetch('/api/chat/search/room?userEmail=' + userEmail);

    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return response.json();
};

Question

처음에는 백엔드 서버에서 localhost, .iptime.org 경로로 다 설정을 추가해도 왜 CORS 이슈가 해결되지 않지? 라고 의문이 들었다.

CORS 정책은 Origin 헤더를 보고 결정되기 때문에 Origin 도메인에 맞는 허용 설정을 해야 합니다.

CORS를 단순 경로로만 보지 않고 헤더, Origin으로 정책이 결정되어서 그런 것이 아닐까 추측해본다.

🔥 CORS 이슈를 위해서는 프론트와 백엔드 모두 설정이 필요하다는 것을 잊지 않기

profile
개발, 그림, 기록

0개의 댓글