js-regex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var reg = /^(d|D)+\d{9}/;
var isValid = reg.test(inputCode);


// 숫자 10자
var reg = /^\d{10}$/;
var isValid = reg.test(currentNumber);

// 숫자 1 ~ 10 자리
/^\d{1,10}$/



//알파벳 숫자 3자리에서 5자리
var reg = /^([a-zA-Z0-9_-]){3,5}$/


// You want to test whether a string is composed of between 1 and 10 letters from A to Z.
^[A-Z]{1,10}$

Input Text 박스 백그라운드 이미지 추가

1
<input type='text' placeholder='입력하세요' maxLength="6"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
input{
font-size: 16px;
border: 1px solid #888888;
height: 56px;
width: 95%;

/* input 텍스트 인텐트 설정*/
text-indent: 16px;

/* input 박스 안의 이미지 설정, 하위 브라우저에서 지원 안함 */
background: url('/ico_error.png') no-repeat center right 16px;
background-size: 24px 24px;

/* placeholder css 설정 */
::placeholder {
color: #bbbbbb;
opacity: 1; /* Firefox */
}

:-ms-input-placeholder { /* Internet Explorer 10-11 */
color: #bbbbbb;
}

::-ms-input-placeholder { /* Microsoft Edge */
color: #bbbbbb;
}
}

References

리엑트에서 input 입력값 처리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import './index.scss'

class Index extends Component {
constructor (props) {
super(props)

this.initialQ = this.props.q || ''
this.state = { q: this.initialQ }

}

handleInputChange = (e) => {
const target = e.target;
//const type = e.type;

const name = target.name;
const value = target.value.trim();
const modifiedValue = value.substring(0,10);

this.setState({
[name]: modifiedValue
});
}

handleInputPress = (e) => {
if (e.key === 'Enter') {
this.goSearch()
}
}

goSearch = (q = this.state.q) => {
if (q) {
this.props.history.push(`/search/${q}`)
}
}

render () {
return (
<React.Fragment>
<input type='text' name='q' className={`searchbox`}
value={this.state.q}
onChange={this.handleInputChange}
onKeyPress={this.handleInputPress}/>
</React.Fragment>
)
}
}

export default Index

Input 숫자 키패드

iOS 사파리에서는 maxLength가 먹지 않아 js로 막아야 합니다.

1
2
3
4
5
6
7
8
9
<input type='number'
pattern="[0-9]*"
placeholder='코드입력'
maxLength="6"
className={this.state.errorMsg && 'error'}
name= "inputCode"
value={this.state.inputCode}
onChange={this.handleInputChange}
onKeyPress={this.handleInputPress}/>

CSS 중앙정렬

text-align

inline 요소만 가능 block 요소는 불가능

width 값이 지정된 block요소의 중앙 정렬

auto 값은 요소 안의 마진 여백이 대등하게 나눠짐을 의미합니다.

1
2
3
4
p { 
width: 100px; /* 정렬하려는 요소의 넓이를 반드시 지정 */
margin: 0 auto;
}
1
2
3
4
<div class="popup">
POPUP
</div>
<div class="dim"></div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.popup {
position: fixed;
bottom: 25%;
left: 0;
right: 0;
margin: 0px 24px;
}

.dim {
position:fixed;
top:0;
bottom:0;
left:0;
right:0;
background-color:#000000;
opacity:0.7;
z-index:1001;

overflow:hidden;
position:fixed;
}
1
window.document.body.style.position = 'fixed'

absoulte

1
2
3
4
5
6
7
8
#content {
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
width: 100px; // Need a specific value to work
}

absoulte 중앙 정렬 , 양옆 여백

1
2
3
4
5
6
7
8
<div class="imageDiv">
<img src="https://static.tmaptaxi.com/promotion/tmembership/mobile/tmapapp.svg" width="100%">
<div class="btn" onclick="download()">
<div style="padding: 0 38px;">
<img src="https://static.tmaptaxi.com/promotion/tmembership/mobile/btn_copy_2.svg" width="100%">
</div>
</div>
</div>
1
2
3
.wrap_EventArea .imageDiv{position:relative;}
.wrap_EventArea img{display:block;width:100%;border:none;vertical-align:top;}
.wrap_EventArea .btn{display:block;position: absolute;bottom: -10px;width: 100%;}

