
이전까지 next/Link 컴포넌트를 사용하면서 새 창을 열어야했던 적이 거의 없었다 왜냐하면 내부의 페이지 이동만 있었고 외부 링크를 타고 가는 개발을 하지 않았어서!! 예전에 사이드 프로젝트를 했을때는 a태그를 사용했어서
target="_blank"를 사용하여 개발을 하였습니다.
next/Link 컴포넌트에서도 그러한 속성이 유효한지 몰랐었습니다! (너무 간단하고 상식이라고 생각하지만 아직 성장중인 단계라 이해좀;;)
이번 글에서는 Next.js의 Link 컴포넌트에서 외부 링크를 새 창으로 여는 방법에 대해 상세하게 소개하고, pages 디렉토리 기반의 라우팅(Page Router)과 app 디렉토리 기반의 라우팅(App Router)에서 각각 어떻게 사용하는지 예제와 함께 설명하려고 합니다.
🔍 pages/ 디렉토리에서 사용하는 방법 (Page Router)
// pages 기반 프로젝트 (Next.js 12 이하 또는 13에서 pages 사용 시) import Link from 'next/link'; <Link href="https://example.com" passHref> <a target="_blank" rel="noopener noreferrer"> 외부 링크 열기 </a> </Link>📌 설명:
- passHref는 꼭 넣어야 합니다. 그래야 Link가 감싸고 있는 a 태그에 href 속성이 제대로 전달됩니다.
- 여기서 passHref는 Link가 감싸고 있는 a 태그에 href를 강제로 넘겨주는 역할을 합니다.
- target="_blank"는 링크를 새 창에서 열기 위한 속성입니다.
- rel="noopener noreferrer"는 보안상 반드시 같이 써야 합니다. 그렇지 않으면 탭 납치(Tabnabbing) 같은 보안 이슈가 발생할 수 있!!
🔍 app/ 디렉토리에서 사용하는 방법 (App Router)
// app 기반 프로젝트 (Next.js 13+ App Router) import Link from 'next/link'; <Link href="https://example.com" target="_blank" rel="noopener noreferrer" 외부 링크 열기 </Link>📌 설명:
- App Router 환경에서는 Link 컴포넌트가 직접 a 태그를 렌더링하므로, passHref가 필요하지 않습니다.
- target과 rel 속성을 Link 컴포넌트에 바로 전달할 수 있어 더 간단하죠!
그렇다면 왜 rel="noopener noreferrer"는 보안상 반드시 같이 써야하는 이유는??
target="_blank"만 쓸 때 생길 수 있는 보안 이슈: Reverse Tabnabbing
💥 시나리오:
당신이 만든 웹사이트에 이런 코드가 있다고 가정<a href="https://aaaaa-site.com" target="_blank">공식 사이트</a>사용자는 공식 사이트라고 생각하고 링크를 클릭합니다. 이 링크는 새로운 탭(또는 창)에서 열립니다.
하지만 이 aaaaa-site.com은 악성 코드를 포함하고 있어서 아래와 같은 JavaScript를 실행할 수 있습니다:window.opener.location = 'https://fake-login-page.com';그러면 어떻게 되냐고요?
👉 원래 열려 있던 탭(당신의 사이트)이 가짜 로그인 페이지로 바뀝니다!
사용자는 자기도 모르게 기존 탭을 그대로 믿고, 이메일이나 비밀번호를 입력하게 되죠. 바로 피싱이 일어남.
✔️ noopener
target="_blank"가 적용되어 있는 링크를 클릭하면 원본 페이지에 대한 컨텍스트 권한을 제공하지 않고 새 탭에서 최상위 브라우징 컨텍스트를 새로 생성하여 링크를 열도록 한다. 따라서 window.opener의 값이 null이 된다.
✔️ noreferrer
다른 페이지로 이동할 때 링크를 건 페이지의 주소 등의 정보를 브라우저가 HTTP 프로토콜의 referrer 이라는 헤더값 생략하여 정보 누출을 막는다. 즉, noreferrer을 설정한 링크를 클릭하면 해당 유입이 어디서 발생하였는지에 대한 정보가 제공하지 않는다.