본문 바로가기

프로그래밍

[티스토리][JS]코드블럭 VSCode처럼 꾸미기(3)_요소찾기 오류 발생 및 해결

오늘 할 내용 및 서론

저번시간에는 코드블럭이 웹페이지의 어느 곳에 위치하는지, 어떤 구조로 이루어져 있는지 확인하였다.

오늘은 이를 토대로 코드블럭을 수정해 상단바 부분을 만들어 보자.

코드블럭 요소 찾기

먼저, 자바스크립트를 통해 HTML코드를 수정하려면 수정하고자 하는 코드블럭 부분을 찾아야 한다.

저번에 코드블럭은 <pre> 태그 아래의 <code class="hljs> 태그로 구성되어 있음을 확인했다.이를 토대로 요소를 찾을 수 있다.

 

자바스크립트에서는 클래스이름, ID, 태그이름 등의 여러 가지 방법을 통해 요소를 찾는 것을 지원하는데, 우리는 클래스 이름을 이용하도록 하자.

 

찾는 방법은 document.querySelectorAll("CSS선택자")을 사용해 찾아주면 된다. 코드블럭들이 여러개 있으므로 해당 코드블럭들이 요소로 담긴 배열로 반환해 준다.

오류 발생

하지만 테스트 과정 문제가 발생하였다. 다음과 같은 코드를 사용하였는데 요소가 제대로 찾아지지가 않는다.

let codeblocks1 = document.querySelectorAll(".hljs");
console.log(typeof(codeblocks1));
console.log(codeblocks1);
console.log(codeblocks1.length);

해당하는 값이 존재하지 않을 때 반환하는 값인 길이가 0 인 배열이 나올 뿐이었다.

 

DOM 요소 찾기 문제 발생
DOM 요소 찾기 문제 발생

 

혹시나 내가 코드를 잘못 입력했나 싶어 개발자도구 콘솔창에서 코드를 다시 입력해 보았는데 정상적으로 요소를 찾고 내가 원하는 변수에 초기화까지 제대로 되었음이 확인가능했다.

 

개발자도구 콘솔창에서 코드 실행
개발자도구 콘솔창에서 코드 실행

1. defer 속성 추가

무슨 문제일까? 곰곰이 생각해 본 결과 스크립트가 페이지 로딩보다 빨리 실행되어서 오류가 발생하였다고 추측하였다.

그래서 스크립트를 불러올 때 페이지가 로딩된 후 스크립트를 로딩되게 하는 옵션인 defer을 추가했다.

스크립트에 defer 속성 부여 이미지
스크립트에 defer 속성 부여

그러나 여전히 문제가 해결되지는 않았다...

 

2. 요소를 찾을 때 다른 코드를 사용하기

다음으로는 요소를 찾는 코드가 잘 작동이 되지 않았을 수 있으므로요소 찾기를 여러 가지의 다른 방법으로 수행하였다.

pre 태그의 자식으로 code태그가 있으며 code태그는 hljs라는 클래스를 가지고 있다는 걸 알고 있다.

요약하자면, 우리는 pre > code, code class="hljs" 임을 알고 있다.

 

getElementsByClassName(클래스이름), querySelectorALL(클래스선택자, 혹은 태그선택자), 그리고 getElementsByTagName(태그이름)으로 요소를 찾도록 해보자.

 

위 방법들을 수행하는 자바스크립트 코드는 다음과 같다.

console.log("document.getElementsByClassName(\"hljs\") 사용");
const codeblocks = document.getElementsByClassName("hljs");
console.log(codeblocks);
console.log("길이:"+codeblocks.length);
console.log("==========================================\n");

console.log('document.querySelectorAll(".hljs") 사용')
const codeblocksA = document.querySelectorAll(".hljs");
console.log(codeblocksA);
console.log("길이:"+codeblocksA.length);
console.log("==========================================\n");

console.log('document.querySelectorAll("pre > code")사용')
const codeblocksB = document.querySelectorAll("pre > code");
console.log(codeblocksB);
console.log("길이:"+codeblocksB.length);
console.log("==========================================\n");

console.log('document.getElementsByTagName("code")사용')
const codeblocksC = document.getElementsByTagName("code");
console.log(codeblocksC);
console.log("길이:"+codeblocksC.length);

 

다양한 방법으로 시도한 요소 찾기 이미지
다양한 방법으로 시도한 요소 찾기

 

해당 스크립트 실행결과, 위 이미지처럼 getElemenstByClassName의 경우 길이가 0으로 표시되는 오류가 있었고 querySelector에서 태그선택자를 사용한 경우와 getElementsByTagName의 경우 오류 없이 잘 실행되었음을 확인이 가능했다.

 

두 개 중 querySelector을 선택하여 document.querySelectorALL()에서. hljs라는 class 선택자가 아닌 태그선택자인 pre>code로 변경하였고 문제가 해결되었다.

 

짤막 지식) CSS선택자에서 >는 자식태그를 의미한다. 예를 들어, pre>code는 pre의 자식으로 온 code태그를 의미한다. 즉, code태그 범위만 해당한다. 

오늘 알게 된 점 및 고찰

HTML 문서에서 외부 스크립트 로딩 시 defer 옵션을 추가하면 HTML의 파싱완료 이후 실행이 된다.

즉, </html> 부분에서 실행되는 것과 동일한 효과를 지닌다고 보면 된다.

 

티스토리에서는 코드블록을 <pre><code> 코드내용 </code></pre>로 지정하고 문법강조플러그인이 적용된 경우, highlight.js를 사용해 code 태그에 hljs 클래스를 붙이고 코드블럭을 수정한다.

아마 클래스선택자나 이름을 사용한 경우 오류가 발생하는 이유가 이것 때문인 듯하다.

 

생각한 대로 요소만 찾고 바꾸면 될 줄 알았으나 일이 쉽게 휙휙 진행되지가 않고 오류가 많이 발생하였다. 생각보다 어렵다.

겪은 시행착오를 쓰다보니 생각보다 글이 많이 길어졌다. 코드블럭을 수정하는 작업은 다음 글에 다루도록 하는게 좋을 듯 하다.

참조

https://ssungkang.tistory.com/entry/css-css-%EC%84%A0%ED%83%9D%EC%9E%90selector-%EC%9D%98-%EC%A2%85%EB%A5%98%EC%99%80-%EC%98%88%EC%8B%9C

 

[css] css 선택자(selector) 의 종류와 예시

css 선택자 css 선택자란? 우리가 html 파일을 만들었다면 각각의 태그에 다르게 css 를 설정 할 것입니다. 이 때, 어느 요소에 스타일을 적용할지 알려주는 방식이 바로 css 선택자 입니다. 선택자가

ssungkang.tistory.com

https://hwani.dev/js-async-defer/

 

자바스크립트 script 태그 async & defer 속성

서론 일반적으로 나는 보통 Vanilla JS 로 프로젝트를 진행할때 태그를 사용하여 파일에 파일을 하는 방식을 일방적으로 떠올렸다. 하지만, 보통 태그 내부에 위와 같이 일반적인 방법으로 쓰곤 하

hwani.dev