반응형

개발을 시작할때 한번쯤 공부하지만
세월이 지나면서 잊게되는 HTML 로드 순서.
그치만 웹 개발자라면 잊어서도 안되고 계속해서
공부해야한다.
브라우저는 계속 발전하기 때문에 새로이 업데이트 되는 사항들을 놓치지 말자.

--------------------------------

HTML이 브라우저에 의해 호출되면
기본적으로 위에서 아래의 순서로 파싱된다.

<html>
  <head></head>
  <body>
    <div>
      <p>Hello world</p>
    </div>
  </body>
</html>

위와 같다면 문제없이 위에서 아래로 파싱되며
끝이 난다.

문제는 script 태그를 만났을때다.
브라우저는 HTML을 읽다가 script 태그를 만나면
파싱을 중단하고 script태그를 다운로드 및 파싱한다.

여기서 두가지 문제가 발생한다.

[ 브라우저가 script 태그를 만났을 때, 발생할 수 있는 두가지 문제 ]
1. script 태그가 다운로드 되고 실행되는 것을 기다리느냐, 페이지 로딩이 지연된다.
2. script 태그가 하단의 dom 요소들 보다 먼저 파싱되기 때문에, 
   script 태그에서 dom요소에 접근하여 이벤트 핸들러를 등록하는 등의 행위가 불가능하다.


2번의 문제로 HTML, Javascript를 처음 배울때면
body 가장 밑쪽에 script태그를 배치하라고 배우게된다.


하지만, 그것만으로 모든 문제가 해결될까?
그것은 아니다.
페이지에서 핵심적으로 작용하는 script가 최하단에서 다운로드 및 파싱된다면
사용자가 끔찍한 화면을 본다거나,
에러상황을 마주하게 될 수 있다.

그리고 최신 웹사이트들은
써드파티 라이브러리를 많이 사용하다보니
script 태그를 예전보다 더 적극적으로 많이 사용하게된다.

혹은, 번들러를 통해 빌드하게되면
html에 상당히 많은 script 태그가 자동으로 추가된다.

페이지에 필수적으로 적용되는 script태그를
계속해서 페이지 최하단에 위치시킬것인가?


--------------------------------


그래서 script 태그에는 defer와 async라는 속성이 존재한다.
먼저, defer를 알아보자.

<html>
  <head>
    <script defer src="cdn-subway-tastgood.js" />
  </head>
  <body>
    <div>
      <p>Hello world</p>
    </div>
  </body>
</html>

위 처럼 defer가 적용된 script가 있을때
HTML의 로드 순서는 어떻게될까?

script는 완전히 독립적으로 실행되게 된다.
브라우저는 HTML을 읽다가 script를 만나도
파싱을 중단하지 않고 계속해서 아래로 파싱해나간다.

HTML을 읽다가 script 태그를 마주친 순간부터
script는 백그라운드(Background)에서 다운로드 된다.
defer script의 실행은 domContentLoaded 직전에 실행된다.
(* domcontentloaded 이벤트는 초기 HTML 문서를 완전히 불러오고 분석했을 때 발생하는 이벤트이다.)

따라서, 어느정도 실행 순서가 보장되며
페이지 로딩 속도를 지연시키지 않기 위한 방법이라고 볼 수 있다.


그렇다면 async는 어떨까?

<html>
  <head>
    <script async src="cdn-lotteria-tastgood.js" />
  </head>
  <body>
    <div>
      <p>Hello world</p>
    </div>
  </body>
</html>

async가 적용된 script를 만났을때 역시
파싱이 중단되지 않고 진행된다.
마찬가지로, 백그라운드에서 script가 다운로드된다.

async는 defer와 실행순서에 있어 차이가 있는데,
defer가 domcontentloaded 직전의 실행 시점을 갖는 반면
async는 백그라운드에서 다운로드가 완료된 순가 실행된다.
따라서, async는 그 실행순서가 보장되지는 않는다.

그래서 async는 써드파티 스크립트 중에서도
페이지의 핵심 기능과 독립적인 기능으로 동작하는..
예를들어, 광고나 페이지 방문자수 카운터 등에 사용된다.

반응형
반응형

attribute중에 contenteditable을 사용하면

div를 input, textarea처럼 쓸수있다.

 

입력창을 커스텀해서쓸때 종종 쓰이곤한다.

방법은 간단하다.

 

html + css / html + scss 버전 두가지를 살펴보자

 

1. html + css

