반응형
반응형

 

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>authentication</title>
</head>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>

<link rel="stylesheet" href="./resource/css/pattern_lock.css">
<script src="./resource/js/pattern_lock.js" charset="utf-8"></script>
<body>


	<!-- 패턴-->
	<svg class="patternlock" id="lock" viewBox="0 0 100 100">
		<g class="lock-actives"></g>
		<g class="lock-lines"></g>
		<g class="lock-dots">
			<circle cx="20" cy="20" r="2"/>
			<circle cx="50" cy="20" r="2"/>
			<circle cx="80" cy="20" r="2"/>
	 
			<circle cx="20" cy="50" r="2"/>
			<circle cx="50" cy="50" r="2"/>
			<circle cx="80" cy="50" r="2"/>
	 
			<circle cx="20" cy="80" r="2"/>
			<circle cx="50" cy="80" r="2"/>
			<circle cx="80" cy="80" r="2"/>
		</g>
    </svg>

	<button onClick="clearPattern()"> Clear </button>

</body>


<script>

	/** 패턴 핸들러 **/
	let lock = new PatternLock("#lock", {
		onPattern: (pattern) => {
			console.log(pattern); // 입력한 패턴 값

			if(pattern === 123){
				lock.success();
			}else{
				lock.error();
			}

		},
		vibrate: false // 진동 on / off
	});

	let clearPattern = () =>{
		lock.clear();
	}

	let getPattern = () =>{
		lock.getPattern();
	}

	
</script>

</html>

index.html

