알림 조회 및 확인 기능을 제공하는 API입니다. 사용자의 팔로우, 좋아요, 댓글, 메시지 관련 알림을 관리하며, 실시간 푸시 알림과 Socket.io와 연동됩니다. 본인의 알림만 조회할 수 있으며, 타인의 알림 대상이 되는 API는 제공되지 않습니다.
- Base URL:
http://localhost:3001 - 인증 방식: JWT Bearer Token (Authorization 헤더) 또는 HTTP-only 쿠키
- 응답 형식: JSON
- 페이지네이션 방식: Offset-based 페이지네이션
- 캐싱: Redis 캐시 활용 (읽지 않은 알림 개수 캐시)
{
"code": 200,
"message": "요청 성공 메시지",
"data": {
// 응답 데이터
}
}{
"code": 400,
"message": "오류 메시지",
"errors": [
{
"field": "필드명",
"message": "상세 오류 메시지"
}
]
}쿠키에서 자동으로 accessToken 추출
Cookie: accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Authorization 헤더에 Bearer 토큰 포함
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...GET /notifications
본인의 알림 목록을 페이지네이션과 필터링으로 조회합니다.
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
| offset | number | 선택 | 0 | 건너뛸 알림 수 (페이지네이션) |
| limit | number | 선택 | 20 | 조회할 최대 알림 수 (최대: 100) |
| type | string | 선택 | - | 알림 타입 필터 ("followed", "feed_liked", "post_liked", "feed_commented", "post_commented", "feed_created", "post_created", "message") |
| isRead | boolean | 선택 | - | 읽음 상태 필터 (true: 읽음, false: 안읽음) |
📋 offset:
- 범위: 0 이상의 정수
- 역할: 다음 알림 목록을 가져올 시작점을 지정
- 예시:
offset=0(첫 페이지),offset=20(두 번째 페이지)
📋 limit:
- 범위: 1-100 사이의 정수 (기본값: 20)
- 역할: 한 번에 가져올 알림 최대 개수 지정
- 목적: 성능 최적화 및 UI 로딩 속도 개선
- 예시:
limit=20(페이지당 20개),limit=50(페이지당 50개)
📋 type:
- 허용값:
"followed"|"feed_liked"|"post_liked"|"feed_commented"|"post_commented"|"feed_created"|"post_created"|"message" - 역할: 특정 타입의 알림만 조회
- 예시:
type=followed(팔로우 알림만),type=post_liked(게시물 좋아요 알림만)
📋 isRead:
- 허용값:
true(읽음) |false(안읽음) - 역할: 읽음 상태에 따른 알림 필터링
- 예시:
isRead=false(안 읽은 알림만),isRead=false(읽은 알림만)
# 전체 알림 목록 조회 (기본값 사용)
GET /notifications
# 다음 페이지 조회 (offset=20, limit=10)
GET /notifications?offset=20&limit=10
# 안 읽은 팔로우 알림만 조회
GET /notifications?type=follow&isRead=false&limit=50
# 읽음 상태에 관계없이 좋아요 알림 모두 조회
GET /notifications?type=like✅ 기본 응답 (전체 알림 목록 조회 성공):
{
"code": 200,
"message": "알림 목록을 조회했습니다.",
"data": {
"notifications": [
{
"id": 12345,
"type": "followed",
"sender": {
"id": 2,
"nickname": "홍길동",
"profile_img": "http://localhost:3001/uploads-profile/2024/01/user2.jpg"
},
"message": "홍길동님이 당신을 팔로우했습니다.",
"reference_id": null,
"is_read": false,
"created_at": "2024-01-15T14:30:25.000Z"
},
{
"id": 12344,
"type": "post_liked",
"sender": {
"id": 3,
"nickname": "김철수",
"profile_img": null
},
"message": "김철수님이 회원님의 게시물을 좋아합니다.",
"reference_id": 456,
"is_read": true,
"created_at": "2024-01-15T14:25:12.000Z"
},
{
"id": 12343,
"type": "post_commented",
"sender": {
"id": 4,
"nickname": "이영희",
"profile_img": "http://localhost:3001/uploads-profile/2024/01/user4.jpg"
},
"message": "이영희님이 회원님의 게시물에 댓글을 남겼습니다.",
"reference_id": 789,
"is_read": false,
"created_at": "2024-01-15T14:20:33.000Z"
}
],
"total_count": 150,
"unread_count": 12,
"has_more": true
}
}✅ 필터링 적용 (안 읽은 팔로우 알림만 조회):
{
"code": 200,
"message": "알림 목록을 조회했습니다.",
"data": {
"notifications": [
{
"id": 12345,
"type": "followed",
"sender": {
"id": 2,
"nickname": "홍길동",
"profile_img": "http://localhost:3001/uploads-profile/2024/01/user2.jpg"
},
"message": "홍길동님이 당신을 팔로우했습니다.",
"reference_id": null,
"is_read": false,
"created_at": "2024-01-15T14:30:25.000Z"
}
],
"total_count": 5,
"unread_count": 12,
"has_more": false
}
}📊 Root Data Object:
| Field | Type | Required | Description |
|---|---|---|---|
| notifications | array | ✅ | 알림 데이터 배열 (최대 limit 개수만큼) |
| total_count | number | ✅ | 해당 필터 조건의 전체 알림 개수 |
| unread_count | number | ✅ | 전체 읽지 않은 알림 개수 (필터 무관) |
| has_more | boolean | ✅ | 다음 페이지 존재 여부 (offset + limit < total_count) |
📝 Notification Item Object:
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | ✅ | 알림 고유 ID (Socket.io 실시간 이벤트에 사용) |
| type | string | ✅ | 알림 타입 ("followed" | "feed_liked" | "post_liked" | "feed_commented" | "post_commented" | "feed_created" | "post_created" | "message") |
| sender | object | ✅ | 알림을 보낸 사용자 정보 |
| message | string | ✅ | 알림 메시지 텍스트 |
| reference_id | number | null | ✅ | 참조 리소스 ID (게시글/피드 등) |
| is_read | boolean | ✅ | 읽음 상태 (클라이언트 UI 렌더링용) |
| created_at | string | ✅ | 알림 생성 시간 (ISO 8601 포맷) |
👤 Sender Object (알림 발신자 정보):
| Field | Type | Required | Description |
|---|---|---|---|
| id | number | ✅ | 발신자 사용자 고유 ID |
| nickname | string | ✅ | 발신자 닉네임 |
| profile_img | string | null | ✅ | 발신자 프로필 이미지 URL (없으면 null) |
| 알림 타입 | reference_id 의미 | 사용처 |
|---|---|---|
followed |
null | 팔로우는 직접적인 리소스 참조 불필요 |
feed_liked |
피드 ID | 좋아요 대상 피드 식별 |
post_liked |
게시글 ID | 좋아요 대상 게시글 식별 |
feed_commented |
피드 ID | 댓글 달린 피드 식별 |
post_commented |
게시글 ID | 댓글 달린 게시글 식별 |
feed_created |
피드 ID | 새로 작성된 피드 ID |
post_created |
게시글 ID | 새로 작성된 게시글 ID |
message |
채팅방 ID | 메시지가 도착한 채팅방 식별 |
✅ message 필드 (알림 메시지):
// 팔로우 알림
"홍길동님이 당신을 팔로우했습니다."""
// 좋아요 알림
"김철수님이 회원님의 게시물을 좋아합니다."""
// 댓글 알림
"이영희님이 회원님의 게시물에 댓글을 남겼습니다."""
// 게시글 알림
"박민수님이 새로운 게시글을 작성했습니다."""
// 메시지 알림
"홍길동님이 메시지를 보냈습니다.""📱 React Component 예시:
const NotificationList = () => {
const [notifications, setNotifications] = useState([]);
const [unreadCount, setUnreadCount] = useState(0);
const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);
// 알림 목록 로드
const loadNotifications = async (offset = 0, type = '', showRead = null) => {
try {
setLoading(true);
const params = new URLSearchParams();
params.set('offset', offset.toString());
params.set('limit', '20');
if (type) params.set('type', type);
if (showRead !== null) params.set('isRead', showRead.toString());
const response = await fetch(`/notifications?${params}`, {
headers: { 'Authorization': `Bearer ${token}` }
});
const result = await response.json();
if (response.ok) {
const { notifications: newNotifications, unread_count: unreadCount, has_more: hasMore } = result.data;
if (offset === 0) {
setNotifications(newNotifications);
} else {
setNotifications(prev => [...prev, ...newNotifications]);
}
setUnreadCount(unreadCount);
setHasMore(hasMore);
} else {
console.error('알림 조회 실패:', result.message);
}
} catch (error) {
console.error('네트워크 오류:', error);
} finally {
setLoading(false);
}
};
// 컴포넌트 마운트 시 로드
useEffect(() => {
loadNotifications();
}, []);
// 더보기 버튼 핸들러
const handleLoadMore = () => {
const nextOffset = notifications.length;
loadNotifications(nextOffset);
};
// 필터링 핸들러
const handleFilter = (type, showRead) => {
loadNotifications(0, type, showRead);
setNotifications([]);
};
return (
<div className="notification-list">
<div className="notification-header">
<h2>알림 <span className="unread-badge">{unreadCount}</span></h2>
<div className="filter-buttons">
<button onClick={() => handleFilter('follow', false)}>안 읽은 팔로우</button>
<button onClick={() => handleFilter('like', null)}>전체 좋아요</button>
<button onClick={() => handleFilter('', null)}>모두</button>
</div>
</div>
<div className="notifications">
{notifications.map(notification => (
<NotificationItem
key={notification.id}
notification={notification}
onMarkAsRead={(id) => markNotificationAsRead(id)}
/>
))}
{hasMore && (
<button
onClick={handleLoadMore}
disabled={loading}
className="load-more-btn"
>
{loading ? '로딩 중...' : '더보기'}
</button>
)}
</div>
</div>
);
};PATCH /notifications/read
특정 알림들을 읽음 상태로 업데이트합니다.
{
"notificationIds": [12345, 12344, 12343]
}| Field | Type | Required | Description |
|---|---|---|---|
| notificationIds | number[] | ✅ | 읽음 처리할 알림 ID 배열 |
📋 notificationIds:
- 형식: 숫자 배열 (examples:
[123, 124, 125]) - 개수 제한: 1개 ~ 무제한
- 각 요소: 양의 정수 (알림 ID)
- 중복 허용: 동일 ID 여러 번 포함 가능 (중복 제거 처리)
🔍 Validation Examples:
// ✅ 올바른 예시들
[123, 456, 789]
[999]
[1, 1, 2] // 중복 허용, 내부적으로 중복 제거됨
// ❌ 잘못된 예시들
[] // 빈 배열 (최소 1개 필요)
"123" // 문자열 (배열이어야 함)
[0] // 0은 유효하지 않은 ID
[-1, 123] // 음수는 유효하지 않은 ID
["abc"] // 문자열 요소 (숫자만 허용)
null // null 허용하지 않음✅ 기본 사용 (여러 알림들이 읽음 처리):
# 여러 알림 읽음 처리
curl -X PATCH http://localhost:3001/notifications/read \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_token_here" \
-d '{
"notificationIds": [12345, 12346, 12347]
}'✅ 단일 알림 읽음 처리:
# 하나의 알림만 읽음 처리
curl -X PATCH http://localhost:3001/notifications/read \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_token_here" \
-d '{
"notificationIds": [12345]
}'✅ 정상 응답:
{
"code": 200,
"message": "2개의 알림을 읽음 처리했습니다.",
"data": {
"affectedRows": 2
}
}✅ 모두 새로운 알림인 경우:
{
"code": 200,
"message": "3개의 알림을 읽음 처리했습니다.",
"data": {
"affectedRows": 3
}
}✅ 이미 읽은 알림이 포함된 경우:
{
"code": 200,
"message": "2개의 알림을 읽음 처리했습니다.",
"data": {
"affectedRows": 2 // 이미 읽은 1개는 카운트되지 않음
}
}| Field | Type | Required | Description |
|---|---|---|---|
| affectedRows | number | ✅ | 실제로 읽음 처리된 알림 개수 (0 이상 정수) |
const markNotificationsAsRead = async (notificationIds) => {
try {
const response = await fetch('/notifications/read', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
notificationIds: notificationIds
})
});
const result = await response.json();
if (response.ok) {
const { affectedRows } = result.data;
// UI 업데이트: 알림들을 읽음으로 표시
updateNotificationsReadStatus(notificationIds, true);
// 전역 읽지 않은 알림 개수 업데이트
updateGlobalUnreadCount(-affectedRows);
// 성공 메시지 표시
showToast(`${affectedRows}개의 알림을 읽음 처리했습니다.`);
} else {
// 에러 처리
console.error('읽음 처리 실패:', result.message);
showErrorToast(result.message);
}
} catch (error) {
console.error('네트워크 에러:', error);
showErrorToast('알림 읽음 처리 중 오류가 발생했습니다.');
}
};PATCH /notifications/read-all
모든 읽지 않은 알림을 일괄 읽음 처리합니다.
이 API는 Request Body가 필요하지 않습니다.
# 모든 읽지 않은 알림을 읽음 처리
curl -X PATCH http://localhost:3001/notifications/read-all \
-H "Authorization: Bearer your_token_here"{
"code": 200,
"message": "모든 알림을 읽음 처리했습니다.",
"data": {
"affectedRows": 5
}
}| Field | Type | Required | Description |
|---|---|---|---|
| affectedRows | number | ✅ | 읽음 처리된 알림 개수 (읽지 않은 알림만 카운트) |
📱 React Hook 예시:
const useMarkAllAsRead = () => {
const [markingAll, setMarkingAll] = useState(false);
const markAllAsRead = useCallback(async () => {
if (markingAll) return; // 중복 요청 방지
try {
setMarkingAll(true);
const response = await fetch('/notifications/read-all', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`
}
});
const result = await response.json();
if (response.ok) {
const { affectedRows } = result.data;
// 모든 알림을 읽음으로 업데이트
setNotifications(prev => prev.map(notification => ({
...notification,
isRead: true
})));
// 읽지 않은 개수 0으로 리셋
setUnreadCount(0);
// 성공 토스트 메시지
showToast(`총 ${affectedRows}개의 알림을 읽음 처리했습니다.`);
} else {
showErrorToast(result.message);
}
} catch (error) {
console.error('모든 알림 읽음 처리 실패:', error);
showErrorToast('알림 처리 중 오류가 발생했습니다.');
} finally {
setMarkingAll(false);
}
}, [markingAll, token]);
return { markAllAsRead, markingAll };
};GET /notifications/unread-count
현재 로그인한 사용자의 전체 읽지 않은 알림 개수를 조회합니다. 상태 표시줄이나 헤더의 배지 아이콘에 표시하는 용도로 사용됩니다.
이 API는 Query Parameter나 Request Body가 필요하지 않습니다.
# 읽지 않은 알림 개수 조회
curl -X GET http://localhost:3001/notifications/unread-count \
-H "Authorization: Bearer your_token_here"{
"code": 200,
"message": "읽지 않은 알림 개수를 조회했습니다.",
"data": {
"unread_count": 12
}
}| Field | Type | Required | Description |
|---|---|---|---|
| unread_count | number | ✅ | 읽지 않은 알림 개수 (0 이상 정수) |
💡 주요 사용처:
// 1. 탭/헤더바에 배지 표시
<TabBarBadge>
<BellIcon />
{unreadCount > 0 && <Badge count={unreadCount} />}
</TabBarBadge>
// 2. 알림 버튼에 전역 상태 표시
const NotificationButton = () => {
const { unreadCount } = useNotificationStore();
return (
<button className="notification-btn">
<BellIcon />
{unreadCount > 0 && (
<span className="badge">{unreadCount > 99 ? '99+' : unreadCount}</span>
)}
</button>
);
};📊 캐싱 설계:
// Redux Store 예시
interface NotificationState {
unreadCount: number;
lastFetched: Date | null;
isLoading: boolean;
}
// 컴포넌트 레벨 캐시 (useNotificationStore)
const useUnreadCount = () => {
const store = useNotificationStore();
const dispatch = useNotificationDispatch();
useEffect(() => {
// 5분 캐시 정책
const CACHE_DURATION = 5 * 60 * 1000; // 5분
if (!store.isLoading &&
(!store.lastFetched ||
Date.now() - store.lastFetched.getTime() > CACHE_DURATION)) {
dispatch(fetchUnreadCount());
}
}, [store.lastFetched, store.isLoading, dispatch]);
return {
unreadCount: store.unreadCount,
isLoading: store.isLoading
};
};🔄 실시간 동기화 현황:
// 1. 새로운 알림 도착 시 (Socket.io 이벤트)
notificationSocket.on('notification:follow', (notification) => {
dispatch(incrementUnreadCount());
showPushNotification(notification.message, notification.sender);
});
// 2. 알림 읽음 처리 시
const markAsRead = async (notificationIds) => {
const result = await API.markNotificationsAsRead(notificationIds);
if (result.affectedRows > 0) {
dispatch(decrementUnreadCount(result.affectedRows));
}
};
// 3. 로그인 시 초기 로드
const initializeUnreadCount = useCallback(async () => {
const { unreadCount } = await API.getUnreadCount();
dispatch(setUnreadCount(unreadCount));
}, [dispatch]);- 200: 성공
- 400: 잘못된 요청 (validation 실패, 잘못된 파라미터)
- 401: 인증 필요
- 404: 리소스 없음 (사용자를 찾을 수 없음)
- 500: 서버 내부 오류
{
"code": 400,
"message": "오류 메시지",
"errors": [
{
"field": "notificationIds",
"message": "알림 ID는 숫자 배열이어야 합니다."
}
]
}❌ Offset 파라미터 오류:
{
"code": 400,
"message": "offset은 0 이상의 숫자여야 합니다.",
"errors": [
{
"field": "offset",
"message": "offset은 0 이상의 숫자여야 합니다."
}
]
}❌ Limit 파라미터 오류:
{
"code": 400,
"message": "limit은 1-100 사이의 값이어야 합니다.",
"errors": [
{
"field": "limit",
"message": "limit은 1-100 사이의 값이어야 합니다."
}
]
}❌ Type 파라미터 오류:
{
"code": 400,
"message": "알림 타입은 'followed', 'feed_liked', 'post_liked', 'feed_commented', 'post_commented', 'feed_created', 'post_created', 'message' 중 하나여야 합니다.",
"errors": [
{
"field": "type",
"message": "알림 타입은 'followed', 'feed_liked', 'post_liked', 'feed_commented', 'post_commented', 'feed_created', 'post_created', 'message' 중 하나여야 합니다."
}
]
}❌ notificationIds 배열 형식 오류:
{
"code": 400,
"message": "notificationIds는 숫자 배열이어야 합니다.",
"errors": [
{
"field": "notificationIds",
"message": "notificationIds는 숫자 배열이어야 합니다."
}
]
}❌ 빈 배열 오류:
{
"code": 400,
"message": "notificationIds는 최소 1개 이상이어야 합니다.",
"errors": [
{
"field": "notificationIds",
"message": "notificationIds는 최소 1개 이상이어야 합니다."
}
]
}❌ 존재하지 않는 알림 ID:
{
"code": 200,
"message": "0개의 알림을 읽음 처리했습니다.",
"data": {
"affectedRows": 0
}
}❌ 인증 토큰 없음:
{
"code": 401,
"message": "인증 토큰이 필요합니다.",
"errors": []
}❌ 유효하지 않은 토큰:
{
"code": 401,
"message": "유효하지 않은 토큰입니다.",
"errors": []
}❌ 데이터베이스 연결 오류:
{
"code": 500,
"message": "알림 조회 중 서버 오류가 발생했습니다.",
"errors": []
}# 웹 쿠키 인증
curl -X GET "http://localhost:3001/notifications?limit=10&type=follow" \
--cookie "accessToken=your_jwt_token"
# 모바일 Bearer 토큰
curl -X GET "http://localhost:3001/notifications?limit=10&type=follow" \
-H "Authorization: Bearer your_jwt_token" \
-H "Content-Type: application/json"# 특정 알림 읽음 처리
curl -X PATCH http://localhost:3001/notifications/read \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_jwt_token" \
-d '{
"notificationIds": [12345, 12346, 12347]
}'
# 모든 알림 읽음 처리
curl -X PATCH http://localhost:3001/notifications/read-all \
-H "Authorization: Bearer your_jwt_token"curl -X GET http://localhost:3001/notifications/unread-count \
-H "Authorization: Bearer your_jwt_token"CREATE TABLE Notification (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
receiver_id BIGINT NOT NULL, -- 수신자 ID
sender_id BIGINT NOT NULL, -- 발신자 ID
type ENUM('follow', 'like', 'comment', 'post'), -- 알림 타입
reference_id BIGINT, -- 참조 리소스 ID
message VARCHAR(255), -- 알림 메시지
is_read TINYINT DEFAULT 0, -- 읽음 상태
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, -- 생성 시간
CONSTRAINT fk_notification_receiver FOREIGN KEY(receiver_id) REFERENCES User(id) ON DELETE RESTRICT,
CONSTRAINT fk_notification_sender FOREIGN KEY(sender_id) REFERENCES User(id) ON DELETE RESTRICT
);- receiver_id: 알림을 받는 사용자 (외래키 → User.id)
- sender_id: 알림을 보낸 사용자 (외래키 → User.id)
- reference_id: 타입별 참조 리소스 ID
follow: null (팔로우는 대상 없음)like: 게시글 또는 피드 IDcomment: 게시글 또는 피드 IDpost: 새 게시글 ID
receiver_id≠sender_id(자기 자신에게 알림 불가)type은 ENUM으로 제한된 값만 허용- 각 필드에 대한 인덱스 설정으로 빠른 조회 보장
-- 필수 인덱스들
CREATE INDEX idx_notification_receiver_created ON Notification(receiver_id, created_at DESC);
CREATE INDEX idx_notification_receiver_isread ON Notification(receiver_id, is_read);
CREATE INDEX idx_notification_type ON Notification(type);
-- 복합 조회용 인덱스
CREATE INDEX idx_notification_receiver_type_created ON Notification(receiver_id, type, created_at DESC);- 인덱스: 수신자 ID + 생성시간 역순으로 클러스터링 인덱스
- 파티셔닝: 시간 기반 파티셔닝으로 대용량 데이터 처리
- Archive 정책: 오래된 알림 자동 삭제 (6개월 이상)
- 읽지 않은 개수 캐시: Redis cache (TTL: 5분)
- 알림 목록 캐시: 분단위 캐시 (TTL: 1분)
- 실시간 갱신: Socket.io 이벤트 수신 시 즉시 캐시 무효화
- 커서 페이지네이션: ID 기반 커서로 인덱스 효율적 이용
- 제한 개수: 한 번에 최대 100개로 성능 부하 방지
- 데이터 프로젝션: 필요한 필드만 select로 트래픽 최소화
- 바인딩된 알림 개수: 사용자당 최대 1000개 알림 유지
- 시스템 알림: 중요하지 않은 알림은 자동 필터링
- 알림 요약: 동일한 유형의 알림을 그룹화하여 병합
- 타입별 알림 켜기/끄기: 팔로우, 좋아요, 댓글 등 세부 설정
- 푸시 알림: 브라우저 푸시와 앱 푸시 별도 설정
- 음소거 시간대: 특정 시간대 알림 차단 기능
- 알림 브로커: 대용량 알림 처리를 위한 메시지 큐 도입
- 캐시 클러스터링: 여러 서버 간 캐시 동기화
- 알림 스토리지: MongoDB나 Elasticsearch로 실시간 검색 지원
이제 Redis, MongoDB, RabbitMQ 등 인프라 확장은 추후 요구사항에 따라 구현되어 구조적인 확장성을 보장합니다.
기존 Notification API에 알림 설정 관리를 위한 API가 추가되었습니다.
GET /notification-settings
현재 로그인한 사용자의 모든 알림 설정을 조회합니다.
curl -X GET http://localhost:3001/notification-settings \
-H "Authorization: Bearer your_jwt_token"{
"success": true,
"data": {
"follow_notification": true,
"feed_like_notification": true,
"post_like_notification": false,
"short_like_notification": true,
"feed_comment_notification": true,
"post_comment_notification": true,
"short_comment_notification": false,
"dm_notification": true,
"feed_created_notification": true,
"post_created_notification": true,
"short_created_notification": true
},
"message": "알림 설정을 조회했습니다."
}| Field | Type | Required | Description |
|---|---|---|---|
| follow_notification | boolean | ✅ | 팔로우 알림 설정 |
| feed_like_notification | boolean | ✅ | 피드 좋아요 알림 설정 |
| post_like_notification | boolean | ✅ | 게시글 좋아요 알림 설정 |
| short_like_notification | boolean | ✅ | 숏츠 좋아요 알림 설정 |
| feed_comment_notification | boolean | ✅ | 피드 댓글 알림 설정 |
| post_comment_notification | boolean | ✅ | 게시글 댓글 알림 설정 |
| short_comment_notification | boolean | ✅ | 숏츠 댓글 알림 설정 |
| dm_notification | boolean | ✅ | DM 알림 설정 |
| feed_created_notification | boolean | ✅ | 피드 작성 알림 설정 |
| post_created_notification | boolean | ✅ | 게시글 작성 알림 설정 |
| short_created_notification | boolean | ✅ | 숏츠 작성 알림 설정 |
PUT /notification-settings
알림 설정을 부분적으로 업데이트합니다. 요청한 필드만 변경되고 나머지는 기존 설정을 유지합니다.
업데이트할 알림 설정 필드를 JSON 객체로 전달합니다.
{
"follow_notification": true,
"feed_like_notification": false,
"post_comment_notification": true
}| Field | Type | Required | Description |
|---|---|---|---|
| follow_notification | boolean | 선택 | 팔로우 알림 설정 변경 |
| feed_like_notification | boolean | 선택 | 피드 좋아요 알림 설정 변경 |
| post_like_notification | boolean | 선택 | 게시글 좋아요 알림 설정 변경 |
| short_like_notification | boolean | 선택 | 숏츠 좋아요 알림 설정 변경 |
| feed_comment_notification | boolean | 선택 | 피드 댓글 알림 설정 변경 |
| post_comment_notification | boolean | 선택 | 게시글 댓글 알림 설정 변경 |
| short_comment_notification | boolean | 선택 | 숏츠 댓글 알림 설정 변경 |
| dm_notification | boolean | 선택 | DM 알림 설정 변경 |
| feed_created_notification | boolean | 선택 | 피드 작성 알림 설정 변경 |
| post_created_notification | boolean | 선택 | 게시글 작성 알림 설정 변경 |
| short_created_notification | boolean | 선택 | 숏츠 작성 알림 설정 변경 |
✅ 부분 업데이트 - 좋아요 알림만 끄기:
curl -X PUT http://localhost:3001/notification-settings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_jwt_token" \
-d '{
"feed_like_notification": false,
"post_like_notification": false,
"short_like_notification": false
}'{
"success": true,
"data": {
"follow_notification": true,
"feed_like_notification": false,
"post_like_notification": false,
"short_like_notification": false,
"feed_comment_notification": true,
"post_comment_notification": true,
"short_comment_notification": false,
"dm_notification": true,
"feed_created_notification": true,
"post_created_notification": true,
"short_created_notification": true
},
"message": "알림 설정이 업데이트되었습니다."
}응답으로 업데이트된 모든 알림 설정의 최종 상태가 반환됩니다.
📱 알림 타입별 세부 제어:
- 팔로우 알림: 팔로우 요청 및 팔로우 수락/거부
- 좋아요 알림: 피드, 게시글, 숏츠별 개별 설정
- 댓글 알림: 피드, 게시글, 숏츠별 개별 설정
- DM 알림: 새로운 메시지 도착
- 작성 알림: 팔로워의 콘텐츠 작성 (피드, 게시글, 숏츠)
🔧 설정 적용 방식:
- 실시간 적용: API 호출 즉시 설정이 반영됩니다
- 부분 업데이트: 변경하지 않은 필드는 기존 설정 유지
- 기본값: 신규 가입자는 모든 알림을 허용한 상태로 시작
⚡ 알림 서비스 연동:
- 모든 알림 생성 시 사용자의 설정을 확인
- 설정이 꺼져 있는 알림 타입은 생성하지 않음
- 푸시 알림과 Socket.io 이벤트 모두 설정 적용됨