<div contenteditable placeholder='메시지를 입력해주세요'></div>
[placeholder]:empty:before {
  display: block;
  content: attr(placeholder);
  color: #a6a6a6;
}

 

 

2. html + scss

<div contenteditable placeholder='메시지를 입력해주세요'></div>
&[placeholder]:empty:before {
  display: block;
  content: attrs(placeholder);
  color: #a6a6a6;
}

 

 

반응형
반응형

최근 웹 사이트 트렌드를 살펴보면

뭐 별것도아닌 사이트 만드는데도

react, vue, angular 등의 라이브러리 혹은

프레임워크를 사용하는 경향이 있습니다.

 

왜 그런걸까요...

아마도 의존성이 생긴것이 아닌가 싶습니다.

너무 길들여진 나머지

pure javascript와 html, css로는

웹 사이트를 만들지 못하게된

개발자가 많아진것은 아닐까요?

 

각설하고

정말 가벼운 웹사이트를 퍼블리상 할 일이 생겨

만들고 난 뒤에 js, css 파일등의 버전 관리를

어떻게 할까 고민해 보았습니다

 

1. 웹팩을 쓴다?

2. 몇번이나 업데이트한다고.. 직접 수정한다.

3. 스크립트를 통해 관리한다!

 

3번 방식을 채택하였습니다.

프로젝트 규모에 비해 너무 과하지도 않고

직접 하는것에 비해 과거 버전과 충돌할 가능성은

0%로 줄이는 효과가 있기 때문입니다.

 

코드는 간략하게 작성했는데요

프로젝트 구조가

index.html
/css (직접 작성한 코드)
  style.css
  pallete.css
/js (직접 작성한 코드)
  something.css
/common (swipe.js나 jquery같은 손대지 않을 소스코드)
  /css
  /js

이렇게 되어있다고 했을때의

코드로 보시면 되겠습니다

const fs = require("fs");
const html = fs.readFileSync("index.html").toString();

fs.readdir("./css", async (err, filenames) => {
  if (err) {
    console.log("err: ", err);
  } else {
    let newHtml = html;

    const renames = filenames.map((filename) => {
      const newFileName = getNewFilename(filename);
      fs.renameSync("./css/" + filename, "./css/" + newFileName);
      newHtml = newHtml.replace(strReplace(filename), newFileName);
      return newFileName;
    });
    await Promise.all(renames);

    fs.writeFileSync("./index.html", newHtml, "utf8");
  }
});

function strReplace(str) {
  return new RegExp(str, "gi");
}

function getNewFilename(currentName) {
  const dotIndex = currentName.indexOf(".");
  return `${currentName.slice(0, dotIndex)}.${new Date().valueOf()}.css`;
}

/css 폴더 경로의 파일들을 버전관리 하는

node script 파일입니다.

 

/js 폴더의 스크립트 버전도 관리하려면

css파트를 복붙해서 js로만 변경해주면 되겟죠?

 

해당 소스코드는  github에도 올려두었습니다

https://github.com/jaekwangLee/css-versioning

반응형
반응형

보통 "반응형", "모바일 사이트" 하면 나오는

 

키워드 두가지가 있다

 

Viewport와 Media 쿼리

 

 

 

둘 중 누구도 없어서는 안되면 필수적인 요소다.

 

media 쿼리는 웹 프론트를 만져본 사람이라면 기본적인 사용법은 익히들 알고있다.

 

물론 이것도 공부하려면 할것들이 제법 많지만

 

필요할때 구글링하면서 쓰면 될만한 내용이라

 

미리부터 공부할 필요는 없을것 같다

 

 

 

그런데 Viewport가 오늘 신선한 충격으로 다가왔다.

 

<meta name='viewport' content='width=device-width, initial-width=1.0' />

그냥 헤더에 이거 한 줄 넣는것.

 

이 이상으로 이것이 무슨 의미를 갖는지 정확히 어떤 역할을 하는지 관심갖지 못했었다.

 

그냥 넣으면 대부분 만사 오케이니까

 

더이상 건드릴 이유도 공부할 이유도 없었다. (몇가지 옵션 정도는 쓰고있지만..)

 

 

 

그런데 재밌는 부분이 있다.

 

내 데스크탑 기준의 css를 태블릿에서도 비율에 맞게 유지하려면 어떻게 하면좋을까?

 

media query로 일일히 퍼센트에 맞게 조정해준다?

 

물론 이거도 노력하면 비슷한 효과를 볼수있다.

 

