5월 3주차 TIL

김민기·2024년 5월 12일
0

TIL

목록 보기
1/3
post-thumbnail

자바스크립트 디자인 패턴

  • Singleton
    • 인스턴스를 하나만 만들어서 공유하자
  • Factory
    • 인터페이스를 사용해서 객체 생성을 위임하자
    • 하나의 인터페이스를 사용해서 여러 객체를 생성할 수 있다
  • Observer
    • 관찰의 대상이 되는 “주제 객체”
    • 관찰하는 “구독 객체”
    • 주제 객체의 상태가 변경되면 구독 객체들에게 상태와 변경을 알린다.
    • polling 방식과 대조되는 방식
  • Facade
    • 간략화된 인터페이스로 사용자가 내부에 직접적인 접근하는 것을 제한한다.
    • POS를 사용해서 햄버거 주문하기!
      • 사용자는 주문 후 상품을 수령하는 것에만 관심
      • 상품이 만들어지는 과정에 접근할 수 없고 관심 없음
  • Command
    • 명령을 캡슐화 한다 (명령 인터페이스 사용)
    • 비즈니스 로직을 실행하는 명령들을 독립적으로 관리하고 추가한다.
  • Proxy
    • 클라이언트가 대상 객체에 접근하려 할 때, 직접 접근하지 않고 Proxy를 통해서 접근한다
    • 클라이언트 → Proxy → 대상 객체
  • Adapter
    • 서로 호환성이 없는 인터페이스나 클래스들을 기존에 구현되어 있는 인터페이스로 감싸서 동작할 수 있게 만든다

Next.js로 프로젝트를 만들고 있는데, 요즘 들어 디자인 패턴에 대한 학습의 필요성을 느꼈다.

React 디자인 패턴에 대해 검색하던 중 자바스크립트 디자인 패턴에 대한 내용이 있어서 유튜브로 공부했음.

공부한 자바스크립트 디자인 패턴들은 class로 설명하고 있는데

React를 사용하면서 함수형 컴포넌트를 사용하고 있어서 class를 사용하는 예시가 얼마나 도움이 될까 싶었다

어차피 디자인 패턴들은 어떤 언어로 구현하느냐에 따라 달리질 것이고 기본적인 컨셉과 개념이 중요하다는 생각이 들어서 모르는건 새로 배우고 알고 있는건 다시 한번 복습하는 시간이 되었다.

Proxy 패턴의 경우 자바스크립트의 Proxy 객체를 사용하는데 한번도 사용해보지 않았던 객체라

Symbol과 같이 한번더 공부해야할 필요성을 느낌!

FSD 폴더 구조?

제로초님 유튜브에서 소개하는 FSD 폴더 구조 영상을 보았는데, 획기적이고 좋은 방법이라는 생각이 들었지만 막상 내가 적용하려고 한다면 어떨까 싶었을 때, 제약사항들이 많아 보였다.

  1. 첫 번째로는 내용이 쉽지 않았다. 계층으로 구분하고 하위 계층은 상위 계층을 사용할 수 없고 오직 상위 계층에서만 하위 계층을 사용할 수 있다는 제약으로 단방향성 흐름을 만드는 것은 좋았지만
    각 계층에서 slice, segment를 만들어서 관리한다는게 복잡한(?) 느낌이 들었다.
    영상에서도 설명하지만 feature 와 entities Layer를 구분하는게 쉽지 않았고 (명확한 설명이였지만)
    slice에서 사용하는 컴포넌트가 현재 Slice의 segment인지, 하위 Layer의 segment인지 헷갈린다…
    공식 예제를 봐도 한눈에 쉽게 이해가 되지는 않았다.

  2. 두 번째로는 팀 단위로 적용이다. 혼자 한다면 혼자만의 규칙을 만들어서 사용할 수 있지만 이런 모호한 개념들을 팀 단위로 적용시킬 때는 항상 문제가 발생했다. 처음에 팀 단위로 규칙을 만들어서 적용을 해보지만 시간이 조금 지난 뒤에 이전에 규칙을 만들 때 생각하지 못했던 엣지 케이스가 나오기도 하고 그로 인해 기존 규칙을 수정해야 하기도 하는… 아토믹 디자인 패턴때와 비슷한 일이 발생할 것으로 생각들었다

만약 적용한다면, 팀 단위로 학습하고 공통 규칙을 잘 만들어야 될 것 같다.

폴더 구조에 대해 생각해보면,

개발할 때 편리한 폴더 구조는 유지보수 할 때 불편하고
개발할 때 불편한 폴더 구조는 유지보수 할 때 편한느낌

Compound Component Pattern

Compound 패턴에 대해서는 알고 있었지만 실제로 적용해보지는 않았음…

오히려 컴포넌트가 더 더러워진다는 느낌?

그리고 컴포넌트와 네임스페이스를 공유하는 컴포넌트간 상태 공유해야 하는데 어떻게 할 수 있는가 궁금했었는데 Context API를 사용해서 공유 할 수 있다

컴포넌트를 작게 나누어서 필요한 조각들을 모아서 쓸 수 있다는 점은 큰 장점이라고 생각된다.

import { FlyOut } from "./FlyOut";

