a 태그 href 속성 값의 javascript:void(0)는 왜 사용할까?
계기
Javascript 강의를 듣던 중 소스 코드를 보며 궁금한 것이 생겼다. 바로 a태그의 주요 속성 중 href의 값으로 이상한 것이 있는 것이었다. 렌더링된 페이지에서 해당 a 태그 버튼을 누르면 아무 동작도 하지 않는다. 아직 구현하지 않은 버튼인 것은 알겠지만 보통은 그냥 "#"만 넣거나 그래서 관련 내용을 좀 더 찾아보게 되었다. 그런데 생각보다 새롭게 알게 된 내용들이 많았다.
a 태그의 목적과 특징
우선 a 태그에 대해서 확실하게 짚고 가야했다. a 태그(Anchor)는 주로 href 속성을 통해 다른 페이지나 같은 페이지의 어떤 요소의 위치로 이동할 수 있는 하이퍼 링크를 만들 때 사용한다. 다시 말하면 href의 속성 값으로 입력된 외부 페이지로 이동시키거나 # 문자를 이용하여 현재 문서 내 다른 태그 요소 위치로 스크롤을 이동시킬 때 쓰인다. navigation 느낌이다. 추가적인 특징으로는 마우스를 hover 시 cursor가 pointer로 변하는 속성이 있다.
a 태그는 img 태그와 함께 사용하여 이미지를 클릭하는 것으로 해당 기능을 동작할 수 있다. 물론 a 태그 없이 img 태그 내에서 onclick 속성과 Javascript로도 페이지 이동을 구현할 수 있지만, a태그와 함께 사용하면 탭 키를 이용하며 현재 포커스 된 요소가 무엇인지 알 수 있다. 특유의 테두리와 브라우저별 포커스 디자인은 다시 고려해보아야 하는 단점도 있다. 이 부분은 웹 퍼블리셔나 디자이너와의 상의가 필요하고 상황과 목적을 잘 생각해서 결정해야 하는 부분인 것 같다. 자세한 내용은 이곳에서 확인할 수 있다.
javascript:
onclick도 있는데 "javscript:"는 무엇인가? 이 질문에 대해서 이 블로그를 참고하였다. "javascript: 를 사용할 경우 해당 구문이 스크립트로 평가되고 실행되어 document의 내용으로 표시됩니다."라는 설명과 예시 코드가 있다. 그래서 임의의 html문서를 생성하고 a 태그에 다음과 같이 속성 값을 준 뒤 클릭해보기로 하였다.
<a href="javascript:'what is this?'">a 태그</a>
이 버튼을 클릭하면 다음과 같은 동작을 볼 수 있었다.
콜론 뒤에 일반 텍스트를 주면 이처럼 화면에 해당 텍스트만 출력된다. 뒤로 가기 버튼이 생기지 않는 걸 보니 페이지 이동이 일어난 것은 아니고 기존에 출력되는 웹 페이지 내에서 일어나는 동작이다. 그렇다면 텍스트가 아닌 변수를 출력한다면 어떻게 될까?
<a href="javascript:tmp">a 태그</a>
...
<script>
const tmp = "hello";
</script>
tmp라는 변수에 "hello"라는 텍스트 저장하고 tmp를 불러 보았다. 결과는 예상대로 hello라는 텍스트가 출력되었다.
다음으로 int 값이나 boolean 값, 그리고 null과 undefined도 넣어보았다. 텍스트 이외의 다른 자료형에는 아무것도 바뀌지 않았다. 나의 실험은 계속되었다. 다양한 시도는 아래 접은 글을 통해 볼 수 있다.
javascript:123 (아무 숫자)
아무 반응이 없다.
javascript: (아무것도 안적기)
아무 반응 없다.
javascript:hello (정의되지 않은 변수)
콘솔 창에 다음과 같은 에러 메세지가 출력된다.