(function (factory) {
  var global = Function('return this')() || (0, eval)('this');
  if (typeof define === 'function' && define.amd) {
      // AMD. Register as an anonymous module.
      define(['jquery'], function($) {
          return factory($, global)
      });
  } else if (typeof exports === 'object') {
      // Node. Does not work with strict CommonJS, but
      // only CommonJS-like environments that support module.exports,
      // like Node.
      module.exports = factory(require('jquery'), global);
  } else {
      // Browser globals (global is window)
      global.PatternLock = factory(global.jQuery, global);
  }
}(function ($, window) {
  var svgns = 'http://www.w3.org/2000/svg'
  var moveEvent = 'touchmove mousemove'

  var scrollKeys = {
      37: true, // left
      38: true, // up
      39: true, // right
      40: true, // down
      32: true, // spacebar
      38: true, // pageup
      34: true, // pagedown
      35: true, // end
      36: true, // home
  };

  function vibrate() {
      navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
      if (navigator.vibrate) {
          window.navigator.vibrate(25)
      }
  }

  function PatternLock(element, options) {
      let svg = $(element)
      let self = this
      let root = svg[0]
      let dots = svg.find('.lock-dots circle')
      let lines = svg.find('.lock-lines')
      let actives = svg.find('.lock-actives')
      var pt = root.createSVGPoint();
      let code = []
      let currentline
      let currenthandler

      options = Object.assign(PatternLock.defaults, options || {})

      svg.on('touchstart mousedown', (e) => {
          clear()
          e.preventDefault()
          disableScroll()
          svg.on(moveEvent, discoverDot)
          let endEvent = e.type == 'touchstart' ? 'touchend' : 'mouseup';
          $(document).one(endEvent, (e) => {
              end()
          })
      })

      // Exported methods
      Object.assign(this, {
          clear,
          success,
          error,
          getPattern,
      })

      function success() {
          svg.removeClass('error')
          svg.addClass('success')
      }

      function error() {
          svg.removeClass('success')
          svg.addClass('error')
      }

      function getPattern() {
          return parseInt(code.map((i) => dots.index(i)+1).join(''))
      }

      function end() {
          enableScroll()
          stopTrack(currentline)
          currentline && currentline.remove()
          svg.off(moveEvent, discoverDot)
          let val = options.onPattern.call(self, getPattern())
          if (val === true) {
              success()
          } else if (val === false) {
              error()
          }
      }

      function clear() {
          code = []
          currentline = undefined
          currenthandler = undefined
          svg.removeClass('success error')
          lines.empty()
          actives.empty()
      }

      function preventDefault(e) {
          e = e || window.event;
          if (e.preventDefault)
              e.preventDefault();
          e.returnValue = false;
      }

      function preventDefaultForScrollKeys(e) {
          if (scrollKeys[e.keyCode]) {
              preventDefault(e);
              return false;
          }
      }

      function disableScroll() {
          if (window.addEventListener) // older FF
              window.addEventListener('DOMMouseScroll', preventDefault, false);
          window.onwheel = preventDefault; // modern standard
          window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
          window.ontouchmove = preventDefault; // mobile
          document.onkeydown = preventDefaultForScrollKeys;
      }

      function enableScroll() {
          if (window.removeEventListener)
              window.removeEventListener('DOMMouseScroll', preventDefault, false);
          window.onmousewheel = document.onmousewheel = null;
          window.onwheel = null;
          window.ontouchmove = null;
          document.onkeydown = null;
      }

      function isUsed(target) {
          for (let i = 0; i < code.length; i++) {
              if (code[i] === target) {
                  return true
              }
          }
          return false
      }

      function isAvailable(target) {
          for (let i = 0; i < dots.length; i++) {
              if (dots[i] === target) {
                  return true
              }
          }
          return false
      }

      function updateLine(line) {
          return function(e) {
              e.preventDefault()
              if (currentline !== line) return
              let pos = svgPosition(e.target, e)
              line.setAttribute('x2', pos.x)
              line.setAttribute('y2', pos.y)
              return false
          }
      }

      function discoverDot(e, target) {
          if (!target) {
              let {x, y} = getMousePos(e)
              target = document.elementFromPoint(x, y);
          }
          let cx = target.getAttribute('cx')
          let cy = target.getAttribute('cy')
          if (isAvailable(target) && !isUsed(target)) {
              stopTrack(currentline, target)
              currentline = beginTrack(target)
          }
      }

      function stopTrack(line, target) {
          if (line === undefined) return
          if (currenthandler) {
              svg.off('touchmove mousemove', currenthandler)
          }
          if (target === undefined) return
          let x = target.getAttribute('cx')
          let y = target.getAttribute('cy')
          line.setAttribute('x2', x)
          line.setAttribute('y2', y)
      }

      function beginTrack(target) {
          code.push(target)
          let x = target.getAttribute('cx')
          let y = target.getAttribute('cy')
          var line = createNewLine(x, y)
          var marker = createNewMarker(x, y)
          actives.append(marker)
          currenthandler = updateLine(line)
          svg.on('touchmove mousemove', currenthandler)
          lines.append(line);
          if(options.vibrate) vibrate()
          return line
      }

      function createNewMarker(x, y) {
          var marker = document.createElementNS(svgns, "circle")
          marker.setAttribute('cx', x)
          marker.setAttribute('cy', y)
          marker.setAttribute('r', 6)
          return marker
      }

      function createNewLine(x1, y1, x2, y2) {
          var line = document.createElementNS(svgns, "line")
          line.setAttribute('x1', x1)
          line.setAttribute('y1', y1)
          if (x2 === undefined || y2 == undefined) {
              line.setAttribute('x2', x1)
              line.setAttribute('y2', y1)
          } else {
              line.setAttribute('x2', x2)
              line.setAttribute('y2', y2)
          }
          return line
      }

      function getMousePos(e) {
          return {
              x: e.clientX || e.originalEvent.touches[0].clientX,
              y :e.clientY || e.originalEvent.touches[0].clientY
          }
      }

      function svgPosition(element, e) {
          let {x, y} = getMousePos(e)
          pt.x = x; pt.y = y;
          return pt.matrixTransform(element.getScreenCTM().inverse());
      }
  }


  PatternLock.defaults = {
      onPattern: () => {},
      vibrate: true,
  }


  return PatternLock
}));

pattern_lock.js

 

svg.patternlock g.lock-lines line {
    stroke-width: 1.5;
    stroke: black;
    opacity: 0.5;
}

svg.patternlock g.lock-dots circle {
    stroke: transparent;
    fill: black;
    stroke-width: 13.5;
}

svg.patternlock g.lock-actives circle {
    fill: black;
    opacity: .2;
    animation: lock-activate-dot .15s 0s ease 1;
    transform-origin: center;
}

svg.patternlock g.lock-lines line {
    stroke-width: 1.5;
    stroke-linecap: round;
}

svg.patternlock.success g.lock-actives circle {
    fill: green;
}

svg.patternlock.error g.lock-actives circle {
    fill: red;
}