References

puppeteer

puppeteer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async login () {
const loginUrl = `https://www.facebook.com/login/?next=https%3A%2F%2Fwww.facebook.com%2Fpriceship%2F`;
const username = config.facebook.id;
const password = config.facebook.pw;

const page = await this.browser.newPage();
await page.goto(loginUrl);

const USERNAME_SELECTOR = '#email';
const PASSWORD_SELECTOR = '#pass';
const BUTTON_SELECTOR = '#loginbutton';

await page.click(USERNAME_SELECTOR);
await page.keyboard.type(username);

await page.click(PASSWORD_SELECTOR);
await page.keyboard.type(password);

await page.click(BUTTON_SELECTOR);
await page.waitForNavigation();
const cookies = await page.cookies();
console.log('cookies',cookies)
}

References

자바스크립트 함수 메서드 (apply, bind, call)

apply

  • this와 argutments 배열로 해당 함수 호출
    1
    fun.apply(thisArg, [argsArray])

bind

  • 새로운 함수를 생성 후 RETURN

    1
    fun.bind(thisArg[, arg1[, arg2[, ...]]])
  • bind 예제

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var module = {
    x: 42,
    getX: function() {
    return this.x;
    }
    }

    var unboundGetX = module.getX;
    console.log(unboundGetX()); // The function gets invoked at the global scope
    // expected output: undefined

    var boundGetX = unboundGetX.bind(module);
    console.log(boundGetX());
    // expected output: 42

call

  • this와 arguments 목록을 가지고 해당 함수 호출
    1
    fun.call(thisArg[, arg1[, arg2[, ...]]])

References

리엑트 16 이상에서 안드로이드 4.1 브라우저 지원하는 방법

리엑트 16 부터 Map, Set 의존성을 가지게 됩니다.
그래서 안드로이드 저버전 브라우저에서 작동을 하지 않는데 pollyfill 추가를 통해서 해결할 수 있습니다.

core-js pollyfill 추가

Yarn eject 명령을 통해서 config 파일을 생성합니다.

1
yarn eject

아래 경로의 파일을 수정합니다.
./config/pollyfills.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

if (typeof Promise === 'undefined') {
// Rejection tracking prevents a common issue where React gets into an
// inconsistent state due to an error, but it gets swallowed by a Promise,
// and the user has no idea what causes React's erratic future behavior.
require('promise/lib/rejection-tracking').enable();
window.Promise = require('promise/lib/es6-extensions.js');
}

// fetch() polyfill for making API calls.
//require('whatwg-fetch'); // axios를 사용하기 때문에 주석 처리

// Object.assign() is commonly used with React.
// It will use the native implementation if it's present and isn't buggy.
//Object.assign = require('object-assign'); // core-js 로 대체

// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
// We don't polyfill it in the browser--this is user's responsibility.
if (process.env.NODE_ENV === 'test') {
require('raf').polyfill(global);
}

require('core-js') // core-js 추가

References

HTML Viewport 설정

viewport

viewport는 웹 컨텐츠를 볼 수 있는 창 영역입니다.
좁은 화면 장치 (예 : 휴대폰)는 화면보다 일반적으로 넓은 가상 창이나 뷰포트에 페이지를 렌더링 한 다음 렌더링 된 결과를 모두 축소하여 한 번에 볼 수 있습니다.
그런 다음 사용자는 이동하고 확대 / 축소하여 페이지의 다른 영역을 볼 수 있습니다.
예를 들어 모바일 화면의 너비가 640px 인 경우 페이지는 가상 뷰포트가 980px로 렌더링 된 다음 640px 공간에 맞게 축소됩니다.

