Next.js 블로그 제작기 (7)
신현호
블로그 제작기
목차
서론
#지금 듣고잇는 구름톤 트레이닝에서 학습중인게 생각보다 유용해서 그런지, 블로그 개발에 시간을 그리 많이 쓰는건 아닌데도 개발의 진척이 상당히 많이 된 것 같습니다.
아무래도 기본부터 하나씩 하다보니 몰랐던 것에 대해서 익히고 이미 알고있엇던 개념들에 대한 점검, 그리고 오개념 교정까지 할 수 있는 것 같아 이틀차인데도 만족하고 있습니다.
해당 구름톤 트레이닝에 대해서는 한 주가 끝날때마다 회고를 해볼 생각이며, 학습한 내용에 대해서도 정리할 예정입니다.
뭐 여튼 이건 블로그 포스팅이니까.. 이번에 업데이트 된 내용에 대해서 설명해보도록 하겠습니다.
변경점
#포스팅 페이지 TOC 고치기
#이전에 추가했던 사이드바 TOC는 기능 자체에는 만족했지만 뭔가 어설프다고 느꼈습니다.
근데 고치려다 든 생각이, 애초에 RootLayout에서 지정해놓은 max-width가 발목을 잡는 것 같았습니다.
이전 사이드바 TOC에서는 다음과 같은 문제가 있었습니다.
-
absolute 로 요소를 배치했기때문에 사이즈를 줄이다보면 포스트와 내용이 겹치게 됩니다.
- 물론 이러한 항목은 tailwindcss의 반응형 디자인으로 조정을 좀 해주면 되나, 저는 tailwindcss에서 지정해준 사이즈 이외에는 잘 사용하지 않습니다. (다른 요소들과 맞춰놔서 통일감이 깨지는 느낌)
-
전반적으로 시인성이 별로라고 느껴졌습니다.
- 사실 이건 비단 TOC만의 문제는 아니었는데, 아무래도 전반적인 색상이 모두 무채색이다보니 시인성이 나쁜 것 같더라구요.
-
크기를 지정하지 않아서 들쭉날쭉한 사이즈.
1번은 그렇다치고 3번은 그냥 사이즈만 지정해 주면 되는 문제였지만. 2번때문에라도 전반적인 레이아웃 변경의 고려가 필요했습니다.
그렇다고 레이아웃 변경이 어려운 것도 아니구요, 구상하는게 귀찮은거지..
근데 이 경우엔 뭐 구상하는게 어려운 문제는 아니었습니다. flex 와 grid를 적절하게 써서 배치를 해줬습니다.
그리고 여기에 이번에 CSS를 다시 공부하면서 아리까리 했던 sticky 속성을 써주면 되겠다는 생각이 들었습니다.
- position: sticky는 relative 속성처럼 동작하다, 스크롤 시 지정 지점에서 요소를 fixed 속성처럼 동작하게 합니다.
근데 sticky 속성을 지정했는데도 작동이 되지않는 문제에 맞닥뜨리게 되었습니다. 해당 내용에 대해서 추가적인 학습을 진행해본 결과 다음과 같은 사실을 알 수 있었습니다.
-
positin: sticky는 부모 요소의 overflow 속성과 잘 호환되지 않습니다.
- 부모 요소의 overflow 속성을 제거해보세요
-
top, bottom , left, right와 같은 속성을 지정해주세요
- 이 경우 sticky의 기준이 설정되지 않아 동작하지 않습니다.
-
특정 브라우저는 지원하지 않습니다.
- IE 같은거 요즘 안쓰니까 이건 패스
저의 경우는 2번의 경우였고, 요소에 top 속성을 추가하여 해결했습니다. 그리고 RootLayout에 적용되어있던 max-width를 각 페이지별로 따로 지정을 해주었습니다.
사실 layout.tsx를 따로 작성하여 해당 페이지에 적용해도 되는데, 해당 항목은 간단하기도 하고 양도 얼마 안되기때문에 그냥 page.tsx를 수정하였습니다.
페이지의 전반적인 디자인 변경
#사이트가 전반적으로 무채색으로 너무 쳐지는 것 같고 시인성도 나빠지는 것 같아 포인트 색을 추가하여 디자인을 변경하였습니다.
확실히 이전보다 더 깔끔하고 이뻐진 것 같다고 느낍니다 (매우 주관적)
특히 포스트 내부 코드 블럭을 가장 많이 수정했습니다. 겸사겸사 DOM을 공부하며 배운 navigator객체를 사용한 코드를 복사하는 기능도 추가하였습니다.
tsx
'use client'
import { ReactNode, useRef, useState } from 'react'
import {
CheckIcon,
CodeBracketIcon,
DocumentDuplicateIcon,
} from '@heroicons/react/24/outline'
interface PreComponentProps {
children: ReactNode
}
export default function PreComponent({ children }: PreComponentProps) {
const preDiv = useRef<HTMLDivElement>(null)
const [copied, setCopied] = useState(false)
const handleExit = () => {
setCopied(false)
}
const handleCopy = () => {
setCopied(true)
navigator.clipboard.writeText(preDiv.current?.textContent as string)
setTimeout(() => setCopied(false), 2000)
}
return (
<div ref={preDiv} className="group flex-col" onMouseLeave={handleExit}>
<div className="bg-ochre flex items-center justify-between rounded-t-lg pb-3 pl-4 pr-4 pt-3">
<CodeBracketIcon className="h-5 w-5 text-white" />
<div className="flex items-center justify-end gap-x-2">
<div className="h-3 w-3 rounded-full bg-red-600" />
<div className="h-3 w-3 rounded-full bg-yellow-500" />
<div className="h-3 w-3 rounded-full bg-green-600" />
</div>
</div>
<div className="relative">
<div
className={`absolute right-2 top-2 rounded-md ${!copied ? 'bg-ochre_light hover:bg-ochre' : 'bg-green-400 hover:bg-green-500'} p-2 opacity-0 transition-all duration-100 ease-in group-hover:opacity-100`}>
{!copied ? (
<DocumentDuplicateIcon
className="h-5 w-5 text-white"
onClick={handleCopy}
/>
) : (
<CheckIcon className="h-5 w-5 text-white" />
)}
</div>
<pre className="rounded-b-lg p-4 leading-4">{children}</pre>
</div>
</div>
)
}
useRef를 통해 DOM 요소를 선택하고 element의 프로퍼티인 .textContent를 사용하면 태그 사이에 존재하는 모든 텍스트를 가져올 수 있습니다.
.textContent말고 .innerText를 사용해야하는거 아니냐구요?
- .textContent는 해당 노드가 가지고 있는 텍스트 값을 그대로 읽습니다. 이 때 태그와 상관없이 가져옵니다.
tsx
<div>
안녕하세요 : <span className="hidden">안보임</span>
</div>
text
안녕하세요 : 안보임 // .textContent의 결과
span 태그가 hidden임에도 불구하고 .textContent는 해당 텍스트를 가져옵니다.
- .innterText는 해당 element 안에서 사용자에게 보여지는 값만 가져옵니다.
tsx
<div>
안녕하세요 : <span className="hidden">안보임</span>
</div>
text
안녕하세요 : // .innerText의 결과
span 태그가 hidden이라서 가져오지 않습니다.
트러블 슈팅
#[Eslint] jsx-a11y/control-has-associated-label
#- button 요소에 텍스트 컨텐츠를 넣으면 됩니다.
tsx
<button type="button">button</button>
- icon이 존재하여 텍스트 컨텐츠가 필요없다면 aria-label을 통해 요소에 특성을 지정하면 됩니다.
tsx
<button type="button" aria-label="save" class="icon-save" />
[Eslint] jsx-a11y/click-events-have-key-events
#div 태그는 대표적인 비대화형(Non-interactive) 요소라 키보드 이동이나 포커스가 되지 않으니, button 혹은 input 처럼 대화형 요소를 사용하라는 의미입니다.
- div와 같은 요소들을 button / input 과 같은 대화형 요소로 변경합니다.
- div에 role 속성을 추가합니다.
참고
#신현호
Frontend Developer
프론트엔드 개발자를 꿈꾸고 있는 대학생입니다. 끊임없이 배우고 성장하는 개발자가 되기 위해 노력하고 있습니다.
블로그 제작기
총 11개의 포스트가 존재합니다.