Now Loading ...
-
FSD 폴더구조 사용 후기 (2)
화면에서 FSD 폴더구조 바로 이해해보기
네이버를 예로 화면과 fsd 폴더구조를 연관지어 이야기해보자.
오늘은 FSD 폴더구조를 실질적으로 어떻게 사용해야 효과적으로 사용할 수 있을지 화면단에서 설명해보고자 한다.
우선 대충 네이버 화면을 보고 생각해보자
난 우선 파란색 박스 내에 있는 것들은 이 페이지 내에서 구성하는 요소들 중 가장 큰 단위로 분류했다.
그리고 pages는 widgets으로 이뤄져 있다고 생각해서 widgets으로 분류했다.
이제 이 widgets들이 무엇으로 이뤄져 있는지 확인해보자.
먼저 가장 위 검색창 부터 분석해보자.
layer별로 분류하려면 먼저 구성 요소에 대해 생각해봐야한다.
N 로고
키보드 아이콘 모양 입력도구 버튼
검색기록 내려보기 버튼
검색 버튼
검색창
크게 네가지로 분류되는데, 우선 1번 로고의 경우 클릭하면 현재 페이지인 home으로 가는 링크가 달려 있으므로 하나의 기능을 한다고 볼 수 있다.
2, 3, 4, 5모두 동일한 경우이다.
이전에 말했듯이 widgets에 들어가는 자잘한 기능들을 features
따라서 1, 2, 3, 4, 5는 모두 Layers 중 features에 해당한다.
근데 이제 여기서 4. 검색 버튼은 features 내부에서도 무언가 분류된다. 그 이유는 바로 검색 버튼을 누르면 일어나는 action 때문인데, “검색 버튼을 누르면 검색 창에 써져 있는 검색어를 통해 검색 요청이 백엔드로 간다”가 이 action이다.
그렇다면 백엔드에 요청이 가는 api는 어디에 포함되어야 할까? 이전에 말했던 entities 레이어에 다음과 같이 들어가게 된다. (내 프로젝트에 맞게 예시를 보여주겠다.)
📁 entities
📁 model
types.ts - typescript를 사용했음 (api response관련 타입 정의)
stores.ts - 상태 관리
📁 api
index.ts - 백엔드 api
export 방식
프로젝트를 진행하면서 이 부분이 간단하지만 중요한 부분이라고 느꼈다.
그 이유를 예를 들어 설명해보겠다. 우선 widgets에 layouts이라는 폴더를 만들어서 대부분의 화면에서 사용되는 레이아웃들을 정의했다.
근데 만약에 각 레이아웃에 대해 단계별로 export 하지 않고 바로 해당 레이아웃을 쓰는 페이지에서 import해서 쓴다면 정확히 해당 레이아웃이 어떤 용도인지 파악하기 힘들 수 있다. 특히나 코드는 보통 혼자 쓰는게 아닌 여러명이 함께 협업하는 경우가 많기 때문에 더욱 중요하다.
📁 widgets
📁 layouts
📁 gnb
index.ts 1️⃣
📁 lnb
index.ts
📁 editForm
index.ts
index.ts 2️⃣
index.ts 3️⃣
위의 경우 export를 총 세번에 거쳐서 하면 된다.
1️⃣ 에서 각 위젯의 화면파일을 import한 후 바로 export한다.
// index.ts
import GNBWidget from './ui/GNBWidget.xx'
export { GNBWidget }
2️⃣ 에서 바로 윗 단위 폴더들을 export 해준다.
export * from './gnb'
export * from './lnb'
export * from './editForm'
마지막으로 3️⃣ 에서 최종으로 export 해준다.
export * from './layouts'
예시만 보면 굳이 이렇게까지 복잡하게 해야하나 싶겠지만, widgets내부에는 프로젝트가 커질수록 점점 더 깊은 tree로 수십개의 폴더가 나오게 된다. 그렇게 되면 위처럼 하지 않았을 때 import한다면 그것만큼 지저분한 import가 없을것이다.
import xxxwidget from ‘@/widgets/user/sign-in/ui/xxxwidget.xx’ 이런식으로…
the end…
이상 내가 프로젝트를 진행하면서 이해한 fsd 폴더구조이다.
사실 공식문서를 따라 이해하려면 꽤 많은 시간이 걸리기 때문에 나 같은 경우에는 공식문서는 1회독 정도 가볍게 읽고 실제로 fsd 폴더구조를 사용한 프로젝트들을 최대한 참고하여 프로젝트를 진행했고, 실제로 중간 중간 수많은 시행착오를 겪으면서 나만의 fsd 폴더구조로 프로젝트를 완성할 수 있었던 것 같다.
공식문서대로 fm으로 이해하고 그대로 수행하는 것도 중요하지만 직접 구현하고 시행착오를 겪으며 여러 상황에 부딪혀보니 이 어려운 방법론에 좀 더 가까이 다가가 이해할 수 있었던 것 같다.
앞으로 새로운 기술 스택이나 방법론을 공부할 때 이론과 실습을 동시에 진행하는게 좀더 이해를 빠르고 정확하게 할 수 있다는 것을 깨달았다.
-
FSD 폴더구조 사용 후기 (1)
FSD 폴더구조
Overview
✍️
실제 프로젝트에서 실제로 FSD 폴더구조를 사용했다
이 글은 그에 대한 회고가 담긴 글이다.
FSD 폴더구조란?
FSD (Feature-Sliced Design)는 프론트엔드 애플리케이션을 구조화하기 위한 아키텍처 방법론이다.
코드를 구성하는 규칙과 관례를 모아놓은 것으로, 이 방법론의 주요 목적은 끊임없이 변화하는 비즈니스 요구사항에 직면해서도 프로젝트를 더 이해하기 쉽고 안정적으로 만드는 것이다.
Tutorial
간단한 예시
자, 가장 부모 단계에 있는 폴더부터 점차적으로 알아가보자.
📁 app
📁 routes
📁 analytics
📁 pages
📁 home
📁 article-reader
📁 ui
📁 api
📁 shared
📁 ui
📁 api
pages폴더는 slices라고 불린다.
해당 폴더는 도메인을 기준으로 레이어를 나눈다. (위의 경우 페이지를 기준으로 레이어를 나눈다.)
app, shared 폴더, 그리고 pages/article-reader 폴더는 segments라고 불린다.
해당 폴더는 기술적인 목적을 기준으로 slices(또는 레이어)를 나눈다.
개념
Layers, slices, 그리고 segments는 아래와 같이 계층을 형성한다.
자, 여기부터는 내가 프로젝트를 진행하면서 활용했던 FSD 폴더구조 방식과 연관지어 말해보겠다.
✓ 우선 위 사진의 Layers부터 보자.
app - app을 실행하기 위한 모든 것들이 여기에 들어간다.
예를 들면, routing, entrypoints, global styles, providers
실제 프로젝트 활용 폴더 구조
📁 app
📁 fonts
📁 i18n
📁 Layouts
📁 providers
📁 router
📁 routes
📁 style
processes - 이젠 없는 개념…deprecated!!
pages - 실제 라우팅에 들어가는 전체 페이지나 큰 단위의 페이지
실제 프로젝트 활용 폴더 구조 (라우팅 단위별 페이지로 구분)
📁 pages
📁 dashboard
📁 source
widgets - 큰 단위의 독립적인 기능이나 UI (주로 전체적인 유스케이스를 전달한다)
실제 프로젝트 활용 폴더 구조
widgets/layout에는 많은 페이지에서 공통적으로 쓰이는 컴포넌트나 헤더, GNB 및 LNB에 들어가는 widget에 대한 폴더들을 모아뒀다.
그 외 다른 폴더들은 큰 단위의 독립적인 UI나 기능 기준으로 분류했다.
근데 해당 기준으로 모든 폴더를 나눠버리면 너무 방대해져서 pages기준으로 같은 페이지에 해당하는 widgets은 같은 폴더로 분류했다.
📁 widgets
📁 layouts
📁 source
📁 source-widgetA
📁 source-widgetB
features - 전체 프로덕트 feature들 중 재사용되는 부분들 (즉, 대중적인 의미로 생각하면 컴포넌트라고 생각하면 된다. → 버튼 컴포넌트, 모달 컴포넌트 등등)
실제 프로젝트 활용 폴더 구조
나의 경우에는 widgets에 들어가는 자잘한 기능들을 feature라고 생각하고 구현했다.
그리고 widgets과 마찬가지로 너무 방대해질 폴더량을 고려하여 특정 기준으로 (widgets과 달리 무조건 페이지 기준은 아니었다. - 레이아웃에 들어가는 feature인 경우도 있었으니…) features를 폴더별로 분류했다.
📁 features
📁 auth
📁 auth-featuresA
📁 lnb
📁 lsb-item
📁 lsb-router-item
entities - user, product와 같은 비즈니스 엔티티에 대한 폴더이다
실제 프로젝트 활용 폴더 구조
나의 경우에는 api (백엔드와 통신하여 데이터를 받아오기 위한 api 구현)와 store (상태 관리), type(typescript를 활용하여 타입 정의는 필수였다)을 page별로 분류했다.
📁 entities
📁 auth
📁 model
- store
- types
📁 api
shared - 재사용 가능한 함수들, 특히 프로젝트 세부 사항과 거리가 있지만 필요한 함수들에 대해 구현하는 폴더이다.
실제 프로젝트 활용 폴더 구조
나의 경우에는 데이터 테이블을 구현하기 위한 재사용 가능한 데이터 관련 훅, 그리고 기타 재사용되는 utils들(date, alert, component 등등)을 분류했다.
📁 shared
📁 hooks
📁 utils
출처: https://feature-sliced.design/docs/get-started/overview
다음 글에 이어서 한 단계 더 들어간 Slices 단계에 대해서 이야기하겠다.
-
WebStorm 사용 후기
WebStorm 사용 후기
우선 WebStorm은 유료 IDE 중 하나인데, 그동안 Visual Studio Code로만 개발해왔던 나에겐 생소한 아이였다.
회사에서 WebStorm을 쓰게돼서 처음으로 깔아봤는데 진짜 까다로운 아이다.
우선, Visual Studio Code에서는 prettier와 eslint를 설정하려면 전역 설정 파일인 setting.json에서 전역으로 설정해도 되고, 특정 작업 영역에서만 적용시키려면 해당 워크스페이스에 .eslintrc.js와 .prettierrc 파일을 통해 쉽게 설정이 가능하다.
근데, WebStorm은 설정파일에서 아래와 같이 따로 설정해줘야 위에서 말한 .eslintrc.js 파일이 적용될 수 있다. (우리의 경우, eslint파일 내에 prettier 설정도 함께해주었다. )
eslint와 prettier 설정하는데만 많은 시간이 들었는데, 이건 WebStorm 때문은 아니고 그냥 eslint 설정이 제대로 안돼서 계속 오류가 났다. extends 부분에 제대로 된 플러그인들을 입력해줘야 하는데 그렇지 못해서 그랬던 것 같다. 최종적으로 모든 파일에 에러 없이 eslint가 적용된 설정파일은 아래와 같다. (참고로 vue2 관련 eslint 설정파일이다)
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier',
'plugin:vue/recommended',
],
rules: {
'prettier/prettier': [
'error',
{
singleQuote: true,
semi: true,
useTabs: false,
tabWidth: 2,
trailingComma: 'all',
printWidth: 80,
bracketSpacing: true,
arrowParens: 'avoid',
},
],
'vue/no-unused-vars': 'warn',
'no-console': 'warn',
'vue/multi-word-component-names': 'off',
"no-unused-vars": "warn"
},
};
-
-
Vue에서 API 연결하기 (1)
Vue에서 API 연결하기 (1)
axios 대신 vueuse의 useAxios를 사용한다면?
useAxios는 Vue의 유틸리티 라이브러리인 VueUse에서 제공하는 훅으로, Axios와 결합하여 더 편리한 API 호출 관리를 돕는다.
useAxios의 장﹒단점
장점
반응형 데이터 관리
useAxios는 Vue의 반응형 시스템과 잘 통합되어, API 호출 결과를 반응형으로 관리할 수 있음.
→ Vue의 ref, reactive와 같은 기능과 결합해 상태 관리가 자연스럽게 이루어짐.
ex) API 응답 데이터를 화면에 실시간으로 반영하거나 로딩 상태 등을 쉽게 추적 가능.
편리한 상태 추적
useAxios는 로딩 상태, 에러 상태, 응답 데이터 등을 관리할 수 있는 상태값 제공.
API 호출의 현 상태 파악 용이 → UI에서 로딩 스피터 표시, 에러메시지 출력 등 구현 용이.
상태값을 컴포넌트 내에서 간편하게 사용 가능 → 코드 가독성 up.
자동 취소 기능
컴포넌트가 언마운트되거나 특정 조건에서 불필요한 API 호출을 자동으로 취소할 수 있는 기능 제공.
→ 불필요한 네트워크 요청 감소 & 자원 효율적 사용 가능.
타입스크립트 지원
useAxios는 타입스크립트와 효환성이 좋음.
→ 요청과 응답의 타입을 명확하게 정의할 수 있어, 타입 안정성 유지하며 개발 가능.
단점
추가 학습 곡선
useAxios를 사용하려면 VueUse 라이브러리와 그 API에 대한 학습 필요
의존성 추가
vue에 대한 프로젝트 의존성 증가 → 프로젝트의 빌드 크기 증가나 업데이트시 호환성 문제 유발 가능성 up.
제한된 커스터마이징
useAxios는 특정 패턴에 따라 동작 → 모든 요구사항에 충족하지 못할 수도 있음.
ex) 매우 세밀한 요청 커스터마이징이 필요한 경우, axios의 고급 기능을 사용하는 경우
useAxios 적절한 사용법
공식문서에는 useAxios 사용시 axios와 적절히 섞어가며 쓰는 걸 알 수 있다.
공식문서에 따르면 axios를 통해 인스턴스를 전역으로 먼저 생성하고 해당 인스턴스를 useAxios의 옵션으로 사용할 수 있다.
useAxios만 활용한다면 아래와 같이,
import { useAxios } from "@vueuse/integrations/useAxios";
const { data, isFinished } = useAxios("/api/posts");
axios를 통해 전역 인스턴스를 생성한 후, 해당 인스턴스를 useAxios의 옵션으로 활용하는 방법은 아래와 같이 쓸 수 있다.
import axios from "axios";
import { useAxios } from "@vueuse/integrations/useAxios";
const instance = axios.create({
baseURL: "/api",
});
const { data, isFinished } = useAxios("/posts", { method: "POST" }, instance);
현재 우리 프로젝트의 추후 확장성과 유연성을 생각하면 axios와 useAxios를 같이 사용하는 방향이 더 낫다고 판단됨.
+) Advanced:
[Advanced] vue에서 axios만 사용하는게 더 편리하지 않을까?
+) 실제 실습 내용:
[Vue] Vue에서 BE의 API 연결하기
-
-
Manage blog comments with Giscus
Giscus is a free comments system powered without your own database. Giscus uses the Github Discussions to store and load associated comments based on a chosen mapping (URL, pathname, title, etc.).
To comment, visitors must authorize the giscus app to post on their behalf using the GitHub OAuth flow. Alternatively, visitors can comment on the GitHub Discussion directly. You can moderate the comments on GitHub.
Prerequisites
Create a github repo
You need a GitHub repository first. If you gonna use GitHub Pages for hosting your website, you can choose the corresponding repository (i.e., [userID].github.io)
The repository should be public, otherwise visitors will not be able to view the discussion.
Turn on Discussion feature
In your GitHub repository Settings, make sure that General > Features > Discussions feature is enabled.
Activate Giscus API
Follow the steps in Configuration guide. Make sure the verification of your repository is successful.
Then, scroll down from the manual page and choose the Discussion Category options. You don’t need to touch other configs.
Copy _config.yml
Now, you get the giscus script. Copy the four properties marked with a red box as shown below:
Paste those values to _config.yml placed in the root directory.
# External API
giscus_repo: "[ENTER REPO HERE]"
giscus_repoId: "[ENTER REPO ID HERE]"
giscus_category: "[ENTER CATEGORY NAME HERE]"
giscus_categoryId: "[ENTER CATEGORY ID HERE]"
None
· 2024-02-03
-
-
Markdown from A to Z
Headings
To create a heading, add number signs (#) in front of a word or phrase. The number of number signs you use should correspond to the heading level. For example, to create a heading level three (<h3>), use three number signs (e.g., ### My Header).
Markdown
HTML
Rendered Output
# Header 1
<h1>Header 1</h1>
Header 1
## Header 2
<h2>Header 2</h2>
Header 2
### Header 3
<h3>Header 3</h3>
Header 3
Emphasis
You can add emphasis by making text bold or italic.
Bold
To bold text, add two asterisks (e.g., **text** = text) or underscores before and after a word or phrase. To bold the middle of a word for emphasis, add two asterisks without spaces around the letters.
Italic
To italicize text, add one asterisk (e.g., *text* = text) or underscore before and after a word or phrase. To italicize the middle of a word for emphasis, add one asterisk without spaces around the letters.
Blockquotes
To create a blockquote, add a > in front of a paragraph.
> Yongha Kim is the best developer in the world.
>
> Factos 👍👀
Yongha Kim is the best developer in the world.
Factos 👍👀
Lists
You can organize items into ordered and unordered lists.
Ordered Lists
To create an ordered list, add line items with numbers followed by periods. The numbers don’t have to be in numerical order, but the list should start with the number one.
1. First item
2. Second item
3. Third item
4. Fourth item
First item
Second item
Third item
Fourth item
Unordered Lists
To create an unordered list, add dashes (-), asterisks (*), or plus signs (+) in front of line items. Indent one or more items to create a nested list.
* First item
* Second item
* Third item
* Fourth item
First item
Second item
Third item
Fourth item
Code
To denote a word or phrase as code, enclose it in backticks (`).
Markdown
HTML
Rendered Output
At the command prompt, type `nano`.
At the command prompt, type <code>nano</code>.
At the command prompt, type nano.
Escaping Backticks
If the word or phrase you want to denote as code includes one or more backticks, you can escape it by enclosing the word or phrase in double backticks (``).
Markdown
HTML
Rendered Output
``Use `code` in your Markdown file.``
<code>Use `code` in your Markdown file.</code>
Use `code` in your Markdown file.
Code Blocks
To create code blocks that spans multiple lines of code, set the text inside three or more backquotes ( ``` ) or tildes ( ~~~ ).
<html>
<head>
</head>
</html>
def foo():
a = 1
for i in [1,2,3]:
a += i
Horizontal Rules
To create a horizontal rule, use three or more asterisks (***), dashes (---), or underscores (___) on a line by themselves.
***
---
_________________
Links
To create a link, enclose the link text in brackets (e.g., [Blue Archive]) and then follow it immediately with the URL in parentheses (e.g., (https://bluearchive.nexon.com)).
My favorite mobile game is [Blue Archive](https://bluearchive.nexon.com).
The rendered output looks like this:
My favorite mobile game is Blue Archive.
Adding Titles
You can optionally add a title for a link. This will appear as a tooltip when the user hovers over the link. To add a title, enclose it in quotation marks after the URL.
My favorite mobile game is [Blue Archive](https://bluearchive.nexon.com "All senseis are welcome!").
The rendered output looks like this:
My favorite mobile game is Blue Archive.
URLs and Email Addresses
To quickly turn a URL or email address into a link, enclose it in angle brackets.
<https://www.youtube.com/>
<fake@example.com>
The rendered output looks like this:
https://www.youtube.com/
fake@example.com
Images
To add an image, add an exclamation mark (!), followed by alt text in brackets, and the path or URL to the image asset in parentheses. You can optionally add a title in quotation marks after the path or URL.
![Tropical Paradise](/assets/img/example.jpg "Maldives, in October")
The rendered output looks like this:
Linking Images
To add a link to an image, enclose the Markdown for the image in brackets, and then add the link in parentheses.
[![La Mancha](/assets/img/La-Mancha.jpg "La Mancha: Spain, Don Quixote")](https://www.britannica.com/place/La-Mancha)
The rendered output looks like this:
Escaping Characters
To display a literal character that would otherwise be used to format text in a Markdown document, add a backslash (\) in front of the character.
\* Without the backslash, this would be a bullet in an unordered list.
The rendered output looks like this:
* Without the backslash, this would be a bullet in an unordered list.
Characters You Can Escape
You can use a backslash to escape the following characters.
Character
Name
`
backtick
*
asterisk
_
underscore
{}
curly braces
[]
brackets
<>
angle brackets
()
parentheses
#
pound sign
+
plus sign
-
minus sign (hyphen)
.
dot
!
exclamation mark
|
pipe
HTML
Many Markdown applications allow you to use HTML tags in Markdown-formatted text. This is helpful if you prefer certain HTML tags to Markdown syntax. For example, some people find it easier to use HTML tags for images. Using HTML is also helpful when you need to change the attributes of an element, like specifying the color of text or changing the width of an image.
To use HTML, place the tags in the text of your Markdown-formatted file.
This **word** is bold. This <span style="font-style: italic;">word</span> is italic.
The rendered output looks like this:
This word is bold. This word is italic.
None
· 2023-09-05
Touch background to close