Ⅰ. 오전 수업
A. 1교시: JavaScript
1. 지난 시간 복습
- 객체
- 함수
- DOM(Document Object Model)
- 실습: 요소 가져오기
2. getElementById() 실습 1
B. 2교시: JavaScript
1. getElementById() 실습 1 (cont.)
2. getElementById() 실습 2
C. 3교시: JavaScript
1. getElementById() 실습 2 (cont.)
2. 이벤트 처리
Ⅱ. 오후 수업
A. 4교시
1. 지난 시간 복습
2. 실습: Gmarket best 상품
B. 5교시
1. 실습: Gmarket best 상품 (cont.)
C. 6교시
1. Gmarket 실습 내용 정리
2. 실습: 이미지 수집 (포켓몬)
Ⅲ. CARRER UP
Ⅳ. 하루 돌아보기
=> 기호를 사용하여 함수를 정의. 자체적인 this 바인딩을 갖지 않고, 자신이 정의된 위치의 lexical scope의 this를 그대로 사용(화살표 함수 내부에서 사용되는 this는 함수가 정의될 때 결정되며, 함수가 호출될 때 동적으로 변경되지 않음)// 함수 선언문(function statement)
function add_statement(x,y) {
return x+y
}
// 함수 표현식(function expression)
var add_expression = function(x,y) {
return x+y
};
// 함수 생성자(arg1,arg2,..,argN,본문)
var add_construction = new Function(‘x’,’y’,’return x+y’)
console.log(add_statement(1,2))
console.log(add_expression(1,2))
console.log(add_construction(1,2))
// 화살표 함수 (Arrow Function)
const multiply = (a, b) => a * b;
console.log(multiply(4, 6)); // 출력: 24
// 화살표 함수의 this에 관하여
const obj = {
value: 10,
getValue: function() {
return this.value;
},
getValueArrow: () => {
return this.value; // obj 객체가 아닌 전역 객체의 value를 가리킴
}
};
console.log(obj.getValue()); // 출력: 10 (obj 객체의 value)
console.log(obj.getValueArrow()); // 출력: undefined 또는 전역 객체의 value (브라우저 환경에서는 window.value)
더 알아보기: 자바스크립트 함수를 선언하는 여섯가지 방법
.innerText=)하면 됨코드 리팩토링 할 때 이런 보안 이슈 신경쓰기
→ TIP: CursorAI나 코드를 담당하는 AI에게 보안 이슈 같은 거 잡아달라고 요청하기

풀다가 막힌 부분 꼭 정리하기
코드 적다가 막히면 바로 생성형 AI한테 물어보지 말고 최대한 먼저 스스로 생각해보는 시간 가지기







document.getElementById("content").innerHTML += data;로 쓰기!
document.getElementById("content").innerHTML 문장이 반복됨 → 반복되는 요소(document.getElementById("content"))를 변수에 저장하기
- 주의 사항 ★★★
- 요소를 변수에 저장할 때는 값이 아닌 요소 자체를 저장한다.
- 값 자체를 가져오면 로직 성립 자체가 안 됨(
"" += "<h1>h1 태그입니다.</h1>"→ 성립되지 않는 로직)- div = document.getElementById("content")
- div 요소 자체(=DOM 객체)를 변수에 저장
- 이후 div.innerHTML을 사용해서 요소의 내용을 조작할 수 있음:
div.innerHTML += h1_data;
- 기존 내용 뒤에 새 HTML 코드를 누적해서 추가할 수 있음
- div = document.getElementById("content").innerHTML
- div 영역의 "내용"(문자열)만을 변수에 저장
- 즉, 실제로는 HTML 요소가 아니라 "텍스트(문자열)"가 저장 → 이후
div += h1_data;를 하면 단지 문자열을 변수에 덧붙이는 것뿐이고, 화면에 아무런 변화가 일어나지 않음: DOM 요소에 접근한 것이 아니기 때문- 좀 더 자세한 원리
- innerHTML은 HTML 요소의 "속성(property)"으로, 해당 요소의 '내용'을 의미
- div = document.getElementById("content")
- div라는 변수가 실제 브라우저에 존재하는
<div id="content">를 가리킴- div.innerHTML을 쓰거나 += 연산을 하면 실제 화면의 내용을 바꿀 수 있음
- div = document.getElementById("content").innerHTML
- div라는 변수에는 현재 화면에 들어있는 "문자열(HTML로 되어있는 텍스트)"만 들어 있음
- div += h1_data 는 이 변수값을 단순히 이어붙이기만 하고, 실제 element에는 아무 효과가 없음
- 결론
- 화면에 변화를 주려면 '엘리먼트 객체' 자체를 변수에 담고, innerHTML을 이용해 조작해야 함
- innerHTML 속성만 변수에 담으면 그건 단순한 문자열일 뿐, 화면에 적용되지 않음
핵심 차이점 요약
| 할당 방식 | 저장되는 값 | 누적 가능? | 화면에 영향? |
|---|---|---|---|
| 요소 객체(div) | DOM Element | innerHTML += ...로 누적 출력 | O (화면 변화) |
| 내용(innerHTML) | String(내용) | 그냥 문자열 누적 | X (화면 변화X) |
나중에 이런 것까지 실습할 예정

