Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
4c08ce5
:construction: feat(signup) inputValidation.ts에 비밀번호 확인 추가
MINJI121 Sep 27, 2025
e26e67f
:recycle: refactor(auth): LoginForm 입력 필드 유효성 검증식 분리 및 공통 훅 적용
MINJI121 Sep 27, 2025
fcdcbf3
chore: 파일 위치 변경
MINJI121 Sep 27, 2025
33b48e2
:sparkles: feat(auth) 회원가입 페이지 구현 및 내비게이션 버튼 분리
MINJI121 Sep 27, 2025
c7d701a
:sparkles: 랜딩 버튼 클릭 시 로그인 페이지 이동
MINJI121 Sep 27, 2025
78d808f
:sparkles: feat(error): 에러 메시지 정규화 함수 분리, 토스트 메시지에 동적 적용
MINJI121 Sep 27, 2025
f6a55ae
chore: NotificationsPanel 배럴 export
MINJI121 Sep 27, 2025
f4919fe
:recycle: refactor(notifications): normalizeError 적용으로 에러 처리 통일
MINJI121 Sep 27, 2025
51efe99
chore
MINJI121 Sep 27, 2025
da185ed
:construction: feat(activities): ProfileCard 초안
Sep 28, 2025
76788eb
:construction: feat(activities): 닉네임 수정 버튼 추가 / 레이아웃에 정렬 추가
Sep 28, 2025
6f9aa86
:sparkles: feat : 공용 컴포넌트 news-card 구현
sori4606 Sep 28, 2025
95ed474
:fire: remove : ArticlesPage 테스트 데이터 제거
sori4606 Sep 28, 2025
664f662
Merge pull request #35 from team-monew/feat/auth
MINJI121 Sep 28, 2025
9a0a580
:sparkles: feat(activities): 닉네임 수정 모달 기능 연
Sep 28, 2025
2ba1628
Merge remote-tracking branch 'origin' into feat/activities
Sep 28, 2025
0d609be
Merge remote-tracking branch 'origin/dev' into feat/activities
Sep 28, 2025
6c81323
:recycle: refactor: 닉네임 수정 모달에 toastAPIError 적용
Sep 28, 2025
10fd21c
:art: design: 스켈레톤 디자인 수정 / 토스트 위치 하단 변경
Sep 28, 2025
a38023b
Merge remote-tracking branch 'origin/dev' into dev
Sep 28, 2025
53a64aa
:sparkles: feat(route): 비로그인 라우트 가드 적용
Sep 28, 2025
b40cad4
:construction: feat(Activities): ActivitiesTabs 컴포넌트 초안
Sep 28, 2025
9578137
:construction: feat(Activities): ActivitiesTabs 컴포넌트 UI 디자인
Sep 29, 2025
31e3323
:construction: feat(Activities): 최근 작성한 댓글 내역 초안
Sep 29, 2025
1a6a99f
✨ feat : 공용 컴포넌트 news-card 구현
sori4606 Sep 29, 2025
76ff898
:recycle: refactor : Tag 컴포넌트 onClick props 제거
sori4606 Sep 29, 2025
3050cc6
:recycle: refactor: CommentHistoryCard 'mode' 타입 추가, 디자인 분기
Sep 29, 2025
63d0e96
chore: CommentHistoryCard 프로퍼티 'type' -> 'mode' 네이밍 수정
Sep 29, 2025
2c4e549
:art: design: CommentHistoryCard css 여백 오류 수정, 상하 여백 시안과 동일하게 변경
Sep 29, 2025
f13f83e
Merge branch 'dev' into feat/activities
Sep 29, 2025
d212167
Merge remote-tracking branch 'origin/dev' into feat/activities
Sep 29, 2025
94b5d22
:construction: feat(Activities): 구독 패널 초안(subscriptions 연결)
Sep 29, 2025
ff2e934
:sparkles: feat(activities): 최근 본 기사 내역 구현
Sep 30, 2025
95ce5d9
:sparkles: feat(activities): SubScriptionPanel: 구독 목록 구현
Sep 30, 2025
2fb1bda
chore(activities): 주석 수정, className prop 삭제
Sep 30, 2025
3204bda
:sparkles: feat: article-page 구현
sori4606 Sep 30, 2025
0798b4a
:recycle: refactor: SubscriptionPanel 시맨틱 태그 변경
Sep 30, 2025
7a92679
:wrench: fix : 댓글삭제 기능 오류해결
sori4606 Sep 30, 2025
a0304cd
:recycle: refactor: ActivitiesTabs: 스크린리더용 안내 변경
Sep 30, 2025
985874a
:recycle: refactor(activities) getUserActivities 조회 로직 공통 훅 분리
Sep 30, 2025
43f8aa3
:recycle: refactor(activities): 기사 제목 클릭 내비게이션 카드 컴포넌트로 이전, 타입 매핑 적용
Sep 30, 2025
a9b7e72
:wrench: fix : 모달 열릴 때 url 변경 및 NewsCard에 onClick prop 추가
sori4606 Oct 1, 2025
668974a
:art: design(activities): empty 메시지를 EmptyState.tsx로 교체
Oct 1, 2025
7f769f4
Merge pull request #39 from team-monew/feat/routeGuard
MINJI121 Oct 1, 2025
04db352
Merge pull request #37 from team-monew/feat/activities
MINJI121 Oct 1, 2025
21437ae
:art: refactor : 민지님 피드백 반영 return 문 변경
sori4606 Oct 1, 2025
af6bb6b
:wrench: fix : 병합 충돌 해결
sori4606 Oct 1, 2025
4bd3a5c
:wrench: fix : vercel 배포오류 해결
sori4606 Oct 1, 2025
671da22
✨ feat: article-page 구현
sori4606 Oct 1, 2025
e2c7824
:sparkles: feat(landing): 랜딩 페이지 디자인 추가, 로그인 상태에 따른 버튼 링크 분기
MINJI121 Oct 1, 2025
f64f87f
:art: design(landing): title 이름 한글 수정
MINJI121 Oct 1, 2025
a19b92a
Merge pull request #40 from team-monew/feat/landing
MINJI121 Oct 1, 2025
88cec8a
:memo: docs : README 작성
sori4606 Oct 1, 2025
5c3f8d8
chore(landing): 겹치는 main 태그 제거
MINJI121 Oct 1, 2025
41f694a
chore: loading 표시 스켈레톤, export 방식 선언과 동시로 통일
MINJI121 Oct 1, 2025
d6a0bf5
Merge branch 'dev' of https://github.com/sori4606/Monew into feat/lan…
MINJI121 Oct 1, 2025
78afdd6
chore: TestPage 제거, export 방식 통일
MINJI121 Oct 1, 2025
e57362d
:memo: docs : README 시작하기 탭 추가
sori4606 Oct 1, 2025
120be33
:art: design(activities): 정렬 및 여백 수정
MINJI121 Oct 1, 2025
0263e0e
:art: design(activities): EmptyState 정렬 수정
MINJI121 Oct 1, 2025
ba8f84e
:art: design(articles, interests): 중복 여백 제거(레이아웃에 공통 여백 설정됨)
MINJI121 Oct 1, 2025
09ad881
chore: 백엔드 확인용 주석 추가
MINJI121 Oct 1, 2025
ed35f63
chore: 백엔드 확인용 주석 추가
MINJI121 Oct 1, 2025
88d3478
Merge pull request #42 from team-monew/feat/landing
MINJI121 Oct 1, 2025
25efbef
:memo: docs : README 작성
sori4606 Oct 1, 2025
964fb15
:wrench: :lipstick: fix : interest-page UI 오류 해결
sori4606 Oct 1, 2025
f1bdce1
:memo: docs: README.md 내용 수정
MINJI121 Oct 1, 2025
0d3d2b2
:wrench: :lipstick: fix : interest-page UI 오류 해결
sori4606 Oct 1, 2025
a81d5ad
Merge pull request #43 from team-monew/feat/landing
MINJI121 Oct 1, 2025
361ceb5
:memo: docs: README.md 내용 수정
MINJI121 Oct 1, 2025
14418f3
Merge pull request #45 from team-monew/feat/landing
MINJI121 Oct 1, 2025
784885a
chore: 폴더 구조 변경: 레이아웃·페이지 등 앱 관련 src/app 하위 이동, 공통 컴포넌트 폴더 src/shared…
MINJI121 Oct 1, 2025
8bda752
chore: 파일 위치 변경: ProfileCard, EditNicknameButton을 features/user/compo…
MINJI121 Oct 1, 2025
da30c60
:recycle: refactor: 로그아웃 시 랜딩 페이지로 리다이렉트
MINJI121 Oct 1, 2025
f726e36
chore: 에러 정규화 유틸 lib/nomalizeError.ts 분리
MINJI121 Oct 1, 2025
34e91f1
chore: 에러 정규화 유틸 lib/nomalizeError.ts 분리
MINJI121 Oct 1, 2025
4ca345d
:wrench: fix : 최근 본 기사 탭에서 기사 누르면 모달이 안 뜨는 오류 해결
sori4606 Oct 1, 2025
08e847a
:recycle: refactor(activities): CommentHistoryCard 기사 제목 링크 제거
MINJI121 Oct 1, 2025
02cf2b0
:wrench: fix : 댓글 데이터 안보이는 현상 해결
sori4606 Oct 1, 2025
3d83f11
:wrench: fix : 최근 본 기사 탭에서 기사 누르면 모달이 안 뜨는 오류 해결
sori4606 Oct 1, 2025
e47ab4f
chore: index.html favicon type 속성 제거(불필요)
MINJI121 Oct 1, 2025
72ff332
chore: merge conflict 해결
MINJI121 Oct 1, 2025
34d04ba
:memo: docs: README.md 폴더 구조 추가
MINJI121 Oct 1, 2025
8cdc67e
:memo: docs: README.md 누락 폴더 추가
MINJI121 Oct 1, 2025
318080c
:memo: docs: README.md 폴더 구조 간략화
MINJI121 Oct 1, 2025
10db9c1
:memo: docs: README.md 폴더 구조 간략화
MINJI121 Oct 1, 2025
cdccadf
Merge pull request #48 from team-monew/feat/activities
MINJI121 Oct 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
265 changes: 199 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,202 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

