간단 정리

shallowCopy ( 얕은 복사 - 기본값 ) : 단순 변수는 복사되고

        오브젝트/배열에 대해서는 같은 메모리를 사용         (값을 바꾸면 기존 오브젝트/배열 값도 같이 바뀜)

 

deepCopy ( 깊은 복사 ) : 오브젝트/배열을 새로운 메모리에 할당    (값을 바꿔도 기존 오브젝트/배열 값과 무관)

 

간단한 얕은 복사 예시..

  const zzz = [123, 456, 789];
  const xxx = zzz; //같은 메모리 참조

  zzz[0] = 66; //xxx[0]도 66
  xxx[1] = 876; //zzz[1] 도 876

  console.log(zzz, xxx); 
// zzz = [66, 876, 789],     xxx = [66, 876, 789]  운명을 함께..

 

 

 _ (lodash) 라는 좋은 라이브러리가 있습니다만 직접 구현해봤습니다. (왜 이런거에 관심이 있으까..ㅋ)

 

origin 과 shallow은 서로 값에 영향. deepcopy는 값 영향 x

 

 

const DeepCopy = (target) => {
  //단순 변수는 그냥 반환
  if (!(target instanceof Object)) {
    return target;
  }

  //배열인 경우는 배열 순회 후 반환
  if (Array.isArray(target)) {
    let arr = [];

    for (let i = 0; i < target.length; ++i) {
      arr.push(DeepCopy(target[i]));
    }

    return arr;
  }

  let newValue = {};
  //오브젝트 형태인 경우 모든 키에 대해 순환 후 반환
  for (let key of Object.keys(target)) {
    if (target[key] instanceof Object) {
      // console.log("key : ", key, "target[key] : ", target[key]);
      if (Array.isArray(target[key])) {
        let arr = [];

        for (let i = 0; i < target[key].length; ++i) {
          arr.push(DeepCopy(target[key][i]));
        }

        newValue = {
          ...newValue,
          [key]: arr,
        };
      } else {
        newValue = {
          ...newValue,
          [key]: DeepCopy(target[key]),
        };
      }
    } else {
      // console.log("key : ", key, "target[key] : ", target[key]);
      newValue = { ...newValue, [key]: target[key] };
    }
  }

  return newValue;
};

const DeepCopyTest = () => {
  const origin1 = {
    a: 123,
    target: {
      b: 456,
      target2: [
        {
          c: 789,
          x: [123, 456, 789],
        },
      ],
    },
  };

  const shallowCopy1 = origin1;
  const deepCopy1 = DeepCopy(origin1);

  shallowCopy1.a = 3;
  origin1.target.target2[0].c = 54;
  origin1.target.target2[0].x[0] = 11111;
  origin1.target.b = 88;

  console.log("origin 1 : ", origin1);
  console.log("shallowCopy 1 : ", shallowCopy1);
  console.log("deepcopy 1 : ", deepCopy1);

  const origin2 = [
    {
      v1: 12,
    },
    {
      v2: 56,
      v3: [
        {
          v4: 123,
        },
        123123123123,
      ],
    },
  ];

  const shallowCopy2 = origin2;
  const deepCopy2 = DeepCopy(origin2);

  origin2[0].v1 = 43666;
  origin2[1].v3[0].v4 = 88;
  origin2[1].v3[1] = 543;

  console.log("origin 2 : ", origin2);
  console.log("shallowCopy 2 : ", shallowCopy2);
  console.log("deepcopy 2 : ", deepCopy2);

  return <></>;
};

export default DeepCopyTest;

window.open,

window.addEventListener

window.opener.postMessage

를 통해 아래와 같이 페이지 간 메시지를 주고 받을 수 있습니다.







 

 

부모 페이지 (window.open 호출)

import { useEffect, useState } from 'react';