항상 껍데기 먼저 만들고(큰 틀 먼저) 그 후에 기능을 추가하기
작성한 코드가 작동이 안 되는 것 같으면 가장 먼저 개발자 도구의 "콘솔창" 확인하기
★오류를 최소화하는 코드 작성 습관을 기릅시다★





TIPS
innerText 조작 예방 : 버튼 클릭 전에 값이 올바른 숫자인지 확인하고 싶을 때, 혹은 입력값 검증이 필요할 때 안전장치 역할로 활용하면 좋음
→ num이라는 변수에 들어있는 요소(num.innerText)의 값이 숫자인지 아닌지 확인
→ num.innerText는 해당 요소의 텍스트 내용을 가져옴:<p id="number">0</p>라면 "0"이라는 문자열을 가져오게 됨
→ Number() 함수는 이 문자열을 숫자로 변환: 만약 "10"이면 숫자 10, "abc"면 NaN(Not a Number)
→ isNaN()는 "파라미터가 숫자가 아닌 경우(true), 숫자인 경우(false)"를 반환
→ 만약<p id="number">이십</p>처럼 숫자가 아닌 텍스트가 들어가 있을 때 이 함수를 통해 유효성 검사를 할 수 있음
0보다 작을 경우 강제로 0으로 반환하는 보정 함수 : 받은 num 값이 음수(0보다 작을 때)면 0으로 바꾸고, 그렇지 않으면 그대로 값을 반환
→ 만약 인자인 num이 0보다 작으면, 내부에서 값을 0으로 바꾸고 그 값을 반환
→ 숫자 값이 "0 이하로 내려가면 안 된다"는 규칙을 강제하기 위해 사용합니다. 만약 실수로 -1, -10 같은 값이 되더라도 무조건 0으로 돌려주기 때문에 값이 음수가 되지 않음
→ 카운터 UI, 점수판, 재고 등 "최소값이 0"이어야 하는 기능에서 값을 보정할 때 사용

addEventListener() ★★★()가 실행하라는 의미라서 우리가 버튼을 안 눌러도 자동 실행되어버림



webdriver: 컴퓨터용 브라우저 → 데이터 요청, 응답, 화면 조종, 관제 담당By: 선택자 구분 시 사용하는 라이브러리 (selenium.webdriver.common.by에 있음)Keys: 컴퓨터용 키보드 → ENTER, DEL, END 등 키보드 기능을 담당 (selenium.webdriver.common.keys에 있음)search.send_keys(Keys.ENTER)), 뒤로 가기(driver.back()) 등
from selenium import webdriver as wb
from selenium.webdriver.common.by import By
import time
import pandas as pd
# 1. 사이트 접근
url = "https://www.gmarket.co.kr/n/best"
driver = wb.Chrome()
driver.get(url)
time.sleep(1)
# 2. 첫 번째 상품 위치 전달
# 첫 번째, 두 번째, 세 번째까지도 가져올 수 있도록 작성
# 첫 번째 상품 절대 경로: #container > div.box__best-list > ul > li:nth-child(1) > a
# 두 번째 상품 절대 경로: #container > div.box__best-list > ul > li:nth-child(2) > a
item = driver.find_elements(By.CSS_SELECTOR, "#container > div.box__best-list > ul > li > a")
# 3. 첫 번째 상품 클릭
item[0].click()

%pip install -q undetected-chromedriverimport undetected_chromedriver as uc
# 사이트 접근
driver = uc.Chrome()
driver.get(url)
# 상품 위치 전달
item = driver.find_elements(By.CSS_SELECTOR,"#container>div.box__best-list>ul>li>a")
# 첫 번째 상품 클릭
item[0].click()
# 상품의 이름과 가격(할인 적용 후) 수집
title = driver.find_element(By.CSS_SELECTOR,"#itemcase_basic > div > div.box__item-info > h1")
price = driver.find_element(By.CSS_SELECTOR,"#itemcase_basic > div > div.box__price.price > span:nth-child(3) > strong")