대부분의 페이지는 모바일에 최적화되어 있지 않으므로 작은 뷰포트 너비에서 렌더링 할 때 깨지거나 (또는 ​​불량하게 보입니다) 수행됩니다.
이 가상 뷰포트는 좁은 화면 장치에서 일반적으로 모바일에 최적화되지 않은 사이트를 더 잘 보이도록 만드는 방법입니다.

viewport 설정

html에 아래 meta태그를 추가하면 됩니다.

1
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  • content=width=device-width : 컨텐츠를 디바이스 가로 사이즈에 맞춰 표현한다고 선언
  • initial-scale=1.0 : 초기 표시 배율 (1.0이 기본, 꽉찬 페이지)
  • maximum-scale=1.0 : 최대 확대 비율 ( 기본값 5.0 범위 0~10.0)
  • minimum-scale=0.25 : 최소 확대 비율 ( 기본값 5.0 범위 0~10.0)
  • user-scalable=no : 확대/축소 설정 (기본값 yes)

References

CORS에서 Credentials(인증서) 통신방법

Credentials (인증서)

  • Credentials 이란 쿠키, 인증헤더, TLS client certificates(증명서)를 말함
  • Credentials 이 있는 CORS 요청은 Client와 Server 둘다 Credentials를 사용하겠다는 속성을 설정해줘야 통신이 가능

클라이언트 Ajax 요청시 XMLHttpRequest.withCredentials 속성 설정

CORS(Cross-Origin Resource Sharing) 요청시 Client에서 XMLHttpRequest.withCredentials 속성을 true 로 설정을 해야합니다.

  • 요청을하기 전에 withCredentials가 true로 설정되어 있지 않으면 다른 도메인의 XMLHttpRequest가 자신의 도메인에 대한 쿠키 값을 설정할 수 없음
  • withCredentials를 true로 설정하여 얻은 타사 쿠키는 여전히 동일한 출처 정책을 준수하므로 document.cookie 또는 응답 헤더를 통해 요청하는 스크립트에서 액세스 할 수 없음
1
2
3
4
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);

서버 응답 헤더에 Access-Control-Allow-Credentials 속성 설정

클라이언트 Preflight Repuest의 응답 헤더에서 Access-Control-Allow-Credentials: true 설정을 해줘야
브라우저에서 응답한 컨텐츠를 사용자에게 제공할 수 있습니다.(Get 요청은 해당되지 않음)

1
Access-Control-Allow-Credentials: true

Resource

URL, 호스트, 도메인 개념 정리

URL(Uniform Resource Locator)

URI의 하위 개념이며 컴퓨터 네트워크 상의 자원을 모두 나타낼 수 있습니다.

scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]

  • URL은 제일 앞에 자원에 접근할 방법을 정의해 둔 프로토콜 이름을 적는다. gopher, telnet, ftp, http, usenet 등이다.
  • 프로토콜 이름 다음에는 프로토콜 이름을 구분하는 구분자인 “:”을 적는다.
  • 만약 IP 혹은 Domain name 정보가 필요한 프로토콜이라면 “:” 다음에 “//“를 적는다.
  • 프로토콜명 구분자인 “:” 혹은 “//“ 다음에는 프로토콜 마다 특화된 정보를 넣는다.

예1) http://www.somehost.com/a.gif - IP 혹은 Domain name 정보가 필요한 형태 ( www.somehost.com에 있는 a.gif를 가리키고 있음 )
예2) ftp://id:pass@192.168.1.234/a.gif - IP 혹은 Domain name 정보가 필요한 형태 ( 192.168.1.234에 있는 a.gif를 가리키고 있음 )
예3) mailto:somebody@mail.somehost.com - IP정보가 필요없는 프로토콜 ( mailto 프로토콜은 단지 메일을 받는 사람의 주소를 나타냄 )

HTTP URL 분석

http://www.example.com:8080/test?search=iphone

프로토콜(Protocol) http://
호스트(Host/Hostname) www.example.com:8080
서브도메인(Subdomain) www.
도메인(Domain/Domain Name) example.com
패스(Path) /test
파라미터(Parameter) search
파라미터 값(Parameter Value) iphone

Resource