Skip to content

Conversation

@sepowered
Copy link
Member

No description provided.

- Add BackButton, Footer, and Recommend components to project pages
- Replace text logo with SymbolIcon in Header and Sidebar
- Add new project content (Millie Renewal)
- Update redirects in next.config.ts
- Fix lint errors
…and integrate them into a new contact buttons component.
…d links on the about page, populating the certificate section.
@coauthors
Copy link

coauthors bot commented Dec 2, 2025

People can be co-author:

Candidate Reasons Count Add this as commit message
@sepowered #77 1 Co-authored-by: sepowered <8400920+sepowered@users.noreply.github.com>

@netlify
Copy link

netlify bot commented Dec 2, 2025

Deploy Preview for semantic-template failed. Why did it fail? →

Name Link
🔨 Latest commit 535765e
🔍 Latest deploy log https://app.netlify.com/projects/semantic-template/deploys/692ea0590f9d160008d3d566

@gemini-code-assist
Copy link

Summary of Changes

Hello @sepowered, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 블로그의 기술 스택을 Gatsby.js에서 Next.js로 전환하고, 개인 포트폴리오를 체계적으로 보여줄 수 있는 'Projects' 섹션을 도입하여 블로그의 전반적인 기능과 사용자 경험을 크게 향상시키는 것을 목표로 합니다. Cloudflare R2를 활용한 이미지 및 파일 관리 시스템을 구축하여 성능과 보안을 강화했으며, 새로운 UI 컴포넌트와 상세한 'About' 페이지를 통해 방문자에게 더욱 풍부하고 인터랙티브한 정보를 제공합니다.

Highlights

  • 블로그 플랫폼 마이그레이션 및 포트폴리오 강화: Gatsby.js 기반의 블로그를 Next.js로 성공적으로 마이그레이션하여 성능을 개선하고, 개인 포트폴리오를 효과적으로 보여줄 수 있는 'Projects' 섹션을 새롭게 추가했습니다.
  • Cloudflare R2를 활용한 이미지 및 파일 관리: 블로그 이미지 및 프로젝트 파일 다운로드에 Cloudflare R2를 통합하여 이미지 로딩 성능을 최적화하고, 보안이 강화된 파일 다운로드 기능을 제공합니다.
  • UI/UX 및 기능 개선: 새로운 히어로 섹션, 상세한 'About' 페이지, Channel.io 연동, 토스트 알림 시스템 등 사용자 경험을 향상시키기 위한 다양한 UI/UX 컴포넌트와 기능을 추가했습니다.
  • 디자인 및 개발 스택 업데이트: shadcn/ui, Lucide 아이콘, Tailwind CSS 유틸리티 등 최신 프론트엔드 기술 스택을 도입하고, 다양한 디자인 및 개발 도구 아이콘을 추가하여 기술 역량을 시각적으로 표현했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이번 PR은 홈 화면에 히어로 영역을 추가하는 것 이상의 많은 변경 사항을 포함하고 있네요. 프로젝트 포트폴리오 기능 추가, 블로그 콘텐츠 마이그레이션, 전반적인 사이트 구조 리팩터링 등 대규모 업데이트가 이루어졌습니다. 제목이 이러한 변경 범위를 충분히 반영하지 못하는 점은 아쉽지만, 새롭게 추가된 프로젝트 필터링 기능과 전체적인 디자인 개선은 매우 인상적입니다. 몇 가지 기술적인 개선점과 오타 수정을 제안드립니다.