```js
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...

// Remove tseslint.configs.recommended and replace with this
...tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
...tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
...tseslint.configs.stylisticTypeChecked,

// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&color=E3F2FD&height=200&section=header&text=Monew&fontSize=80&fontColor=1976D2&animation=fadeIn"/>
</div>

### 🖐️ 프로젝트 소개

<div align="center">
<img src="./src/assets/readme/landing.png"/>
</br>
</br>
<blockquote>여러 뉴스 API를 통합하여 사용자에게 맞춤형 뉴스를 제공하고, 의견을 나눌 수 있는 소셜 기능을 갖춘 서비스
</blockquote>
</br>
</br>
</br>
</div>
<div align="center">
<p>
<strong>Monew</strong>는 사용자가 등록한 관심사를 기반으로 개인화된 뉴스를 제공하고, 댓글과 좋아요를 통해 다른 사용자들과 의견을 나눌 수 있는 소셜 뉴스 플랫폼입니다.
</p>
<nav>
<a href="#서비스소개">📅 서비스 소개</a></br>
<a href="#시작하기">🚀 시작하기</a></br>
<a href="#주요기술스택">💎 주요 기술 스택</a></br>
<a href="#폴더 구조">🗂️ 폴더 구조</a></br>
<a href="#팀원소개">🧑 팀원 소개</a></br>
</nav>

<br/>

</div>
<h2 id="서비스소개">📅 서비스 소개</h2>
<div align="center">
<section>
<h3>📰 맞춤형 뉴스 큐레이션</h3>
<p>
📢 관심사를 등록하면 관련된 뉴스 기사를 자동으로 추천받을 수 있습니다.</br>
📢 여러 뉴스 API를 통합하여 다양한 출처의 뉴스를 한 곳에서 확인할 수 있습니다.
</p>
<img src="./src/assets/readme/news.png" width="800px"/>
</section>
</br>
<section>
<h3>💬 소셜 기능으로 의견 공유</h3>
<p>📢 뉴스 기사에 댓글을 달아 다른 사용자들과 의견을 나눌 수 있습니다.</br>
📢 수정 및 삭제 기능을 통해 자유롭게 소통할 수 있습니다.</br>
📢 좋아요 기능으로 관심 있는 뉴스와 댓글에 공감을 표현할 수 있습니다.
</p>
<img src="./src/assets/readme/reply.png" width="500px"/>
</section>
</br>
</br>
<section>
<h3>⏬아래 링크를 클릭하시면 더 다양한 기능들을 만날 수 있습니다!⏬</h3>
<a href="https://monew.vercel.app">⏩지금 Monew 사용하러 가보기!⏪</a>
</section>
</div>

<br />

<h2 id="시작하기">🚀 시작하기</h2>

### 사전 요구사항

- Node.js 20.19+ 또는 22.12+ 이상 (Vite 요구사항)
- npm 또는 yarn

> ⚠️ Node.js 버전 확인
>
> ```bash
> node -v
> ```
>
> 버전이 낮다면 [Node.js 공식 사이트](https://nodejs.org/)에서 최신 LTS 버전을 설치하세요.

### 설치방법

1. **저장소 클론**

```bash
git clone https://github.com/team-monew/Monew.git .
```

2. **의존성 설치**

```bash
npm install
# 또는
yarn install
```

### 실행방법

#### **개발 서버 실행**

```bash
npm run dev
# 또는
yarn dev
```

브라우저에서 `http://localhost:5173` 접속