@keyframes lock-activate-dot {
    0% {
        transform: scale(0);
    }
    75% {
        transform: scale(1.1);
    }
    100% {
        transform: scale(1.0);
    }
}

pattern_lock.css

 

성공
실패

출처 : https://github.com/tympanix/pattern-lock-js

 

GitHub - tympanix/pattern-lock-js: An android inspired pattern lock in scalable vector graphics and pure javascript

An android inspired pattern lock in scalable vector graphics and pure javascript - GitHub - tympanix/pattern-lock-js: An android inspired pattern lock in scalable vector graphics and pure javascript

github.com

 

자세한 문서는 위에 깃허브 참조하시면 됩니다.

반응형
반응형

 

 

이클립스 폴더 안에 eclipse.ini 에 하기 내용을 추가한다.

-Dfile.encoding=UTF-8

반응형
반응형

ajax로 받아온 데이터 jstl에서 사용하고 싶을 시

 

웹페이지 구동 순서는 JAVA(Controller) > JSTL > HTML > JavaScript 순이기 때문에

ajax로 받아온다한들 JSTL부분이 앞에 있어서 화면에 받아온 데이터를 다시 그려주질 못한다.

 

그래서 내가 생각하기에는 SPA를 구현할거면 ajax만 이용하고 MPA의 경우는 JSTL만 사용하는게 올바르다.

 

MPA를 SPA로 다 뜯어고치기 힘든 경우라면 이런 방법을 추천한다.

 

1. ajax로 다시 그려줄 부분을 jsp로 뺀다.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world! My Name is ${name}  
</h1>

<P>  The time on the server is ${serverTime}. </P>

<button> 현재 시각을 동적으로 가져옵니다. </button>

</body>
</html>

원본 JSP

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>
<head>
	<title>Home</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>
<h1>
	Hello world! My Name is ${name}  
</h1>

<div id='ajaxRendering'>
	<P>  The time on the server is ${serverTime}. </P>
</div>

<button onClick=getTime()> 현재 시각을 동적으로 가져옵니다. </button>
	
</body>

<script>

	function getTime() {
		$.ajax({
			url: "/ajax",
			type: 'GET',
			success: function(result){
				$("#ajaxRendering").html(result);
			}	
		
		}); //ajax end	
	} 
</script>
</html>

원본 수정한 페이지 (button으로 ajax 렌더링하는 부분 및 그려줄 부분을 뺐다.)

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>

<P>  The time on the server is ${serverTime}. </P>

</body>
</html>

ajax로 그려주는 페이지

 

 

2. Controller에서 다시 그려줄 부분을 뺀 jsp를 호출한다.

package com.lsj.spring_study;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class AjaxController {
	/** ajax로 호출할 페이지 **/
	@RequestMapping(value = "/ajax", method = RequestMethod.GET)
	public String ajaxPage(Model model) {
		
        Date now = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = sdf1.format(now);
		
		model.addAttribute("serverTime", nowTime);
		
		return "ajax";
		
	}
	
    	/** 원본 페이지 **/
	@RequestMapping(value = "/origin", method = RequestMethod.GET)
	public String originPage(Model model) {
        
		
        Date now = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = sdf1.format(now);
		
		model.addAttribute("name", "마이클");
		model.addAttribute("serverTime", nowTime);
		
		return "origin";
		
	}

	
}

3. 본 페이지에서 해당 버튼을 클릭시 ajax를 호출한다.

 

origin이라는 URL 호출시 나오는 화면 (JSTL로 현재시각을 받아오려면 해당 URL을 호출해야함 → 새로고침)

 

버튼 클릭 후 네트워크 통신해서 다시 그려준 화면

 

 

 

 

 

 

출처 : https://my-t-space.tistory.com/47

반응형
반응형
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>
<body>

    <div id="Ahistory">
        Ahistory (뒤로가기가 존재합니다.)
    </div>

    <div id="Bhistory">
        Bhistory (뒤로가기가 존재하지 않습니다.)
    </div>
</body>

<script>

$('#Ahistory').click(() =>{
    location.href = 'https://www.naver.com';
});

$('#Bhistory').click(() =>{
    location.replace('https://www.naver.com');
});

</script>
</html>

 

반응형
반응형

📝 파라미터 변조

BackEnd에 값을 보낼때 이상한 값을 보내서 프로그램이 오동작하게끔 하는 방식이다
예를 들어 GET 방식인 경우 http://www.naver.com?doc=100 http://www.naver.com?doc=101 ...
이런식으로 계속 호출해서 권한이 없어도 값을 읽던가 아니면 POST방식이여도 주문을 넣을 때 문자같은 걸 넣어서 처리하면 BackEnd에서 이상하게 동작해 서버를 공격하거나 이상하게 동작하게 만들 수도 있다

📝XSS (Cross Site Scripting)

자바스크립트를 Injection하는 해킹 공격으로 크게 3가지 유형이 있다.

반사형 공격

http://naver.com?search=<script>alert("hello")</script>와 같은 형식으로 URL을 만들어 다른 사용자가 누를시 해당 사용자에게 해당 script를 실행하게끔 한다

저장형 공격

게시글 따위를 저장할 때 본문 내용에 스크립트를 넣어서 DB에 저장하게하고 다른 사용자가 읽었을 때 본문내용의 script가 js엔진에서 해석해 공격하는 방식이다.

DOM based XSS

http://127.0.0.1:5501/test.html가 본래 URL이고 http://127.0.0.1:5501/test.html#javascript:function%20a(){alert(%22hello%22);}%20a(); 같은 걸 호출 할 시 url 파싱이 script문에 있다면 이런식으로 자바스크립트 Injection이 가능합니다

<!DOCTYPE html>
<head>
    <style>
    </style>
    <script type="text/javascript">
        const hash = window.location.hash.slice(1)
        console.log(hash)
        
        if (hash) {
            window.location.href = decodeURIComponent(hash)
        }
<!--https://blogpack.tistory.com/105-->
    </script>
    <meta charset="UTF-8">
    <title>DOM Based XSS 공격</title>
</head>

<body>
<h1>DOM Based XSS 공격</h1>

<div class="container">
</div>
</body>
</html>

이것도 여러가지 방법 중 하나입니다

방지하는 방법은 백단으로 해당 데이터를 넘기기 전에 <script>등과 같은 위험 요소를 없애는 과정 또는 check하는 과정을 통해 XSS가 일어나지 못하게 막을 수 있다 또는 잘 만들어진 lucy-xss 라이브러리로 간단하게 처리할 수 있다
내가 직접 만들어서 처리할 수 있지만 경우의 수가 워낙 많아서 잘 만들어진 화이트리스트 라이브러리인 lucy-xss를 이용해 처리하는게 좋다

📝 SQL 인젝션

SQL을 오동작하게끔 하는 공격방식이다

 

예를 들어 SELECT * FROM users where auth = 'root' AND id = ? 이러한 식으로 권한 요청 체크가 있을 때
id적는 란에 ' OR '1' = '1라고 적을 경우 SELECT * FROM users where auth = 'root' AND id = '' 에서
SELECT * FROM users where auth = 'root' AND id = '' OR '1' = '1'이 되어 전부 뚫리게된다.

또한 '; DROP DATABASE mysql; -- 이런식으로 적을 경우 
SELECT * FROM users where auth = 'root' AND id = ''; DROP DATABASE mysql; --' 
이런식으로 되어 마지막 ' 부분은 주석처리가 되고 데이터베이스를 날려버리는 괴랄한 짓도 가능하다.

📝 CSRF

로그인 된 상태로 스크립트가 주입된 게시물 따위를 읽을 때 가짜 사이트로 Ajax 실행 또는 url 클릭이 일어날 경우
로그인 된 사용자의 권한에 따라 해당 사용자의 정보만 가져가거나 관리자 권한일 경우 사용자의 정보를 다 훔쳐갑니다

 

XSS와 다른 점은 인증된 상태 즉, 인가로 인해 내 계좌에 이체할 수 있는 권한을 행사하는 등에서 차이점이 있다.

스크립트를 주입해서 공격하는 방식은 동일합니다

방지 방법

  • Front-End, Back-End 두 곳에서 이러한 값들을 방지해야한다.
  • 에러가 났을 때 에러에 대한 디버깅 페이지가 아닌 500 , 404 등에 대한 페이지를 따로 보여줘야한다
  • SQL의 경우 CRUD 및 테이블 권한별로 계정을 따로따로 만들어서 제공해줘야한다
  • Referrer 검증request Referrer을 확인 해 동일 서버에서 호출한지 확인하기
  • Security Token (CSRF Token)로그인시 사용자 세션에 난수 따위 복잡한 값을 Token에 넣습니다
    • 사용자가 해당 서버에 요청할 때 세션을 넣어서 요청합니다 즉, URL 클릭이나 Ajax로 해커 서버를 요청한경우 해당 서버에서 현재 로그인된 사용자의 권한으로 요청을 할텐데 URL 클릭이나 Ajax로 해커 서버에 요청을 할 때 CSRF값이 넘어가지지 않기 때문에 사용자 권한으로 처리할 수 없습니다
  • 위에 행위를 멈추기 위해 자기가 직접 막을수도 있지만 어떤 업체에서 쓰라고 만든 것을 쓰는게 훨씬 안전하다
  • 예) spring boot prevent sql injection 등

 

📝 세션 하이재킹 (Session Hijacking)

공격자가 사용자의 세션 ID를 탈취하여 사용자가 인증된 상태로 시스템에 접근하는 공격 기법을 의미합니다

 

 

 

🔗 참고 및 출처
https://blogpack.tistory.com/105

반응형
반응형

자바스크립트에서 이벤트가 동작되는 과정에는 두가지 방식이 있습니다.

 

기본적으로 이벤트 버블링으로 동작합니다.

📝이벤트 버블링

이벤트 버블링이란 하위 태그에서 이벤트가 발생할시 위에 태그로 전달하는 형태입니다.

 

이렇게 전달하면 이벤트가 전파되는데 밑에와 같은 코드가 있을 경우 Three → Two → One 순으로 누를시

Three 누르면 Three, Two, One이 출력이 됩니다.

Two 누르면 Two, One이 출력이 되고

One 누르면 One이 출력이 됩니다.

<!DOCTYPE html>
<head>

</head>



<body>
	<div class="one" id="one">
        one
		<div class="two" id="two">
            two 
			<div class="three" id="three">
                three
			</div>
		</div>
	</div>
</body>

<script>


var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}
</script>

 

 

이렇게 동작하는 과정을 이벤트 버블링이라고 합니다.

 

 

 

📝이벤트 캡처

 

이벤트 캡처라는 방식도 존재합니다.

이벤트 캡처란 이벤트 버블링이랑 다르게 최상위 태그에서 해당 이벤트 태그로 전파합니다.

 

이벤트가 전파되는데 밑에와 같은 코드가 있을 경우 Three → Two → One 순으로 누를시

Three 누르면 One, Two, Three이 출력이 됩니다.

Two 누르면 Two, One이 출력이 되고

One 누르면 One이 출력이 됩니다.

* 이벤트 버블과 반대 순서로 작동

<!DOCTYPE html>
<head>

</head>

<body>
	<div class="one" id="one">
        one
		<div class="two" id="two">
            two 
			<div class="three" id="three">
                three
			</div>
		</div>
	</div>
</body>

<script>


var divs = document.querySelectorAll('div');
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.
	});
});

function logEvent(event) {
	console.log(event.currentTarget.className);
}
</script>

 

 

위와 같은 걸 고려해서 만들기 귀찮거나 할 경우에는 event.stopPropagation()을 사용하면 됩니다.

아까랑 스크립트 코드가 다르지만 이것은 이벤트 버블링이 적용된 상태입니다.

event.stopPropagation() 을 사용할 경우 전파하지않고 해당 태그만 이벤트가 작동합니다.

<!DOCTYPE html>
<head>

</head>



<body>
	<div class="one" id="one" onclick="hello1()">
			one
		<div class="two" id="two" onclick="hello2()">
				two 
			<div class="three" id="three" onclick="hello3()">
					three
			</div>
		</div>
	</div>
</body>

<script>
    function hello1(){
        event.stopPropagation();
        console.log(event.currentTarget.className);
    }

    function hello2(){
        event.stopPropagation();
        console.log(event.currentTarget.className);
    }
    function hello3(){
        event.stopPropagation();
        console.log(event.currentTarget.className);
    }
</script>

 

 

 

 

 

 

📝이벤트 위임

