티스토리

괴발개발
검색하기

블로그 홈

괴발개발

bulsok.tistory.com/m

ebulsok 님의 블로그입니다.

구독자
5
방명록 방문하기

주요 글 목록

  • [node.js] ch15. AWS와 GCP로 배포하기 morgan: 요청과 응답에 대한 정보를 콘솔에 기록 개발환경: app.use(morgan('dev')); 배포환경: app.use(morgan('combined')); 시퀄라이즈 배포환경 설정 config.json → config.js require('dotenv').config(); module.exports = { ... } cross-env: 동적으로 process.env를 변경할 수 있음 // package.json // ONLY linux/mac "start": "NODE_ENV=production PORT=80 node server", "dev": "nodemon server", // ONLY window "start": "cross-env NODE_ENV=production PORT=80 .. 공감수 0 댓글수 0 2023. 2. 14.
  • [node.js 교과서] ch13. 실시간 경매 시스템 만들기 서버센트 이벤트(sse) sse 모듈을 불러와 new SSE(익스프레스 서버)로 서버 객체 생성 생성한 객체에는 connection 이벤트 리스너를 연결하여 클라이언트와 연결할 때 어떤 동작을 할지 정의, 매개변수로 client 객체 사용(client.send: 클라이언트에 메시지 전송, 문자열만 가능) 라우터에서 SSE를 사용하고 싶다면 app.set 메서드로 client 객체를 등록하고, req.app.get으로 가져옴 IE, 엣지 브라우저에서 사용 불가: EventSource 지원하지 않기 때문, 그러나 사용자가 직접 구현할 수 있음 스케줄링(node-schedule) schedule 객체의 scheduleJob 메서드로 일정 예약 첫번째 인수: 시행될 시각 두번째 인수: 해당 시각이 되었을 때 수.. 공감수 1 댓글수 0 2023. 2. 7.
  • [node.js 교과서] ch12. 웹 소켓으로 실시간 데이터 전송하기 웹 소켓 실시간 양방향 데이터 전송을 위한 기술 폴링: 웹소켓이 나오기 이전 HTTP 기술을 사용하여 구현. 주기적으로 서버에 새로운 업데이트가 있는지 확인하는 요청을 보낸 후 있다면 새로운 내용을 가져옴 HTTP와 다르게 WS라는 프로토콜 사용 ⇒ 브라우저와 서버가 WS를 지원해야 사용할 수 있음 처음에 웹 소켓 연결이 이루어지고 나면 업데이트 요청을 따로 보낼 필요가 없고, 업데이트 할 내용이 생겼다면 서버에서 바로 클라이언트에 알림. HTTP 프로토콜과 포트를 공유할 수 있으므로 다른 포트에 연결할 필요 없음 Socket.IO: 웹소켓을 편리하게 사용할 수 있도록 도와주는 라이브러리 웹소켓은 이벤트 기반으로 작동하고, 실시간으로 데이터를 전달받으므로 항상 대기하고 있어야 함. connection 이.. 공감수 0 댓글수 0 2023. 2. 7.
  • [node.js 교과서] ch10. 웹 API 서버 만들기 JWT(json web token) 헤더: 토큰 종류와 해시 알고리즘 정보 페이로드: 토큰의 내용물이 인코딩된 부분 시그니처: 일련의 문자열이며, 시그니처를 통해 토큰이 변조되었는지 여부를 확인할 수 있음. 비밀키로 만들어짐 장점: JWT 비밀키를 알지 않는 이상 변조가불가능하기 때문에 믿고 사용할 수 있음 단점: 용량이 큼 요청 헤더에 저장된 토큰(req.headers.authorization)을 사용. jwt.verify 메서드로 토큰을 검증, 첫번째 인수에는 토큰, 두번째 인수에는 토큰의 비밀키 토큰의 비밀키가 일치하지 않으면 인증을 받을 수 없고, 에러가 발생하여 catch문으로 이동. 유효기간 만료 시 400번대 숫자 중 아무거나 정함 인증에 성공한 경우 토큰의 내용이 반환되어 req.decod.. 공감수 0 댓글수 0 2023. 2. 7.
  • [Node.js 교과서] ch9. 익스프레스로 SNS 서비스 만들기 passport serializeUser: 로그인 시에만 실행, 객체에 어떤 데이터를 저장할지 정함 deserializeUser: 매 요청 시 실행, 세션에 저장한 아이디를 통해 사용자 정보 객체를 불러옴 sU의 두번째 인수로 넣었던 데이터가 dU의 매개변수가 됨. sU에서 세션에 저장했던 아이디를 받아 데이터베이스에서 사용자 정보를 조회함. 조한 정보를 req.user에 저장함 라우터를 통해 로그인 요청이 들어옴 라우터에서 passport.authenticate 메서드 호출 로그인 전략 수행 로그인 성공 시 사용자 정보 객체와 함께 req.login 호출 req.login 메서드가 passport.serializeUser 호출 req.session에 사용자 아이디만 저장 로그인 완료 로그인 이후, 요청.. 공감수 0 댓글수 0 2023. 2. 7.
  • [Node.js 교과서] ch8. 몽고디비 // 모두 조회 db.users.find({}); // 특정 필드만 조회 // _id는 기본적으로 가져오게 되어 있으므로 0 또는 false를 입력해 가져오지 않도록 함 db.users.find({}, { _id: 0, name: 1, married: 1}); // 조건 조회 // $gt, $gte, $lt, $lte, $ne, $or, $in db.users.find({ age: { $gt: 30 }, married: true }, { _id: 0, name: 1, married: 1}); db.users.find({ $or: [{age: { $gt: 30 }}, { married: false }], { _id: 0, name: 1, married: 1}); // 정렬 // -1은 내림차순, 1은 오름.. 공감수 0 댓글수 0 2023. 2. 2.
  • [Node.js 교과서] ch7. MySQL Sequelize(Object Relation Mapping) npx sequelize init 자동으로 id를 기본키로 연결 VARCHAR: STRING INT: INTEGER TINYINT: BOOLEAN DATETIME: DATE models/user.js User 모델은 Sequelize.Model을 확장한 클래스로 선언, 크게 static init 메서드와 static associate 메서드로 나뉨 init: 테이블에 대한 설정. super.init의 첫번째 인수가 테이블 컬럼에 대한 설정 두번째 인수가 테이블 자체에 대한 설정 sequelize: static init 메서드의 매개변수와 연결되는 옵션, db.sequelize 객체를 넣어야 함 timestamps: createdAt, upda.. 공감수 0 댓글수 0 2023. 2. 2.
  • [Node.js 교과서] ch6. 익스프레스 웹 서버 만들기 app.use(미들웨어): 모든 요청에서 미들웨어 실행 app.use(’/abc’, 미들웨어): abc로 시작하는 요청에서 미들웨어 실행 app.post(’/abc’, 미들웨어): abc로 시작하는 POST 요청에서 미들웨어 실행 express-session: 세션 관리 시 클라이언트에 쿠키를 보냄 resave: 요청이 올 때 세션에 수정 사항이 생기지 않더라도 세션을 다시 저장할지 설정 saveUninitialized: 세션에 저장할 내역이 없더라도 처음부터 세션을 생성할지 설정 secret: 안전하게 쿠키를 전송하려면 쿠키에 서명을 추가해야 하고, cookie-parser의 secret과 같게 설정하는 것이 좋음 name: 세션 쿠키의 이름 설정, 기본값 connect.sid cookie httpOn.. 공감수 0 댓글수 0 2023. 2. 2.
  • [Node.js 교과서] ch3. 노드 기능 알아보기 REPL: Read, Eval, Print, Loop 입력한 코드를 읽고, 해석하고, 결과물을 반환하고, 종료할 때까지 반복한다 ES2015 모듈: require, exports ⇒ import, export (default) node에 DOM/BOM이 없으므로 window/document를 사용하면 에러 발생 console.time(레이블): console.timeEnd(레이블)과 대응되어 같은 레이블을 가진 time과 timeEnd 사이의 시간을 측정 console.log(내용): 평범한 로그를 콘솔에 표시 console.error(에러 내용): 에러를 콘솔에 표시 console.table(배열): 배열의 요소로 객체 리터럴을 넣으면, 객체의 속성들이 테이블 형식으로 표현됨console.dir(객체,.. 공감수 0 댓글수 0 2023. 2. 2.
  • [Node.js 교과서] ch1. 노드 시작하기 node.js: Chrome V8 Javascript 엔진으로 빌드된 Javascript 런타임 서버: 네트워크를 통해 클라이언트(요청을 보내는 주체)에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램 이벤트 기반: 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식(클릭, 네트워크 요청 등).이벤트 리스너에 콜백 함수 등록이벤트 발생등록된 콜백 함수 호출 이벤트 루프: 이벤트 발생 시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행 순서를 결정하는 역할 담당. 노드가 종료될 때까지 이벤트 처리를 위한 작업을 반복하므로 루프라고 함 백그라운드: setTimeout 같은 타이머나 이벤트 리스너들이 대기하는 곳. 자바스크립트가 아닌 언어로 작성된 프로그램. 여러 작업이 동시에 실행될 수 있음 태스.. 공감수 1 댓글수 31 2023. 2. 2.
  • [All Last] 프로젝트 회고 📌 코드: https://github.com/ebulsok/ALL-LAST.git 📌 결과물: https://port-0-all-last-fao2flc7imovf.gksl2.cloudtype.app/ 🔎 프로젝트 소개: 마작 대국의 점수를 기록하는 사이트 🔎 사용한 스택: Node.js(express), MySQL, ejs, Bootstrap 🔎 서비스 내용: 홈 ‘공개’ 상태인 기록만 보임 로그인이 되어있지 않은 경우, 된 경우의 버거 메뉴 내용이 다름 pagination: pageNum을 query로 전달, MySQL의 LIMIT 사용, 1페이지 당 5개의 기록 회원가입/로그인 중복체크: POST 통신 후, 결과에 따라 관련 변수(idChecked, nameChecked) 변경 + alert 창으로 .. 공감수 4 댓글수 0 2023. 1. 4.
  • [MarkYour2022] 프로젝트 회고 📌 코드: https://github.com/MarkYour2022 📌 결과물: http://markyour2022.site/ 📌 예시: http://markyour2022.site/result/2509248128 🔎 프로젝트 소개: 올해의 OO 키워드로 2022을 돌아보고 기록하는 사이트 🔎 사용한 스택: React.js, Node.js(express), MongoDB, AWS(EC2) 🔎 서비스 내용: 홈 MY 2022 만들기 → 로그인 페이지로 이동 공유하기 → 카카오 공유하기 로그인 회원가입 없이 카카오 간편로그인 회원정보 DB에 저장하지 않고 redux에 저장(보완 필요) 로그인 시 버거메뉴 내용 변화 로그인 → 글이 있을 경우 본인 글 조회, 없을 경우 글쓰기 페이지로 이동 글쓰기 닉네임 / .. 공감수 2 댓글수 0 2022. 12. 14.
  • [MarkYour2022/backend] 4. 글 상세, 수정, 삭제, 댓글 등록, 수정, 삭제 /routes/posts.js .get('/:postId'): 글 상세 post_id와 req.params.postId가 일치하는 document를 전달 본인의 post인지 확인하는 isMine 값 전달 .get('/:postId/edit'): 글 수정 - 데이터 받기 post_user와 req.user.id가 일치하는지 확인 후, post_id와 req.params.postId가 일치하는 document를 전달 사실 React 상에서 처리해줄 수 있는 부분인 것 같은데 일단은 구현해놓았다 .post('/:postId/edit'): 글 수정 req.body에 값이 정상적으로 담긴 경우, post_id와 req.params.postId가 일치하는 document를 update .delete('/:postI.. 공감수 3 댓글수 0 2022. 10. 23.
  • [MarkYour2022/backend] 3. 글쓰기 app.js postsRouter(/posts) 추가 routes/login.js req.user를 통해 로그인 했는지 확인하는 함수 isLogin 추가 routes/passport.js 간편로그인으로 계정 생성 시 posted(기본값: false) 항목 추가: 계정 당 게시글을 1개만 쓸 수 있도록 routes/posts.js .get(/new) isLogin으로 로그인 되었는지 확인 users collection에서 현재 로그인 한 계정의 document를 찾고, posted 항목이 false인 경우에만 글쓰기 페이지를 렌더링할 수 있도록 .post(/new) req.body에 값이 담긴 경우 데이터를 정리해서 DB에 저장 postId의 경우 기본값은 1, posts collection에 1개 이상의.. 공감수 2 댓글수 0 2022. 10. 22.
  • [MarkYour2022/backend] 2. 로그인(네이버, 카카오, 구글) 네이버: https://developers.naver.com/ 카카오: https://developers.kakao.com/docs/latest/ko/kakaologin/common 구글: https://console.cloud.google.com/ 가장 중요한 것은 callback url을 api 설정창과 백엔드 코드에서 똑같이 입력하는 것 app.js(추가 코드만) const session = require('express-session'); const passport = require('passport'); const loginRouter = require('./routes/login'); const passportRouter = require('./routes/passport'); passport.. 공감수 3 댓글수 0 2022. 10. 22.
  • [MarkYour2022/backend] 1. node.js 서버 기초세팅 npm init -y npm i --save-dev prettier eslint eslint-config-airbnb-base eslint-plugin-import typescript @types/node @types/express nodemon ejs npm i express express-session dotenv mongodb passport passport-google-oauth20 passport-kakao passport-naver // .prettierrc { "semi": true, "singleQuote": true } // .vscode/setting.json { "[javascript]": { "editor.formatOnSave": true, "editor.defaultFormatt.. 공감수 3 댓글수 0 2022. 10. 21.
  • 10/17 TIL : MySQL 정규화, Mbti-App에 MongoDB 적용 🔎 정규화 DB 설계에 있어서 중복을 최소화 하기 위해 데이터를 구조화 하는 과정 크고 조직화 되지 않은 테이블을 작고 잘 조직화 된 테이블로 변경 데이터 추가 및 삭제 시에 이상 현상을 예방할 수 있음 🚩 제1정규형(1NF): 하나의 컬럼은 반드시 하나의 속성만을 가져야 함 🚩 제2정규형(2NF): 모든 컬럼에 대한 부분 종속이 없어야 함 🚩 제3정규형(3NF): 이행 종속성(A=B, B=C여서 A=C인 경우)이 없어야 함 🔎 Foreign Key(외래 키) 정규화를 하게 되면 테이블은 최소한의 단위로 쪼개지게 됨 하지만 데이터를 불러들일 때에는 한꺼번에 많은 값을 가지는 테이블을 JOIN 해서 가지고 와야 하는 경우가 많음 JOIN을 통해 테이블을 합치는데, 이 때 기준이 되는 값(서로 공유하고 있는.. 공감수 1 댓글수 0 2022. 10. 17.
  • 10/14 TIL : MySQL 적용 🔎 SQL(Structured Query Language) 관계형, Relational DBMS(RDBMS) 키와 값의 관계를 테이블화 시킨 원칙을 토대로 DB를 구성 장점: 구조화가 명확하여 예외가 없음, 데이터 입출력 속도가 매우 빠름, 신뢰성이 높음 단점: DB 구조 변경이 매우 어렵기 때문에 빅데이터 등 새로운 키가 추가될 수 있는 것에는 사용이 어려움 구문 연습: https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all 🚩 DB에서 데이터 가져오기 SELECT * FROM 이름; SELECT * FROM Customers; 🚩 원하는 컬럼의 값만 가져오기 SELECT 컬럼명 FROM table; SELECT City, Country.. 공감수 1 댓글수 0 2022. 10. 17.
  • 10/12 TIL : React SPA 제작(Mbti-app) 🔎 리액트 SPA(Single Page Application) 제작 [터미널] npx create-react-app mbti-app [터미널] npm i redux react-redux @reduxjs/toolkit styled-components prettier .prettierrc { "semi": true, "singleQuote": true } /.vscode/settings.json { "[javascript]": { "editor.maxTokenizationLineLength": 2500, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" } } 폴더 구조 세팅 🚩 redux 기초 세팅 // src/.. 공감수 1 댓글수 0 2022. 10. 17.
  • 10/7 TIL : Redux, 간단한 Todo-list 만들기 🔎 Redux 상태 관리 라이브러리 컴포넌트의 상태를 하나하나 props로 전달하는 것을 방지하고자 생김 컴포넌트의 상태를 store.js 에서 관리 1. dispatch 함수를 실행하면 2. action 발생 3. action을 reducer가 받아서 4. state를 변경 5. state가 변경되면 컴포넌트가 리렌더링 [터미널] npm i redux [터미널] npm i react-redux redux 적용을 위해서 컴포넌트를 import하고 을 감싸줘야 함 // src/index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import.. 공감수 1 댓글수 0 2022. 10. 14.
  • 10/5 TIL : React Router 🔎 public 폴더 사용 상대 경로를 이용해서 src 폴더 이상으로 가서 다른 폴더에 접근하여 내려가는 방식, 절대 경로를 이용하는 방식 사용 불가 기존 백엔드에서는 public 폴더를 static이라는 express 메소드를 사용해서 특정 주소 값을 요청하면 연결이 되었음 npx create-react-app을 통해 만들어진 리액트 앱의 경우는 public 폴더가 자동으로 static 처리됨 따라서 어느 위치에서건 / 를 써서 접근하면 public 폴더를 호출할 수 있음 🔎 Composition(합성), Specialization, Containment 🔎 React Router 리액트에서는 컴포넌트별 라우팅이 가능 [터미널] npm i react-router-dom index.js 에서 App 컴포.. 공감수 0 댓글수 0 2022. 10. 14.
  • 9/30 TIL : React Hooks(useEffect, useMemo) 🔎 React HOOKS 기존 클래스형 컴포넌트에서 사용하던 편리한 기능을 함수형에 적용하려니 기존 것을 그대로 사용할 수 없고 새로운 것이 필요하여 탄생한 것 useState, useRef, useEffect, useContext, useMemo, useCallback, useReducer ... 🔎 React.Fragment 실제 리액트에서 컴포넌트를 조합할 때, 최상위에 div를 사용하지 않고 반환해야만 하는 경우가 생길 때 사용 React 라이브러리 추가 필요 를 로 대체 가능, 속성 값이 필요한 경우 빈 태그는 사용 불가 // src/components/ReactFragment.js import React from "react"; export default function ReactFragmen.. 공감수 1 댓글수 0 2022. 10. 14.
  • 9/28 TIL : props, 컴포넌트 꾸미기(inline, sass, styled-components), useRef 실습: 카운터 만들기 최상단에 태그로 0 인 숫자가 있고, 아래에는 +1, -1 이라는 버튼 +1 버튼을 누르면 숫자가 +1 이 되고, -1 버튼을 누르면 숫자가 -1 이 되도록 import React, { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); const onInc = () => { setCount(count + 1) }; const onDec = () => { setCount(count - 1) }; return ( {count} +1 -1 ) } 🔎 props 리액트에서 백엔드의 데이터를 프론트로 전달하는 방식 html의 속성을 부여하는 것처럼 props명과 전.. 공감수 3 댓글수 0 2022. 9. 28.
  • 9/26 TIL : MVC 패턴, React(Component, state) 🔎 MVC 패턴(Model View Controller) 🚩 장점 역할이 명확히 구분되어 있어 유지보수, 기능 추가/확장이 쉽다 프론트와 백이 서로 독립적으로 개발 가능, 협업하기 좋음 🚩 단점 MVC 구조에 대한 이해를 바탕으로 설계가 필요함 MVC를 명확히 나누기 어려울 경우 구조상으로 복잡해질 수 있음 🚩 Model 어플리케이션의 데이터를 처리 사용자가 볼 수 없는 곳에서 DB로부터 데이터를 읽고, 삽입하고, 수정하고, 삭제하는 역할 Controller와 소통, View와는 소통하지 않음 🚩 Controller Model과 View의 상호작용을 컨트롤 Model로부터 전달받은 데이터를 가공하여 View에 전달 View로부터 들어온 사용자 요청을 Model에 전달 🚩 View Model로부터 받은 정.. 공감수 1 댓글수 0 2022. 9. 27.
  • 9/23 TIL : koa, pug, 채팅 기능 구현 🔎 koa express 팀에서 만든 프레임워크 express 대비 더 가볍고 빠름 미들웨어 레벨에서도 async/await를 제공하여 비동기 프로그래밍을 더 편리하게 사용 가능 프레임워크 설치: [터미널] npm i koa // @ts-check const Koa = require('koa'); const app = new Koa(); const PORT = 4500; app.use(async (ctx, next) => { console.log(ctx.request); console.log(ctx.response); ctx.body = 'Hello, koa world!'; }); app.listen(PORT, () => { console.log(`서버는 ${PORT}에서 작동 중입니다.`); }); 🚩.. 공감수 0 댓글수 0 2022. 9. 26.
  • 9/21 TIL : multer, 암호화(crypto), 웹 소켓으로 채팅 서비스 구현 🔎 multer 모듈로 이미지 업로드 모듈 설치: [터미널] npm i multer -s 🚩 board_write.ejs 파일 수정 input type="file" encrypt="multipart/form-data" 제목 내용 이미지 업로드 작성 🚩 board.js 수정 multer 모듈 불러오기 저장 설정: destination(업로드 할 폴더 설정), filename(파일 이름 설정) 한계 설정: 파일크기, 이름 등 글쓰기 요청 시, 폴더가 없으면 만들기 파일의 정보는 upload.single(' ')를 통해 req.file에 담겨서 들어옴 req.file이 있을 경우 img에 파일명 넣어서 DB 처리 // board.js const multer = require('multer'); const fs.. 공감수 1 댓글수 0 2022. 9. 22.
  • 9/19 TIL : 자동 로그인(쿠키), DOTENV, OAuth(페이스북, 네이버, 카카오, 구글 로그인) 🔎 쿠키를 사용한 자동 로그인 로그인 하면 쿠키 발행(사용자 id 정도, 60초의 expires 설정, httpOnly 옵션 켜기, signed 옵션 켜기+서버의 cookie-parser에 암호화 키 설정) router.post('/', (req, res, next) => { passport.authenticate('local', (err, user, info) => { if (err) throw err; if (!user) { return res.send( `${info.message} 로그인 페이지로 이동` ); } req.logIn(user, (err) => { if (err) throw err; res.cookie('user', req.body.id, { expires: new Date(Date... 공감수 1 댓글수 0 2022. 9. 20.
  • 9/16 TIL : cookie, HTTP session, passport 🔎 cookie HTTP 쿠키는 서버가 사용자의 웹 브라우저에 전송하여 저장하는 작은 데이터 저장소 JS 객체처럼 key, data가 들어있음 브라우저는 쿠키로 데이터를 저장해뒀다가 동일한 서버에 다시 요청을 보내게 될 때 쿠키에 저장된 정보를 함께 전송 => 서버에서는 쿠키를 통해 요청이 어떤 브라우저에 들어왔는지/요청이 동일한 브라우저에서 들어왔는지 등을 파악할 수 있음 서버에 저장해야할 정보를 관리 => 로그인 정보, 장바구니, 팝업 하루동안 안 보기 등 이름, 데이터, 만료일, 경로 등이 저장됨 🔎 프론트에서 쿠키 사용하기 개발자도구 - Application - Storage - Cookies에서 확인 🔎 백엔드에서 쿠키 사용하기 🚩 cookie-parser 모듈 사용 [터미널] npm i coo.. 공감수 0 댓글수 0 2022. 9. 20.
  • 9/14 TIL : 게시판 기능에 MongoDB 적용, 서버 배포 🔎 url vs uri URL(Uniform Resource Location): 주소까지만 알려줌 URI(Uniform Resource Identifier): 주소+파일명까지 표시 🔎 async/await 를 사용하여 board.js에 코드 적용 + 모듈화 /routes/mongo.js // @ts-check const { MongoClient, ServerApiVersion } = require('mongodb'); const uri = 'mongodb+srv://ebulsok:@cluster0.mhxf9lp.mongodb.net/?retryWrites=true&w=majority'; const client = new MongoClient(uri, { useNewUrlParser: true, useUn.. 공감수 0 댓글수 0 2022. 9. 20.
  • 9/13 과제 : node.js, express, ejs를 이용해서 게시판 만들기 node.js, express, ejs를 이용해서 게시판 만들기(DB 없이) localhost:4000/board => 게시글 목록 보기 게시글 수정, 삭제 버튼 만들기 삭제 버튼 클릭 => 게시글 삭제 수정 버튼 클릭 => 수정 모드로 이동 => 저장 버튼 클릭하면 수정 내용 반영하기 📌 코드: https://github.com/ebulsok/KDT-hw-913.git 📌 결과물: 게시글 작성 게시글 수정 게시글 삭제 공감수 0 댓글수 0 2022. 9. 18.
    문의안내
    • 티스토리
    • 로그인
    • 고객센터

    티스토리는 카카오에서 사랑을 담아 만듭니다.

    © Kakao Corp.