푸하하
이력서 멘토링 기간이 끝나고, 최종 과제로 10개 기업에 지원했습니다. 이력서는 원티드를 통해서 제출했구요.
가능하면 회사 홈페이지로 직접 지원하려고 했는데, 회사 홈페이지 지원 루트에서는 신입을 뽑지 않는다고 되어있거나, 회사 홈페이지에 지원공고가 없거나 등등 예외상황이 많았습니다.
그리고 어제 밤에 제출하고 오늘 아침에 4개 불합격이에요! 아마 나머지 6개도 내일, 모레 중으로 불합격 연락을 받아볼 수 있을 것 같습니다. 앞으로 한 5천번정도 떨어질 것 같은데 그 중에 첫 4번의 불합격이에요!
제가 지원한 기업들의 이름을 밝히기엔 아무래도 쪼끔 그렇고... 전체적인 기조만 적어두자면
등의 공통점이 있었습니다. 이렇게 늘어놓고 보니 꽤나 당연하게 느껴지는 요구사항들인데요, 조금 주제넘게 말하면 '그나마 만만해보이는' 공고만 골라서 지원했어요. 리액트든 타입스크립트든 잘은 모르지만 다뤄본 경험은 있고, 상태관리도 어찌어찌 해봤고... Next.js를 요구하는 회사들이 생각보다 많아서 놀랐는데, 아예 접해본 적이 없는 프레임워크라 지원할 엄두가 안났습니다.
에 대한 분석이 필요한 시점이라고 생각합니다. 서류 탈락인 건 서류의 문제가 크겠죠... 이력서 멘토링을 받으면서 자기소개나 스택, 경험 등을 다듬어 작성하긴 했지만 기본적인 내용이 부실하면 좋은 이력서라고 할 수 없겠죠? 누워서 천장 보면서 생각해보니, 아마 이런 문제점들이 있지 않나 하는 생각입니다.
한 마디로 정리해보자면, '할 일 없어서 개발 배우겠다고 슬쩍 부트캠프 발 담궈놓고 이제 수료했으니 취직 되겠지? 하고 대충 지원 넣어본 멍청이' 티가 너무 나는 이력서라서 떨어진 것 같습니다.
총체적 난국입니다. 일단은 해야 할 일을 해야겠죠...
결국은 정신론이네요... 하지만 이런 케케묵은 정신론이라도 들먹여야 해결이 가능할 것 같은 상황입니다. 제 살 깎아먹으며 버틸 수 있는 시간이 얼마 남지 않았는데 할 일은 산더미처럼 많으니까요.
그래도 일기는 열심히 쓰네요 허허
내일은 좀 더 열심히 하겠습니다
정말 멋진 포트폴리오를 찾아서 레퍼런스 삼아 구현해보고 싶은 마음이 들었습니다. 완전히 표절하겠다는 건 아니고 (어차피 못함), 그 중에서 인상깊었던 부분 딱 하나만 따오려는 겁니다. 그게 웹 페이지 전체에 적용된 필름 그레인 효과였는데요, 왠지 모르겠는데 예쁘더라구요. 저는 큰 쓸모 없이 예쁜 걸 정말 좋아합니다.
해당 포트폴리오 구현 코드는 공개되어있지 않아서, 웹을 떠돌면서 필름그레인 효과를 구현할 수 있는 방법을 찾아봤습니다.
grained.js라는 라이브러리가 있어서 다운받아서 이용해봤습니다.
그레인 효과를 여러가지로 커스터마이징할 수 있는 부분이 마음에 들었는데, 튜토리얼에 나와있는 대로 적용해보니 폰트, 이미지 등의 요소는 그레인이 적용되지 않고 배경에만 그레인이 적용된 채로 출력되는 게 아쉬웠습니다.
다른 라이브러리는 없나? 이걸 필요하다고 생각한 사람이 전 세계에 나뿐인가? 하면서 계속 찾아봤습니다. 아니더라구요. 코드펜에서 좋은 예시를 찾을 수 있었어요! js로 노이즈를 생성해서 캔버스에 띄우는 (솔직히 아직 잘 이해 안감) 식으로 필름 그레인을 구현할 수 있었는데, 노이즈 입자가 너무 굵어서 눈이 아프길래 함수 여기저기를 만져보면서 입자를 가늘게 수정해보았습니다.
const createNoise = () => {
const idata = ctx.createImageData(wWidth, wHeight);
const buffer32 = new Uint32Array(idata.data.buffer);
const len = buffer32.length;
for (let i = 0; i < len; i++) {
if (Math.random() < 0.5) {
buffer32[i] = 0xff000000;
} //여기서 0.5를 0.1로 줄여줬어요! 뭐하는 부분인지는 솔직히 아직 잘 모르겠어요!
}
noiseData.push(idata);
};
이렇게 바꾼 후에, 해당 코드를 react custom hook으로 바꿔서 useGrain이라는 훅을 만들어 보았습니다.
import { useEffect, useRef } from "react";
const createNoise = (
ctx: CanvasRenderingContext2D,
wWidth: number,
wHeight: number
): ImageData => {
const iData = ctx.createImageData(wWidth, wHeight);
const buffer32 = new Uint32Array(iData.data.buffer);
const len = buffer32.length;
for (let i = 0; i < len; i++) {
if (Math.random() < 0.1) {
buffer32[i] = 0xff000000;
}
}
return iData;
};
export const useGrain = () => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current!;
const ctx = canvas.getContext("2d")!;
let noiseData: ImageData[] = [];
let frame = 0;
let loopTimeout: number;
const paintNoise = () => {
if (frame === 9) {
frame = 0;
} else {
frame++;
}
ctx.putImageData(noiseData[frame], 0, 0);
};
const loop = () => {
paintNoise();
loopTimeout = window.setTimeout(() => {
requestAnimationFrame(loop);
}, 1000 / 25);
};
const setup = () => {
const wWidth = window.innerWidth;
const wHeight = window.innerHeight;
canvas.width = wWidth;
canvas.height = wHeight;
noiseData = [];
for (let i = 0; i < 10; i++) {
noiseData.push(createNoise(ctx, wWidth, wHeight));
}
clearTimeout(loopTimeout);
loop();
};
const handleResize = () => {
clearTimeout(loopTimeout);
setup();
};
setup();
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
clearTimeout(loopTimeout);
};
}, []);
return canvasRef;
};
전문을 이렇게 길게 공유해도 되나 싶긴 하지만...
아무튼 App.tsx에서 아래와 같이 불러와서 연결해주었어요.
function App() {
const canvasRef = useGrain();
return (
<>
<canvas
ref={canvasRef}
className="absolute top-0 left-0 w-full h-full z-10 opacity-5 pointer-events-none"
/>
<Routes>
.
.
.
</Routes>
</>
);
}
canvas의 css는 테일윈드로 바꿔주었구요. 이거 제가 코드를 다 이해하고 있어서 멋지게 설명해주면 되게 좋을텐데... 이게 어떤 방식으로 되는 건지는 아직 공부중입니다. 나중에 알게 되면 업데이트하겠습니다.
아무튼 두 가지를 테스트해보았습니다
1. App에다 canvas를 만들어두면 하위의 모든 루트에서도 적용이 되는지 => yes
2. 하위 루트 내에 canvas를 적용하면 상위 루트나 등위의 다른 루트에서는 적용이 되는지 => yes
3. 컴포넌트가 언마운트될 때 이벤트가 제거되는지 => yes
를 여기에서 테스트해보았고, Vite+React+Ts라는 동일한 환경에서 잘 작동하는 걸 확인한 후에 포트폴리오 앱에 적용했습니다! 여기서 볼 수 있어요
자세히 보지 않으면 그레인 효과가 잘 안보일 수도 있는데, 그게 더 예쁘다고 생각해서 보일듯 말듯 고운 입자로 적용했습니다.
뭐라도 하니까 좋네요! 다음엔 좀 더 쓸모있는 걸 해야겠어요