Comment on lines +84 to +112
<a
href="#"
className="relative overflow-hidden flex-1 flex items-center justify-center gap-2 px-4 py-3 hover:brightness-95 transition-all border-l border-b border-r border-t-0 border-[rgba(0,0,0,0.03)] rounded-none tablet:rounded-bl-[0.875rem] shadow-[inset_0_-0.125rem_0.125rem_rgba(255,255,255,0.3)]"
style={{
backgroundColor: PROFILE.cardBackgroundColor,
color: PROFILE.contentTextColor,
}}
>
<div className="absolute inset-0 bg-white/20 pointer-events-none" />
<div className="relative z-10 flex items-center gap-2">
<DownloadIcon size={20} />
<span className="font-medium">이력서 다운로드</span>
</div>
</a>
<a
href="#"
className="relative overflow-hidden flex-1 flex items-center justify-center gap-2 px-4 py-3 hover:brightness-95 transition-all border-l border-b border-r border-t-0 tablet:border-l-0 border-[rgba(0,0,0,0.03)] rounded-b-[0.875rem] tablet:rounded-bl-none tablet:rounded-br-[0.875rem] shadow-[inset_0_-0.125rem_0.125rem_rgba(255,255,255,0.3)]"
style={{
backgroundColor: PROFILE.cardBackgroundColor,
color: PROFILE.contentTextColor,
}}
>
<div className="absolute inset-0 bg-white/20 pointer-events-none" />
<div className="relative z-10 flex items-center gap-2">
<DownloadIcon size={20} />
<span className="font-medium">자기소개서 다운로드</span>
</div>
</a>
</div>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

이력서 및 자기소개서 다운로드 링크가 현재 작동하지 않습니다. href 속성이 "#"로 설정되어 있고, 클릭 이벤트 핸들러가 구현되어 있지 않습니다. 새로 추가된 FileDownload 컴포넌트를 활용하여 R2 등에서 파일을 다운로드하는 기능을 구현하는 것을 고려해보세요.

@@ -0,0 +1,78 @@
'use client';

// @ts-expect-error - LogoLoop is JSX

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

@ts-expect-error 주석은 타입 에러를 무시하기 위해 사용되지만, 장기적인 유지보수 관점에서 좋지 않습니다. logo-loop.jsx 파일을 타입스크립트 파일(.tsx)로 변환하여 타입 정의를 추가하고, 이 주석을 제거하는 것을 권장합니다. 이렇게 하면 타입 안정성을 높이고 코드의 신뢰성을 향상시킬 수 있습니다.

Comment on lines +39 to +53
.sort((a, b) => {
if (sortOption === 'recommended') {
if (a.order !== undefined && b.order !== undefined) return a.order - b.order;
if (a.order !== undefined) return -1;
if (b.order !== undefined) return 1;
return dayjs(a.createdAt).isAfter(dayjs(b.createdAt)) ? -1 : 1;
}
if (sortOption === 'newest') {
return dayjs(a.createdAt).isAfter(dayjs(b.createdAt)) ? -1 : 1;
}
if (sortOption === 'alphabetical') {
return a.title.localeCompare(b.title);
}
return 0;
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

프로젝트 정렬 로직이 src/app/projects/page.tsx 파일에도 중복으로 존재합니다. 코드 중복을 피하고 유지보수성을 높이기 위해 이 정렬 로직을 별도의 유틸리티 함수로 분리하여 두 곳에서 모두 재사용하는 것을 권장합니다.

Comment on lines +10 to +113
const DownloadButton = ({
children,
href,
type = 'default',
...props
}: ComponentProps<'a'> & { type?: 'default' | 'pdf' }) => {
const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
if (isLoading) {
const timer = setTimeout(() => {
setIsLoading(false);
if (href) window.open(href, '_blank');
}, 400);

return () => clearTimeout(timer);
}
}, [isLoading, href]);

const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
if (!isLoading) {
setIsLoading(true);
}
};

