기능

javascript와 img태그를 사용하여 사용자로부터 버튼 클릭을 입력 받을 시 a 태그를 생성, blob을 불러와 이미지를 다운로드 하려고 한다. 

 

 

발생문제

1. 단순 blob이 아닌 url을 이용하여 파일을 다운로드 시 새창으로 열리는 현상이 있다.

(해결)아래와 같이 fetch, axios등을 이용하여 blob으로 내려받아 오픈한다.

     const response = await axios.get(IMG_URL + url, {
        responseType: 'blob',
      });

      const blob = new Blob([response.data]);
      const imageUrl = URL.createObjectURL(blob);

      const link = document.createElement('a');
      link.href = imageUrl;
      link.download = url;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

 

2. 간헐적 cors 에러가 발생

 

(1)의 코드를 이용하여 다운로드를 시도 시 간헐적으로 cors가 발생한다.

크롬 개발자 도구의 disable cache를 체크 시 정상적으로 다운로드 수행됨을 확인하여, 캐시 문제라고 판단하였다. 이 캐시 문제를 해결하기 위하여 아래와 같은 헤더 설정을 해보았지만 브라우저는 여전히 캐싱을 하였다.

      const response = await axios.get(IMG_URL + url, {
        responseType: 'blob',
        withCredentials: false,
        headers: {
          'Cache-Control': 'no-store',
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Credentials': 'true',
        },
      });

 

이 원인에 대해 자세히 설명해준 " https://blog.hwahae.co.kr/all/tech/5412 " 글을 요약하면

 

html 태그 상 img src태그에서 aaa.co.kr/img1.png를 불러들일때 헤더를 포함하여 브라우저가 캐싱, 추 후 사용자의 버튼 클릭을 입력받아 다운로드 받는 함수 (1)를 수행하지만, 이미 img태그에서 aaa.co.kr/img1.png를 캐싱해버렸고, axios함수에서 또 한번 같은 주소인 aaa.co.kr/img1.png를 호출할때 img태그에서 사용한 헤더 정보를 가지고 요청(특정 정보가 없는 헤더정보)하여 cors에러가 발생하게 된것.

 

그 외 https를 서버에 올렸을 때, 서버상에서는 정상동작하고 로컬(http)에서는 cors가 발생하기도 하였다.

'Javascript > DOM 관련' 카테고리의 다른 글

[DOM API] DOM 그리고 HTMLElement  (0) 2019.12.17
[JAVASCRIPT] 브라우저 로드 순서  (0) 2019.12.01
[JAVASCRIPT] 스크롤 거리 구하기  (2) 2019.12.01
[JAVASCRIPT] event processing  (0) 2019.12.01

Document

 

- DOM을 설명하기 앞서, Document는 브라우저가 불러온 웹 페이지를 나타내며, 모든 종류의 문서에 대한 공통의 속성과 메서드를 묘사합니다. 

- Document는 node tree로 표현될 수 있으며, tree안의 일부 node들은 children을 가질 수 있고 단순히 node만 존재할 수 있습니다. Document또한 Node를 상속받습니다. 

 

DOM

 

- "DOM"이란 간단히, Document( HTML or XML)을 접근/조작하는 API라고 할 수 있습니다. 문서의 유형(HTML, XML, SVG 등)에 따라서 더 다양한 API가 존재합니다. 그러므로 DOM은 HTML, XML, SVG등을 다루는 API 인터페이스 중 하나이지 DOM이 HTML은 아닙니다.

예컨대 "text/html" 콘텐츠 유형으로 제공되는 HTML 문서는 HTMLDocument 인터페이스도 구현하는 반면, XML과 SVG 문서는 XMLDocument 인터페이스를 구현합니다.

 

 

<!DOCTYPE html>
<html class=e>
 <head><title>Aliens?</title></head>
 <body>Why yes.</body>
</html>

위의 HTML 코드에서 Document는 아래와 같이 node tree로 표현됩니다.

 

 

 

