반응형

사이트가 복잡해져 가면 component 를 잘게 찢어서 사용하기에 한계가 있다. 이유는 상위 parent component 에서 하위 childe component 를 호출하는 거야 문제가 없겠지만, 하위 child component 내부에서 변경된 변수값을 상위 parent 에 전달하기 복잡하다.

복잡하지만 그래도 사이트를 만들어야 하니 해야지..

참조페이지

https://svelte.dev/examples/component-bindings

1. dispatcher 사용

참조 페이지 : https://svelte.dev/tutorial/component-events

자주 애용하지만 복잡하다. vuejs 에서 $emit()과 거의 같은 역할을 한다. vuejs 를 하다 보니 아래 $emit과 동일한 걸 찾느라 bind를 보지 못했던 것 같다.

다만 변수명을 어떻게 했더라?? 하고 헤깔리는 경우가 많다. 사용법은 아래와 같다. 

parent component

<script>
	import Inner from './Inner.svelte';

	function handleMessage(event) {
		alert(event.detail.text);
	}
</script>

<Inner on:message={handleMessage}/>

child component

<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	function sayHello() {
		dispatch('message', { text: 'Hello!' });
	}
</script>

<button on:click={sayHello}>
	Click to say hello
</button>

child component에서 dispatcher 를 선언하고, parent 에서 받을 이벤트명과 값을 지정한다. 

상위부모 컴포넌트에서는 on:eventname={callback} 함수 형태로 이벤트 발생시 실행할 함수 콜백명을 지정하고, 해당 함수에서 event 값을 받으면 된다. 단, 주의할 사항은 변수로 넘어온 값이 단순한 값이 아니고 객체 구조에 포함된 값이기 때문에, e.detail 이하에 해당 값이 포함되어 있다.

아래 bind를 알고 나서는 부모 컴포넌트의 함수 호출용으로만 사용 중이다.

2. bind를 이용한 방법

svelte에서 권장하는 방법이지만, 영어가 짧은 관계로 잘 못알아 먹고 이제서야 해보는 방법이다. ㅠ,.ㅠ;

https://svelte.dev/examples/component-bindings

parent component

<script>
	import Keypad from './Keypad.svelte';

	let pin;
	$: view = pin ? pin.replace(/\d(?!$)/g, '•') : 'enter your pin';

	function handleSubmit() {
		alert(`submitted ${pin}`);
	}
</script>

<h1 style="color: {pin ? '#333' : '#ccc'}">{view}</h1>

<Keypad bind:value={pin} on:submit={handleSubmit}/>

child component

<script>
	import { createEventDispatcher } from 'svelte';

	export let value = '';

	const dispatch = createEventDispatcher();

	const select = num => () => value += num;
	const clear  = () => value = '';
	const submit = () => dispatch('submit');
</script>

<div class="keypad">
	<button on:click={select(1)}>1</button>
	<button on:click={select(2)}>2</button>
	<button on:click={select(3)}>3</button>
	<button on:click={select(4)}>4</button>
	<button on:click={select(5)}>5</button>
	<button on:click={select(6)}>6</button>
	<button on:click={select(7)}>7</button>
	<button on:click={select(8)}>8</button>
	<button on:click={select(9)}>9</button>

	<button disabled={!value} on:click={clear}>clear</button>
	<button on:click={select(0)}>0</button>
	<button disabled={!value} on:click={submit}>submit</button>
</div>

<style>
	.keypad {
		display: grid;
		grid-template-columns: repeat(3, 5em);
		grid-template-rows: repeat(4, 3em);
		grid-gap: 0.5em
	}

	button {
		margin: 0
	}
</style>

간단히 말해서 그냥 bind로 묶어 주면 된다. 상위 부모 컴포넌트에서 사용하는 변수를 하위 자식 컴포넌트에서 사용하는 변수명과 묶어 주면 된다.

bind:value={pin}. value=자식이 사용하는 변수명, {pin}=부모가 사용 중인 변수명

별거 없다. 그냥 연동되더라. dispatcher를 사용하던 시절이 한탄스럽기만 하더라

실무에 많은 도움이 되었기를... 적어도 난 도움이 많이 되었다는 거.. ^^

반응형
블로그 이미지

BitSense

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

https://k6.io/

설치(mac)

brew install k6

기본 테스트 스크립트 샘플

# filename: script.js
import http from 'k6/http';
import { sleep } from 'k6';

export default function () {
  http.get('https://test.k6.io');
  sleep(1);
}

기본 실행 방법

k6 run script.js

VU (Virtual User) 추가 실행

k6 run --vus 10 --duration 30s script.js

--vus : 동시접속자를 10명으로 유지
--duration : 30초 동안 vus 수를 유지 호출

옵션 vu, duration을 소스에 추가해서 실행

import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
  vus: 10,
  duration: '30s',
};
export default function () {
  http.get('http://test.k6.io');
  sleep(1);
}

vu를 원하는 시간만큼 조절해서 사용 가능

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 20 },
    { duration: '1m30s', target: 10 },
    { duration: '20s', target: 0 },
  ],
};

export default function () {
  const res = http.get('https://httpbin.org/');
  check(res, { 'status was 200': (r) => r.status == 200 });
  sleep(1);
}

테스트 결과 설명

 k6 run stages.js                        

          /\      |‾‾| /‾‾/   /‾‾/   
     /\  /  \     |  |/  /   /  /    
    /  \/    \    |     (   /   ‾‾\  
   /          \   |  |\  \ |  (‾)  | 
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: stages.js
     output: -

  scenarios: (100.00%) 1 scenario, 20 max VUs, 2m50s max duration (incl. graceful stop):
           * default: Up to 20 looping VUs for 2m20s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)


running (2m20.2s), 00/20 VUs, 1473 complete and 0 interrupted iterations
default ✓ [======================================] 00/20 VUs  2m20s

     ✓ status was 200

     checks.........................: 100.00% ✓ 1473      ✗ 0   
     data_received..................: 15 MB   104 kB/s
     data_sent......................: 137 kB  974 B/s
     http_req_blocked...............: avg=8.56ms   min=0s       med=1µs      max=763.5ms  p(90)=2µs      p(95)=4µs     
     http_req_connecting............: avg=2.78ms   min=0s       med=0s       max=232.77ms p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=224.38ms min=190.95ms med=201.72ms max=961.94ms p(90)=236.09ms p(95)=351.89ms
       { expected_response:true }...: avg=224.38ms min=190.95ms med=201.72ms max=961.94ms p(90)=236.09ms p(95)=351.89ms
     http_req_failed................: 0.00%   ✓ 0         ✗ 1473
     http_req_receiving.............: avg=165.03µs min=43µs     med=162µs    max=1.75ms   p(90)=222µs    p(95)=236.39µs
     http_req_sending...............: avg=145.88µs min=31µs     med=140µs    max=1.39ms   p(90)=218µs    p(95)=241µs   
     http_req_tls_handshaking.......: avg=5.72ms   min=0s       med=0s       max=510.91ms p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=224.06ms min=190.72ms med=201.37ms max=961.59ms p(90)=235.76ms p(95)=351.55ms
     http_reqs......................: 1473    10.504156/s
     iteration_duration.............: avg=1.23s    min=1.19s    med=1.2s     max=1.96s    p(90)=1.24s    p(95)=1.39s   
     iterations.....................: 1473    10.504156/s
     vus............................: 1       min=1       max=20
     vus_max........................: 20      min=20      max=20
  • vus — 활성 가상 사용자 수
  • vus_max — 테스트에 할당 된 최대 가상 사용자
  • iterations— default함수가 호출 된 총 횟수
  • iteration_duration— default함수 를 실행하는 데 걸린 총 시간
  • dropped_iterations— iterations시작할 수없는 수
  • data_received — 수신 된 데이터의 양
  • data_sent — 전송 된 데이터 양
  • checks — 성공적인 검사 비율 (나중에 설명)
  • http_reqs — k6에 의해 생성 된 총 요청
  • http_req_blocked — 요청을 시작하기 전에 사용 가능한 TCP 연결을 기다리는 데 소요 된 시간
  • http_req_connecting — TCP 연결 설정에 소요 된 시간
  • http_req_tls_handshaking — TLS 핸드 쉐이킹에 소요 된 시간
  • http_req_sending — 데이터 전송에 소요 된 시간
  • http_req_waiting — 원격 호스트의 응답을 기다리는 데 소요 된 시간
  • http_req_receiving — 데이터 수신에 소요 된 시간
  • http_req_duration— 요청에 대한 총 시간. http_req_sending+ http_req_waiting+를 기준으로 계산됩니다.http_req_receiving.
반응형
블로그 이미지

BitSense

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

SvelteJS 사용 이유?

