Programming 38

웹 사이트 성능 측정 및 최적화 (with LightHouse)

LightHouse 성능 측정 웹 사이트를 만들고 배포까지 마쳤다. 그런데 SSR임에도 불구하고 초기 렌더링이 느려서 성능 측정이 필요했다. 크롬 확장 프로그램인 LightHouse을 사용해서 사용자 입장의 성능을 측정했다. 다른 것들은 준수했으나 가장 중요한 퍼포먼스 점수가 처참했기에 최적화를 진행했다, 💡 이미지 최적화 성능 하락의 주된 원인은 이미지였기에 두 가지 과정을 거쳤다. Next.js에서 제공하는 Image 태그 커스텀 해당 Image 태그는 width, height를 필수적으로 적어야 했는데, 나는 이미지의 크기가 부모의 맞춰서 유동적으로 변화하는 것을 원했다. 그래서 기본 속성을 이용하여 커스텀했다. Image의 width나 height는 px단위의 숫자만 넣을 수 있기에 0을 넣고 s..

Programming/Client 2023.04.06

[Next.js] Tailwind-styled-components의 SSR 구현하기

🤔 문제 상황 tailwind-styled-components를 사용해서 스타일을 부여했는데 초기 렌더링되는 찰나에 css가 적용되지 않는 문제가 있었다. 자바스크립트 파일이 다운로드 되고 나서야 제대로 적용되니 보기 싫었다. css가 next.js가 ssr할 때 부여되도록 설정이 따로 필요했다. Next.js + tailwind + styled-components를 결합할 때 twin.marco + emotion 조합을 더 많이 사용해서 자료가 많았는데, Next.js와 tailwind-styled-components를 사용하는 경우는 많지 않아서 자료 찾기가 어려웠다. 그래도 좋은 글들이 몇 개 있어서 참고해서 해결했다. ✅ 해결 방법 ssr 적용하지 않는다면 styled-components를 깔지 ..

Programming/Client 2023.04.06

[Tailwind] react-markdown 적용하기

🤔 문제 상황 react-markdown을 적용이 안되서 찾아보니까 tailwind가 기본적인 html의 스타일을 제어하고 있어서 그냥 적용하면 안된다는 것을 알았다. 그래서 마크다운을 사용할 부분만 tailwind의 스타일이 적용되지 않도록 해야한다. ✅ 해결 방법 다행히 tailwind 자체에서 markdown 컴포넌트를 사용할 수 있도록 플러그인을 제공하고 있었다. 해당 플러그인을 사용하면 하위 태그는 tailwind 스타일이 적용되지 않는다. @tailwindcss/typography 설치 https://tailwindcss.com/docs/typography-plugin$ npm install @tailwindcss/typography tailwind.config.js 파일에 플러그인 추가// ..

Programming/Styles 2023.04.03

[React-slick] Carousel 만들기 (+ Typescript, Tailwind, styled-components)

🤔 문제 상황 현재 tailwind와 styled-components가 결합된 tailwind-styled-components를 사용하고 있는데 이미지 슬라이더가 필요했다. 찾아보니 carousel이 정식 명칭이었고 찾아보니 사용할 수 있는 소스가 많았다. 처음에는 간단할 줄 알았는데 구현하는데 거의 이틀이 걸렸다. 세 가지 프레임워크를 사용해봤는데 결론적으로 react-slick을 사용했다. 실패 기록 flowbite 이미 navbar를 flowbite로 구현했던지라 그 안에서 해결하고 싶었다. 그래서 flowbite에도 좋은 carousel이 있길래 사용하려고 했는데... 실패했다. 거의 하루를 붙잡고 있었는데 공식 문서에 나와있는대로 복붙을 해도 안됐다. 이미지를 싸고 있는 div를 벗기니까 이미지..

Programming/Styles 2023.03.31

[Typescript] 'HTMLElement | null' 형식은 'HTMLElement' 형식에 할당할 수 없습니다.

🤔 문제 상황 getElementById로 돔 요소에 접근해서 변수에 할당하려는데 에러가 떴다. 해당 요소가 제대로 읽히지 않아 HTMLElement 타입으로 할당이 불가능한 것이다. 조건을 붙여 null이 아님을 확인하고 할당할 수 있지만 보다 간편한 방법이 있다. ✅ 해결 방법 1. 연산자 ! 붙이기 const portalDiv = document.getElementById('your-element')!; 타입스크립트에서 !은 Null이 아닌 어선셜 연산자(Non-null assertion operator), 피연산자가 null이 아니라고 컴파일러에게 전달하여 일시적으로 null 제약조건을 완화하는 역할을 한다. 그래서 위 코드에 느낌표를 붙여주면 값이 무조건 할당되어 있다고, null..