#### **프로덕션 빌드**

```bash
npm run build
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
<br />

<h2 id="주요기술스택">💎 주요 기술 스택</h2>

| 기술 이름 | 선정 이유 |
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| ![Static Badge](https://img.shields.io/badge/React-61DAFB?style=for-the-badge&logo=react&logoColor=black) | 컴포넌트 기반 설계 방식으로 재사용 가능한 UI를 구축하고, Virtual DOM을 통한 효율적인 렌더링을 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white) | Props 타입 지정으로 인한 런타임 오류 감소, IDE 자동 완성 기능 등 타입 안정성을 통한 코드 품질 개선을 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/Vite-646CFF?style=for-the-badge&logo=vite&logoColor=white) | 빠른 개발 서버 시작 속도와 HMR(Hot Module Replacement)을 통한 개발 생산성 향상을 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/React_Router-CA4245?style=for-the-badge&logo=react-router&logoColor=white) | SPA에서 클라이언트 사이드 라우팅을 구현하고, 페이지 전환 시 부드러운 사용자 경험을 제공하기 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/Axios-5A29E4?style=for-the-badge&logo=axios&logoColor=white) | axios instance의 interceptor 기능을 통한 중복 코드 최소화 및 여러 뉴스 API 통합 관리를 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/Tailwind_CSS-06B6D4?style=for-the-badge&logo=tailwind-css&logoColor=white) | 유틸리티 클래스 사용으로 클래스 네이밍 고민 감소, 디자인 시스템이 미흡할 시 유연한 대응이 가능하기에 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/date--fns-770C56?style=for-the-badge&logo=date-fns&logoColor=white) | 경량화된 날짜 처리 라이브러리로 뉴스 게시 시간, 댓글 작성 시간 등을 직관적으로 포맷팅하기 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/React_Toastify-45CC11?style=for-the-badge&logo=react&logoColor=white) | 사용자 액션(좋아요, 댓글 작성, 관심사 등록 등)에 대한 즉각적인 피드백을 제공하여 UX를 향상시키기 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/ESLint-4B32C3?style=for-the-badge&logo=eslint&logoColor=white) | 코드 품질 향상과 일관된 코딩 스타일 유지, 잠재적 버그를 사전에 방지하기 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/Prettier-F7B93E?style=for-the-badge&logo=prettier&logoColor=black) | 자동 코드 포맷팅을 통한 일관된 코드 스타일 유지 및 팀원 간 코드 리뷰 시 스타일 논쟁을 줄이기 위해 선정했습니다. |
| ![Static Badge](https://img.shields.io/badge/Husky-000000?style=for-the-badge&logo=git&logoColor=white) | Git hooks를 통한 커밋 전 자동 린트 및 포맷팅 검사로 코드 품질을 보장하고, 불필요한 커밋을 방지하기 위해 선정했습니다. |

<br />

<h2 id="폴더 구조">🗂️ 폴더 구조</h2>

```text
MONEW/
├─ public/
│ ├─ fonts/
│ └─ favicon.ico
├─ src/
│ ├─ api/ # 리소스별 API 래퍼 : index.ts + types.ts 페어
│ │ ├─ articles/
│ │ ├─ comments/
│ │ ├─ interests/
│ │ ├─ notifications/
│ │ ├─ user-activities/
│ │ └─ users/
│ ├─ app/ # 레이아웃/라우트 프레임
│ │ ├─ layouts/
│ │ └─ routes/
│ │ ├─ public/
│ │ └─ private/
│ │ └─ App.tsx
│ ├─ assets/ # 앱에서 쓰는 정적 에셋
│ │ ├─ icons/
│ │ ├─ images/
│ │ └─ logos/
│ ├─ features/ # 도메인 단위 UI/로직
│ │ ├─ activities/
│ │ ├─ articles/
│ │ ├─ auth/
│ │ ├─ comments/
│ │ ├─ interests/
│ │ ├─ notifications/
│ │ └─ user/
│ ├─ shared/ # 전역 공용 레이어
│ │ ├─ components/
│ │ ├─ constants/
│ │ ├─ hooks/
│ │ ├─ lib/
│ │ ├─ utils/
│ │ ├─ styles/
│ │ └─ types/
│ └─ main.tsx
```

<br/>

<h2 id="팀원소개">🧑 팀원 소개</h2>

<a href="https://www.notion.so/26f2c744f86a8000bdb0d71497422216?source=copy_link">📑 프로젝트 협업 문서(노션) 바로가기</a>

<div align="center">
<table>
<tr>
<td align="center" width="150px">
<a href="https://github.com/member1">
<img src="https://avatars.githubusercontent.com/u/189521259?v=4" width="120px" alt="조민지"/>
</a>
<br />
<a href="https://github.com/member1"><b>조민지</b></a>
</td>
<td align="center" width="150px">
<a href="https://github.com/sori4606">
<img src="https://avatars.githubusercontent.com/u/110970570?v=4" width="120px" alt="송형진"/>
</a>
<br />
<a href="https://github.com/sori4606"><b>송형진</b></a>
</td>
</tr>
</table>
</div>
<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&color=E3F2FD&height=200&section=footer&fontSize=80" />
</div>
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MONEW</title>
</head>
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router": "^7.9.1",
"react-router-dom": "^7.9.2",
"react-router-dom": "^7.9.3",
"react-toastify": "^11.0.5"
},
"devDependencies": {
Expand Down
33 changes: 0 additions & 33 deletions src/App.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/api/articles/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export type GetArticlesParams = {
cursor?: string;
after?: string;
limit: number;
requestUserId: UserId;
requestUserId?: UserId;
};

/* 뉴스 기사 목록 조회 - 응답 */
Expand Down
1 change: 1 addition & 0 deletions src/api/comments/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export type LikeCommentResponse = {
createdAt: string;
commentId: CommentId;
articleId: ArticleId;
articleTitle: string;
commentUserId: UserId;
commentUserNickname: string;
commentContent: string;
Expand Down
5 changes: 4 additions & 1 deletion src/api/user-activities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ import type * as T from "@/api/user-activities/types";
import type { UserId } from "@/types/ids";

export async function getUserActivities(userId: UserId) {
await http.get<T.GetUserActivitiesResponse>(`/user-activities/${userId}`);
const { data } = await http.get<T.GetUserActivitiesResponse>(
`/user-activities/${userId}`,
);
return data;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Outlet } from "react-router";
import { PrivateHeader } from "@/components/gnb";
import Footer from "@/components/Footer";
import { PrivateHeader } from "@/shared/components/gnb";
import Footer from "@/shared/components/Footer";

export default function PrivateLayout() {
return (
Expand Down
Loading
Loading