지금 내가 말하려고 하는것은 물리적/논리적 해상도의 차이에 대해서다.

 

(지금부터, 아래의 내용은 다소 비 전문적이거나 부정확할 수 있습니다.)

 

 

 

 

물리적은 실제 디바이스의 너비이고

 

논리적은 제품사양에 명시된 스펙에 나온 해상도라고 생각하면 될것같다...

 

 

 

자, 먼저 Viewport를 제외하고 생각하면 media 쿼리는 물리적 해상도를 기준으로 

 

컴포넌트/태그 들의 크기를 일정하게 조정해 주는 역할을 한다고 보면 될것같다

 

 

그런데, Viewport를 잘 이용하면 특정 값을 기준으로 논리적 해상도를 기준으로 css를 적용할수있다. (내가 오늘 이해한 바로는)

 

간단히는 이렇게 볼수있다.

 

<meta name='viewport' content='width=1190' />

이렇게 설정해둔다면

 

디바이스의 크기에 상관없이 

 

css의 width: 100%를 1190px로 보게한다.

 

이미 작성해둔 css들은 걱정하지 않아도, 이를 기준으로해서 알맞게 조정한 크기를 보여주게된다.

 

viewport는 정말 어마무시한 친구다.

 

위의 설정을 누가 이용하는지 아는가?

 

바로, 우리가 매일 보고 사용하고 있는 "네이버"다

 

 

 

네이버를 데스크탑에서 열고 개발자 도구를 보면 viewport가 위와 같이 설정되어있다.

 

그런데, 화면의 크기를 모바일 사이즈정도로 작게하고

 

화면을 다시 로드하면 m.naver.com으로 리디렉션하며 

 

해당 페이지에서 개발자 도구를 보면 viewport는

 

<meta name='viewport' content='width=device-width, initial-width=1.0' />

과 같은 우리가 흔히 아는 내용으로 작성되어있다.

 

정말 놀라운 viewport의 세계다.

 

 

 

 

현재 내가 운영중인 서비스에서는 네이버처럼 m.을 분리하여 운영할 여력은 없어서

 

javascript를 이용해 디바이스 크기에 따라 로드 시점에 viewport를 다르게 주도록 설정해보았다.

반응형
반응형

모바일 반응형의 기본인 viewport메타태그

 

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=yes" />

maximum-scale을 포함해 다양한 옵션이 존재한다.

 

이중에서 user-scaleable이 yes 상태이면

input창을 focus했을떄 자동으로 화면이 줌인된다.

user-scalable=0 으로 설정하면 해당 이슈는 해결된다

 

다양한 사용자들에게 접근성을 제공하는 옵션이기도하니 서비스의 특성에 맞게 설정하도록하자.

반응형
반응형

Input에서 한글입력을 막는 방법에는

여러가지 접근 방법이 있다.

 

절대적인 방법을 발견하여 메모해둔다.

 

1. Input타입이 text인 경우에는 정규식을 통해 체크하여 원하는 문자열 입력방지를 실시할수있다.

예를들어, 숫자만 입력받고싶다면

 

