본문 바로가기

[React]

[React] React + Node.js로 사용자별 알림 기능 구현하기 (Notification System)

728x90

 

[React] 실시간 검색 - debouncing 기능 구현하기

 

[React] 실시간 검색 - debouncing 기능 구현하기

[React, Express] 서버 구현 및 데이터베이스 연결하기(REST API) [React, Express] 서버 구현 및 데이터베이스 연결하기(REST API)[EZ_Scheduler] - [React] 로그인 페이지 스타일링 [React] 로그인 페이지 스타일링📌

juyear-coding.tistory.com

이전 글 읽으러 가기! (실시간 검색 기능)

🚩소개

안녕하세요! 대학생 개발자 주이어입니다! 오늘은 React에서 사용자별 알림 기능을 구현하는 방법에 대해서 정리해보려고 합니다!
Notification System, 즉 알림 기능은 우리가 평소에 자주 사용하는 기능입니다. 유튜브에 새로운 영상이 올라오거나, 인스타그램에 새로운 게시글이 올라왔을 때 알려주는 알림이 이에 해당됩니다.

 

알림 시스템의 기본 흐름은 아래와 같습니다.

새로운 이벤트 -> 알림 추가 -> 사용자 상호작용 -> 알림 삭제

하지만 이런 시스템을 여러 사용자 동시에 사용하는 서비스에 적용하려면 사용자마다 알림 상태를 다르게 저장하고 처리해줘야 한다는 점에서 조금 더 복잡해집니다.


💻 Notification System 구현하기

📍 클라이언트 (App.jsx)

useEffect(() => {
  axios.get(`http://localhost:5000/notification/${userId}`).then((res) => {
    setNotiData(res.data);
    console.log(res.data);
  });
}, [changeNoti]);

먼저 App.jsx에서 위와 같이 userId를 이용하여 현재 사용자가 읽지 않은 알림은 서버에서 받아오도록 작성해주었습니다.
(useEffect 사용, 변경시 실행하도록 설정)

 

로그인 하기 전에는 현재 사용자가 누구인지 알 수 없으므로, 로그인 할 때, changeNoti State 변수 값을 바꿔 값을 가져오도록 해주었습니다.

📍 클라이언트 (Sidebar.jsx)

<div className="section" onClick={onClickNoti}>
  <img src={heartIcon} alt="Info" width="25" />
  <p>알림</p>
  {notiData && notiData.length > 0 && <div className="notiDot"></div>}
</div>

읽지 않은 알림이 있을 경우 알림 버튼에 빨간 점(.notiDot)을 표시해 알림이 있다는 것을 알려줄 수 있도록 만들었습니다.

const onClickNoti = () => {
  setIsOpenNoti(!isOpenNoti);
  axios
    .post("http://localhost:5000/readNoti", {
      userId,
      notiIds: notiData.map((item) => item.id),
    })
    .then((res) => {
      if (res.data.success) {
        console.log("알림 읽음.");
      }
    });
};

알림 버튼 클릭 시, 현재 읽지 않은 알림들의 ID 배열을 서버에 전송하고, 서버에서는 해당 알림들을 읽은 상태로 처리해줄 수 있도록 만들어 주었습니다.

🛠️ 서버 (server.js)

✔️ 읽지 않은 알림 가져오기

app.get("/notification/:userId", async (req, res) => {
  const userId = req.params.userId;
  const query = `
    SELECT * FROM file_info f 
    WHERE f.userId != ? 
      AND NOT EXISTS (
        SELECT 1 FROM notification_reads r 
        WHERE r.post_id = f.id AND r.reader_id = ?
      ) 
    ORDER BY f.created_at DESC
  `;

  try {
    const [result] = await db.execute(query, [userId, userId]);
    res.json(result);
  } catch (err) {
    res.json({ message: err });
  }
});

file_info 테이블에서 다른 사용자가 업로드한 게시글 중, 해당 사용자가 읽지 않은 글만 필터링 해서 가져와 주었습니다.

그 후, notifications_reads 테이블과 NOX EXISTS 조건을 이용해 읽은 기록이 없는 글만 추출해 주었습니다.

(서버는 node + express, DB는 MySQL 사용해서 만들었습니다.)

 

✔️ 알림 읽음 처리

app.post("/readNoti", async (req, res) => {
  const { userId, notiIds } = req.body;
  const query = `
    INSERT IGNORE INTO notification_reads (post_id, reader_id) 
    VALUES (?, ?)
  `;
  try {
    notiIds.map(async (id) => {
      await db.execute(query, [id, userId]);
    });
    res.json({ success: true });
  } catch (err) {
    res.json({ message: err });
  }
});

클라이언트로부터 받은 알림 ID 배열을 기반으로, 각 알림을 읽음 처리 해주었습니다. (db에 데이터 추가로 처리)

INSERT IGNORE를 사용해서 중복된 값이 있을 경우 무시하도록 처리 해주었습니다.


💻 구현 화면

알림 기능 구현 화면

위 두개의 사진을 보면 읽지 않은 알림이 있을 경우 빨간 점이 표시되고,

알림을 읽을 이후에는 빨간 점이 사라지는 것을 알 수 있습니다.

알림 화면 예시

알림 버튼을 클릭하면 위와 같이 알림 정보가 표시되는 알 수 있습니다.

한번 읽은 후 새로고침하면 더 이상 알림 정보가 나오지 않도록 해주었습니다.


😊 마무리

지금까지 React Node.jsNotification System, 알림 기능을 구현하는 방법에 대해서 정리해 보았습니다.

처음 제가 이 기능을 만들 때만 해도, 단순히 알림 데이터를 보여주기만 하면 될 줄 알았는데, 사용자별로 알림 상태를 따로 관리해야한다는 점에서 SQL 쿼리 작성이 꽤 까다로웠습니다.

 

특히 INSERT IGNORE와 NOT EXISTS와 같은 조건을 적절히 활용해야 제대로 된 알림 필터링이 가능하다는 걸 배웠습니다.

 

이 글을 읽는 분들도 한 번씩 구현해보시고, 프로젝트에 적용해보시길 바랍니다! 알림 기능은 자주 사용되는 기술이니 원리와 구조에 대해서도 공부하시는 것을 추천드립니다!

 

https://discord.gg/8Hh8WgM4zp

 

KYT CODING COMMUNITY Discord 서버에 가입하세요!

Discord에서 KYT CODING COMMUNITY 커뮤니티를 확인하세요. 20명과 어울리며 무료 음성 및 텍스트 채팅을 즐기세요.

discord.com

KYT CODING COMMUNITY 가입하기!

728x90

'[React]' 카테고리의 다른 글

[React] 실시간 검색 - debouncing 기능 구현하기  (0) 2025.04.19