지금까지 위에서 한 행위들은 이벤트 위임을 이해하기 위함입니다. 물론 내가 원하는 방식하고 다르게 동작하는 것에 대한 파악도 가능하지만요 이벤트 위임은 바닐라 JS로 웹 앱을 구현할 때 자주 사용하게 되는 코딩 패턴입니다. 하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어합니다.

 

<!DOCTYPE html>
<head>

</head>
<body>

<h1>오늘의 할 일</h1>
<ul class="itemList">
	<li>
		<input type="checkbox" id="item1">
		<label for="item1">이벤트 버블링 학습</label>
	</li>
	<li>
		<input type="checkbox" id="item2">
		<label for="item2">이벤트 캡쳐 학습</label>
	</li>
</ul>
</body>


<script>
var inputs = document.querySelectorAll('input');
inputs.forEach(function(input) {
	input.addEventListener('click', function(event) {
		alert('clicked');
	});
});
    
</script>

 

위에 코드는 체크박스 클릭시 Alert이 노출되는 형식으로 돌아갑니다.

여기에서 회원의 권한에 따라 보여지는 체크박스 수가 달라질 경우 추가된 체크박스에 이벤트 리스너를 또 추가해야 추가된 체크박스도 또한 위와 같이 동작하게 됩니다. 이러한 걸 이벤트 위임으로 간단하게 처리할 수 있습니다.

 

 

<!DOCTYPE html>
<head>

</head>
<body>

<h1>오늘의 할 일</h1>
<ul class="itemList">
	<li>
		<input class="item" type="checkbox" id="item1" >
		<label for="item1">이벤트 버블링 학습</label>
	</li>
	<li>
		<input class="item" type="checkbox" id="item2">
		<label for="item2">이벤트 캡처 학습</label>
	</li>
</ul>
</body>


<script>
let itemList = document.querySelector('.itemList');

itemList.addEventListener('click', function(event) {
	alert('clicked');
});


let createCheckBox = () => {

    let li = document.createElement('li');
    let input = document.createElement('input');
    let label = document.createElement('label');
    let labelText = document.createTextNode(' 이벤트 위임');

    input.setAttribute('type','checkbox');
    input.setAttribute('id','item3');
    label.setAttribute('for','item3');
    label.appendChild(labelText);
    
    li.appendChild(input);
    li.appendChild(label);
    itemList.appendChild(li);
}

createCheckBox();

</script>

 

 

label 해당 영역을 누른 경우 2번 호출되는데 클릭시 label이 input checkbox를 호출하면서 ul범위 안에 있기 때문에 alert이 한번 호출되고 1번 ul 자체를 클릭한 거이기 때문에 1번 이런식으로 호출된다. 

 

label을 다른 방식으로 처리하든가 분기처리를 하던가 하면 될 거 같다 (label 자체의 문제임)

 

생각해봤는데 이벤트 위임의 경우 ul태그가 크니까 ul태그안에 어딜 눌러도 ul에 적용되어있는 이벤트는 다 동작한다

직접 안 써봐서 모르겠는데 복잡하게 생각할 건 없는 거 같다.

 

 

 

출처 : https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

반응형
반응형

앵커(Anchor) A태그를 의미한다.


A태그로 function 사용하는 방법은 3가지가 있습니다.
1. <a href="javascript:callHello();">javascript function</a>
<a href="javascript:function callHello(){alert("hello");} a();">javascript function</a> <!-- 위와 동일 -->

2. <a href="javascript:void(0);" onclick="callHello();">onclick function</a>

3. <a href="#" onclick="callHello();">call function</a>
href="#"을 해 놓으면 클릭시 이벤트 버블링으로 인해 anchor을 타서 브라우저 상단으로 이동합니다.
2번과 같은 방식또는 <a href="#;" onclick="callHello(); return false;">onclick function</a>와 같이 처리로
브라우저 상단으로 안 가게 가능합니다.

반응형
반응형

📝파이프라인 / 파이프라이닝

CPU 내부에는 여러가지 일꾼들이 있습니다

대표적인 일꾼으로 읽기, 해석, 실행, 기록이 있습니다

 

 

 

시간에 따른 명령어 처리를 도식화할 시 위 이미지와 같습니다

마치 파이프와 비슷한 형태이죠? 이걸 파이프라인이라고 합니다