Programming/Client 2023.03.30

[Tailwind] 동적 클래스 할당하기 (+Typescript, Styled-components)

🤔 문제 상황 Typescript 환경에서 Tailwind와 styled-components를 함께 사용하는 tailwind-styled-components를 사용하던 중, 공통적으로 사용되는 컴포넌트의 스타일을 prop로 받아서 적용하고 싶었다. 즉, 동적으로 클래스를 할당하려고 한 것이다. 셋을 함께 사용하면서 작성하는 과정이 꽤나 까다로웠기에 기록해본다. ✅ 해결방법 tailwind와 동적 클래스 Tailwind의 공식 문서는 동적 클래스 사용을 지양하라고 써있다. 정규표현식을 통해 단어의 있는 그대로를 가져와서 클래스로 적용하기 때문에 코드적으로 분석이 필요한 부분은 건너뛰어버리기 때문이다. 그래서 아예 동적 클래스를 못 쓰느냐? 그건 아니다. 중요한 것은 '완전한 상태의 단어'로 ..

Programming/Styles 2023.03.28

[Styled-components] Semantic-ui-react의 스타일 커스터마이징하기

🤔 문제 상황 Semantic-ui-react를 사용해서 css 스타일링을 하는데 추가로 커스터마이징이 필요했다. 그래서 클래스명을 사용한 덮어쓰기도 해보고, 태그를 사용하여 추가해봤지만 무용지물이었다. !important만이 방법인가... 하고 있던 중 좋은 글을 발견해서 실마리를 찾았다 참고: Customizing the Semantic UI React library with Styled Components ✅ 해결 방법 보통 css에서 !important를 사용되는 것은 지양된다. 모든 우선순위를 무시한 채 최상위에서 적용되기 때문에 어떤 부작용이 나타날지 모르기 때문이다. 하지만 styled-components를 사용하면 말이 달라진다. styled-components는 자체 class명을 컴포넌..

Programming/Styles 2023.03.24

[React] 프론트단에서 페이지네이션 구현하기

들어가기 전에... 유저가 많고 데이터가 방대한 서비스라면 백단에서 페이지에 따라 데이터를 나눠서 넘겨줘야 하고, 그것이 이상적인 구조이다. 하지만 내가 진행하는 프로젝트는 작은 서비스이고 백의 인력이 너무나 부족해서 페이지네이션 API를 구현할 여력이 없었다. 그래서 프론트단에서 데이터 전체를 받아와서 직접 나누어 출력하는 페이지네이션 컴포넌트를 구현했다. 📌 컴포넌트 구현 import { useState } from "react"; import { PageWrapper, PageBtn } from "../styles/Styled"; // total(데이터 총 갯수), limit(한 페이지에 보여줄 갯수) const Pagination = ({ total, limit, page, setPage }) =..

Programming/Client 2023.02.15

[Javascript] formData로 이미지, 문자열 묶어서 전달하기

📌 상황 이름, 주소, 이미지 정보를 서버로 전달해야 했다. 이미지는 multer를 사용했기에 프론트에서 이미지 정보를 formData로 보내야 했고, 문자열로 데이터를 전달할 때와 axios의 header 안의 Content-Type이 달라졌다. 그렇기 때문에 이름, 주소는 문자열로 전달하고, 이미지를 formdata로 보내서 API를 두 번 호출해야했다. 그런데 나는 API 호출을 최소화하고 싶었기에 한 번에 같이 보낼 수 있는 방법이 없을까 고민했다. 아무리 검색해봐도 이렇게 정보를 함께 보내는 경우를 볼 수 없어서 백엔드 팀원과 새벽에 3시간을 고전하다가, 결국 해결책을 찾았다. 이름, 주소도 formdata 안에 넣어서 이미지와 함께 보내는 것이다. 이런 방법도 있다~ 하면서 참고로 봐주시면 좋..

Programming/Client 2023.01.08

[React] 전역에서 사용 가능한 모달 만들기

📌 모달 구현 1. 모달의 오픈 여부를 알 수 있는 상태값이 있는 slice 만들기 // ModalSlice.jsx import { createSlice } from '@reduxjs/toolkit'; const initialState = { modal: false, }; export const modalSlice = createSlice({ name: 'modal', initialState, reducers: { showModal: (state) => { state.modal = true; }, closeModal: (state) => { state.modal = false; }, }, }); export default modalSlice.reducer; export con..

Programming/Client 2023.01.08