-
Notifications
You must be signed in to change notification settings - Fork 5
Day 30 개발일지 Web
HMAC을 직접 구현해보고 적용하였다..! 처음에 생성 과정을 봤을 때는 이게 뭔가 싶었는데 지금은 이해를 다 하고 있으니까 생각보다 쉽게 코드로 구현할 수 있었다. 그래서 마스터 세션에서 본 함수형 프로그래밍도 나름대로 적용해보고 재미있었던 경험이었다.
hmac.js
파일 안에 createHmac
이라는 함수를 구현하여 export하였고, 그 외에 작은 여러 함수들도 새로 만들었다. createHmac
함수는 4개의 인자를 받도록 설계했고 key
는 HMAC을 만드는데 사용할 비밀 키, data
는 해싱될 메세지, algorithm
은 적용될 알고리즘, encoding
은 HMAC 결과 문자열의 인코딩 방식을 지정한다.
exports.createHmac = ({ key, data, algorithm, encoding }) => {
그리고 이제 계산에 필요한 값들을 준비한다. 최종적으로 필요한 값들은 dataBuffer
, iKeyPad
, oKeyPad
3가지이다.
const keyBuffer = Buffer.from(key);
const dataBuffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
const targetBuffer = Buffer.alloc(MAX_KEY_BYTES, 0);
keyBuffer.copy(targetBuffer, 0, 0, keyBuffer.byteLength);
const iKeyPad = xor(targetBuffer, I_PAD);
const oKeyPad = xor(targetBuffer, O_PAD);
마지막으로 HMAC을 계산하여 만들어낸다. 이 부분에서 함수형 프로그래밍으로 해보기 위해 pipe
함수를 정의했다. pipe
함수는 전달받은 함수들을 차례대로 연결시켜주는 역할을 하게 된다. 이렇게 준비한 pipe
에 버퍼를 합치는 함수, 해시를 만드는 함수 등의 함수들을 계산 순서대로 전달하면 쉽게 계산을 할 수 있게 된다!
그리고 key
, algorithm
, encoding
조건에 따라 다른 값으로 계산을 해주기 위해서 계산과정의 함수들을 고차함수로 정의하고, 클로저를 활용하도록 했다.
const pipe = (...functions) => (arg) => functions.reduce((prev, fn) => fn(prev), arg);
return pipe(
concatBuffer(iKeyPad),
createHash({ algorithm, encoding }),
strToBuffer(encoding),
concatBuffer(oKeyPad),
createHash({ algorithm, encoding })
)(dataBuffer);
어제는 Drag, Drop 컴포넌트를 구성했다면 오늘은 데이터들의 상태를 지정하고, 컴포넌트를 띄워주고 onDrop 이벤트핸들러를 구현하여 완성하였다.
우선 어제 만들어놓은 SVG파일을 가져다가 img 태그로 만들어 Drag되는 컴포넌트를 구성해야하기 때문에 SVG파일 데이터들이 상태안에 존재해야했다.
간단하게 예시를 작성해보면
const state = {
timeStamp: [{name: timeStamp1, svg: svgTimeStampData}, ],
secretKey: [{name: secretKey2, svg: svgSecretKeyData}, ],
hmac: [],
...
Drop될 컨테이너(timeStamp, secretKey, hmac, ...)안에 Drag된 컴포넌트들이 들어있는 상태를 관리하면서 state상태가 바뀔 때 마다 리렌더링을 통해 변경된 사항들을 보여주는 방식으로 구현을 하였다.
다음으로 onDrop 함수를 구성하였는데 onDrop함수에서 가장 중요한 부분은
const originData = e.dataTransfer.getData('text');
이부분이다. e.dataTransfer.getData함수를 사용하면 Drag Event를 처리할 때 e.dataTransfer.setData에서 설정해놓은 값을 받을 수 있다. 위 코드에서 받은 originData는
이동 전 Drop컨테이너의 이름 : Drag 컴포넌트의 이름 ex) hmac: timeStamp1
이런 문자열이 들어있다.
이말은 즉 :(콜론)을 기준으로 앞뒤로 나누면 어떤 Drag컴포넌트가 어디 Drop 컨테이너에서 왔는지 알수있다는 말이다.
targetContainer.push(originContainer[idx]);
originContainer.splice(idx, 1);
때문에 위 코드와 같이 현재컨테이너에 Drag된 컴포넌트를 추가하고, 이전컨테이너에서 삭제하면 SVG img태그가 이동이 되는 것이다.
이렇게 나름 필요한 이벤트 핸들러를 구현한 것 같다는 생각이 들었다.
이제 마지막으로 어떻게 이 컨테이너들을 컴포넌트와 함께 보여줬는지 봐보자.
//StudyContainer.tsx
{Object.keys(state)
.filter((value) => value !== 'list')
.map((value) => {
return <StudyBox key={value} value={value} list={state[value]} onDrop={onDrop} />;
})}
//StudyBox.tsx
{list.map((item: any): any => {
return (
<Drag key={item.name} dataItem={`${value}:${item.name}`}>
<DragImg styles={initialArrayData[item.name]} src={item.svg} />
</Drag>
);
})}
위 코드에서 StudyContainer.tsx
에서 이전에 설명했던 state의 컨테이너들을 반복문을 통해서 순차적으로 만들어주는 것이 첫번째이다.
컨테이너들을 만들면서 <StudyBox />
컴포넌트의 Props로 value = '현재 컨테이너 이름'
, list= '현재컨테이너에 있는 컴포넌트'
를 넘겨줘서 StudyBox에서 다시 컴포넌트를 map으로 전체순회를 하며 컴포넌트를 그려주도록 하였다.
이렇게 하고나니 머릿속으로 생각만 하고 있던 페이지가 진짜 만들어졌다! ㅎㅎㅎㅎ
물론 진짜 필요한 것들만 만들어서 아쉬운 느낌은 있지만 이후에 시간이 돌아오면 버전 업그레이드 시키기위해 다시 돌아오겠다.
이전에는 어려워서 API를 사용하고 넘어갔던 부분을 직접 구현해보니 새롭고 신기했다. 이전에 했을 때는 이미 API로 잘 짜여져있어서 '내가 이걸 할 수 있나..?' 라는 생각을 갖고 두려웠던 것 같았다...
얼른 중요한 것들을 더 열심히하고 Drag & Drop 페이지를 업그레이드 시키기위해 다시 돌아오겠다 !!!
특별하게 새로운 것을 진행하지 않았고 기존에 짜여진 코드들에서 몇가지 기능을 추가하는 일을 하였다. Swagger 문서의 오류를 많이 제거하고 인증 정보 수정등을 진행하였다.
© Boostcamp