javascript:tmpFunction() (함수 실행)
다음과 같이 함수를 세팅하고 실행시켜보았다.
<a href="javascript:tmpFunction()">a 태그</a>
...
<script>
const tmpFunction = function () {
console.log("Function!");
};
</script>
그랬더니 함수가 실행되었다.

이렇게 javascript: 를 다양하게 시도했다. 그러다가 javascript가 아닌 다른 것들도 시도해보게 되었다. 그랬더니 신기한 것을 알게 되었다!
<a href="abc:">a 태그</a>
에러 문구에 scheme이라는 것이 핸들러로 등록되지 않아서 실행을 하지 못했다는 것이다. 이렇게 키워드를 찾게 되어서 추가적인 검색을 할 수 있었다. intent scheme이라는 것이었는데 웹에서 앱을 실행할 때 사용하는 방식으로 타임아웃을 주지 않고 마켓 연동까지 할 수 있어 많이 사용하는 방식이라고 한다. (참고 블로그 게시물) 한마디로 웹에서 앱을 여는 방법!
이제 javascript: 가 의미하는 것이 intent scheme이라는 방식으로 javascript라는 앱을 실행하는 것을 알 수 있었다!! 이 개념은 나중에 알아보아야겠다.
href="javascript:void(0)"와 같은 방식은 일반적으로 사용하는데 문제는 없지만 CSP(Content Security Policy) 설정에 따라 Inline 방식의 이벤트 핸들러가 블록 될 수 있다고 한다. CSP는 기본적으로 위험한 스크립트가 실행되는 것을 방지하기 위한 정책이라고 한다. 사이트에 따라서 XSS (Cross site script) 취약점에 의해 외부 스크립트가 주입되어 실행되는 것을 차단하기 위해 Inline script를 사용하지 못하게 할 수도 있다고 하는데, 내가 생각해도 document에 있는 a 태그 속성으로 어떠한 앱을 실행시킬 수 있다는 것은 취약할 것 같긴 하다. Inline script의 단점이라고 볼 수 있겠다. onclick도 CSP 위반이라는 마찬가지의 이유로 사용을 지양한다. 그냥 마음 편하게 external 방식으로 모듈화 해서 써야겠다.
굳이 javascript:void(0)에서 void(0)를 사용할 필요성
아무튼 다시 본론으로 돌아와서 href="javascript:void(0)"을 사용할 수 있는 이유를 알게 되었다. void(0)을 출력하면 undefined가 출력되는 것을 보아 a 태그의 기본 동작을 막을 수 있다. 다른 블로그들의 글을 보면 void() 안에 아무 숫자나 넣어도 상관없고 0을 기본으로 한다고 되어있었는데 그것도 마찬가지로 undefined를 반환한다.
그렇다면 그냥 javascript:undefined로 사용하면 안 될까? 언뜻 보면 큰 문제는 없어 보인다. 하지만 예전에는 이 undefined가 global 변수로 사용되어 다시 재사용될 소지가 있었다고 한다. 또한 구버전 브라우저에 대한 대응 이슈도 있으므로 void(0)를 선호한다고 한다. 구버전 브라우저에 대한 테스트는 어떻게 하지...? 어? 지금까지 테스트는 크롬에서 했었는데 혹시나 궁금해서 사파리로 실행해보았다. 앞의 여러 테스트들을 해보니 사파리에서는 텍스트 출력이 되지 않았다. 그 이유는 추후에 알아보아야겠다 ^^ 어쨌든 intent scheme 방식으로 사용하려면 void(0)으로 사용하는 것이 암묵적인 룰(?) 같으니 이것을 사용할 일이 있다면 나도 따라야겠다.
이것을 사용하는 이유를 엘리스 헬프 센터에 질문 등록했었는데 답변이 와서 공유하려고 한다. 보통 a 태그에 링크를 넣지 않은 경우는 당연히 개발이 완료되지 않은 임시 상태이며 HTML, CSS를 전문적으로 하는 퍼블리셔 분들이 직접 링크를 입력하지 않기 때문에 javascript:void(0)과 같이 해두고 개발자에게 파일을 넘기는 경우가 많다고 한다. 추가적으로 해당 코드는 a 태그에서만 주로 쓰이기 때문에 Ctrl + F를 이용하여 작업해야 할 링크 영역을 찾기에 용이하다!
빈 href 속성 사용?
우리는 왜 href 속성에 빈 링크를 걸려고 하는 걸까? 근본적인 질문을 다시 해보았다. 그 이유를 생각해보다가 href 속성 자체를 안 쓰면 되지 않겠냐는 아이디어가 떠올랐다. 바로 실행해 보자.
<a>a 태그</a>
이와 같이 a 태그의 정체성을 잃어버린다. 즉, a 태그의 href 속성은 꼭 필요하다. 그래서 사람들이 href에 어떤 값을 넣는지 고민을 하는지 이해가 되었다.
자 그럼 href=""와 같이 빈 값을 주는 것은 어떨까? 이와 같은 방법도 문제가 있었다. href=""과 같이 사용할 때의 문제점은 현재 접속 중인 페이지의 url과 같은 의미로 해석된다는 점에 있다. 다른 말로 하면 페이지 새로고침이 일어난다. 이와 비슷한 문제로 img 태그의 src 속성도 빈 값이 들어가게 되면 현재 페이지를 외부 리소스로서 불러오게 되어 같은 페이지를 두 번 불러오는 꼴이 된다고 한다. 이를 차단해주는 브라우저도 있지만 그렇지 않은 브라우저도 있기에 이와 같은 코드들은 지양하는 게 좋아 보인다.
결론
a 태그는 어디론가 navigation 해주는 페이지 이동이라는 목적을 가지고 있다. 페이지나 스크롤 이동 기능 없이 굳이 a 태그의 기본 효과를 사용하려면 몇 가지 방법이 있다. 그중 intent scheme의 방식으로 javascript 앱을 실행시키고 void(0)이라는 것을 요청 후 undefined를 반환받는 과정으로 페이지 이동 동작을 막는 방법이 내 생각에는 가장 효율적이라고 생각한다. 그 이유는 href="#"와 같이 event.preventDefault()를 적어주지 않아도 되기 때문이다. 물론 어느 것을 사용하던지 개발자 마음이기는 하다.
이번 계기를 통해 다음과 같이 여러 가지를 배울 수 있었고 추가적으로 알아볼만한 개념을 찾게 되었다. 아직 더 알아볼만한 것들이나 궁금한 것들에 대한 키워드들을 정리해보면 다음과 같다. 시간 나는 대로 알아볼 것들이 많아졌다 😅
- intent scheme
- 버블링과 캡쳐링, 버블링을 막기 위한 javascript:void(0) 혹은 event.stopPropagation();
- a 태그에서의 onclick과 href의 javascript 호출 시 차이점
- 웹 표준과 웹 접근성
- Safari에서 href="javascript:'text'"의 텍스트 출력이 일어나지 않는 이유
- href="#;" ?
Reference
https://developer.mozilla.org/ko/docs/Web/HTML/Element/a
https://stackoverflow.com/questions/1291942/what-does-javascriptvoid0-mean/1291950#1291950
그 외 본문 내 하이퍼텍스트 링크
'JavaScript' 카테고리의 다른 글
[npm/yarn] package.json 스크립트 명령어 예시 (0) | 2025.03.17 |
---|---|
[JavaScript] 디바운스와 쓰로틀링 구현하고 활용하기 (0) | 2025.03.17 |
[JavaScript] axios 인터셉터로 전역 에러 처리하기 (0) | 2025.03.17 |
[JavaScript] sort() 숫자 정렬 안되는 문제 해결법 - 숫자 정렬 / 비교 함수 (1) | 2022.09.30 |
[JavaScript] DateTime 을 AM/PM 포맷으로 변환하는 법 / AMPM 시간 변환 (0) | 2022.09.16 |