return (
<a
href={href}
onClick={handleClick}
className="flex items-center justify-center w-full tablet:w-fit px-4 py-3 border border-[var(--color-border)] rounded-xl bg-[var(--color-background)] hover:bg-[var(--color-gray-hover)] transition-colors duration-200 cursor-pointer no-underline relative overflow-hidden min-h-[52px] min-w-[280px]"
{...props}
>
{/* Default Content - Keeps height fixed */}
<div
className={`flex items-center justify-between w-full gap-3 transition-opacity duration-200 ${
isLoading ? 'opacity-0' : 'opacity-100'
}`}
>
<div className="flex items-center gap-2">
<span className="text-xl">{type === 'pdf' ? '📄' : '📎'}</span>
<span className="font-medium text-[var(--color-gray-bold)]">{children}</span>
</div>
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="text-[var(--color-gray-mid)]"
>
<path
d="M3.64645 11.3536C3.45118 11.1583 3.45118 10.8417 3.64645 10.6465L10.2929 4L6 4C5.72386 4 5.5 3.77614 5.5 3.5C5.5 3.22386 5.72386 3 6 3L11.5 3C11.7761 3 12 3.22386 12 3.5L12 9C12 9.27614 11.7761 9.5 11.5 9.5C11.2239 9.5 11 9.27614 11 9L11 4.70711L4.35355 11.3536C4.15829 11.5488 3.84171 11.5488 3.64645 11.3536Z"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
/>
</svg>
</div>

{/* Loading Overlay */}
<AnimatePresence>
{isLoading && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
className="absolute inset-0 flex items-center justify-center gap-3 bg-[var(--color-background)]"
>
<div className="relative w-5 h-5 animate-spin">
<svg className="w-full h-full" viewBox="0 0 24 24">
<circle
className="text-[var(--color-border)]"
strokeWidth="3"
stroke="currentColor"
fill="transparent"
r="10"
cx="12"
cy="12"
/>
<circle
className="text-[var(--color-primary)]"
strokeWidth="3"
strokeDasharray={15}
strokeDashoffset={15}
strokeLinecap="round"
stroke="currentColor"
fill="transparent"
r="10"
cx="12"
cy="12"
/>
</svg>
</div>
<span className="font-medium text-[var(--color-gray-bold)] text-sm">
파일을 여는 중이에요...
</span>
</motion.div>
)}
</AnimatePresence>
</a>
);
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

DownloadButton 컴포넌트가 파일 내에서 정의되었지만, 실제로는 사용되지 않는 것으로 보입니다. 사용하지 않는 코드는 혼란을 줄 수 있으므로 제거하는 것이 좋습니다. 만약 나중에 사용할 계획이라면, 그 목적을 주석으로 명시해두는 것이 좋겠습니다.

생성형 인공지능은 기존의 제품과 다른 상호작용 방식을 사용합니다. 제가 느끼는 가장 큰 차이는 기존의 제품은 내가 정보를 탐색해야 한다면, 생성형 인공지능을 사용하게 되면 그러한 기능을 사용자가 아닌 제품 스스로가 수행하게 된다는 점입니다.
![create](./difference-generativeai-with-search.png)

Google와 같은 검색엔진에서 정보를 찾기 위해서는 여러 웹사이트를 직접 돌아가면서 **나에게 적합한 정보인지 판단하고, 아닌 경우에는 다시 찾는** 작업을 나 지신이 수행해야합니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

오타가 있습니다. '나 지신이'는 '나 자신이'의 오타인 것 같습니다.

Google와 같은 검색엔진에서 정보를 찾기 위해서는 여러 웹사이트를 직접 돌아가면서 **나에게 적합한 정보인지 판단하고, 아닌 경우에는 다시 찾는** 작업을 나 자신이 수행해야합니다.


![gh-push-blodked](./gh-push-blocked.jpeg)

그리고 이것을 시도하면 GitHub 차원에서 막습니다. 깃허브를 제외하고도 토큰은 정말 비밀번호 같은 것이기에 AWS의 권한이 탈취뒤어서 보지도 못한 스팟 인스턴스가 무수히 생기고 코인을 채굴하는 피해가 생기는 등... 수많은 사람들이 토큰을 올리다 흘린 눈물이 저를 살리게 된것입니다. 전세계 개발자분들께 감사 드립니다.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

오타가 있습니다. '탈취뒤어서'는 '탈취되어서'가 올바른 표현이며, '된것입니다'는 '된 것입니다'로 띄어쓰기를 수정하는 것이 자연스럽습니다.

그리고 이것을 시도하면 GitHub 차원에서 막습니다. 깃허브를 제외하고도 토큰은 정말 비밀번호 같은 것이기에 AWS의 권한이 탈취되어서 보지도 못한 스팟 인스턴스가 무수히 생기고 코인을 채굴하는 피해가 생기는 등... 수많은 사람들이 토큰을 올리다 흘린 눈물이 저를 살리게 된 것입니다. 전세계 개발자분들께 감사 드립니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant