[JavaScript] 자바스크립트 ( + 1급객체, CSR, 람다식 != 람다표현식 )

내용수정 및 썸넬이미지 추가 필요
김호정's avatar
Sep 01, 2024
[JavaScript] 자바스크립트 ( + 1급객체, CSR, 람다식 != 람다표현식 )
 

단축키 설정

 
notion image
 
  • 이클립스 키맵에 익숙하면 이걸써라
 
notion image
 
  • 인텔리제이 단축키가 익숙하면 이걸써라
 
→ 젯브레인이 인텔리제이, 안스, 코틀린 만듦. 나중에 flutter 시간에 사용할
안드로이드 스튜디오를 인텔리제이 만든 회사가 만들어서 단축키 비슷.
→ 인텔리제이 쓰자.
 
 
💡
자동정렬 Ctrl + Alt + L
 
notion image
  • alt + shift 누르고 마우스 클릭하면 2개 이상 잡을 수 있음
 
notion image
 
  • alt + shift 방향키 위(or 아래) 누르면 해당열 위(or 아래) 로 복사할 수 있음
 

저장 시 자동정렬

notion image
notion image
 
클릭해두면 저장 시 자동정렬됨
 
++
notion image
node.js
 
는 자바스크립트 런타임 환경 임 ( 자바의 JVM 같은거 )
 
터미널에
 
node.자바스크립트파일.js
 
라고 치고 입력하면 개발자모드의 콘솔에 뜨는거 터미널창에 뜬다 !
 
난 지금 설치 + 환경변수 설정 안해서 command not found 뜨는데
 
암튼 설치/설정하고 터미널 창에 입력하면 뜬다.
 
 

 
💡
변수의 스코프 ( → 변수가 살아있는 시기 ) 문제가 있으니 var 쓰지 말고 let 만 쓰자
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> let n1 = 1; let n2 = 1.5; console.log("정수", n1); console.log("실수", n2); let n3 = "자바스크립트 자료형 강좌"; console.log("문자열", n3); let n4 = true; console.log("불리언", n4); let n5 = null; console.log("널", n5); let n6 = undefined; let n7; console.log("언디파인", n6); console.log("언디파인", n7); let user = { id: 1, username: "ssar", password: "1234" }; // .으로 찾아갈 수 있는데 문자열은 이런게 안됨 console.log("객체", user); console.log("객체", user.id); console.log("객체", user.username); console.log("객체", user.password); let arr = [1, 2, 3]; console.log("배열", arr); console.log("배열", arr[0]); console.log("배열", arr[1]); console.log("배열", arr[2]); function fun1() { console.log("fun1 함수"); } fun1(); let f = function () { // 익명함수 console.log("fun2 함수"); }; f(); let f1 = () => 1; let f2 = () => { console.log(1); }; function f2() { console.log(1); } </script> </body> </html>
notion image
 
값이 들어갈 때 형이 결정됨 (→ true 가 n4 에 들어갈때 불리언이 됨 )
 
타입추론
 
어떤 사이즈의 값이 들어올지 모르니까
 
값이 들어올 때 추론해서 공간을 확보 → 그래서 느리다 !
 
  • 일반 자료형 : 데이터 사이즈가 있는 것
 
C언어 : 값을 저장할 때 타입이 지정되어있다.
 
하지만
 
C언어 구조체, 자바 Stirng 같은 건
문자가 몇 개 들어올지 사이즈 확보를 미리 할 수 없다.
 
타입이 있는 언어는 컴파일 시에 해당 바이트만큼 메모리에 공간 확보
 
타입이 없거나 레퍼런스형 자료는 알 수 없음.
 
⇒ 힙이라는 공간을 만들어서 매우 넓은 부지를 확보(42억 9천 ? )
 
⇒ 무조건 크기를 4바이트로 잡음
 
⇒ 스트링은 무조건 4바이트를 확보해서 주소만 가지고 있음. 아직 데이터는 X
 
⇒ 데이터가 들어오면 실제 주소에 넣음 ( → 포인터 )
 
⇒ 이런 포인터 자료형은 레퍼런스 자료형 (→ EX. 스트링 )
 
자바는 기본자료형 빼고 전부다 레퍼런스형 자료들
 
자바스크립는도 모두 메모리 자료형을 레퍼런스로 가진다.
 
그래서 느림
 
💡
타입추론 언어들은 전부 다 포인터 다! 느리다!
 
undefined 는 은 자바의 null 같은 거
 
값을 안넣었으면 == undefined 로 비교
 
명시적으로 null을 넣은 경우에만 == null 로 비교
 
 
notion image
 
띄어쓰기 1개 1바이트 ㅎ
 
letuser={id:1,username:"ssar",password:"1234"};
 
이렇게 데이터를 압축해서 전송함(띄어쓰기, 내려쓰기 없애서)
++
min.js
 
나의 버퍼 (bufferedwriter)에 담음.
 
Buffer 에 있는걸 거내서 읽는건
 
readwriter 로 읽음
 
자바는 이 데이터를 받았을 때 이게 뭐지? 이럼
자바스크립트인지 먼지 모름
그래서 contenttype에 자바스크립트오브젝트 라고 적어서 보냄
그래도 자바는 자바스크립트오브젝트를 파싱할 수 없음
그래서 자바 오브젝트로 바꿔서 보내라고 함
 
💡
class User(int id =1, String username=”ssar”, String password =”1234”);
이렇게 바꿔서 보내면 자바가 읽을 수 있음
 
컨텐트타입에는 이미 등록되어 있는 표준을 씀 → MIME 타입 →
 
x-www-form-urlencoded 타입 같은거 ( 보내는 데이터를 url 인코딩 후 웹 서버에 보내는 방식 )
 
💡
id=1&username=ssar&password=1234
 
이렇게 보내면 파싱하기 좋음
 
지금은 국제적 표준이 JSON (자바스크립트 오브젝트 노테이션 ? )
→ 자바스크립트 오브젝트랑 매우 비슷하게 생긴 데이터 타입
💡
{”id”:1,”username”:ssar,”password”:1234}
 
즉,
letuser={id:1,username:"ssar",password:"1234"};
이 자바스크립트 오브젝트 타입을
mime 타입에 있는 것 중 하나로 바꿔서 보내야 한다!
제일 인기 많은게 json ( {”id”:1,”username”:ssar,”password”:1234} )
 
 
왜 다른걸로 바꿔서 보내는가 ?
→ 자바든 자바스크립트든 읽을 수 있어야 하니까!
그러니 통신할 때 자기 오브젝트로 보내지 말고, JSON 혹은 X-WWW-FORM-URL 로 바꿔서 보내자!
 
💡
정리
let user={id:1,username:"ssar",password:"1234"}; → 자바스크립트 오브젝트 타입 class User{int id=1;String username="ssar";String password="1234} → 자바 오브젝트 타입 id=1&username=ssar&password=1234 → x-www-form-urlencoded 타입 {"id":1,"username":ssar,"password":1234} → JSON 타입
 
참고
x-www-form-urlencoded
 
notion image
 
자바스크립트 오브젝트는 . 으로 값을 찾아갈 수 있다!
 
 
++
사이즈를 확보하고 쓰면
100바이트로 설정되어있으니까
데이터가 더 들어갈 수 없음
 
 
자바
int [] a = new int[3];
연속된 공간에 4바이트를 잡음
배열의 목표는 연속된 공간을 확보해서 빠르게 접근하는것 ( → 연산이 빠름 )
 
자바스크립트
배열은 자바의 속도를 못따라간다.
하지만 쓰기는 쉽다.
 
 
notion image
 
이렇게 return 을 할 수도 있고 안할 수도 있다.
 
클래스 안에 있는건 상태를 변경시키니까 매서드 라고 한다. (자바)
독립적으로 실행되는 코드덩어리는 함수 라고 한다.
여기서 function fun1 은 함수 다!
 
 
자바가 전달 받을 수 있는건
기본자료형이랑 클래스타입 2개 밖에 없다.
 
→ 자바는 1급 객체가 obejct (클래스)밖에 없다.
 
모든 프로그래밍 랭기지는 1급 객체를 가지고 있다.
1급 객체는
 
매서드는 1급 객체가 아니다.
 
그래서 자바에서 매서드를 전달하려면 클래스를 만들고 안에 매서드를 만들고
클래스를 매개변수로 받아서 매서드를 꺼내써야 한다.
 
→ 자바스트립트는 모든게 1급 객체다.
모든 타입을 전달할 수 있다. function (함수)도 전달할 수 있다.
 
자바는 class를 new 해서 담을 수 있지만 매서드를 담을 수는 없다.
 
 
 
language를 공부할 때는
 
메모리를 관리해주는 언어인지 아닌지,
가바지 컬렉션이 관리해주는지 아닌지
 
멀티스레드인지 단일스레드인 언어인지
 
컴파일하는 언어인지 실행시에 타입추론해서 실행하는 언어인지
 
이 3가지를 비교하면서 공부해야한다.
 
 
자바스크립트는 static 이 없다.
main이 없으니 시작전에 띄울게 없다.
다 띄우고 시작한다.
 
notion image
 
함수를 let f (변수)에 전달
 
notion image
 
expression 표현식
 
→ 실행시에 뭐가 return 되는거
 
 
if문은 expression일까 ? 내부에 있는걸 return 하지 않으니 expression이 아님
삼항 연산자가 expression일까 ? 첫번째 애 아니면 두번째애가 리턴 되니까 expression임
 
실행만 되는건 expression이 아님
 
notion image
이건 함수이기도 하고 return 하니가 표현식임
 
→ 익스프레션은 람다표현식 으로 변경 가능
notion image
 
람다식(정확히는 람다표현식)으로 변경한 것
 
notion image
리턴안하면 그냥 람다식
 
notion image
람다표현식은 { } 중괄호가 없이 이렇게 표현할 수 있다.
( ⇒ 뒤에 있는걸 return 함 )
 
notion image
1) 함수
2) 익명함수
3) 람다표현식 → 표현식인 건 모두 return 이 되어야 함
4) 람다식
 
 
 
💡
람다식, 화살표함수, 익명함수 정리
 
 
 
notion image
 
⇒ f1 람다표현식을 일반 표현식으로 바꿔봄
 
notion image
 
⇒ f2 람다식을 일반함수로 바꿔봄
 
이렇게 바꿀 수 있어야 한다.!
 

 
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> const myBtn = document.getElementById("myBtn"); myBtn.addEventListener("click", function () { alert("Hello World!"); }); </script> <button id="myBtn">Click me</button> </body> </html>
 
위 코드에서 <button>이 <script>보다 아래에 있다.
그럼 Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') 이런
에러가 난다. → myBtn 요소가 아직 DOM에 존재하지 않아서 발생.
 
⇒ script는 무조건 body 맨 아랫부분에 작성한다.
notion image
 
자바의 기본라이브러리 jre 처럼 자바스크립트도 기본 라이브러리를 가지고 있따.
 
  1. window → 브라우저
    1. 1) document → 바디 영역 (의 모든 정보를 다 들고있음)
→ 바디영역에 접근하고 싶으면 window.document
→ document 안에 어떤 라이브러리가 있는지 알아야 사용할 수 있다.
2) navigator →
history.back → 페이지를 어떻게 이동했는지 다 들고있음 (stack으로 쌓아둠)
history.go(-2) : 2칸 뒤로감
 
1의 document는 생략가능
 
자바스크립트는 돔(DOM)을 제어하기 위해 사용!
 
notion image
 
BOM은 그냥 쓰면 되는거구 DOM을 컨트롤해야한다.
 
익명함수 쓴 이유 : 클릭하면 바로 호출될 거니까 익명함수를 씀. 이름을 부를 일이 없으니까 익명함수를 씀
익명함수 쓴 이유 : 클릭하면 바로 호출될 거니까 익명함수를 씀. 이름을 부를 일이 없으니까 익명함수를 씀
DOM TREE
 
BODY
|
BUTTON
 
 
CONST는 FINAL 같은거
자바스크립트가 매개변수로 function 을 받을 수 있는 이유는 ?
 
function은 1급 객체이니까!
 
 
버튼을 클릭하는 건 인간
 
이벤트 리스너는 실행타임을 모를때 다는것. 인간이 언제 누를지 모르니까.
 
listener를 달때는 연산을 많이 함
 
위의경우
 
리스너가 버튼을 관찰. → “클릭을 관찰해!”
 
버튼에 id가 달려있음. myBtn
 
리스너는 Id가 myBtn인 버튼만 관찰.
 
클릭이 발생하면 행위를 때린다(실행시킨다)
 
봤다가 안봤다가 하긴하지만
클릭됐는지 체킹해야하니까 이벤트리스너를 쓰면 연산이 많다. .
 
notion image
 
어떤 대상에 어떤이벤트가 발생했을때 어떤 행위를 할건지 를 적으면 된다.
모든 랭귀지가 같다.
 
 
notion image
인터프러터
 
그림이 밑에있으니까 myBtn이 undefined로 들어감
 
그러니
 
자바스크립트 코드는 무조건 body 젤 밑에 넣는다.
 
→ 돔이 실행되고 나서 자바스크립트 코드가 실행되어야 한다.
 

이벤트리스너에 넣을 수 있는 이벤트 연습

<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> #loadImg { width: 100%; height: 100%; top: 0; left: 0; position: fixed; display: flex; justify-content: center; align-items: center; opacity: 0.8; background: white; z-index: 99; text-align: center; } #loadImg>img { position: relative; } </style> </head> <body> <form id="frm"> <input type="text" id="formData"> <button id="formBtn">전송</button> </form> <button id="myBtn">Click me</button> <input type="text" id="myIp"> <div id="loadImg"> <img src="https://picsum.photos/id/18/2500/1667" alt="로딩이미지"> </div> <script> const myBtn = document.getElementById("myBtn"); myBtn.addEventListener("dblclick", function (e) { console.log(e); }); const myIp = document.getElementById("myIp"); myIp.addEventListener("mouseout", function (e) { console.log(e); console.log(e.target.value); alert("마우스out!"); }); const frm = document.getElementById("frm"); let formData = document.getElementById("formData"); frm.addEventListener("submit", function (e) { alert("전송!"); alert(formData.value); console.log(formData.value); }) window.addEventListener('load', function () { setTimeout(function () { const loadImg = document.getElementById("loadImg"); if (loadImg) { loadImg.style.display = 'none'; } }, 1000) //1초 }); // 체크박스 라디오 버튼 이벤트 발생시키는 것도 해서 클릭했을 때 이벤트 어떻게 발생시키는지 해보기 </script> </body> </html>
 
💡
1. click : 요소를 클릭할 때 발생합니다.
2. dblclick : 요소를 더블 클릭할 때 발생합니다.
3. mousedown : 요소에서 마우스 버튼이 눌릴 때 발생합니다.
4. mouseup : 요소에서 마우스 버튼이 떼어질 때 발생합니다.
5. mousemove : 요소에서 마우스가 움직일 때 발생합니다.
6. mouseover : 요소에 마우스 커서가 올라갈 때 발생합니다.
7. mouseout : 요소에서 마우스 커서가 벗어날 때 발생합니다.
8. keydown : 키보드에서 키를 누를 때 발생합니다.
9. keyup : 키보드에서 키를 뗄 때 발생합니다.
10. submit : 폼을 제출할 때 발생합니다.
11. change : 요소의 값이 변경될 때 발생합니다.
12. load : 웹 페이지나 이미지 등이 로딩되었을 때 발생합니다.
 
 
클릭, 키업, 체인지, 마우스오버 많이 사용한다.
 
체크박스 만들어서 연습해보자!
 

 
ex02. test1.html
 
notion image
++
전부 다 리액트를 쓰지는 않고 제이쿼리 마니씀
++
 
SSR 로 하면
 
<sector> 3개 중 아래 부분만 변경하면 돼도
아래만 변경하지 않고 전체페이지를 돌려줌. ( 전체페이지 리로드 됨 )
→ SSR 로 하면 서버가 부하가 걸리겠다. 고 느낌
 
비동기 통신을 하면 아래 부분만 리로드 할 수 있음!
ajax로 요청하면 html이 아닌 json (그림 안에 들어갈 데이터) 같은 걸로 돌려줌
 
!) content-type이
text/html 이 아닌 ( → text/html 을 받으면 전체를 리로드함)
application/json 이면 화면이 리로드가 안됨
 
→ 받은걸로(데이터) 부분만 다시 그림 ( by 자바스크립트 )
→ 이걸 클라이언트 사이드 렌더링(CSR) 이라고 한다.
 
한 부분만 수정하고 싶으면 http 통신으로 하면 안됨 ( → 전체가 리로드됨)
http 요청말고 ajax 요청을 한다!
요청할거니까 데이터만 줘!
데이터를 순수하게 json으로 만들어서 응답한다. (무조건 json은 아님. 젤 많이 쓰는게 json)
 
form 태그는 무조건 http 요청이어서
form 태그로 요청하지 말고 자바스크립트로 ajax 요청해야 한다.
 
form은 get , post 만 하는데
자바스크립트 ajax 요청하면 get, post, put, delete 요청을 할 수 있다.
 
ajax 하면 부분 리로딩을 해서 서버의 부하를 줄일 수 있다.
 
서버쪽에서 렌더링안해도 되니까 많이 선호함
 
브라우저에서 자바스크립트를 사용해서 CSR 하는 사람들을 프론트엔드 개발자라고 함.
 
자바 스윙 ? 하는 그런것두 프론트엔드 개발자가 한다고 함
 
페이스북이 전부 다 ajax를 조져버림
 
싱글페이지 에플리케이션 이라고 함 (SPA) ++
++
ajax가 되어야지 spa 할 수 있음
notion image
<index html >
<body id=root> 만 넣어두고
싹 다 동적으로 생성해버림. 프론트엔드 개발자 죽음. (AJAX로 다하면 개발자가 죽는다)
 
음 복잡하니 다시 서버사이드랜더링으로 돌아가자! 고 햇는데
 
그때 나온게 리액트다!
 
기존에 CSR은 id를 다 만들어놓고 id를 찾아서 데이터를 넣었는데 리액트는 그렇게 안해도 된다.
 
notion image
즉, 서버사이드랜더링 SSR 하면 프론트는 편하지만 서버에 부하가 많이감.
AJAX로 다 하니까 프론트개발자가 죽어서
그래서 나온게 리액트.(from 페이스북) → 상태를 관리 → 아이디같은거 몰라도됨 !
 
리액트란 기술이 있으니 이제 제이쿼리 잘 안씀. 새로 들어가는 개발에는.
유지보수해야하니까 제이쿼리 배워야함!
 

 
제이쿼리 본격적으로 들어가보자
(바닐라 자바스크립트 → 제이쿼리 로 바꿔보자)
 
notion image
CSS 선택자는 3개 ( ID, CLASS, 태그)
.
#
태그는 그냥
 