Node

 

 

 

  • 노드는 다양한 DOM API(Document, Element ... )가 상속되는 인터페이스입니다.(모든 DOM 객체는 Node를 상속)

  • 다음 메소드와 속성들이 Node 인터페이스를 상속합니다. ( Document, Element, Attr, Text, Comment, CDATASection, ProcessingInstruction, DocumentFragment, DocumentType, Notation, Entity, EntityReference 등)

  • 엘리먼트는 Node를 상속받으므로 Node.baseURI, Node.childNodes, Node.nodeType 등 (어떤 카테고리에 속해 있는 노드인지 알려주는 식별자)과 같은 속성을 사용할 수 있습니다.

  • 즉, 문서에는 나와있지 않지만, HTML Document를 구성하는 node tree에서 최상단에 속한 것이 node이고 모든 엘리먼트들은 이 node 인터페이스를 상속받는다고 볼 수 있습니다.

 

 

 

Element

 

 

Element가 Node를 상속함.

Element의 대표적 속성 : attributes, classList, className, clientHeight, id, innerHTML등

 

 

  • 부모의 Node와 그 부모인 EventTarget의 속성을 상속하고 어떤 것들은 직접 구현(implement)합니다.

 

 

HTMLElement

 

HTMLElement은 Element를 상속함.

 

HTMLElement의 대표적 속성 : dataset, innerText, style, Element를 상속한 id 등

 

  • 대표적인 Document 인터페이스 메소드인 getElementById()에 의하여 HTMLElement를 얻을 수 있습니다.
  • 모든 종류의 HTML요소를 나타냅니다. 일부 요소는 이 인터페이스를 직접 구현하지만 나머지 요소는 HTMLElement를 상속한 자식 인터페이스를 구현합니다.

  • 이 요소가 하나 일 경우 HTMLElement이고 복수일경우 HTMLCollection을 반환한다.

 

HTMLCollection

 

  • 일반적으로 document.getElemetsByTag와 같이 복수의 노드를 접근할때 리턴된다. 

  • 유사 배열이다.
  • 가장 큰 특징으로 라이브 컬렉션이다.

  • NodeType을 오로지 ElementNode만 포함한다.

 

 

NodeList

 

  • HTMLCollection과는 다르게 모든 NodeType을 포함한다. 

  • Array는 아니지만 forEach를 사용이 가능하며 Array.from()을 사용하여 Array로도 변환 할 수 있다.
  • document.querySelectorAll은 정적 NodeList를 반환한다.

  • element.childNode는 동적 NodeList(라이브 컬렉션)을 반환한다.
  • 리스트의 항목을 열거할때는 for...in/for each..in을 사용하지말고 for of를 사용하면 NodeList객체를 올바르게 반복합니다.

 

 

 

 

 

 

'Javascript > DOM 관련' 카테고리의 다른 글

img, a 태그의 CORS 문제  (0) 2024.04.23
[JAVASCRIPT] 브라우저 로드 순서  (0) 2019.12.01
[JAVASCRIPT] 스크롤 거리 구하기  (2) 2019.12.01
[JAVASCRIPT] event processing  (0) 2019.12.01





window.onload() : image, style, script가 모~두 로드 되었을 때 trigger된다.

DOMContentLoaded : HTML(DOM)이 로드되었을때 발생하고, image나 css등을 기다리지 않는다.







순서