const regExp = /[a-z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;

 

이런식의 정규식으로 입력값을 체크해서 입력을 방지하면 된다.

그리고 실제로 가능한 방법이다.

 

 

그러나,  우리는 사용자의 입력 편의성을 위하여 input타입을 number로 잡아줘야한다.

그때는 숫자외 다른 입력값을 입력했을때 정규식이 바보가된다.

인지를 못한다.

 

왜 그런가하고 타겟의 값을 콘솔에 찍어보았다.

console.log(e.target.value)

결과: 

분명히 실제로는 "123ㄱ"라고 화면에 나타나 있지만 결과에는 빈값이 출력되었다.

그러니 정규식이 캐치할래야 할수가 없는 상황이었다.

 

2. 정규식이 안먹히면 어떻게하지? 키코드를 사용해야하나?

원하는게 안먹히면 우리들은 발상의 전환을 시도한다.

하지만, 헛탕일 켤뿐 안된다는것을 미리 밝히는 바이다.

 

3. 그래서 어떻게 해야되는가?

input태그에  onchange이벤트를 걸었다면 아래와 같은 방법으로

숫자입력만 받는 방법이 가능하다.

const isNotNumber = () => {
  const regExp = /[a-z|ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/g;
  return regExp.test(value);
}

<input 
  type='text'
  onchange={e => {
    if (e.nativeEvent.data && isNotNumber(e.nativeEvent.data) {
      e.preventDefault();
      return null;
    }
    
    ...something
  }}
/>

 

매우 아름다운 방법으로 생각된다.

e.nativeEvent.data에는 놀랍게도 내가 지금 입력한 그 키값이 나타난다.

3이라면 3, t라면 t가 말이다.

backspace는 null이 나타난다. 따라서 null인 경우에는 허용을 해줘야한다.

 

 

사실 그동안 숫자만 입력받는 코드를 짜뒀다고 했는데

자꾸 한글이 입력된다는 리포트를 받아서 당황스러웠던적이 있다.

코드는 거짓말을 하지않는다...

나의 실책일뿐~~ ㅎㅎ

 

이 방법이 유효하지 않다거나 더 좋은방법이 있다면 댓글을 달아주시면 정말 감사하겠습니다.

반응형
반응형

사용자 기반 서비스를 만들다보니 Textarea에서 라인별 글자수 제한 및 총 라인 제한을 해야할 일이 생겼다

아래와 같은 코드로 해당 문제를 처리하였다.

 

필요한 사람들을 위해 공유한다.

const textareaLimitWordAndRow = (text, limitWordPerline, limeLines) => {
  let lines = text.split('\n');
  const charlimit = limitWordPerline; // 글자수 제한

  for (let i = 0; i < lines.length; i++) {
    if (lines[i].length <= charlimit) continue;
    let j = 0;
    let space = charlimit;
    while (j++ <= charlimit) {
      if (lines[i].charAt(j) === ' ') space = j;
    }
    
    lines[i + 1] = lines[i].substring(space + 1) + (lines[i + 1] || '');
    lines[i] = lines[i].substring(0, space);
  }

  return lines.slice(0, limeLines).join('\n');
};

 

 

반응형
반응형
const data = 'hello\nworld'
{
  data.split('\n').map(word => {
    return (<span>{ word }<br/></span>)
  })
}

 

반응형

'개발, 코딩 > React' 카테고리의 다른 글

React, how do i improve page loading?  (0) 2020.05.14
React, Context API 기초 익혀보기  (0) 2020.04.20
CRA(create-react-app), IE대응  (0) 2020.01.31
불변성, array  (0) 2019.11.04
react, cors 그리고 chrome  (0) 2019.10.31
반응형

Html, JS를 가지고

 

이미지 파일을 불러온 후, 미리보기를 구현하는 아주 간단한 방식을 소개해본다.

 

window객체에 내장되어있는 FileReader를 이용한 것이다.

 

먼저, input file에 onChange이벤트리스너를 붙여준다.

 

const oFReader = new FileReader();
oFReader.readAsDataURL(ev.target.files[0]);
oFReader.onload = ev => {
    document.querySelector('#uploadImage').src = ev.target.result;
};

위와 같은 코드로, 이미지 미리보기를 간단히 구현해볼 수 있다.

uploadImage는 해당 이미지 태그이다.

 

(예, <img id='uploadImage' alt='profile' />)

 

 

 


웹사이트 개발 / 홈페이지 제작 / android앱 개발 / ios 앱 개발 / server / client / aws / fullstack / buisness partner / 외주 / 용역

https://open.kakao.com/o/sNETgUJb

http://self-made.cloud

 

 

 

반응형
반응형

File upload는 대부분의 앱/웹에서 사용되는 아주 기본적인 기능

 

클라이언트 사이드에서의 처리는 생각보다 간단하다.

 

1. input type='file'로 태그를 생성하고,

 

2. onChange 이벤트리스너를 통해 ev.target.files[0]으로 선택된 파일을 읽어와 변수에 담는다.

 

3. 서버로 보내준다. 보내줄때는 formdata에 넣어보내줘야한다.

const formdata = new Formdata();

formdata.append('photo', file);

여기서 photo는 서버에서 해당 요청을 받을때 사용하게된다.

(예를들어, multer를 이용한 미들웨어에서 사용한다면 photo.upload(photo);

이때는 헤더설정도 해줘야한다. 

const config = { headers: { 'Content-Type': 'multipart/form-data' } }; << 이렇게

axios.post(url, formdata, config) 와 같이 서버에 요청을 날리면된다.

 

 

 


웹사이트 개발 / 홈페이지 제작 / android앱 개발 / ios 앱 개발 / server / client / aws / fullstack / buisness partner / 외주 / 용역

https://open.kakao.com/o/sNETgUJb

http://self-made.cloud

 

 

 

반응형