TIL - Day2_2

정태호·2023년 6월 5일

TIL

목록 보기
3/23

정규표현식

목적

  • 문자 검색(Search)
  • 문자 대체(replace)
  • 문자 추출(extract)

성능은?

  • 엄청 느리다.. 하지만 너무 편하다..

연습이 필요할 땐?
https://rubular.com/
https://regexone.com/

휴대폰 번호를 찾아보자!

이메일에서 @만 빼고 찾아보자!

  • .+ -> 한 개 이상의 문자열, (...) -> 캡처

JS에서의 사용방법

  • JS는 RegExp 객체로 정규표현식 기능을 제공한다.
  • 배열이나 객체처럼 Literal로 생성 가능하다.
//new RegExp(표현식)
const regexp1 = new RegExp("^\d+");
//new RegExp(표현식,플래그)
const regexp2 = new RegExp("^\d+","gi");

//리터럴 방식
// /표현식/
const regexp1 = /^\d+/;
// /표현식/플래그
const regexp2 = /^\d+/gi;

test

  • 입력받은 문자열에 찾는 패턴이 있는지 찾은 후 있으면 true, 없으면 false
const message = "안녕하세요. 010-1234-5678로 전화주세요!"
const message1 = "안녕하세요. 반갑습니다."

const regExp = /\d{3}-\d{4}-\d{4}/;

console.log(regExp.test(message)); //true
console.log(regExp.test(message1)); //false

exec

  • 입력받은 문자열에 찾는 패턴이 있는지 찾은 후 일치한 패턴 정보를 반환하고 없으면 null을 반환(문자 추출)
const message = "안녕하세요. 010-1234-5678로 전화주세요!"
const message1 = "안녕하세요. 반갑습니다."

const regExp = /\d{3}-\d{4}-\d{4}/;

console.log(regExp.exec(message));
console.log(regExp.exec(message1));

match

  • String 객체의 match 함수는 정규표현식 객체를 파라미터로 받아 패턴 확인 후 일치한 패턴 정보를 반환하고 없으면 null 반환. > exec와 비슷
  • matchAll은 매칭된 모든 케이스를 반환
const message = "안녕하세요. 010-1234-5678로 전화주세요!"
const message1 = "안녕하세요. 반갑습니다."

const regExp = /\d{3}-\d{4}-\d{4}/;

console.log(message.match(regExp));
console.log(message1.match(regExp));

replace

  • 패턴 확인 후 일치한 패턴 정보를 원하는 문자열로 바꿀 수 있다.(문자 대체)
const message = "안녕하세요. 010-1234-5678로 전화주세요!"
const message1 = "안녕하세요. 010-1234-5678말고 010-7890-4561로 전화주세요!";

const regExp = /\d{3}-\d{4}-\d{4}/;

console.log(message.replace(regExp,"전화번호"));
console.log(message1.replace(regExp,"전화번호"));
//모두 바꾸기
console.log(message1.replace(/\d{3}-\d{4}-\d{4}/g,"전화번호"));
//안녕하세요. 전화번호로 전화주세요!
//안녕하세요. 전화번호말고 010-7890-4561로 전화주세요!
//안녕하세요. 전화번호말고 전화번호로 전화주세요!
  • 패턴 확인 후 일치한 패턴 정보의 (무조건 처음)위치를 반환한다. (문자 검색)

capture

  • match 반환값의 1번 인덱스부터 순차적으로 캡처 결과가 들어간다.

연습

  • \1로 첫번째 캡처를 이용하겠다는 뜻
const raw = "AAAAAABBBDFFFFFFFKK"
const compressed = "6A3B1D7F2K";

const regExp = /(.)\1*/g;

const result = raw
  .match(regExp)
  .reduce((a,b) => a + `${b.length}${b.slice(0,1)}`,"");

console.log(result); //6A3B1D7F2K
console.log(result === compressed); //true

개미수열

function ant(n){
  let answer = '1';
  // \1*은 캡처된 문자와 동일한 문자들의 반복을 의미
  let regexp = /(.)\1*/g;

  for(let i=1; i<n; i++){
    let result = answer
      .match(regexp)
      .reduce((acc,cur)=> acc + `${cur.length}${cur.slice(0,1)}`,"");
    answer = result;
  }

  return answer;
}

쿠키와 세션, 웹 스토리지

HTTP 통신

  • HTTP Request는 상태가 존재하지 않는다.(stateless)
  • 서버는 어떤 브라우저에서 요청이 온 것인지 알 수 없다.
  • 헤더에 쿠기를 담아 서버가 쿠키를 읽어 어디에서 온 것인지 알 수 있다.
  • 클라이언트에서 저장, 관리하는 데이터들. 브라우저를 닫아도 유지 가능
  • 서버에서 Set-Cookie를 응답 헤더로 내려주면 클라이언트는 받아서 저장
  • 각 상태에 수명을 정할 수 있다.
  • 키 = 값; 옵션
  • 응답 헤더에 담으면 브라우저가 알아서 저장. 여러 옵션이 존재한다.
    - Expires : 쿠키 만료 날짜 지정
    • Secure : HTTPS에서만 쿠키 전송
    • HttpOnly : JS에서 쿠키 접근 불가
    • Max-Age : 쿠키 수명. Expires는 무시됨
    • Domain : 도메인이 일치하는 요청만 쿠키 전송
    • Path : 패스와 일치하는 요청만 쿠키 전송