(초기값은 readyState = loading)

  1. 가장 먼저 window 객체가 생성. (window는 전역 객체로 웹 페이지와 탭마다 생성)

  1. documet객체가 window의 프로퍼티로 생성되며 DOM트리의 구축을 한다. document객체는 readyState 프로퍼티를 가진다.

       3. DOM트리를 구축 중 script요소를 만나면 해당 script의 구문 분석 후 오류 발생하지 않으면 바로 그 자리에서 실행한다. 
         실행시 동기적으로 실행되어 html문서의 DOM트리 구축은 블로킹 된다. 오류가 발생한다면 멈추며, HTML DOM트리 구축을 중단한다. 

       4. script까지 모두 읽고 DOM구축이 성공한다면 readyState = interactive를 가진다.

       5. 이때 웹 브라우저는 DOM트리 구축을 알리기 위해 DOMContentLoaded 이벤트를 발생시킨다.

       6. img등 이미지 파일등의 외부 리소스를 읽어 들여야 한다면 이 시점에 읽는다

       7. 리소스까지 모두 읽어 들인 후에는 readyState = complete 으로 바뀌고 브라우저는 Window객체를 상대로 load이벤트(onload)를 발생시킨다.

모던 자바스크립트 ( 487page )






'Javascript > DOM 관련' 카테고리의 다른 글

img, a 태그의 CORS 문제  (0) 2024.04.23
[DOM API] DOM 그리고 HTMLElement  (0) 2019.12.17
[JAVASCRIPT] 스크롤 거리 구하기  (2) 2019.12.01
[JAVASCRIPT] event processing  (0) 2019.12.01



  • IE, firefox
document.documentElement.scrollLeft : x 축 방향으로 스크롤한 거리
document.documentElement.scrollTop : y 축 방향으로 스크롤한 거리
  크롬, 사파리, 오페라에도 같은 프로퍼티가 있지만 값이 항상 0

  • Chrome, safari, opera, edge, Quirks Mode
document.body.scrollLeft : x 축 방향으로 스크롤한 거리
document.body.scrollTop : y 축 방향으로 스크롤한 거리

  • Firefox, chrome, safari, opera, edge, IE>=9
window.pageXOffset : x 축 방향으로 스크롤한 거리
window.pageYOffset : y 축 방향으로 스크롤한 거리


  • 크로스브라우징 대응








function getScrollTop()
{
    if(window.pageYOffset !== undefined)
    {
        return window.pageYOffset;
    } else {
        return document.documentElement.scrollTop || document.body.scrollTop;
    }
}

function getScrollLeft()
{
    if(window.pageXOffset !== undefined)
    {
        return window.pageXOffset;
    } else {
        return document.documentElement.scrollLeft || document.body.scrollLeft;
    }
}

'Javascript > DOM 관련' 카테고리의 다른 글

img, a 태그의 CORS 문제  (0) 2024.04.23
[DOM API] DOM 그리고 HTMLElement  (0) 2019.12.17
[JAVASCRIPT] 브라우저 로드 순서  (0) 2019.12.01
[JAVASCRIPT] event processing  (0) 2019.12.01


  • event 등록 방법

  1. HTML 요소의 속성으로 등록하는 방법
            onclick, ondblclick, 등의 html 속성에 javascript 함수를 정의하여 작동시키는 방법.
            <input type="button" onclick="이런식();">

  1. DOM 요소의 프로퍼티로 등록하는 방법
            DOM의 객체인 window의 onload를 사용하여 등록하는 방법.
            
            ex) 
                        





  • addEventListener 메서드를 사용하는 방법
            
  • 등록
        
        target.addEventListener(type, listener, useCapture);
        
        target : 보통은 등록할 DOM 노드, Element, Document, Window, XmlHttpReqeust와 같이 이벤트를 지원하는 모든 객체
        type : 이벤트 유형 문자열 ( "click", "mouseup"..... )  https://developer.mozilla.org/ko/docs/Web/Events
        listener : 처리 담당 함수
        useCapture : 이벤트 단계 ( default : false )

  • 삭제
            target.removeEventListener(type, listener, useCapture);


문제점
1의 경우, HTML/JS가 섞여 가독성이 떨어짐. 특정 요소의 특정 이벤트(input button의 onclick에 단 하나의 이벤트)만 등록할 수 있는 단점이 있고, 그 요소에 똑같은 이벤트를 등록하면 override됨. 
2의 경우, HTML/JS를 분리 할 수 있다. 그러나 1과 같이 특정 요소의 특정 이벤트에 대해서 이벤트 처리기를 단 하나만 등록할 수 있는 단점이 있다.
1.2의 경우 공통적인 단점이 여러 개발자가 작성할 경우 이전 이벤트가 override 되는 단점을 갖고 있다.




  • 이벤트 전파