# 다음 10개 페이지 출력하기
# #premium-pagenation-wrap > div.board_pagenation > a.next
driver.find_element(By.CSS_SELECTOR,"#premium-pagenation-wrap > div.board_pagenation > a.next").click()
# 리뷰 데이터에서 다음 페이지 버튼을 눌러 많은 양의 리뷰 데이터 수집하는 코드
# 반복문 활용
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
import time
import pandas as pd
# 사이트 접근
driver = uc.Chrome()
driver.get("https://www.gmarket.co.kr/n/best")
time.sleep(1)
# 상품 위치 전달
item = driver.find_elements(By.CSS_SELECTOR,"#container>div.box__best-list>ul>li>a")
# 첫 번째 상품 클릭
item[0].click()
time.sleep(1)
# 상품평 클릭
review = driver.find_element(By.CSS_SELECTOR,"#container > div.vip-tabwrap.uxetabs > div.vip-tabnavi.uxeposfix > ul > li:nth-child(2) > a")
review.click()
time.sleep(1)
review_list = []
for chunck in range(2): # 최대 세트 수
for i in range(10):
page_num = driver.find_elements(By.CSS_SELECTOR,"#premium-pagenation-wrap > div.board_pagenation > ul > li > a")
try:
page_num[i].click()
time.sleep(2)
rv = driver.find_elements(By.CSS_SELECTOR,'#premium-wrapper > table > tbody > tr > td.comment-content > a > p.con')
for j in rv:
review_list.append(j.text)
except:
# 해당 chunck의 페이지 수가 부족할 경우
print("모든 페이지를 수집하였습니다.")
break
try:
# 마지막 chunk가 아니라면 '다음' 버튼 누르기 (다음 10개 페이지 출력)
next_btn = driver.find_element(By.CSS_SELECTOR,"#premium-pagenation-wrap > div.board_pagenation > a.next")
next_btn.click()
time.sleep(2)
except:
# 다음 버튼이 없는 경우 (더 이상의 페이지 없음)
print("모든 페이지를 수집하였습니다.")
break # 반복 종료
driver.quit()
len(review_list)
100
from selenium import webdriver as wb
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
import os
from urllib.request import urlretrieve
os.mkdir("경로")\\ 두 번 작성해야 함\는 이스케이프코드이기 때문os.makedirs("C:/Users/내 PC/Desktop/Pokemon")

if not os.path.isdir("C:/Users/내 PC/Desktop/Pokemon"):
os.makedirs("C:/Users/내 PC/Desktop/Pokemon")
print("폴더 생성 완료")
else:
print("이미 폴더가 존재합니다!")
# 브라우저 열기
driver = wb.Chrome()
url = "https://www.pokemonkorea.co.kr/pokedex#pokedex_1"
driver.get(url)
# 이미지 데이터 태그 정보 수집하기
img = driver.find_elements(By.CSS_SELECTOR, "div.img > div > img")
# 수집된 데이터 개수 확인
len(img)
18
#\#pokedex_1 > a > div.img > div > img#\#pokedex_2 > a > div.img > div > img#\#pokedex_3 > a > div.img > div > img find_elements하면 모든 데이터를 가져다가 사용할 수 있음# 페이지의 전체를 관장하는 Body 태그에 end 키보드 전송하자!
body = driver.find_element(By.CSS_SELECTOR,"body")
body.send_keys(Keys.END)
# end 키 입력 반복!
# 드라이버에게 body 태그 알려주기
body = driver.find_element(By.CSS_SELECTOR,"body")
# 스크롤 끝까지 내리는 코드도 있지만 실습 편의를 위해 20번만 내리기
for i in range(20):
body.send_keys(Keys.END)
time.sleep(1)
img = driver.find_elements(By.CSS_SELECTOR, "div.img > div > img")
len(img)
378
요소.get_attribute("속성명")img[0].get_attribute("src")요소["속성명"]urlretrive(이미지 주소, "저장 경로/파일이름.jpg") 함수 사용urlretrieve(img[0].get_attribute("src"), "C:/Users/내 PC/Desktop/Pokemon/test.jpg")
('C:\\Users\\내 PC\\Desktop\\Pokemon\\test.jpg',
<http.client.HTTPMessage at 0x1beb6827290>)
# 반복문 써서 수집한 이미지 데이터 전체 파일로 저장하고 드라이버 종료하기
for i in range(len(img)):
urlretrieve(img[i].get_attribute("src"), f"C:/Users/내 PC/Desktop/Pokemon/{i}.jpg")
driver.quit()