제이쿼리쓰면 $(”#아이디”) 쓰면 됨
document.getElementById("myBtn"); 랑 동일
notion image
 
notion image
 
document.getElementById(”myBtn”) 쓰지말고
document.querySelector(”#myBtn”) 으로 쓰기
 
클래스는
document.querySelector(”.class이름”)
 
태그는
document.querySelector(”button”)
 
이렇게 쓴다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { border: 1px solid black; padding: 10px; } </style> </head> <body> <h1>숨기기</h1> <button onclick="hideDisplay()">display로 숨기기</button> <button onclick="hideVisible()">visible로 숨기기</button> <div class="box"> <div class="box" id="innerBox1"> 내부박스1 </div> <div class="box" id="innerBox2"> 내부박스2 </div> </div> <script> function hideDisplay() { let el = document.querySelector("#innerBox1"); el.style.display = "none"; } function hideVisible() { let el = document.querySelector("#innerBox2"); el.style.visibility = "hidden"; } </script> </body> </html>
notion image
 
 
input의 name, value 같은건 생성자 라고 보면 됨
 
💡
id로 거는거 보다 onclick으로 걸자
 
notion image
notion image
notion image
 
style.display = “none” → 영역까지 다 사라짐 → 댓글삭제 같은건 none으로
style.visibility = “hidden” → 영역은 남아있고 내용만 사라짐
 
 
제이쿼리는 w3schools 에서 연습하자 ^__^
 
notion image
notion image
notion image
 
notion image
 
 
notion image
제이쿼리 쓸거니까 test2 만들어서 넣어주기
 
 
notion image
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { border: 1px solid black; padding: 10px; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <h1>숨기기</h1> <button onclick="hideDisplay()">display로 숨기기</button> <button onclick="hideVisible()">visible로 숨기기</button> <div class="box"> <div class="box" id="innerBox1"> 내부박스1 </div> <div class="box" id="innerBox2"> 내부박스2 </div> </div> <script> function hideDisplay() { $("#innerBox1").hide(); // display = none 과 동일 } function hideVisible() { $("#innerBox2").remove(); // dom을 삭제해줌. } </script> </body> </html>
 
notion image
→ display 로 숨기기를 누르면 hide 발동
 
notion image
지정해둔 innerBox1이 화면에서 사라지고 (hide는 display=none 과 동일)
코드에 흔적은 남는다.
 
Elements 에서 확인하면 id가 innerBox1인 코드가 남아있고,
style에 display:none 이 설정되었다고 보여주고 있다.
 
notion image
 
이 상태에서 visible로 숨기기를 클릭하면 (remove 걸어둔 거)
notion image
 
dom을 아예 삭제해준다. 그래서 우측에 확인해보면 아예 id가 innerBox2 인 div가 사라졌다.
 
명령어가 한 20개 정도 밖에 안돼서 공부하면 금방 습득 할 수 있다고 한다.
 

제이쿼리 매서드

 
💡
jQuery에는 다양한 메서드들이 존재하며, 그 중에서 요소를 조작하거나 숨기고 보여주는 것과 관련된 메서드들이 많이 있습니다. hide()remove()도 그 중 일부입니다. 아래는 이러한 메서드들 중 일부를 소개합니다:

1. 요소를 숨기거나 보여주는 메서드

  1. hide(): 선택한 요소를 숨깁니다 (display: none과 유사).
  1. show(): 숨겨진 요소를 다시 보여줍니다 (display: block과 유사).
  1. toggle(): 요소가 보이는 상태면 숨기고, 숨겨진 상태면 보이게 전환합니다.
  1. fadeIn(): 요소를 페이드 인(fade-in) 효과로 서서히 나타나게 합니다.
  1. fadeOut(): 요소를 페이드 아웃(fade-out) 효과로 서서히 사라지게 합니다.
  1. fadeToggle(): 요소의 페이드 인/아웃 상태를 전환합니다.
  1. slideDown(): 요소를 슬라이드 다운(slide-down) 효과로 서서히 나타나게 합니다.
  1. slideUp(): 요소를 슬라이드 업(slide-up) 효과로 서서히 사라지게 합니다.
  1. slideToggle(): 요소의 슬라이드 상태를 전환합니다.

2. DOM 조작 관련 메서드

  1. remove(): 선택한 요소를 DOM에서 완전히 제거합니다.
  1. empty(): 선택한 요소의 모든 자식 요소를 제거하지만, 해당 요소 자체는 남겨둡니다.
  1. detach(): 요소를 DOM에서 제거하지만, 나중에 다시 삽입할 수 있도록 데이터와 이벤트를 유지합니다.
  1. append(): 선택한 요소의 마지막에 새로운 내용을 추가합니다.
  1. prepend(): 선택한 요소의 처음에 새로운 내용을 추가합니다.
  1. after(): 선택한 요소의 바로 다음에 새로운 내용을 추가합니다.
  1. before(): 선택한 요소의 바로 앞에 새로운 내용을 추가합니다.
  1. replaceWith(): 선택한 요소를 다른 내용으로 대체합니다.
  1. clone(): 선택한 요소와 그 내용을 복제합니다.
  1. wrap(): 선택한 요소를 지정한 HTML 요소로 감쌉니다.
  1. unwrap(): 선택한 요소의 부모 요소를 제거하여, 부모 요소로부터 분리합니다.

3. 기타 유용한 메서드

  1. css(): 선택한 요소의 CSS 속성을 읽거나 설정합니다.
  1. attr(): 선택한 요소의 속성을 읽거나 설정합니다.
  1. prop(): 선택한 요소의 속성(Property)을 읽거나 설정합니다.
  1. val(): 폼 요소의 값을 읽거나 설정합니다.
  1. text(): 선택한 요소의 텍스트 내용을 읽거나 설정합니다.
  1. html(): 선택한 요소의 HTML 내용을 읽거나 설정합니다.
  1. addClass(): 선택한 요소에 하나 이상의 클래스를 추가합니다.
  1. removeClass(): 선택한 요소에서 하나 이상의 클래스를 제거합니다.
  1. toggleClass(): 선택한 요소에 클래스가 있으면 제거하고, 없으면 추가합니다.
이 외에도 jQuery에는 수많은 메서드가 있습니다. 여기에서 언급한 것들은 DOM 조작과 시각적 효과를 적용하는 데 자주 사용되는 메서드들입니다. 각 메서드는 다양한 방식으로 조합할 수 있으며, 이를 통해 복잡한 UI 동작을 간단하게 구현할 수 있습니다.
 
 

댓글

 
댓글추가 → 부분 리로딩
 
댓글 삭제 → 서버로 통신 → db에서 삭제 → dom을 삭제 → 자바스크립트 remove
 
CSR
 
→ 팀원들끼리 할때, 바닐라로 할건지 제이쿼리로 할건지 정해야한다.
 

 
notion image
 
여기까지 한 번 보기
 
notion image
 
해봄
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { border: 1px solid black; padding: 10px; } #innerBox1 { display: none; } #innerBox2 { visibility: hidden; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <h1>나타내기</h1> <button onclick="showByDisplay()">display로 나타내기</button> <button onclick="showByVisible()">visible로 나타내기</button> <div class="box" id="outerBox"> <div class="box" id="innerBox1"> 내부박스1 </div> <div class="box" id="innerBox2"> 내부박스2 </div> </div> <script> function showByDisplay() { //let el = document.querySelector("#innerBox1"); innerBox1을 찾아서 //el.style.display = "block"; // block으로 바꿔준다. $("#innerBox1").css("display", "block"); // 제이쿼리를 사용해서 바로 바꿔줌 } function showByVisible() { //let el = document.querySelector("#innerBox2"); //el.style.visibility = "visible"; $("#innerBox2").css("visibility", "visible"); } </script> </body> </html>
notion image
 
fadeIn
fadeOut
 
같은것도 바닐라자바스크립트로 구현하기는 복잡한데
 
제이쿼리가 제공해줌
 

Prepend 앞으로 들어감 → 댓글을 등록하면 내가 등록한게 맨 위에 보여야하니까 prepend 사용
Append 뒤로 들어감
 
댓글박스가 있어야 csr 를 할수있음
 
댓글 3
댓글 2
댓글 1
 
→ 부모를 잡아서 append나 prepend로 댓글을 넣는다.
 
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { border: 1px solid black; padding: 10px; } </style> </head> <body> <h1>추가하기</h1> <button onclick="addAppend()">append로 추가하기</button> <button onclick="addPrepend()">prepend로 추가하기</button> <button onclick="addBefore()">before로 추가하기</button> <button onclick="addAfter()">after로 추가하기</button> <div class="box" id="outerBox"> </div> <script> function addAppend() { let newEl = document.createElement("div"); // 빈 돔 생성. -> 객체. el은 element의 약자 newEl.setAttribute("class", "box"); newEl.setAttribute("id", "innerBox1"); // <div class="box" id="innerBox1"></div> newEl.innerHTML = "내부박스1"; // <div class="box" id="innerBox1">내부박스1</div> let el = document.querySelector("#outerBox"); el.append(newEl); // <div class="box" id="outerBox"> // 자식으로 위의 <div class="box>가 들어감 } function addPrepend() { let newEl = document.createElement("div"); newEl.setAttribute("class", "box"); newEl.setAttribute("id", "innerBox2"); newEl.innerHTML = "내부박스2"; let el = document.querySelector("#outerBox"); el.prepend(newEl); } function addBefore() { let newEl = document.createElement("div"); newEl.setAttribute("class", "box"); newEl.setAttribute("id", "innerBox3"); newEl.innerHTML = "내부박스3"; let el = document.querySelector("#outerBox"); el.before(newEl); } function addAfter() { let newEl = document.createElement("div"); newEl.setAttribute("class", "box"); newEl.setAttribute("id", "innerBox4"); newEl.innerHTML = "내부박스4"; let el = document.querySelector("#outerBox"); el.after(newEl); } </script> </body> </html>
notion image
클라이언트 사이드 랜더링 하기
 
 
`` 백틱으로 넣으면 여러줄로 쓸 수 있따. 엔터쳐도 됨
 
`` 으로 넣으면 데이터 바인딩이 된다. <div class=""></div>
 
 
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { border: 1px solid black; padding: 10px; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <h1>추가하기</h1> <button onclick="addAppend()">append로 추가하기</button> <button onclick="addPrepend()">prepend로 추가하기</button> <button onclick="addBefore()">before로 추가하기</button> <button onclick="addAfter()">after로 추가하기</button> <div class="box" id="outerBox"> </div> <script> function render(id, text) { return `<div class="box" id="${id}">${text}</div>`; } function addAppend() { let box = render("inner1", "내부박스1"); $("#outerBox").append(box); } function addPrepend() { let box = render("inner2", "내부박스2"); $("#outerBox").prepend(box); } function addBefore() { let box = render("outer1", "외부박스1"); $("#outerBox").before(box); } function addAfter() { let box = render("outer2", "외부박스2"); $("#outerBox").after(box); } </script> </body> </html>
 
→ 제이쿼리 이용해서 작성한 것
 
제이쿼리로 바꾸는거 해보자 !
 
 
 

삭제

 

반복문으로 리스트 만들기 - CSR

 
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { display: grid; grid-template-columns: 1fr 1fr 1fr; border: 1px solid black; padding: 10px; } .card { border: 1px solid lightgray; box-shadow: 0 4px 4px 0 grey; padding: 10px; margin: 5px; border-radius: 5px; } </style> </head> <body> <h1>반복문으로 리스트 만들기</h1> <button onclick="render()">render</button> <div class="box" id="outerBox"> </div> <script> // 1. 그림그리기 function render() { let el = document.querySelector("#outerBox"); for (let i = 1; i < 5; i++) { el.append(makeCard(i)); } } // 2. DOM 만들기 function makeCard(id) { let card = document.createElement("div"); card.setAttribute("class", "card"); card.setAttribute("id", "card-" + id); // 나중에 이 자리에 PK가 오면된다. card.innerHTML = ` <h3>제목${id} 입니다</h3> <p>내용${id} 입니다</p> <button onclick="del(${id})">삭제</button> `; return card; } function del(id) { let el = document.querySelector("#card-" + id); el.remove(); } </script> </body> </html>
 
 
 
notion image
렌더링할때 PK를 삭제()에 넣어야 한다.
 
 
notion image
 
💡
클라이언트 사이드 렌더링(CSR)로 만들땐 Id, onclick 같은 애들은 미리 걸어놔야 한다.
 
function makeCard(id) { return `<div id="card-${id}" class="card"> <h3>제목${id} 입니다</h3> <p>내용${id} 입니다</p> <button onclick="del(${id})">삭제</button> </div>`; }
 
일부 제이쿼리로 수정
 
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { display: grid; grid-template-columns: 1fr 1fr 1fr; border: 1px solid black; padding: 10px; } .card { border: 1px solid lightgray; box-shadow: 0 4px 4px 0 grey; padding: 10px; margin: 5px; border-radius: 5px; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <h1>반복문으로 리스트 만들기</h1> <button onclick="render()">render</button> <div class="box" id="outerBox"> </div> <script> // 1. 그림그리기 function render() { for (let i = 1; i < 5; i++) { $("#outerBox").append(makeCard(i)); } } // 2. DOM 만들기 function makeCard(id) { return `<div id="card-${id}" class="card"> <h3>제목${id} 입니다</h3> <p>내용${id} 입니다</p> <button onclick="del(${id})">삭제</button> </div>`; } function del(id) { $(`#card-${id}`).remove(); } </script> </body> </html>
전체 제이쿼리로 수정
 
 

토글

 
💡
DOM에서 특정 클래스의 존재 여부에 따라 스타일이나 속성을 변경하는 방법
 
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <style> .like-heart { font-size: 24px; color: gray; cursor: pointer; } .like-heart.liked { color: red; } </style> </head> <body> <span class="like-heart" onclick="likeToggle()">&#10084;</span> <script> // https://www.htmlsymbols.xyz/heart-symbols function likeToggle() { let likeHeart = document.querySelector('.like-heart'); likeHeart.classList.toggle('liked'); } </script> </body> </html>
💡
DOM(Domain Object Model)에서 "토글(toggle)"은 주어진 상태를 반복적으로 변경하는 동작을 의미합니다. 예를 들어, 어떤 요소에 특정 클래스가 적용되어 있으면 이를 제거하고, 클래스가 없으면 새로 추가하는 방식으로 상태를 전환하는 것입니다.
위 코드에서 likeToggle() 함수는 like-heart라는 클래스를 가진 HTML 요소의 상태를 "좋아요"와 "좋아요 해제" 사이에서 전환하는 기능을 수행합니다.

DOM Toggle 동작 원리:

  1. 요소 선택:
      • document.querySelector('.like-heart')를 통해 DOM에서 like-heart 클래스를 가진 첫 번째 요소를 선택합니다. 이 선택된 요소는 likeHeart 변수에 저장됩니다.
  1. 클래스 토글:
      • likeHeart.classList.toggle('liked');에서 classList.toggle 메서드가 사용됩니다. 이 메서드는 다음과 같이 동작합니다:
        • 만약 선택된 요소에 'liked' 클래스가 없다면, 해당 클래스를 추가합니다.
        • 반대로 'liked' 클래스가 이미 존재하면, 그 클래스를 제거합니다.

예시 동작:

  • 초기 상태에서는 심장 모양이 회색입니다(기본 상태에서 .liked 클래스가 없기 때문에).
  • 사용자가 심장 모양을 클릭하면, likeToggle() 함수가 호출되어 .liked 클래스가 추가됩니다. 이는 심장 모양의 색상을 회색에서 빨간색으로 변경합니다.
  • 다시 클릭하면, .liked 클래스가 제거되고 심장 모양이 다시 회색으로 돌아갑니다.
이처럼 DOM에서 특정 클래스의 존재 여부에 따라 스타일이나 속성을 변경하는 방법을 "토글"이라고 부르며, 이는 사용자 인터페이스에서 상태를 쉽게 전환하는 데 자주 사용됩니다.
 

Promise 통신

 
→ 인텔리제이에 8080서버로 실행시키기
→ 아래코드 localhost로 바꿔서 하면 연습할 수 있음
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="root"> </div> <script> function makeDom() { return `<div>그림</div>`; } function download() { const xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8080/test", false); // false는 동기 요청을 의미함 xhr.send(); return xhr; } $("#root").append(makeDom()); $("#root").append(makeDom()); let xhr = download(); $("#root").append(`<div>${xhr.responseText}</div>`); $("#root").append(makeDom()); </script> </body> </html>
  • 동기적 요청 - 고장난 것 처럼 보인다. UX가 안좋아진다.
 
notion image
 
열어보면 이 데이터가 뜨는데 5초나 걸림
 
notion image
 
download 실행돼서 /test 로 요청하면 5초 걸리게 설정해둬서.
notion image
 
  • 자바스크립트는 단일 스레드 → 한번에 하나의 작업만 수행할 수 있음
  • 자바는 멀티스레드
 
( 지피티 왈,
자바스크립트는 비동기 작업(예: setTimeout, Promise, async/await)과 같은 기능을 통해 이벤트 루프를 활용하여 비동기적으로 코드를 실행할 수 있습니다. )
→ 멀티스레드면 let xhr = download (); 처럼 오래걸리는걸 다른 스레드한테 넘기고
아래줄로 내려가서 dom 을 마저 그리면 되는데
단일 스레드는 이게 안되고 download 에서 기다려야함. 멍때려야함. 단일 스레드라서.
 
그래서 자바스크립트는 download를 비동기로 실행시켜야 함!!
 
💡
원칙 1. 무거운 코드는 함수로 만든다.
  1. 그리고 그 함수는 비동기로 실행한다.
 
동기 작업?을 하는 무거운 코드를 download 함수로 만들고 이걸 async await 비동기로 실행 하기!
 
비동기로 바꾸면
download 주문하고 나서 내가 해야 할 일을 다 끝내고 (dom 그림그리기 끝내고) 돌아가면 됨
→ download 실행하고 안 기다리고 그림 그리고! download 다 되면 거기로 간다!
비동기는 순서가 없다
 
++
맥쓰는 팀원 이거하다가 이슈발생함.
xhr 이 엄청 옛날 기술이어서 최신 크롬?에서는 안됨. 지원 안함.
 
자 이제 비동기 요청을 하도록 위의 코드를 수정해보자.
다하고 실행시켜서 속도 체감해보기.
 
8080서버. → 인텔리제이로 clone 해서 실행시켜두기. 여기 /랑 /test 로 요청보낼거임
 
notion image
→ 192.168.0.99 선생님 서버로 일단 했는데
인텔리제이에 8080서버 실행시켜두고 localhost로 수정해서 연습하기
 
notion image
download 함수가 실행되면 패치를 때려서 ”response 객체”에 프로미스를 줌 !
 
프로미스는 “어음” → 돈이 없으니까 어음을 줌. → 기다려라 !
 
PromiseState에 “pending” 이라고 뜰거임 ( ~ing 라는 의미 )
notion image
 
난 왜 fulfilled 가 뜨지
 
어쨌든
 
나는 promise 받기 싫어. 다돼면 돈으로 줘
 
하면 async 와 await 를 걸어줌
 
notion image
test로 요청보내면 sleep 5000을 걸어둬서 전체 처리하는데 5초 정도 걸림
test로 요청보내면 sleep 5000을 걸어둬서 전체 처리하는데 5초 정도 걸림
await 에서 response 가는게 5초가 걸리지만 ( → 8080서버의 /test에 일처리하는데 5초 정도 걸리도록 Thread.sleep 을 설정해둠. 그래서 await 에서 5초 기다렸다가! response로 값이 넘어감)
 
await를 걸면
 
response 는 어음이 아닌 “값”을 받음
 
notion image
 
response.json → 가져온 데이터 json으로 파싱해서
body에는 값이 들어감 ( → json 형태로 ! )
 
그전에 response로 뭐가 넘어왔는지 console에 찍어보면
(선생님 퇴근해서 localhost로 바꿔서 찍어보기)
notion image
진짜 object Response 가 넘어옴.
 
“response 객체”
 
이걸 json으로 바꿔서 찍어보면
notion image
 
notion image
 
data에 json데이터가 들어간건지, data가 자바스크립트 오브젝트인지 헷갈려서 지피티한테 물어봄
 
notion image
 
엄밀히 말하면 response 객체에서 JSON 형태의 데이터를 추출하여 JavaScript 객체 로 변환
한다고 함.
⇒ 그래서 console.log(data) 를 찍어서 나오는 건 “자바스크립트 객체” 이고 ?
이후에 data.body 로 JSON 객체 안의 특정 속성에 접근할 수 있다고 함
 
아니 그래서 data 를 콘솔에 찍으면
자바스크립트 객체를console.log에 찍어보았을 때
자바스크립트 객체를console.log에 찍어보았을 때
이렇게 나오는데 이게 머라고 ?
 
→ 자바스크립트 객체!
 
{
body : “test”
msg : “성공”
status : 200
}
 
처럼 값에 “”가 붙어있는건 ⇒ JavaScript 객체
 
JSON 데이터의 키-값 쌍이 그대로 JavaScript 객체의 속성으로 매핑되어,
이 객체를 통해 데이터를 접근할 수 있습니다.
 
data.body
data.msg
data.id
 
이렇게 접근한다.
 
notion image
 
 
notion image
 
 
→ JSON과 자바스크립트 객체가 어떻게 다른지 어느정도 이해하였다!
 
그리고
 
notion image
 
await를 걸면 프로미스를 안주고 “값”을 준다.
5초를 기다렸다가 값이 response 로 들어온다.
body에 자바스크립트 오브젝트를 파싱해서 준다.
( → JSON 데이터를 파싱해서 JS객체로 만들어 body에 담음)
그리고 아래줄에서 div에 그림을 그린다. (→ $("#root").append(<div>${data.body}</div>); 이부분 )
notion image
그럼 data.body 의 값인 test가 잘 들어와서
<div>test</div>가 들어오게 된다.
 
코드 순서로 치면 test가 마지막 그림 위에 와야하는게 아닌가 싶었는데
어차피 이렇게 받아오는 건 대부분 데이터이고 데이터는 dom이 다 생성된 후에
그 사이에 집어넣을 거니까 (즉, 지금처럼 <div>로 넣을게 아니니까 ) 상관없다고 생각한다 (내의견)
notion image
 
여기를 자세히 설명하면
 
async 를 붙이면 “비동기함수”인 것을 인식한다고 한다.
fetch가 실행되며 5초 걸리는걸 알아채고 await 에 체크포인트(북마크)를 걸고 그 함수를 빠져나감.
→ 즉, 멍 때리는 시간(기다리는 시간)을 없애려고 async 와 await 를 건다.
dom의 맨 아래 </html>까지 다 실행되고 나서야 await로 돌아가서 실행한다.
→ 이렇게 하면 화면 그림 그릴거 다 그리고 5초(기다리는 시간)뒤에
<div>${data.body}</div> 가 딱 들어간다.
 
 
notion image
 
  • 전체 코드는 비동기로 실행됨
  • 코드블록안에는 동기적으로 실행됨. → download 함수 안에는 동기적!
 
await 에서 체크포인트 걸고 빠져나와서 그 다음줄 $("#root").append(makeDom());
실행하면 download 함수에서 읽은 거 다 사라지는거 아닌가 ? 라고 생각할 수도 있지만
메모리에 스택이 살아있어서 download의 지역변수가 살아있음 ( 대신 await 가 적혀있어야 함)
 
라고 한다.
 
💡
async await 외에 then then 도 있지만 async await 가 제일 트렌디하다고 함!!! 그러니 async await 를 사용하자 ! → then then 은 통신이 끝나면 then 이 자동으로 호출됨 ( callback ) (url이 통신이 완료되면 then으로 넘어감)
 

Promise Callback

Promise가 실행된 뒤, 거부 당하거나, 성공했을 때의 콜백 메서드
 
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button onclick="runAsyncTask()">Promise Callback Test</button> <script> function doAsyncTask() { return new Promise(function (resolve, reject) { setTimeout(function () { let success = false; if (success) { resolve('Async task completed successfully.'); } else { reject('Async task failed.'); } }, 1000); }); } async function runAsyncTask() { console.log("test start"); try { const result = await doAsyncTask(); console.log(result); } catch (error) { console.error(error); } console.log("test end"); } </script> </body> </html>
notion image
 
runAsyncTask 가 실행되고 (→ “test start”)
doAsyncTask 가 실행되는데
 
notion image
success 를 false 로 설정해두어서,
 
else 가 실행됨 → reject( ‘Async task failed ‘ ); 내 생각에는 error(”에러임”) 랑 비슷한거 같음.
 
암튼 reject 되어서
 
notion image
다시 runAsyncTask 로 넘어와서 ( 2 실행하다가 reject 되었음 )
console.log(result); 못찍고
 
에러 발생했으니 console.error(error) 에 가져온 메세지 찍어주고
아래 console.log(”test end”) 가 실행되는 거 같음
 
⇒ Promise 요청이 성공 or 실패해서 콜백된 후에 어떻게 처리해야하는 과정이 있으면
이걸 쓰는거 같음

Ajax Fetch ( Fetch API )

💡
AJAX는 "Asynchronous JavaScript and XML"의 약자로,
자바스크립트를 사용하여 비동기적으로 서버와 데이터를 주고받는 기술입니다.
 
기존에는 웹 페이지에서 사용자 입력을 받고, 서버로 데이터를 전송하여 새로운 페이지를 받아와서 보여주는 방식이었습니다. 이러한 방식은 화면이 깜빡이는 등의 불편한 경험을 제공하며, 데이터의 양이 많아지면 더욱느려질 수 있습니다.
 
AJAX는 이러한 문제점을 개선하기 위해, 웹 페이지에서 동적으로 데이터를 가져오거나 업데이트하는 기술입니다. AJAX를 사용하면, 서버와 비동기적으로 데이터를 주고받아 필요한 부분만 화면을 갱신할 수 있으며, 화면 전환이 발생하지 않아 사용자가 불편한 경험을 하지 않습니다.
 
AJAX는 자바스크립트를 사용하여 서버에 요청을 보내고, 이에 대한 응답을 처리합니다. 이를 위해 XMLHttpRequest 객체를 사용하여 서버와 통신합니다. 최근에는 fetch API를 사용하는 방법이 많이 사용되고 있습니다.
 
AJAX를 사용하면 사용자 경험이 개선되고, 서버의 부하가 감소하여 웹 애플리케이션의 성능을 개선할 수 있습니다.
 
요즘은 XMLHttpRequest 객체 사용하는건 잘 안한다고 함
 
 

연습

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button onclick="fetchTodo()">통신하기</button> <script> // https://jsonplaceholder.typicode.com // async -> 비동기함수가 되기 위한 키워드 // await -> Promise가 처리될 때까지 기다리는 키워드 async function fetchTodo() { try { let promiseData = await fetch("https://jsonplaceholder.typicode.com/todos/1"); let todos = await promiseData.json(); console.log(todos); } catch (err) { console.log(err); } } </script> </body>
 
예시에 JsonPlaceHolder 이용함
 
  • async -> 비동기함수가 되기 위한 키워드
  • await -> Promise가 처리될 때까지 기다리는 키워드
 
notion image
 
통신하기를 클릭하면
 
promiseData 에 Response 객체가 담기고, .json()으로 파싱해서 todos에 자바스크립트 객체가 담김
→ console.log(todos); 로 자바스크립트 객체의 값을 콘솔에서 확인해봄
 

AJAX Fetch Render

 
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box { border: 1px solid black; padding: 10px; } </style> </head> <body> <input type="text" id="num" rrr="100" value="1" /> <button onclick="fetchTodo()">통신하기 </button> <div class="box" id="box"> </div> <script> async function fetchTodo() { let el = document.querySelector("#num"); let id = el.value; let rrr = el.getAttribute("rrr"); console.log("기본속성이 아니면 getAttribute()", rrr); try { let promiseData = await fetch("https://jsonplaceholder.typicode.com/todos/" + id); let todo = await promiseData.json(); render(todo); } catch (err) { console.log(err); } } function render(todo) { let le = document.querySelector("#box"); le.innerHTML = todo.title; } </script> </body> </html>
 
AJAX Fetch 해서 가져온걸 렌더링 해보자!
 
notion image
 
값을 넣고 통신하기를 누르면 자바스크립트 객체.title 해서 타이틀을
화면에 렌더링 할 수 있다 : )
 
notion image
다 콘솔에 찍어보면 흐름을 알 수 있다.
 
  • el 에 Id가 num인 DOM 객체가 담긴다.
  • id 에 해당 DOM 객체의 Value 값이 담긴다. (위에선 1로 고정되어 있음)
    • 참고로 rrr 처럼 태그의 기본속성 ( 예 - type, id, value ) 이 아니면
      • .getAttribute() 해서 해당 속성의 값을 가져올 수 있다.
    • 기본속성이면 dom객체변수명.기본속성 ( 예 - el.value , el.id) 해서 가져올 수 있음
  • response 객체에 담긴 값을 파싱해서 자바스크립트 객체 형태로 todo 에 담음
  • console.log(todo) 찍어보면 자바스크립트 객체 안에 데이터가 담긴 걸 확인할 수 있음
  • 바로 render 함수로 todo 넘김
  • render 함수에서 todo(자바스크립트 객체).title 해서 값을 화면에 렌더링 함! 끝
 
notion image
notion image
객체안의 다른 데이터도 렌더링 잘 되는것을 확인할 수 있다 :)
 
notion image
💡
DOM 객체는 HTML 요소를 JavaScript에서 조작할 수 있게 해주는 인터페이스입니다. DOM 객체는 HTML 요소의 속성, 메서드, 이벤트 등을 접근하고 조작할 수 있는 방법을 제공합니다. 따라서, console.log(el);을 통해 출력된 결과는 "input 요소를 가리키는 DOM 객체"라고 할 수 있습니다.
 

Todo List 만들어보기

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>To-Do List</title> <style> .container { width: 400px; margin: 0 auto; text-align: center; font-family: Arial, sans-serif; } h1 { font-size: 2rem; margin: 0; padding: 20px 0; color: #444; } ul { list-style: none; padding: 0; margin: 0; } li { border-bottom: 1px solid #ddd; padding: 10px; font-size: 16px; display: flex; align-items: center; } li:last-child { border-bottom: none; } label { margin-left: 10px; } input[type="checkbox"] { margin: 0; transform: scale(1.5); margin-right: 10px; } </style> </head> <body> <div class="container"> <h1>To-Do List</h1> <button onclick="todoAllFetch()">todo 가져오기</button> <ul class="todo-list" id="todoBox"> </ul> </div> <script> async function todoAllFetch() { let promiseData = await fetch("https://jsonplaceholder.typicode.com/todos"); let todos = await promiseData.json(); render(todos); } function render(todos) { let el = document.querySelector("#todoBox"); for (const todo of todos) { let newEl = document.createElement("li"); newEl.innerHTML = ` <input type="checkbox" id="todo-${todo.id}" style="text-decoration: none"> <label for="todo-1">${todo.title}</label> `; el.append(newEl); } addCheckBoxEvent(); } function addCheckBoxEvent() { const checkboxes = document.querySelectorAll('input[type="checkbox"]'); checkboxes.forEach((checkbox) => { checkbox.addEventListener('click', () => { if (checkbox.checked) { checkbox.nextElementSibling.style.textDecoration = 'line-through'; } else { checkbox.nextElementSibling.style.textDecoration = 'none'; } }); }); } </script> </body> </html>
notion image
notion image
 
 
notion image
 
데이터가 200개 넘어옴.
notion image
마우스 우클릭 → Copy Object 해서 복사한 값을 메모장에 넣어서 확인하면
 
notion image
 
이렇게 생겼음.
 
⇒ 객체 배열. 즉, 배열안의 객체들
 
notion image
 
이렇게 객체 배열이 넘어왔으니
 
반복문을 사용해서 배열 속의 객체를 꺼내야 함
 
notion image
 
→ for ( const todo of todos )
→ 자바스크립트 반복문은 이렇게 생겼다. of 를 사용함
 
notion image
 
콘솔에 찍어보면 자바스크립트 객체가 200개 쫙 찍히는 것을 확인할 수 있다.
 
그리고 <li> 태그를 생성해서 그 안에
<input type="checkbox" id="todo-${todo.id}" style="text-decoration:none"> <label for="todo-1">${todo.title}</label>
 
를 생성해주고 ( → 중간에 ${} 를 사용해서 값을 랜더링? 해주기 위해 앞뒤로 백틱 사용 )
 
id가 todoBox 인 <ul> 태그 안에 append 해줌
 
그리고 addCheckBoxEvent 함수 실행
 
input[type="checkbox"] 인풋 타입이 checkbox인 애를 찾아서
( → 방금 <li> 안에 렌더링? 생성 ? 해준 <input 체크박스>. 반복문 돌려서 200개 만들어졌음.ㅎ )
 
각각의 checkbox에 반복문으로 이벤트 리스너 달아줌 .
 
click 해서 checked 되면 line-through 되도록
 
💡
checkbox.nextElementSibling.style.textDecoration = 'line-through';
 
 
 
 
자 그럼 이제 우리가 만든 블로그로 요청해보자.
 
 
notion image
notion image
notion image
이 문자열 데이터를 받을 거임
 
 
notion image
 
<!DOCTYPE html> <html lang="en"> <head> <title>Blog</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="list.html">Metacoding</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="save-form.html">글쓰기</a> </li> </ul> </div> </div> </nav> <div class="container p-5"> <div id="board-box"></div> <!--게시글 박스 만들어주기. 그래야 append 할 수 있다.--> </div> <footer class="bg-light p-5 text-center"> <h4>Created by Metacoding</h4> <h5>☎ 010-2222-7777</h5> <button class="btn btn-outline-primary">고객센터</button> <button class="btn btn-outline-primary">오시는길</button> </footer> <script> async function getBoards() { let response = await fetch("http://localhost:8080"); // fetch 호출하고 cpu는 도망나와서 자기 할거 함. -> 스프링 서버임. 선생님이 깃허브로 준거 실행시키고 거기서 json을 가지고 온다. let data = await response.json(); console.log(data); let boardList = data.body; //자바스크립트 forEach 문 for (board of boardList) { console.log(board); let dom = makeBox(board); console.log(dom); $("#board-box").append(dom); //append 하면 뿌려진다. } } getBoards(); function makeBox(board) { return ` <div class="card mb-3"> <div class="card-body"> <div class="d-flex justify-content-between"> <div> <h4 class="card-title mb-3">${board.title}</h4> <span>${board.content}</span> </div> <button class="btn btn-outline-danger" onclick="del(${board.id})">삭제</button> </div> </div> </div>`; } </script> </body> </html>
 
notion image
 
 
notion image
엔티티명-{id(pk)} 로 아이디 걸어줘야 한다.
 
notion image
이렇게 아이디가 걸려있어야 지정해서 삭제할 수 있다.
 
 
notion image
여기 id를 걸어준건 통신해서 삭제를 하려고 걸어준거고
 
위에 아이디를 걸어서 지정하는건 어떤 div인지 식별하기 위해서임
 
notion image
notion image
notion image
 

블로그 동적으로 생성해보기

 
notion image
 
 

save-form.html

<!DOCTYPE html> <html lang="en"> <head> <title>Blog</title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"/> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="list.html">Metacoding</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="save-form.html">글쓰기</a> </li> </ul> </div> </div> </nav> <div class="container p-5"> <div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">제목1</h4> <a href="detail.html" class="btn btn-primary">상세보기</a> </div> </div> <div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">제목2</h4> <a href="detail.html" class="btn btn-primary">상세보기</a> </div> </div> </div> <footer class="bg-light p-5 text-center"> <h4>Created by Metacoding</h4> <h5>☎ 010-2222-7777</h5> <button class="btn btn-outline-primary">고객센터</button> <button class="btn btn-outline-primary">오시는길</button> </footer> </body> </html>
 

list.html

<!DOCTYPE html> <html lang="en"> <head> <title>Blog</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="list.html">Metacoding</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="save-form.html">글쓰기</a> </li> </ul> </div> </div> </nav> <div class="container p-5"> <div class="card mb-3"> <div class="card-body"> <div class="d-flex justify-content-between"> <div> <h4 class="card-title mb-3">제목1</h4> <span>내용1</span> </div> <button class="btn btn-outline-danger" onclick="del(1)">삭제</button> </div> </div> </div> </div> <footer class="bg-light p-5 text-center"> <h4>Created by Metacoding</h4> <h5>☎ 010-2222-7777</h5> <button class="btn btn-outline-primary">고객센터</button> <button class="btn btn-outline-primary">오시는길</button> </footer> </body> </html>
 
list 에 delete 먼저 작성해봄
 
notion image
→ container div 안에 box div 를 하나 더 만들어줘야 append 할 수 있다! 만들어주기 !
 

list 1차 작성.html

<!DOCTYPE html> <html lang="en"> <head> <title>Blog</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="list.html">Metacoding</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="save-form.html">글쓰기</a> </li> </ul> </div> </div> </nav> <div class="container p-5"> <div id="board-box"></div> <!--게시글 박스 만들어주기. 그래야 append 할 수 있다.--> </div> <footer class="bg-light p-5 text-center"> <h4>Created by Metacoding</h4> <h5>☎ 010-2222-7777</h5> <button class="btn btn-outline-primary">고객센터</button> <button class="btn btn-outline-primary">오시는길</button> </footer> <script> function del(boardId) { fetch( "http://localhost:8080/board/" + boardId, { method: "delete" }); } async function getBoards() { let response = await fetch("http://localhost:8080"); // fetch 호출하고 cpu는 도망나와서 자기 할거 함. -> 스프링 서버임. 선생님이 깃허브로 준거 실행시키고 거기서 json을 가지고 온다. let data = await response.json(); console.log(data); let boardList = data.body; //자바스크립트 forEach 문 for (board of boardList) { console.log(board); let dom = makeBox(board); console.log(dom); $("#board-box").append(dom); //append 하면 뿌려진다. } } getBoards(); function makeBox(board) { return ` <div class="card mb-3" id="board-${board.id}"> <div class="card-body"> <div class="d-flex justify-content-between"> <div> <h4 class="card-title mb-3">${board.title}</h4> <span>${board.content}</span> </div> <button class="btn btn-outline-danger" onclick="del(${board.id})">삭제</button> </div> </div> </div>`; } </script> </body> </html>
 
  • 인텔리제이에 8080 서버 켜두고 해야함. localhost로 요청하기
notion image
reload 해야지 삭제가 반영이 된다.
 
왜 이전 코드는 삭제를 해도 바로 반영이 안되는걸까 ?
 
notion image
notion image
 

수정된 list.html

<!DOCTYPE html> <html lang="en"> <head> <title>Blog</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="list.html">Metacoding</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="save-form.html">글쓰기</a> </li> </ul> </div> </div> </nav> <div class="container p-5"> <div id="board-box"></div> </div> <footer class="bg-light p-5 text-center"> <h4>Created by Metacoding</h4> <h5>☎ 010-2222-7777</h5> <button class="btn btn-outline-primary">고객센터</button> <button class="btn btn-outline-primary">오시는길</button> </footer> <script> async function del(boardId) { let response = await fetch("http://localhost:8080/board/" + boardId, { method: "delete" }); let data = await response.json(); console.log(data); $(`#board-${boardId}`).remove(); } async function getBoards() { let response = await fetch("http://localhost:8080"); let data = await response.json(); //console.log(data); let boardList = data.body; for (board of boardList) { let dom = makeBox(board); $("#board-box").append(dom); } } getBoards(); function makeBox(board) { return `<div class="card mb-3" id="board-${board.id}"> <div class="card-body"> <div class="d-flex justify-content-between"> <div> <h4 class="card-title mb-3">${board.title}</h4> <span>${board.content}</span> </div> <button class="btn btn-outline-danger" onclick="del(${board.id})">삭제</button> </div> </div> </div>`; } </script> </body> </html>
하면 바로 삭제된게 반영된다.
 
 
 
vscode 로 연습
 
notion image
 
기타 참고
 
 
제이쿼리 연습
 
SPA란?
 
API JSON 데이터 받아와서 NODE.JS 활용해서 자바스크립트 객체안에 담는방법
 

x-www-form-urlencoded 타입이란 (multipart/form-data와의 차이점)

 
WINDOW, DOM, BOM
 
 
다음날. 이어서 수업 중.
 
 
💡
1건만 수정해줘 할때 Patch를 쓰는데 잘 안쓰고 PUT을 쓴다. POST, PUT, PATCH → 에서는 body 를 사용하고 GET, DELETE → body를 사용하지 못한다. 8bit 통신 → 바이트로 통신한다는 거
 
약속 = 프로토콜 (동등함 ) → 프로토콜이 계쏙 성장해서 만들어진게 http 프로토콜!
http는 이런 약속이 모인 것
인터페이스가 갑.
 
새로운 국가가 나타남 → 프로토콜이 http 프로토콜에 맞춰서 들어와야 함
→ 이제 RFC 7231랑 협의, 약속해서 들어오는게 아니고 무조건 맞춰서 들어와야 한다.
 
RFC 7231
 
페이로드는 데이터의 바디
 
notion image
notion image
스프링의 기본전략은 xxx-form encoded 어쩌고 이지만, ( → title=머시기&content=머시기 )
 
스프링에서 DTO 앞에 @RequestBody 붙이면 JSON으로 보낸다.
 
{”title”:”머시기”,”content”:”머시기”}
 
notion image
⇒ @ReestController 라고 붙이고 응답할때 object 로 응답하면 object 를 json으로 파싱해서 보낸다!
 
제네릭의 타입은 new 할 때 결정난다.
→ String 이 될 수도 있고, User object 가 될 수도 있고, Board object 가 될 수도 있고
 
ResponseEntity 도 제네릭 타입이다.
? 와일드 카드를 넣는다.
new ApiUtil<> → 여기에 바디데이터 넣는다.
 
return new ResponseEntity<>(new ApiUtil<>(404, 자원을 찾을 수 없습니다 ) 이런식으로 쓰면
404를 리턴함
 
 
모든 언어는 json (중간언어. 통신할때쓰는언어?)으로 바꿔서 통신하고
자바, 자바스크립트는 자기 오브젝트로 바꿔서 읽는다.
 
form 태그는 json을 지원하지 않는다.
 
notion image
 
 
바닐라 자바스크립트의 innerText(앤쓸일 많이 없음), innerHtml 이랑 같은거인데
 
닫는 태그가 있는 모든 태그의 사이 공간에 값만 들고올때는 text
그 사이의 태그도 함께 들고오고 싶으면 html
value 속성값을 들고오고 싶으면 val
 
console.log( “v4”, 값조회할변수명 );
→ 콘솔에 prefix 줄 수 있음 이렇게
 

샘플

<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="b1"> <h3>hello</h3> </div> <input id="b2" type="text" value="bye"> <script> let v1 = $("#b1").text(); console.log("v1", v1); let v2 = $("#b1").html(); console.log("v2", v2); let v3 = $("#b2").val(); console.log("v3", v3); let v4 = document.querySelector("#b1").innerHTML; console.log("v4", v4); let v5 = document.querySelector("#b2").value; console.log("v5", v5); </script> </body> </html>
 

중요

 
MIME 타입을 CONTENT-TYPE이라는 키값에 넣어줘야함
→ application/json인지 www-form 어쩌고인지, xml인지, text/html 인지
바디데이터가 뭔지 알려줘야함! 내가 들고가는 데이터에 레이블링을 해주는 것
데이터 타입을 알려줘!
 
notion image
text/plain 으로 마임타입을 설정하고 요청보낸걸 확인하면
<h1>를 못읽어서 <h1>hello</h1> 이라고 브라우저에 뜬걸 확인할 수 있다.
notion image
text/html 로 mimetype을 설정하니 태그를 인식함.
 
 
 
 
notion image
notion image
이해하기보다는 문서를 보고 정리
 
이해할건 promise가 어떻게 작동하는지이고
 
위의 문서보고 사용법을 익히기
 
중요한건 네트워크, os
 
Fetch Api는 아래처럼 컨텐츠 타입을 넣는다! 각 api 마다 다르기 때문에
이런건 찾아보면서 사용하기.
 
 
headers : {
‘Content-type’ : ‘application/json; charset=utf-8;
}
 
1.1에서는 charset 넣어야함
 
++
마임타입 종류
 

save-form.html

<!DOCTYPE html> <html lang="en"> <head> <title>Blog</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> </head> <body> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href="list.html">Metacoding</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="collapsibleNavbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="save-form.html">글쓰기</a> </li> </ul> </div> </div> </nav> <div class="container p-5"> <!-- 요청을 하면 localhost:8080/board/save POST로 요청됨 title=사용자입력값&content=사용자값 --> <div class="card"> <div class="card-header"><b>글쓰기 화면입니다</b></div> <div class="card-body"> <form> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter title" id="title"> </div> <div class="mb-3"> <textarea class="form-control" rows="5" id="content"></textarea> </div> <button onclick="btnSave()" type="button" class="btn btn-primary form-control">글쓰기완료</button> </form> </div> </div> </div> <footer class="bg-light p-5 text-center"> <h4>Created by Metacoding</h4> <h5>☎ 010-2222-7777</h5> <button class="btn btn-outline-primary">고객센터</button> <button class="btn btn-outline-primary">오시는길</button> </footer> <script> async function btnSave() { // 1. dom에서 값 가져오기 (제이쿼리 사용하기) let reqDTO = { title: $("#title").val(), content: $("#content").val() }; // 2. json으로 변경하기 let reqBody = JSON.stringify(reqDTO); // 3. fetch로 post 요청하기 let response = await fetch("http://localhost:8080/board", { method: "post", body: reqBody, headers: { 'Content-type': 'application/json; charset=utf-8', } }); // 4. 응답후 처리 let respBody = await response.json(); console.log("respBody", respBody); // 5. 응답후 처리 location.href = "/blog/list.html";ㄴ } </script> </body> </html>
 
응답 후에 list 로 가도록 수정함
 
 
Share article

keepgoing