쿠키의 취약점

  • Cross-Site Script(XSS) 공격 당할 수 있다.
  • JS를 이용해 다른 사용자의 쿠키값을 탈취 할 수 있다.
  • 쿠키를 암호화하지 않고 서버에 보낼 경우 탈취 당할 가능성이 있다.
    - 해결책 : HTTPS

서버가 사용자를 구분하려면?

Session

  • HTTP Session Id를 식별자로 사용자 구분
  • 클라이언트는 HTTP Session Id를 쿠키 형태로 저장

세션의 문제점

  • 세션은 서버에 파일 형태로 저장되어 사용자가 많아지면 저장공간이 부족해 서버가 마비될 수 있다.

지금은? 서버/클라이언트 간 인증은 별도 토큰(JWT)을 사용하고 쿠키는 클라이언트 자체적인 지속적 데이터 관리 용도로 사용된다.

웹 스토리지

  • 쿠키 대신 로컬 데이터를 관리
  • 로컬 스토리지와 세션 스토리지가 있다.

로컬 스토리지

  • 로컬 스토리지에 데이터를 저장하면 반영구적으로 데이터가 저장된다.
  • 브라우저를 닫아도 데이터가 유지된다.
  • 저장했던 도메인과 이용하는 도메인이 다른 경우 접근 불가
  • Key-Value 형태로 저장

세션 스토리지

  • 새 창(새 탭)을 생성 시 개별적으로 저장되는 데이터를 관리한다.
  • 브라우저를 닫으면 사라진다.
  • 같은 도메인이어도 세션이 다르면 데이터에 접근할 수 없다.
  • Key-Value 형태로 저장

IndexedDB

IndexedDB란 무엇일까?

IndexedDB는 파일이나 블롭 등 많은 양의 구조화된 데이터를 클라이언트에 저장하기 위한 로우 레벨 API

  • 우리가 데이터를 저장할 때, 클라이언트 스토리지를 이용할 수 있다.
  • localStorage, cookies, indexedDB가 존재한다.

localStorage가 있음에도 IndexedDB를 사용하는 이유가 있을까?

  • localStorage
    • 적은 양의 데이터를 저장할 때 유용하다.
    • 동기적으로 작동하며 키와 값은 문자열 타입만 가능하다.
    • JSON.parse(), JSON.stringfy()가 꼭 필요하다.

  • indexedDB
    • 많은 양의 구조화된 데이터를 저장할 때 유용하다.
    • JS가 인식할 수 있는 자료형과 객체를 저장할 수 있다.
    • 키와 값이 꼭 문자열이 아니어도 된다!!
    • 비동기적으로 작동한다.

indexedDB 사용해보기

  1. 데이터베이스 열기
  2. 데이터베이스에 객체 저장소(Object store) 생성하기
  3. 트랜젝션(Transaction) 시작하기 (데이터 읽기, 쓰기, 제거 등)
  4. 이벤트 리스너를 사용해 요청이 완료될 때까지 기다리기
  5. 동작

1. open 함수로 DataBase 열기

  • 브라우저에서 여러 개의 데이터베이스를 만들 수 있다.
  • 데이터베이스는 버전 정보를 가지고 있으며, 여러 개의 객체 저장소를 가질 수 있다.
    • 데이터베이스 수정 시 버전도 수정해줘야 함!!
const indexDB = window.indexedDB

if(!indexDB) window.alert('해당 브라우저에서는 indexedDB를 제공하지 않습니다')
else{
	const request = indexDB.open('testDB')
	request.onerror = (event) => alert('실패했습니다.')
	request.onsuccess = (event) => this.result
}

2. DataBase에 객체 저장소(ObjectStore) 추가

  • ObjectStore는 데이터를 담는 공간으로 이름은 고유해야 한다.
  • 여러 개의 레코드(Key-Value)를 가진다.
  • 각 객체에 유일성을 부여하기 위해 keyPath를 정의
  • createObjectStore를 사용해 생성한다.
  • onupgradeneeded 이벤트와 함께 사용
    • 새로운 데이터베이스를 만들 때
    • 기존 데이터베이스의 버전을 높일 때
    • 해당 이벤트가 성공하면 onsuccess 핸들러가 트리거 됨!!
const indexDB = window.indexedDB

if (!indexDB) window.alert('해당 브라우저에서는 indexedDB를 제공하지 않습니다')
else {
	let db;
	const request = indexDB.open('testDB')
            
	// ObjectStore를 만들거나 수정할때 이 이벤트내에서 진행함
	request.onupgradeneeded = (e) =>{
		db = e.target.result;
		let objectStore = db.createObjectStore("username", {keyPath : "id"})
	}
	request.onerror = (e) => alert('실패했습니다.')
	request.onsuccess = (e) => db = request.result
}

3. Transaction을 시작하고 데이터 생성, 조회, 수정, 삭제 등의 작업을 요청

  • indexedDB.open 성공 시 transaction을 사용해 저장소에 데이터를 입력할 수 있다.
  • 트랜잭션은 DB의 상태를 변화시키기 위해 수행하는 작업 단위이다.
  • 데이터베이스 객체 단위로 작동하며, 사용할 객체 저장소를 지정해줘야 한다.
  • 우리는 트랜잭션을 통해, 객체 저장소에 접근하거나 데이터 요청을 할 수 있다.

생성, 조회, 수정, 삭제

profile
주니어 프론트엔드 개발자가 되고 싶습니다!

0개의 댓글