명령어(덧셈, 뺄셈 등)가 들어왔을 때 먼저 해당 명령어를 읽고 해석한 뒤 실행시키고 기록이 필요한 경우 기록합니다.

하지만 이렇게 하나의 명령어가 끝날때까지 다른 파트들이 노는 시간이 발생합니다 이렇게 되면 그 후에 들어오는 명령어에 대한 처리가 길어지겠죠

 

 

이걸 해결 하기 위해서는 노는 시간에 다른 명령어들이 들어오도록 하면 됩니다.

밑 사진과 같은 방식으로 처리할시에는 노는 시간도 없어지고 리소스를 최대한 활용이 가능하겠죠?

이러한 행동을 파이프라이닝이라고합니다 → 물론 그만큼 CPU에 부담이 가긴 합니다

 

인텔에서는 CPU의 파이프라인이 길어 명령어를 많이 축적시킬 수 있고 AMD에서는 파이프라인 폭이 넓다고합니다

폭이 넓다는 건 "읽기 처리하는 파이프라인이 여러개이다"라고 해석이 가능할 것 같습니다

 

 

📝클럭

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    clock_t start, end;
    double result;


    start = clock();			// 현재 시간 반환

    long sum = 0;
    for (long i = 0; i <= 380000000; i++) {
        sum += i;
    }

    end = clock();
    result = (double)(end - start);

    printf("수행 시간 : %f", result);

    return 0;
}

CPU의 속도를 나타내는 단위로서 1초동안 파장이 한번 움직인 시간을 의미하는데 클럭이 높아질수록 발열량과 소비 전력이 커지는 문제 생긴다 → CPU 3.8GHz 의 경우 1초당 (380,000,000) = 3억 8천만의 연산이 가능하다

위에는 3억 8천만번 덧셈 연산을 한 결과이다 보면 대략 1초가량 걸린 걸 확인할 수 있다

 

📝하이퍼스레드

물리적인 CPU(2코어[2개의 CPU] 4코어[4개의 CPU] 등)을 논리적인 CPU로 나누어서 처리하는 방법

즉 2코어 4스레드의 경우 1개의 CPU를 2개의 CPU로 인식시켜서 처리하게 한다

 

파워포인트, 카카오톡, 크롬, 엑셀을 사용한다고 가정하자

멀티 프로세싱의 경우 (2개 설정 시) 파워포인트에 1번 CPU를 카카오톡에 2번 CPU를 할당한다 그리고 크롬과 엑셀의 경우 1번 또는 2번에서 번갈아가면서 처리한다

 

하이퍼스레드의 경우 2개의 CPU(듀얼코어)인 경우 4개의 논리적 CPU가 생겨난다

1번 스레드의 경우 파워포인트, 2번 스레드의 경우 카카오톡, 3번 스레드의 경우 크롬, 4번 스레드의 경우 엑셀

이렇게 실행되게 된다

게임의 경우 하이퍼스레드를 사용하면 4개를 병렬적으로 처리하기 때문에 더 빠른 화면 렌더링이 가능하다

물론 게임도 하이퍼스레드를 지원하는 프로그램이여야만 한다

하지만 어떤 처리가 CPU를 많이 먹는 경우 하이퍼 스레드를 안 쓰는게 좋다 → 100%를 50% 50%로 분할하기 때문이다

 

🔗 참고 및 출처

https://smsinfo.tistory.com/514

반응형
반응형

📝컴퓨터 동작 구조

 

 

사용자가 명령어(입력 또는 저장 등)을 주면 주기억장치에서 해당 명령어를 가지고 있습니다

그러면 해당 명령어를 CPU로 보내고 다시 RAM으로 가져와서 휘발성의 데이터(인터넷 창 키기 등)일 경우 바로 출력하고 보조기억 장치가 필요한 경우(프로그램 저장, 다운로드 등) HDD에 저장합니다.

 

HDD의 데이터를 읽어야하는 경우라면 저도 정확히는 모르겠지만 주기억장치에 명령어가 들어오고 CPU에 적재되어 처리된 후 RAM을 거쳐서 HDD를 다시 읽어서 주기억장치에 올리고 CPU가 그걸 가지고 연산처리한 후에 더이상 HDD 접근이 필요 없는 경우 해당 정보를 RAM에 올려 사용자 화면등 출력 장치에 출력하는 형태인 것 같습니다.

반응형