Node.js

메모 앱 만들기 - frontend

imysydesu 2026. 7. 7. 19:21

 

 

 

 

순서

 

 

 

1. 백엔드로 만들었던 js 파일 연결

2. html 생성

3. js 생성

4. css 생성

 

 

 

 

 


 

 

 

백엔드로 만들었던 js 파일 연결

 

 

 

 

- 기존 백엔드 js파일에 작성

const path = require("path")
app.use(express.static(path.join(__dirname, "public")))

 

 

 

차례대로

  • Node.js 내장 모듈인 path를 가져옴 => 파일 경로를 안전하게 만들어주는 역할
  • public : 연결할 프론트의 파일들이 담긴 폴더 이름
  • static : public 폴더 안에 있는 파일들은 브라우저가 직접 접근할 수 있게 해줌
  • path.join : 폴더/파일 경로 만들어주는 함수
  • __dirname : 현재 실행 중인 js파일(백엔드 파일)이 있는 폴더의 절대 경로

 

 

 

 


 

 

 

 

 

html 생성

 

 

 

 

- public 폴더 안에 들어있는 .html 파일 (파일명: index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>메모 앱</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <div class="container">
        <h2>메모 앱</h2>
        <div class="input-area">
            <input type="text" id="memoInput" placeholder="메모를 입력하세요"> <button id="addBtn">추가</button>
        </div>
        <ul id="memoList"></ul>
    </div>
    <script src="./app.js"></script>
</body>
</html>

 

 

 

 

  • <link rel="stylesheet" href="./style.css"> : 이후 생성할 css 파일과 연결 (파일명 : style.css)
  • <script src="./app.js"></script> : 이후 생성할 .js 파일과 연결 (파일명: app.js)

 

 

 

 


 

 

 

 

 js 생성

 

 

 

 

const memoInput = document.getElementById("memoInput")
const addBtn = document.getElementById("addBtn")
const memoList = document.getElementById("memoList")

 

 

  • html파일에서 만든 id 가져오기

 

 

 

 

 

 

메모 출력 기능(화면에 보여주는)

 

function renderMemos(memos) {
    memoList.innerHTML = ""

    memos.forEach((memo) => {
        const li = document.createElement("li") // <li></li>
        li.className = "memo-item"  // <li class="memo-item"></li>
        li.innerHTML = `
            <span>${memo.text}</span>
            <div class="memo-buttons">
                <button onclick="editMemo('${memo._id}')">수정</button> <button onclick="deleteMemo('${memo._id}')">삭제</button>
            </div>
        `
        memoList.appendChild(li)
    })
}

 

 

 

  • renderMemos(memos) : 받은 메모 배열을 HTML로 만들어 화면에 보여주는 함수
  • memoList.innerHTML = "" : 기존 메모 목록 초기화 (새로운 데이터를 다시 그리기 위해)
  • memos.forEach((memo) : 메모 개수만큼 반복한다는 의미
  • li.innerHTML = `` : 내부 HTML 작성 -> 수정 버튼, 삭제 버튼
  • memoList.appendChild(li) : 만든 li를 ul안에 넣음(memoList에 연결)

 

 

 

 

 

메모 불러오기

 

// 메모 불러오기

async function loadMemos() {
    try {
        const response = await fetch("/memos")
        const data = await response.json()
        renderMemos(data.memos)
    }catch(error){
        console.log("메모 조회 실패: ", error)
    }
}

 

 

 

  • fetch("/memos") : 벡엔드 서버에 요청을 보냄 => 백엔드의 get 호출
  • response.json() : 서버가 보내주는 응답 데이터를 저장하는 변수 response을 자바스크립트 객체로 변환하는 코드
  • renderMemos(data.memos) : 가져온 메모 데이터를 화면에 표시하는 함수 호출

 

 

 

 

 

 

메모 추가하기

 

// 메모 추가하기
addBtn.addEventListener("click", async() => {
    const text = memoInput.value.trim()
    if(!text) {
        alert("메모를 입력하세요")
        return
    }

    try {
        const response = await fetch("/memo", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({text})
        })
        const data = await response.json()
        memoInput.value = ""
        renderMemos(data.memos)

    }catch (error) {
        console.log("메모 추가 실패", error)
    }
})

 

 

 

 

  • addBtn : html 파일에서 만든 버튼
  • addBtn.addEventListener("click" : addBtn을 클릭했을 때 이벤트가 실행되는 코드
  • const response = await fetch("/memo" : 백엔드 js 파일의 post로 요청 보냄
  • method: "POST" : 요청 방식 지정. 기본 fetch는 GET이기 때문에 POST로 지정
  • headers : {"Content-Type": "application/json"} : 보내는 데이터 형식이 JSON 형식이라는 표시
  • body: JSON.stringify({text}) : 실제 데이터를 보냄
  • stringify() : 객체나 배열을 JSON 형태의 문자열로 변환하는 함수
  • renderMemos(data.memos) : 새로운 메모 목록 화면 출력

 

 

 

 

 

메모 삭제하기

 

// 메모 삭제
async function deleteMemo(id) {
    const check = confirm("정말 삭제하시겠습니까?")  // confirm 예, 아니오를 띄움
    //console.log(check)
    //console.log(id)
    if(!check) return

    try {
        const response = await fetch(`/memos/${id}`, {
            method: "DELETE"
        })
        const data = await response.json()
        renderMemos(data.memos)
    }catch(error){
        console.log("메모 삭제 실패: ", error)
    }
}

 

 

 

  • confirm : 예 아니오를 띄움, 삭제 버튼을 누를 시 보여짐
  • fetch(`/memos/${id}` : 백엔드의 delete 호출
  • method: "DELETE" : 요청 방식 지정. delete로 설정
  • renderMemos(data.memos) : 삭제 후의 새로운 메모 목록을 화면에 출력함

 

 

 

 

 

 

메모 수정하기

 

// 메모 수정
async function editMemo(id) {
    const newText = prompt("수정할 내용을 입력하세요"
    //console.log(newText)
    //console.log(id)

    if(!newText || newText.trim() === "") return
    try {
        const response = await fetch(`/memos/${id}`, {
            method: "PUT",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({text : newText})
        })
        loadMemos()
    } catch (error) {
        console.log("메모 수정 실패: ", error)
    }
}

 

 

 

 

  • prompt : 수정할 내용을 입력받음(잘 사용하지 않음)
  • fetch(`/memos/${id}` : 백엔드의 put 호출
  • method: "PUT" : 요청 방식 지정. PUT 설정
  • body: JSON.stringify({text:newText}) : 수정할 내용을 JSON으로 변환해서 보냄
  • ({text: newText})인 이유 : 객체를 만들어서 보내는데 이때 객체는 키:값 형태로 만듦
  • loadMemos() : 전체 메모 출력하는 함수 -> renderMemo 사용 시 수정된 부분만 출력됨

 

 

 

 

 


 

 

 

 

css 생성

 

 

body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f4;
  padding: 40px;
}

.container {
  max-width: 600px;
  margin: auto;
  background: white;
  padding: 20px;
  border-radius: 10px;
}

h1 {
  text-align: center;
}

.input-area {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.input-area input {
  flex: 1;
  padding: 10px;
  font-size: 16px;
}

.input-area button {
  padding: 10px 20px;
  cursor: pointer;
}

#memoList {
  list-style: none;
  padding: 0;
}

.memo-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #eee;
  padding: 10px;
  margin-bottom: 10px;
  border-radius: 5px;
}

.memo-buttons {
  display: flex;
  gap: 5px;
}

.memo-buttons button {
  cursor: pointer;
}

 

 

 

 

 


 

 

 

  • async : 비동기 작업을 위한 선언 키워드
  • await : 비동기 시 사용 가능. 비동기 작업이 끝날 때까지 기다리는 키워드

 

 

 

'Node.js' 카테고리의 다른 글

메모 앱 만들기 - backend  (1) 2026.07.07
MongoDB  (0) 2026.07.06
Node.js - 2  (0) 2026.06.29
Node.js - 1  (0) 2026.06.26