빠르다니깐, 궁금해서~! 그런데 모르겠다. react, vue, svelte 모두 빌드한 js 소스를 서버에 올리고 다운로드 받아서 사용하는 진짜 프론트엔드 사이드 스크립트다. 중간의 내용이야 어찌저찌 해서 팩키징 결과물이 조금씩 틀려지기는 하겠지만, 그렇다고 속도 측면은 잘 모르겠다.  react는 안써보고, vue랑 별반 차이가... 그냥 빠르다니깐.. 그런가? 하는데.. 알아서들 참조하시고~

아직 vite, rollup 차이를 구분 못하고, 실무에 sveltejs를 적용해 보면서, 맨땅에 헤딩하는 심정으로 진행하면서 실무에 필요한 내용 중에 빠져 있거나, 샘플에서 커스터마이징이 필요한 내용들을 정리해서 올려 보겠다.

typescript를 사용하는 이유?

정형화된 틀에 맞춰보려고 하는데, 생각보다 쉽지 않다. typescript에서 제일 중요한 것은 받거나 보낼 데이터 뭉치에 대한 선언(type)이다. 이런 데이터를 받겠으니, 이런 포맷으로 주세요~~. 그런데.. 이건 디비에 넣을때나 중요한 거지, 막상 실무에서는 any만 열심히 쓴다. 특히 프론트에서는 더더욱 그렇더라. basic, php를 먼저 다룬 개발자로서 부정형 데이터에 대한 자유도를 놓칠 수 없더라. 물론 이것도 개인차라.. 알아서들 잘~ ^^

HTML 에디터 - QUILL 샘플

참조사이트: https://svelte.dev/repl/e2bbe94abb19419892442729752ee308?version=3.19.1 

 

Quill Demo • REPL • Svelte

 

svelte.dev

몇 안되는 주요 샘플코드이다. svelte 소스들이 대부분 보여주기식인 경우가 많아서, 이 소스도 안타깝게 보여주기만 한다. "에디터 이렇게 연결할 수 있다~!!" 더욱이 quill 을 잘 모른다. vue에서는 ckeditor를 주로 사용해서... 일단 있으니 감사하면서 사용했고, 에디터에 등록한 데이터를 가져오는 방법을 아래에 추가함

// quill 설치 (^1.3.7)
yarn add quill

// 에디터에서 소스 가져오기
<script lang="ts">

....

  let text
  let html
  
  onMount(async () => {
    const { default: Quill } = await import("quill");
	
    let quill = new Quill(editor, {
      modules: {
        toolbar: toolbarOptions
      },
      theme: "snow",
      placeholder: "Write your story..."
    });
 
    // 에디터 데이터 수집 소스
    quill.on('text-change', function() {
      text = quill.getContents()     // 에디터에 사용된 구조 데이터
      html = quill.root.innerHTML    // html 결과물
    })
  })
  
....

</script>

SEO를 적용할 수 있다고?

물론 아니다. 처음에는 나도 깜빡 속았다. 요새 구글 로봇이 js도 읽는다고 하지만, SSR에서 강제로 꽂아 주는 것이 속이 편하다. 단지, 백엔드 개발자인 나는 자주 SEO 태그를 멀 넣어야 하는지 고민이다. 나같은 분들에게는 좋은 샘플이 될 거 같아서 가져와 봤다.

참조 페이지 : https://svelte.dev/repl/ffd783c9b8e54d97b6b7cac6eadace42?version=3.49.0 

 

Including SEO metadata in Svelte • REPL • Svelte

 

svelte.dev

위 샘플 소스에 대한 결과물이다. 잘만 정리하면 내가 원하는 데이터만 잡아서 SSR 단에서 꽂아 주면 될 거 같다.

오늘은 이 정도로 정리해 봤다.

다음은 서버 스크립트와 연동을 얘기해 볼까? 참고로 현재 sveltejs 와 연동 중인 언어는 python + flask 를 사용 중이다.

오늘도 좋은 하루 보내시길~

반응형
블로그 이미지

BitSense

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

맥 원격접속은 파인더(Finder)에서 [Command+K] 로 쉽게 VNC를 실행할 수 있습니다. 이때 사용되는 디폴트 포트는 5900 입니다.

개인적으로 회사컴에 원격접속을 하기 위해서 열린 포트는 윈도우용 원격데스크톱의 포트인 3389 입니다. 그렇다 보니 윈도 접근은 쉬운데, 회사 맥에 원격접속을 하려면 절차가 까다롭습니다. 그래서 맥 VNC서버 포트 자체를 5900에서 3389로 바꾸려고 합니다.