HTML에서는 부모 요소의 보더 박스 안에 자식 요소를 배치하며, 자식 요소는 부모 요소 안에 겹쳐진 상태로 표시된다. 이런 상태에서 자식 요소를 클릭하면 컴퓨터는 클릭한 요소가 부모/자식인지 알 수가 없다. 그래서 요소에서 이벤트가 발생하면 해당 요소의 조상요소를 포함한 전체에 이벤트 처리기나 이벤트가 리스너가 등록되어 있는지 확인하는 작업을 거쳐 등록된 함수가 있을 때 그 함수를 실행하도록 설계되어 있다.

  • 이벤트 객체

  • 이벤트의 단계
        
  1. 캡쳐링 단계(useCatpure : true)

[ 캡쳐링 - 최상위에서 타겟 요소까지 전파 ]

            이벤트가 최상위 window 객체에서 DOM트리를 타고 이벤트 타겟(발생한 요소)까지 전파됨. 이 단계에서 이벤트 타겟에 등록한 리스너보다
            타고 내려가는 중간 과정에 어떠한 이벤트 리스너등이 있으면 그것이 먼저 실행됨. 즉 이벤트 타겟이 이벤트를 수신하기 전에 이벤트를 
            중간에 가로채기(캡쳐)한다고 하여 캡쳐링 단계라고 한다. useCatpure의 기본값은 false이며 버블링단계에서만 리스닝 한다. true일 경우 캡쳐링단계.

  1. 타겟 단계
            이벤트가 이벤트 타겟에 도착(전파)된 단계. 이벤트 타겟에 등록된 이벤트는 이 시점에 실행됨.

  1. 버블링 단계(useCapture : false)

[ 버블링 - 하위 엘리멘트에서 상위 엘리먼트로 전파 ]


            이벤트가 이벤트 타겟에서 출발하여 DOM 트리를 타고 window객체까지 거슬러 올라가 전파되는 단계. 이 단계에 반응하도록 등록된 이벤
            트 리스너는 타겟에 등록된 이벤트 이후에 실행됨. 단 focus / blur이벤트는 그 요소만 필요한 이벤트이므로 버블링이 발생되지 않음.
            이벤트 리스너의 useCapture가 true면 타겟과 캡쳐링 단계에서만 실행되고 false이면 타겟 단계와 버블링 단계에서만 실행된다.
            이벤트 처리기와 리스너 모두 같은 요소에 등록되어 있다면 이벤트 처리기 먼저 실행되고 리스너에 등록된 순서에 따라 순차적 실행된다.

  1. 제공 메서드
            stopPropagation : 그 다음 요소로 이벤트가 전파되는 것을 막는다. 버블링 또한 되지 않음. 같은 단계의 리스너는 수행됨. 상위로 전파안됨
            stopImmediatePropagation : 상위로의 전파뿐만 아니라 같은 단계로도 전파되지 않고 일시적으로 멈춤.
            preventDefault : 웹 브라우저에 구현된 기본 동작을 취소. 해당 이벤트 객체의 cancelable 프로퍼티가 true일 경우만 사용가능.

  • 주요 이벤트 처리기






  • 이벤트 위임

개념 : 하위 요소에 각각 이벤트를 직접 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식.




















'Javascript > DOM 관련' 카테고리의 다른 글

img, a 태그의 CORS 문제  (0) 2024.04.23
[DOM API] DOM 그리고 HTMLElement  (0) 2019.12.17
[JAVASCRIPT] 브라우저 로드 순서  (0) 2019.12.01
[JAVASCRIPT] 스크롤 거리 구하기  (2) 2019.12.01

+ Recent posts