const PostMessageExample = () => {
  const [msg, setMsg] = useState([]);

  useEffect(() => {
    //다른 웹 페이지를 띄웁니다.
    const w = window.open(
      'http://172.18.144.1:3001',
      'popup',
      'width=500, height=500'
    );

    const listen = (message) => {
      console.log('받은 메시지 : ', message);
      if (message?.data?.msg) {
        setMsg((prev) => {
          return [...prev, message.data.msg];
        });
      }

      //메시지가 종료 플래그면 이벤트를 제거해줍니다.
      if (message?.data?.msg === 'end bye!') {
        console.log('이벤트 제거!');
        window.removeEventListener('message', listen);
      }
    };

    window.addEventListener('message', listen, false);

    //윈도우 닫히는 것을 확인합니다.
    //메시지를 통해서도 제어 가능!
    const timer = setInterval(() => {
      if (w.closed) {
        clearInterval(timer);
      }
    }, 1000);

    return () => {
      console.log('메시지 및 타이머 제거!!');
      if (timer) {
        clearInterval(timer);
      }
      window.removeEventListener('message', listen);
    };
  }, []);

  return (
    <div>
      <div>
        <div>
          {msg.map((item, idx) => {
            return <div key={idx}>{item}</div>;
          })}
        </div>
      </div>
    </div>
  );
};

export default PostMessageExample;

 

 

open 되는 페이지 (window.opener를 통해 open한 곳에 값 전달)

import { useEffect, useState } from 'react';

const Home = () => {
  const [input, setInput] = useState('');

  useEffect(() => {
    //윈도우가 종료 될 때 메시지를 보냅니다.
    window.onbeforeunload = () => {
      //*는 CORS의 origin 에 대한 값
      window.opener.postMessage({ msg: 'end bye!' }, '*');
    };
  }, []);

  return (
    <div>
      <div>
        <input
          type="text"
          value={input}
          onChange={(e) => {
            setInput(e.target.value);
          }}
        />
        <button
          onClick={() => {
            window.opener.postMessage({ msg: input }, '*');
            setInput('');
          }}
        >
          보내기
        </button>
      </div>
    </div>
  );
};

export default Home;

'React > 문법' 카테고리의 다른 글

[React] DeepCopy 직접 구현 (깊은 복사)  (1) 2023.12.30
[Crypto-js] AES256 사용 방법  (0) 2023.10.31

[모듈 없을 시 설치]

npm install crypto-js

 

import crypto from 'crypto-js';
import { useState } from 'react';

const CryptoAES256 = () => {
  const [encrypt, setEncrypt] = useState('');
  const [decrypt, setDecrypt] = useState('');

  const Go = () => {
    const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456'; //32자리

    const initVector = key.substr(0, 16); //16자리

    const dataObject = {
      value1: 'v1',
      value2: 'v2',
      value3: 'v3',
    };

    const data = JSON.stringify(dataObject);
    console.log(data);

    //암호화
    let cipher = crypto.AES.encrypt(data, crypto.enc.Utf8.parse(key), {
      iv: crypto.enc.Utf8.parse(initVector),
      padding: crypto.pad.Pkcs7,
      mode: crypto.mode.CBC,
    });

    console.log('Encrypt cipher : ', cipher);
    const encryptResult = cipher.toString();
    setEncrypt(encryptResult);

    //복호화
    cipher = crypto.AES.decrypt(encryptResult, crypto.enc.Utf8.parse(key), {
      iv: crypto.enc.Utf8.parse(initVector),
      padding: crypto.pad.Pkcs7,
      mode: crypto.mode.CBC,
    });

    console.log('Decrypt cipher : ', cipher);
    const decryptResult = cipher.toString(crypto.enc.Utf8); //★복호화 후 인코딩 지정!
    setDecrypt(decryptResult);
  };

  return (
    <div>
      <div>
        <button onClick={Go}>암/복호화</button>
        <div>암호화 : {encrypt}</div>
        <div>복호화 : {decrypt}</div>
      </div>
    </div>
  );
};

export default CryptoAES256;

 

클라이언트/서버 대칭 키 알고리즘입니다. (암/복호화에 같은 키 사용)

사용할 일이 있어 간단히 정리해봅니다.

 

AES ( Advanced Encryption Standard ) 128, 192, 256  숫자는 bit를 의미하며 key의 길이가 결정 됩니다.

128 = 128 / 8 = 16 (byte)

192 = 192 / 8 = 24 (byte)

256 = 256 / 8 = 32 (byte)

 

mode :

1. ECB (Electronic Code Block) : 각 블록 단위 별개로 나눠서 암호화.

2. CBC (Cipher Block Chaining) : 앞 뒤 값에 대해 XOR 연산하여 모든 블록이 연관 (iv 개념 필요!)

 

iv (Initialize Vector) : CBC에서 첫 자리에 대해 XOR 연산을 할 값을 의미합니다. (길이가 맞아야 합니다.)

 

padding : 부족한 값 채우는 방식

+ Recent posts