한번쯤 만들어 보고 싶다는 생각이 있었고, 소마 15기를 지원하기 전, 필요할 것 같다는 생각이 들었다.
매번 시도만 하고 끝을 맺지를 못해서 흐지부지 되었었는데, 군대에 오니 이런 건 좋은 것 같다.
밖에서는 이런 걸 하지 않아도 무언가를 계속 할 수 있지만, 여기서는 이런 것 밖에 할 게 없다.
처음엔 단순히 Chris Yang의 포트폴리오를 클론하는 것에서 출발했다.
오랜만에 코딩을 해서 재미는 있었지만, 이 뭔가 해결되지 않은 찝찝함이 있었다.
그래서 대본은 완성되었으니, 여기에 이것저것 추가해보았다.
해소가 되지 않았다. 생각을 다시 정리했다.
그러던 중 Alluring Entities(Ali Zafar Iqbal)을 발견했다.
내가 딱 원하던 분위기라고 생각하여 디자인에 들어갔다.
큐브는 다음과 같은 효과를 넣어 주었고, 바닥에 비치는 빛은 따로 타원으로 만들어 주었다.
3d객체를 사용할까 생각도 했지만, 2d로 충분히 표현 가능할 것 같다고 생각했다.
이제, 다음 페이지를 만들었다.
생각한 인터랙션은 다음과 같았다.
interactions
이쯤에서, 이거 이대로면 재미가 없을 것 같다는 생각이 들었다.
사용자와 인터랙션할 수 있는 요소가 너무 적었다.
그래서 이런 식으로 만들어 보았다.
인터랙션은 아니지만, 무언가 넣을 수 있는 공간을 만들어 줬다.
이제, 각 페이지마다 뭐가 들어갈 지를 생각하면 될 것 같았다.
요새 핫한 Generative AI에서 영감을 받은 디자인을 만들어 보았다. 요새 OCaml에 빠져있어서 OCaml 코드를 넣었다.
추가로, GitHub 버튼을 새로 만들고, 중앙 객체는 좀 더 코드에 적합한 이미지로 대체하였다.
피그마가 가장 중요하다고 생각했고, 그래서 피그마 화면을 넣었다.
(이 페이지의 디자인도 피그마로 이루어져있다.)
중앙 객체는 alluring: 매혹적인을 추상화하려고 했고, 나쁘지 않게 들어간 것 같다.
ui 페이지에서는 아직 외부링크를 생각을 못했다.
추후에 디자인 포트폴리오를 만들면, 그게 들어갈 것 같다.
이쯤에서, 레퍼런스의 반짝거리는 효과를 따라하고 싶었다.
Noise & Texture 플러그인을 사용하여 배경에 노이즈를 추가하였다.
추가로, 사지방 모니터의 색 구현이 이상하게 되는 것 같아서, 핸드폰으로 보며 전체적인 색을 변경하였다.
무난하게 로고를 박아서 만들었다.
Musetown은 svg 로고가 나와있는게 없어서 Vectorizer를 이용했다.
SVG를 만들어줬던 Vectorizer.ai가 유료로 전환되었다.
그래서 이 글을 보고 사용해보실 분들에게는 Creative Fabrica의 무료 SVG 변환기를 추천한다.
최근에 쓴 글을 흉내내어 그림을 그렸다.
이미지는 freepik에서 받아왔는 데, 후처리가 너무 힘들었다. 어떻게 해야 이전 이미지들과 톤을 맞출 수 있을 지 많이 고민했고, 나쁘지 않게 나온 것 같다.
애니메이션에 Framer-motion을 사용하였다. 화면 전환에도 애니메이션이 필요하기 때문에 여러 모로 쓸모있는 라이브러리라 생각되어 추가하였다.
큐브가 점프하는 걸 ease
애니메이션으로 추가하고, 그에 따라 바닥의 불빛도 함께 커지고 작아지도록 만들었다.
const jumpVariants: Variants = {
jump: {
y: [0, -30],
x: [0, 0],
transition: {
duration: 0.6,
ease: ["easeOut"],
repeat: Infinity,
repeatType: "reverse",
},
},
jumpBlur: {
opacity: [1, 0.5],
scale: [1, 1.5],
transition: {
duration: 0.6,
ease: ["easeOut"],
repeat: Infinity,
repeatType: "reverse",
},
},
};
pagelayout.tsx
를 만들어 중복을 제거하려 하였다.
그런데, 다음 페이지 화살표와 이전 페이지 화살표를 만드는 과정에서 문득 ts-pattern
이 생각났다.
바로 다음과 같이 적용해보았다.
import Link from "next/link";
import { P, match } from "ts-pattern";
interface ArrowsProps {
next?: string;
prev?: string;
}
const Arrows = ({ next, prev }: ArrowsProps) =>
match({ next, prev })
.with({ next: undefined, prev: P.string }, ({ next, prev }) => (
<span className="arrow-l fixed block bg-gradient-to-b from-[#F1EFB4] to-[#F2C783] text-transparent bg-clip-text mt-auto mb-auto font-alphapipe text-6xl drop-shadow-[0_0_4px_rgba(255,160,0,1)] select-none">
<Link href={prev}>{"<"}</Link>
</span>
))
.with({ next: P.string, prev: undefined }, ({ next, prev }) => (
<span className="arrow-r fixed block bg-gradient-to-b from-[#F1EFB4] to-[#F2C783] text-transparent bg-clip-text mt-auto mb-auto font-alphapipe text-6xl drop-shadow-[0_0_4px_rgba(255,160,0,1)] select-none">
<Link href={next}>{">"}</Link>
</span>
))
.with({ next: P.string, prev: P.string }, ({ next, prev }) => (
<>
<span className="arrow-l fixed block bg-gradient-to-b from-[#F1EFB4] to-[#F2C783] text-transparent bg-clip-text mt-auto mb-auto font-alphapipe text-6xl drop-shadow-[0_0_4px_rgba(255,160,0,1)] select-none">
<Link href={prev}>{"<"}</Link>
</span>
<span className="arrow-r fixed block bg-gradient-to-b from-[#F1EFB4] to-[#F2C783] text-transparent bg-clip-text mt-auto mb-auto font-alphapipe text-6xl drop-shadow-[0_0_4px_rgba(255,160,0,1)] select-none">
<Link href={next}>{">"}</Link>
</span>
</>
))
.otherwise(() => <></>);
export default Arrows;
약간 못생겼지만, 만족스러웠다..!
PageLayout
컴포넌트를 활용하여 다른 이미지들을 아래처럼 찍어낼 수 있었다.
"use client";
import PageLayout from "@/components/pagelayout";
import writeImg from "$/write.svg";
import velogImg from "$/velog-big.svg";
export default function BlogPage() {
return (
<PageLayout
innerText="I love to write what i learned on my <span class='bg-gradient-to-b from-[#F1EFB4] to-[#F2C783] text-transparent bg-clip-text drop-shadow-[0_0_4px_rgba(255,160,0,1)]'>blog</span>."
MainObject={velogImg}
SmallObject={writeImg}
next="/sns"
prev="/intern"
/>
);
}
이쯤 되었을 때, 기존 디자인이 너무 물렸다.
너무 요소가 많았고, 모든 항목을 보는 것이 너무 불편했으며, 쓰잘데기 없는 디자인이 거슬렸다.
가장 후회했던 건 Next.js이다.
나는 Next.js를 고집하고 있었다. 내가 Next.js를 못 쓰기 때문에, 하면서 공부가 될 거라고 생각했다.
그런데 너무 거슬렸다. 나는 간단한 애니메이션을 구현하고 싶은데, 자꾸 써야할 코드가 많아졌다.
굳이 고집할 이유가 없다고 생각했고, React SPA를 만들기로 했다.
React를 선택한 이유는, 내가 React를 사용할 때 생산성이 가장 좋다고 느꼈기 때문이다.
시간이 부족하다. 언제까지고 프로필 웹사이트에 시간을 쏟을 수 없다.
최대한 간단하게 다시 디자인을 시작했다.
다음 화에 계속 ...
잘 읽었습니다. 좋은 정보 감사드립니다.