export default function FlyoutMenu() {
	return (
		<FlyOut>
			<FlyOut.Toggle/>
			<FlyOut.List>
				<FlyOut.Item>Edit</FlyOut.Item>
				<FlyOut.Item>Delete</FlyOut.Item>
			</FlyOut.List>
		</FlyOut>
	);
}
export default Modal() {
	const [ name, setName ] = useState("");
	const [ subname, setSubname] = useState("");
	return (
		<Modal>
			<Modal.Title>{ title }</Modal.title>
			<Modal.Item>
				<label>Name</label>
				<input onChange={(e) => setName(e.target.value)} value={name} />
			</Modal.Item>
			<Modal.Item>
				<label>Subname</label>
				<input onChange={(e) => setSubname(e.target.value)} value={subname} />
			</Modal.Item>
			<Modal.Item>
				<button onClick={AddFolder}>Add</button>
			</Modal.Item>
		</Modal>
	)
}

Composition Component Pattern

HOC(고차컴포넌트를 사용한다)

function withLabel(Component) {
	return ({ children, ...rest}) => (
		<div>
			<label>{children}</label>
			<Component {...rest}/>
		</div>
	);
}
// ...
const TextFieldWithLabel = withLabel(TextField);
// ...
{
	// ...
	return (
		<TextFieldWithLabel
			value={value}
			onChange={setValue}
			placeholder="please enter..."
			error={error}
		>
			<h2>Text</h2>
		</TextFieldWithLabel>
	);
}
//...

function TextField({ value, onChange, placeholder }) {
	return (
		<div>
			<input
				value={value}
				type="text"
				placeholder={placeholder}
				onChange={(e) => onChange(e.target.value)}
			/>
		</div>
	);
}

TextFieldWithLabel을 사용 할때 사용하는 props는 TextField 컴포넌트에 전달된다
기본 컴포넌트 구조를 하나 만들고 고차 컴포넌트를 사용해서 필요한 부분만 추가할 수 있다는 점이 좋았다. 클래스에서 상속을 받아 확장하는 느낌(?)

Tailwind in HTML

회사에서 같이 일하는 디자이너분께서 테일윈드를 테스트 해보려고 하시는데

tailwind playground를 사용하거나 웹에서 간단히 테스트하는 것도 좋지만

간단하게 프로젝트를 하나 셋업해서 전달드리면 어떨까 싶었다.

그런데 나는 항상 React, Next.js 프레임워크를 사용하면서 테일윈드를 사용했었다.

React 프로젝트를 셋업해서 드리면, 디자이너분께서 jsx를 사용해서 테스트를 해야했기 때문에 그 방법은 좋지 않다고 생각이 들었다

그러다 보니 그냥 HTML에서 테일윈드를 적용시키는 방법이 궁금했었음

yarn도 사용하지 않고 npm으로 만들었음

폴더를 하나 생성하고 (npm init으로 기본 설정, node.js(npm)설치 필요)

npm install -D tailwindcss@latest autoprefixer postcss-cli@latest

postcss, tailwindcss 를 설치해준다

그리고

npx tailwindcss init -p

테일윈드 초기화도 실행한다.

이때 파일 두 개가 생성됨 postcss.config.js, tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./public/**/*.html"],
  theme: {
    extend: {},
  },
  plugins: [],
};

여기서 public 폴더 안에 index.html을 만들었기 때문에 경로가 다르다면 수정해야 한다.

tailwind를 사용하고 컴파일된 내용이 index.html에 반영이 되어야 한다.

따라서 폴더를 생성하는데 src와 public 폴더를 생성하고 각각 styles.css 파일을 추가한다.

// src/styles.css
@tailwind base;
@tailwind components;
@tailwind utilities;
// public/styles.css
// { 컴파일된 tailwindcss 내용이 들어옴 }

이렇게 만들어주면

라이브 서버로 실행했을 때 테일윈드가 적용되는 것을 확인할 수 있다 (public 폴더에 있는 style.css 파일에 내용이 채워짐)

단, 새로운 내용을 추가하거나 변경하면 적용되지 않는다. (라이브서버가 html 변경내용은 감지하지만 테일윈드 컴파일은 실행되지 않기 때문)

때문에 nodemon을 사용한다.

그냥 사용해서는 안되고 nodemon.json 파일을 생성

{
	"watch": ["src/style.css", "public/index.html"], // html은 필요 없어 보임
	"ext": "html, css",
	"exec": "npm run tailwind:css",
	"verbose": true, // 디버깅을 위해
}

package.json 파일에 스크립트를 수정한다.

{
	"scripts": {
		"tailwind:css": "postcss ./src/styles.css -o ./public/styles.css",
		"dev": "concurrently \"npm run tailwind:css && live-server public\" \"nodemon\""
    }
}

npm run dev 로 실행한다.

이렇게 하면, html 파일 내용이 수정되어서 새로운 tailwind 내용이 추가된다면

컴파일을 실행하고 변경 사항을 라이브 서버로 바로 확인할 수 있다.

약간의 컴파일 시간이 걸리기는 하지만, 서버를 다시 실행하는 것보다 좋아 보인다.

0개의 댓글