맥 VNC 원격접속 포트를 5900에서 윈도우 원격데스크탑 포트인 3389로 변경하기

$ sudo vi /etc/services

# 5900 포트 검색 후 3389로 변경
/5900

# 기존 3389는 주석 처리
# ms-wbt-server 3389/udp    # MS WBT Server
# ms-wbt-server 3389/tcp    # MS WBT Server

# 5900 포트는 3389로 변경
rfb             3389/tcp    vnc-server # VNC Server
rfb             3389/udp    vnc-server # VNC Server

ARDAgent.app 재실행

sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -restart -agent

3389 포트로 원격 접속 (Finder > [Command+K] 단축키)

원격 접속이 안되는 경우에는 시스템을 리붓 후 연결을 해보세요.

반응형
블로그 이미지

BitSense

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요

반응형

갑자기 크롬 확장 앱이 만들어 보고 싶어졌습니다. 몇년 전에 관심을 가지고 잠깐 보기는 했지만, 멀 만들지??? 하는 생각에 잠깐 보고, 이렇게 만드는 구나~~ 하고 말았는데, 유투브 동영상에 나오는 광고가 귀찮아서 없애볼까 하는 생각에 다시 크롭앱을 보기 시작했네요..

크롬 관련된 개발할 수 있는 종류가 몇가지 됩니다. https://developer.chrome.com/docs/

 

Documentation - Chrome Developers

Build the next generation of web experiences.

developer.chrome.com

이중에서 페이지가 로딩되면 곧바로 실행되어야 하니, Extensions 항목을 먼저 공부해 봅니다.

https://developer.chrome.com/docs/extensions/

 

Extensions - Chrome Developers

Extensions are software programs, built on web technologies (such as HTML, CSS, and JavaScript) that enable users to customize the Chrome browsing experience.

developer.chrome.com

크롬앱은 기본 js/ ts 구동이 됩니다. js는 쉽지만, 또 쉽지 않은 언어라, 잠시 훑어 보고 오시는 것도 좋은 방법일 거 같습니다.

소스 보기

잠시 크롬 확장앱 구조를 보겠습니다. (샘플 참조 : https://developer.chrome.com/docs/extensions/mv3/overview/)

- manifest.json
- hello.html
- icon.png

1. manifest.json

해당 파일은 설정 페이지 입니다. 실행시 필요 권한, 백그라운드 콜백 파일 등을 지정합니다. 현재는 v3를 사용하는 것을 권장하고 있습니다.

{
  "name": "Hello Extensions",
  "description": "Base Level Extension",
  "version": "1.0",
  "manifest_version": 3,
  "action": {
    "default_popup": "hello.html",
    "default_icon": "icon.png"
  },
  "commands": {
    "_execute_action": {
      "suggested_key": {
        "default": "Ctrl+Shift+F",
        "mac": "MacCtrl+Shift+F"
      },
      "description": "Opens hello.html"
    }
  }
}

1-1. action : 등록된 아이콘을 클릭할 경우 실행될 팝업창과 아이콘을 지정합니다.

1-2. commands : 바로가기 키를 활성화 하는 명령어 입니다. 해당 키조합을 누를 경우, 실행 됩니다. (선택사항. 없어도 됩니다.)

2. hello.html

<html>
  <body>
    <h1>Hello Extensions</h1>
  </body>
</html>

3. icon.png

아이콘 파일 링크 : https://raw.githubusercontent.com/GoogleChrome/chrome-extensions-samples/main/tutorials/hello-world/hello_extensions.png

크롬 extensions을 웹브라우저에 등록하기

1. 크롬 브라우저 주소표시줄 - chrome://extesions

2. 개발자 모드 선택 > [압축해제된 확장 프로그램을 로드합니다.] 클릭

3. 작업한 소스 폴더 선택

4. 크롬 "확장 브라우저" 아이콘 클릭 > "Hello Extensions" 핀 클릭

5. 크롬 "확장 브라우저" 아이콘 왼쪽 > "Hi" 아이콘 클릭

기본 크롬 Extensions 앱 작업 및 크롬 브라우저 추가 작업은 완료했습니다.

다음은 크롬 Extensions에서 Service Worker로  자동실행하여서 현재 웹페이지의 배경화면을 변경하는 작업을 해보겠습니다.

감사합니다.

반응형
블로그 이미지

BitSense

뷰파인더로 보는 프로그래머의 세상 페이스북 @bitsense 트위터 @picory 스카이프 picory MSN drawhalf@dreamwiz.com

댓글을 달아 주세요