TIL-5주차 코드 - Day1~3

 

1. Servlet 이용 : 22.12.26


1) 이전 강의 복습 : 오늘의 질문

  • 톰캣이 서블릿 코드를 실행 해준다. // 서블릿을 언제 메모리에 올리는지? 클라이언트로부터 최초 요청을 받았을 때..
  • 서블릿 컨테이너 = 톰캣 (메모리에 올리는 것을 누가 해주냐? 톰캣이 해준다.**)
  • WAS가 객체생성을 도와준다? 서블릿 컨테이너에 보관이 되어 있다가 실행이 되면 코드에 들어온다.
  • 톰캣은 WAS의 한 종류이다. 톰캣은 WAS이다. WAS는 톰캣이 아니다.


2) [톰캣 질문 정리]**

이미지

  • 문제 1 : 톰캣이 서블릿 코드를 실행해준다.

  • 문제 2 : 메모리에 올리는 것을 누가 해주냐? 톰캣이 해준다.**

  • 문제 3 : 메모리에 언제 올라가는지? : web.xml을 읽을 때!! (클라이언트로부터 최초 요청을 받을 때 올라간다. ***)

  • 문제 4 : web.xml를 읽을 때, 컨테이너에 담는다.(하지만, web.xml 파일의 load-on-startup 설정으로 순서를 바꿀수 도 있다.)

  • 문제 5 : 사용자의 요청이 들어오면, 담아 놓은 컨테이너에서 읽어서 실행한다.

  • 문제 6 : 서블릿이 언제 실행하는지? 언제 만드는지? : service () 메서드를 호출하기 전에 Servlet 객체를 메모리에 올린다.

  • Web Container는 service() 메서드를 호출하기 전에 Servlet 객체를 메모리에 올린다.


2-1) [서블릿 동작 과정 추가 정리]** (참고 - https://coooding.tistory.com/14) :

  • Web Server는 HTTP request를 Web Container(Servlet Container == 톰캣)에게 위임한다.

    • web.xml 설정에서 어떤 URL과 매핑되어 있는지 확인(없으면 기본 설정으로 돌아간다.)
    • 클라이언트(browser)의 요청 URL을 보고 적절한 Servlet을 실행


  • Web Container는 service() 메서드를 호출하기 전에 Servlet 객체를 메모리에 올린다.
    • Web Container는 적절한 Servlet 파일을 컴파일(.class 파일 생성)한다.
    • .class 파일을 메모리에 올려 Servlet 객체를 만든다.
    • 메모리에 로드될 때 Servlet 객체를 초기화하는 init() 메서드가 실행된다.


  • Web Container는 Request가 올 때마다 thread를 생성하여 처리한다.
    • 각 thread는 Servlet의 단일 객체에 대한 service() 메서드를 실행한다.


  • 클라이언트의 요청이 들어오면 WAS는 해당 요청에 맞는 Servlet이 메모리에 있는지 확인한다.

  • 만약 메모리에 없다면,
    • 해당 Servlet Class를 메모리에 올린 후(Servlet 객체 생성) init() 메서드 실행
    • 이후 service() 메서드를 실행
  • 메모리에 있다면
    • 바로 service() 메서드 실행


3) [web.xml 파일에서 서블랫 매핑 설정]**


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd http://xmlns.jcp.org/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="5.0">
  <display-name>webprj</display-name>
  
  						<!-- web.xml를 읽어 들일 , 메모리에 올리고 서블릿 객체화한다. 객체화하고 이름을 달아줘야하는데 이것이 servlet-name이다. -->
  <servlet>	
  	<servlet-name>nana</servlet-name>
  	<servlet-class>com.newlecture.Nana</servlet-class>
  </servlet>

  <servlet-mapping>
  	<servlet-name>nana</servlet-name>
  	<url-pattern>/hello.txt</url-pattern>
  </servlet-mapping>
  
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.jsp</welcome-file>
    <welcome-file>default.htm</welcome-file>
  </welcome-file-list>
</web-app>


4) [어노테이션 매핑 정리]**

						// 얘도 고치면 다른 것도 고쳐야해서(동기화 문제) 번거롭다. 
						// 외부파일을 열수 있으면 xml파일에서 설정하고, 그럴수 없으면 어노테이션으로 설정한다.
@WebServlet("/hello")	 
public class HelloServlet extends HttpServlet {

@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) 
							throws ServletException, IOException {
							
	}
}


5) [에러 발견]

  • 이전 상태의 코드가 계속 실행되는 경우 : Project 탭 - Clean 클릭해서 프로젝트가 실행되었던 문제가 발생.

  • 배포가 안되는 경우 : 브라우저가 열린 상태에서는 배포가 되지 않는다.


6) [서블릿에 html 파일 적용]

  • 프로젝트명을 만들 때, 충돌날까봐 context명(/webprj)을 만들어 줬는데 충돌이 나지 않아서 root(/)로 바꾸기


7) [GET 요청]

  • Get 요청 : html에게 데이터를 달라고 하는 요청이지만 값을 전달할 수 있다. 옵션 느낌이다.

  • 쿼리스트링(parameter) : 예전에는 url의 길이 제한이 있었다. 질의(쿼리)하기 위한 욥션 느낌이다.(“/hello?c=3”)


 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>						<!-- html 공부하기 -->
	<section>
		<h1>인사말을 몇 번 듣고 싶으세요?</h1>
		<ul>
			<li><a href="/hello?c=5">5번</a></li>
			<li><a href="/hello?c=10">10번</a></li>
			<li><a href="/hello?c=100">100번</a></li>
		</ul>
	</section>
	<a href="/hello">hello</a>
</body>
</html>


 package com.newlecture.web;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


@WebServlet("/hello")				
public class HelloServlet extends HttpServlet {
	
	
 	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) 
							throws ServletException, IOException {

		// response.getOutputStream(); 는 바이너리 파일과 같이 1바이트씩 가져오고 싶을 때 사용.

		// PrintStream는 다국어를 지원하기 전에 사용되었다.
		// PrintWriter은 다국어를 지원할 때, 사용되었다.
		
		// PrintStream out = new PrintStream(response.getWriter());
		PrintWriter out = response.getWriter();		// 저장을 하면, 이클립스가 알아서 컴파일 해주고 서버에 옮기는 작업을 한다.(배포) 
													// 우리는 그것을 톰캣으로 실행만 하면, 이다.
		
		
		// 쿼리스트링 초기화 해주기, 옵션이라서 조건문 넣어주기
		
		String c = request.getParameter("c");
		
	
		int count = 10;
		
		if(c != null)
			count = Integer.parseInt(c);
		
		for(int i=0; i<count; i++)
			out.println("hello Servlet");
	}
}




2. Canvas(프론트)와 Servlet(백엔드)을 이용해서 게임 만들기 (+ 자바 스크립트 공부)


1) [자바 스크립트]

  • ES5 vs ES6 : ES5부터 먼저 공부하고 ES6를 공부하기
    • ES5는 예전 버전이라서 에러가 많이 발생한다.(모듈화(= 객체지향)를 제공하지 않아서)
    • ES6만 공부하면, ES5와의 기준을 몰라서 기준이 사라진다.


이미지 - 언어와 플랫폼을 공부하고나서 하나의 제품을 만들고 나중에는 가운데 부분에 있는 것을 관심있는 것 공부하기!

- 웹 프론트 API : 
	- 윈도우 UI : DOM
	- Ajax : XHR, Fetch
	- 2D/3D 그래픽 : SVG, Canvas
<br>	
- 백엔드 API : 
	- 실행 환경 : NodeJS
	- 웹 서버 겸 WAS : Express


- 통계학의 필요성 - 서비스를 운영하면서, 통계학이 필요하다.(하지만, 먼저 R을 공부하지마라.) - 데이터 분석 : 빈도수, 시간대별 빈도수 등등 - 확률 공부 : 모집합, 표본 집합 - 이런 것들로 예측한다.



2) [Wrapper 클래스]

var x = 3;   // 여기선, 3을 자동으로 박스화해준다. 그리고 x가 이것을 참조한다. 이렇게 박스처럼 만들어서 값을 참조하는 모습을 Wrapper Class에서 참조하는 모습과 같다.
  • Java에서는 부모를 갖지 않아도 Object 클래스에서 상속 받아서 이용한다.

  • Object 클래스는 모든 객체를 한 번에 묶을 수 있는 역할을 한다. 배열을 Object 형식으로 만들면, 참조 못할 것이 없다. 객체를 서로 연결 지을 수 있다.

  • 하지만, 이렇게 어떠한 공간이여서 Wrapper 클래스는 모든 것을 엮고 담을 수 있지만, primitive 타입만 모든 것을 담을 수 없다.

package ex8.wrapper;

public class WrapperTest {

	public static void main(String[] args) {
		// Object obj = 3;				// 값을 담는 것은 불가능하고 참조하는 것이 가능하다.								
		Object obj = new Integer(3);	// wrapper 클래스 적용!!

		int x = 3;						// primitive 타입 설정!!

		System.out.println(obj);
		System.out.println(x);

	}
}



3. Javascript 이용 : 22.12.27


1) Wrapper 클래스 정리(javascript은 모든 것이 객체형태이므로 Wrapper 클래스 형태이다.)

package ex8.wrapper;

import ex7.is_a.Exam;

public class WrapperTest {

	public static void main(String[] args) {
		// Object obj = 3;				// 값을 담는 것은 불가능하고 참조하는 것이 가능하다.								
		Object obj = new Integer(3);	// wrapper 클래스 적용!!

		int x = 3;						// primitive 타입 설정!!

		System.out.println(obj);
		System.out.println(x);

		
  //------------------------------------------------------------------------
		Exam exam = new Exam();
		String str = new String("Hello~");
		
		Exam[] list1 = new Exam();		// 불가능(타입이 다르다.)
		String[] list2 = new String[2];	// 가능
		Object[] list3 = new Object[5];	// 가능 Obj
		
		list3[0] = exam;
		list3[1] = exam;

	// ** 중요!!	
		Object d = 3;				// 자바 예전 버전에서는 원래, 값을 참조해서는 안 된다.
		Object d2 = new Integer(3);	// 이렇게 박스에 담에서 사용하면 가능하다.
		
		// 원래 값으로 담으면 공간이다. 따라서, 참조와 달라서 에러가 발생
		int x = (Integer) d2;	// 에러 발생(정확히 형변환 까지 해주면,)

		
		
    //------------------------------------------------------------------------
	
		}

}
  • 이것과 마찬가지로, 자바스크립트는 값 변수가 없어서 모든 것이 객체화 되어 있다.


var x = 3;	// undefined로 설정이 되어 있는데 값이 입력되면, Wrapper 클래스가 기본형이 되어 불러온다.
  • 컴파일 타임에 의한 에러가 나지 않는다.

  • undefined를 판단하기 위해서, “undefined” 이렇게 쓰지 않는다. undefined 이렇게 사용한다.

  • 자바 스크립트 작성법 : html 코드에 script 태그의 내부에 작성한다.

  • 자바 스크립트의 구분자는 줄바꾸기와 “;”로 2가지 형태로 구분된다.

  • 자바스크립트는 문서 안에서 사용하기 때문에 Single인데도 문서 안에서는 Double을 사용한다. 따라서, 기준이 없다.


2) [Array 객체]

  • Index 기반의 저장소, Stack 저장소, queue 저장소, Deque 저장소

  • Array 객체는 알아서 index를 늘려준다.

var nums = new Array();
nums[0] = 5;
nums[1] = 5;
nums[2] = 5;

  • 콜렉션은 자리가 모자라면. 자리를 알아서 늘려간다.



3) [javascript Array 사용법 #1]

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script>
	var x;
	alert(x==undefined);
	
/* 	var nums = new Array();	자바에서는 바로 안 만들고 공간을 설정해줬어야 했다. 
	
	nums[0] = 3;
	nums[1] = 10;
	nums[2] = 21;
	
	console.log(nums[0]);
	console.log(nums[1]);
	console.log(nums); */
	
	var nums = new Array();
	nums[3] = 5;
	
	console.log(nums);
	console.log(nums.length);
	
	
</script>

</head>
<body>						<!-- html 공부하기 -->
	<section>
		<h1>인사말을 몇 번 듣고 싶으세요?</h1>
		<ul>
			<li><a href="/hello?c=5">5번</a></li>
			<li><a href="/hello?c=10">10번</a></li>
			<li><a href="/hello?c=100">100번</a></li>
		</ul>
	</section>
	
	<form action = "/hello">
		<label>기타</label>
		<input placeholder="원하는 횟수를 입력하세요." name = "c"/>
		<input type = "submit" value = "전송"/>
	</form>

	<a href="/hello">hello</a>
	

	
</body>
</html>



4) [javascript Array 사용법 #2]

  • 자바스크립트에서 배열이 1개만 받으면 크기이고 1개를 넘어서는 순간, 초기값을 설정한다.
<script>
 	var nums = new Array();			 typeof : 배열의 타입을 반환 해준다.
	var nums = new Array(5);
	var nums = new Array(5,10,21);
	var nums = new Array(5,10,21,'Hello');
	console.log(typeof nums[3]); 
</script>
  • 자바 스크립트 2차원 배열
<script>
	var nums = new Array(5,10,21,'Hello', Array(5,10,21,'Hello'));
</script>



5) [Stack] : 뒤로가기에서 쓰임

  • LiFO(Last In First Out) : 데이터를 쌓았다가 지운다.

  • push : 하나씩 데이터를 쌓을 때, 이용(index를 안 쓰므로 좋다.)

  • pop : 데이터를 꺼내서 없앨 때, 이용(마지막에 쌓은거부터 사라짐)

<script>
/* Stack */ 
var nums = new Array()
nums.push(4);
console.log(nums);

var n1 = nums.pop();
console.log(nums); 
</script>



6) [Queue]

  • FiFO(First In First Out) : 데이터를 쌓았다가 지운다.

  • push : 하나씩 데이터를 쌓을 때, 이용(index를 안 쓰므로 좋다.)

  • shift : 데이터를 꺼내서 없앨 때, 하나씩 밀면서 이용해서 shift 이다.(데이터를 다 쌓고 그다음에 밀면서 없애버림.)

/* Queue */ 
<script>
var nums = new Array(1,2,3,4,5);

nums.push(6);
var num = nums.shift();
console.log(num);
</script>



7) [DeQue(Double-Ended Queue)] : 공부하기

<script>
	var nums = new Array(1,2,3,4,5);	
	console.log(nums);				//[1, 2, 3, 4, 5]
	nums.push(6);						// 마지막부터 새로운 데이터를 채운다.
	console.log(nums);				// [1, 2, 3, 4, 5, 6]
	
	var pos = nums.pop();				// 뒤에서부터 데이터를 없앤다.
	console.log(pos);					// 6
	console.log(nums);				// [1, 2, 3, 4, 5]
	
	var num = nums.shift();			// [2, 3, 4, 5] : 뒤에서부터 데이터를 밀어서 버린다.
	console.log(num);
	console.log(nums);				
									
	var num = nums.unshift(3);			// [3, 2, 3, 4, 5] : unshift는 앞에서부터 데이터를 채워준다.	
	console.log(num);					// 새로운 길이를 출력한다. 배열 전체 길이 : 5
	console.log(nums); 				// [3, 2, 3, 4, 5]
</script>
  • 데이터를 양쪽에서 push하고 shift하여 밀고 pop하여 없애버린다. 한다.(여러개로 섞임)



8) splice

  • 배열과 배열을 끝에 잇거나 중간에 들어갈 수도 있다. 또는 중간에 들어가기 위해 배열을 자르고 안 들어갈수도 있다.

    • nums.splice(2) : 0번째 인덱스부터 마지막 인덱스를 버리고 출력.
      • 1,2 출력
    • nums.splice(2,1) : 1개를 지우고 거기에 배열을 넣으려고 이렇게 사용.
      • 1,2,4,5 출력
      • nums.splice(2,1)
    • nums.splice(1,0,23,100,124) : 2번째 인덱스에 0이 들어가면, 그 인덱스부터 삽입
      • 1,23,100,124,2,3,4,5 출력
      • nums.splice(2,1)
    • nums.splice(1,2,23) : 1,23,4,5 출력(중요!! : 1번째 인덱스부터 2개 지우고 그자리에 23을 삽입)
  • 따라서, 이것은 배열을 조작하기 위해서 사용된다.**

  • 추가 도구** : 배열을 이용하는 메서드 Loop over, Find, Filter, Map, Concat, Join 이용



9) Object

  • 하지만, 객체에 속성이 늘어나면 문제가 많다.
  • 자바와 달리 자바스크립트는 계획되지 않는 속성이므로… 에러 발생한다.(ex) exam.Kor과 같은 경우)
<script>
var exam = new Object();		
exam.kor = 30;					
exam.eng = 70;
exam.math = 90;

alert(exam.kor + exam.eng);
</script>



4. 자바스크립트 객체와 JSON 사용법 및 기본 문법 :

  • JSON은 데이터를 저장하고 조회할 때, 사용하는 데이터 타입이다.


1) 자바스크립트 객체의 속성 설정

  • exam[“kor”]은 exam.kor과 같은 의미이다. : 즉, 변수명을 속성으로 사용할 수 없는 경우에 이렇게 쓴다.(ex) 변수명에 빈공백을 넣어주는 경우)

  • 객체의 속성 제거 : delete exam.kor;(데이터 손실 때문에 키와 값을 빈 배열에 각각 담아줄수도 있다. 이런 것을 map 같은 콜렉션에 넣어줄 수 있다.)

<script>

var exam = new Object();
exam.kor = 30;
console.log(exam);
delete exam.kor;
console.log(exam);

</script>



2) JSON (중요!!)

이미지

  • 데이터를 표기하는데 가장 기본적인 모습 : JSON이며 그외는 XML, CSV가 있다.


이미지


이미지


<script>
	var notice = [{"id":1, "title":"hello json"},
				 {"id":2, "title":"hi json"},
				 {"id":3, "title":"json is ~"}];
</script>
  • Json 이용법
<script>
	var exam ="[3,5,3,2]";
	alert(exam[2]);			// 외부에서 데이터를 받으면 이런식으로, 문자열로 받아오므로 "["부터 index 2번째인 ","가 출력된다.

	
	// 자바 스트립트에서 코드를 value로 인식하여 실행해주는 경우
 	eval("var x = 3+5");
	alert(x);	
</script>
  • eval()의 문제점 eval()은 보안에서 주의해야 한다.(외부에서 Injection 문제 : SQL Injection과 같이 보안 문제(해킹) 같은 경우)

  • eval()은 원격으로 데이터가 오는 경우 객체화하는 경우 용이하다. 하지만 보안때문에 JSON을 이용한다.



3) JSON 데이터형으로 파싱하는 방법

	var exam1 = eval("([3,5,3,2])");	// eval에는 원래 완전한 문장이 들어가야하는데 문장으로 쓰기 위해서는 "" 안에도 ()를 써준다.
	alert(exam1[2]);
	
	// 중요!!!****
	// eval()은 객체화를 해주지만 어떠한 것도 만들어주므로 문제가 많다.(모든 형태만 변환해줘서)
	// 새롭게 Json 파싱해주는 도구: reference 찾기
	// 따라서, Json.parse()를 이용한다. (올바른 방법)
	var data = JSON.parse("[3,5,3,2]");
	alert(data[3]);
	
	// 객체를 만들다음에 스트링 형태로 바꿔주는 도구 : JSON.stringify() (올바른 방법)
	var data1 = JSON.stringify("[3,5,3,2]");
	alert(data1[2]);



4) 연산자

  • 기본 연산자
	var str1 = "hello";
	var str2 = "hello";
		
	console.log(str1 == str2);			// true
	
	var str3 = "hello";
	var str4 = new String("hello");		
									// 자바스크립트에서는 ==가 값을 비교해준다.	
	console.log(str3 == str4);			// true
	
	var str5 = "hello";
	var str6 = new String("hello");		
									// ===가 객체까지 비교한다.
	console.log(str5 === str6);		// false


  • 논리 연산자 및 값 비교
    • if문이 유연하다. 0이 아니면 전부 true이다.(자바에서는 불가능)

    • Truthy : if([]), if({})
    • Falsy : if(“”), if(NaN)

    • Or 연산자(   ) : 가장 앞에 것이 참이면 바로 앞에 것을 반환, 만약 앞에 것이 거짓이면, 뒤에 것이 결과가 된다.(이경우에는 뒤에 값은 무엇이든 결과에 상관이 없다.)
  <script>
  								// 가장 앞에 것을 반환
    console.log('Cat' || 'Dog');		// true : 빈문자가 아니면 true일 듯?
    console.log('null' || '' || ' ' || 0);	// true 반환한다.(' '가 빈공백이라서 0보다는 크다.)
  </script>
<br>
- null이 들어오면, 기본값으로 설정된 값이 입력된다.
  <script>	
    var x = null;
    var name = x || "newlec";		// name은 newlec 출력	
  </script>


  • [And 연산자(&&)] : 보통 앞에 true가 없으면(false) 뒤에 것을 반환
  • 또한, 첫번째 항이 참인 경우에는 두번째 항이 참이냐 거짓이냐는 결과에 영향을 미치지 않습니다. 따라서 ‘aaa’ && ‘bbb’ 처럼 두번째 항이 참인 경우도, ‘aaa’ && 0 처럼 두번째 항이 거짓인 경우도 첫번째 항인 ‘aaa’가 모두 참이므로 모두 결과는 두번째 항이 됩니다.
  <script>		
    var x = null;
    var name = x && "newlec";		// name은 newlec 반환
  </script>
  • 정리*** :   는 처음으로 참이 되는 경우에, &&는 처음으로 거짓이 되는 경우를 찾을 때 이용한다.


  • Nullish : null이 아니다라는 것을 알려준다.(Truthy, Falsy 같은 느낌)
<script>
	var foo = null ?? 42;
	console.log(foo); 		// 42가 출력
	
	var baz = 0 ?? 42;
	console.log(baz); 		// 0이 출력
</script>


  • NaN : Not a Number
<script>
	var x = 3;
	var y = '3';
	console.log(x*y);		// 문자가 숫자로 바뀐다.
	
	var x = 3;
	var y = 'a';
	console.log(x*y);		// NaN : Not a Number - 'a'가 숫자가 아니라서 NaN이 출력

	// NaN은 연산자로 비교할 수 없다. 그래서 isNaN(), isFinite()으로 비교한다.
	var x = 3*'a';
	
	if(isNaN(x))
	    console.log("오류 발생");
</script>



5) 제어구조

  • for in, for of : index를 꺼내거나 value를 꺼내서 반환

    • for in은 index를 어떤 것을 쓰겠다고 알려주면, 인덱스가 알아서 증가한다.

      <script>
          var ar = ["철수","영희","맹구","동천"];
      		
          for(i in ar)
              console.log(ar[i]);
      </script>
      


- for of는 ES6에 존재하고 index를 꺼내는 방법이다. (배열 요소의 위치 반환)

```html
<script>
	var ar2 = ["철수","영희","맹구","동천"];
	
	for(v of ar2)
		console.log(v);
</script>
```


- for in, for of에는 Object 형태도 넣어서 값을 꺼낼 수 있다.(map 형태 : key, value) - for in은 key값을 이용해서 출력해준다.

	```html
	<script>
		var record = {kor:30, eng:40, math:50};		
		
		for(var k in record)
			console.log(record[k]);
	</script>
	```


- for of은 value값을 이용해서 출력해준다.

	```html
	<script>
		var record = {kor:30, eng:40, math:50};
		
		for(var v of record)		// ES6에서 사용된다, 
			console.log(v);				// map 콜렉션에서 사용할 것이고 
	</script>
	```


15) 앞으로의 프로젝트 목적

  • 재밌게 구현하는 시각적인 도구 만들기. 시각 도구화?된 공부하려고 만드는 것을 만들기

  • ex) 웹 페이지용 와이어 프레임 만드는 것?(기존의 문제점: 유료화라 프로젝트가 1개만 만들어지고, 데이터 저장 기간이 존재하고, 아이폰만 기종이 있다.)




4. javascript function : 22.12.28

1) 자바스크립트의 함수 정의

  • 자바 스크립트에서 함수를 정의하는 경우가 없다.(익명 함수?) : 내가 쓰면서 정의한다.
<script>
	var add = new Function("x,y","return x+y;");
	console.log(add(3,4));
</script>
  • 인자와 반환값을 나눠서 함수 객체를 만든다.

  • 자바 스크립트에서 함수를 정의하는 방법 : 정의한 것이 아니라 함수 이름을 붙여 준것이라서 참조가 가능하다.


<script>
	var add = function(x, y) {		// 가장 올바른 방법
		return x+y;
	}
</script>


<script>
	function add(x, y) {			// 입문자의 입장에서 쓰는 방법
		return x+y;
	}
<script>

  • 특이한 자바스크립트 함수 특징 :

    • 자바스크립트는 argument랑 값을 모두 컬렉션이 받는다. 따라서, 입력값의 개수는 의미가 없다.
    <script>
        function add (x,y) {            // 다른 방법 사용하자
            return x + y;
        }

        console.log(add(3,4,5,6));      // 에러가 발생하지 않아서 문제가 많다.

    </script>



5. 특이한 자바스크립트 함수 특징 정리

1) 자바스크립트의 콜렉션 사용?

  <script>
        // var add = new Function("x,y","return x+y");
        // console.log(add(3,4));

        // var add = function(x,y) {       // 가장 올바른 방법
        //     return x + y;
        // }

        // function add (x,y) {            // 다른 방법 사용하자
        //     return x + y;
        // }

        // console.log(add(3,4,5,6));      // 에러가 발생하지 않아서 문제가 많다.

        
        // function add () {           
        //     return arguments[0] + arguments[1];
        // }
        // // 자바스크립트는 arguments랑 값을 모두 컬렉션이 받는다. 따라서, 입력값의 개수는 의미가 없다.
        // console.log(add(4,5));      
  </script>


2) 자바스크립트의 var 선언과 전역 객체(window)의 의미

    <script>
        alert(a);           // 선언한 적이 있어서 undefined가 나오는 것이다.
                            // 내가 실행하여 사용하기 전에 코드가 stack에 저장된다.
        var a= 1;

        // ------- 전역 객체 --------------
        a = 1;              // var로 선언되지 않는데 1로 출력된다. 아직 stack에 쌓이지 않았다.
                            // 아무개에 저장이되는 것인데 아무개가 전역 객체(window)이며 전역 객체에 속성으로 들어간다.
        alert(a);


        //------- 심볼의 의미 --------------
        alert(a);           // Uncaught ReferenceError: a is not defined
        a = 1;              // a라는 심볼이 아예 없다는 뜻이다.(undefined와 다른 의미이다.)

        //------- 전역 객체(기본적으로 window)의 의미 --------------          
        a = 1;              // 아무개인 window가 전역객체라서 this와 같은 역할이다.
        alert(window.a);    // 여기서 a가 window 그자체이고 window.a는 a와 같다. 그래서, window를 생략할 수 있다.

  </script>


3) 객체의 변수 범위 정하는 법

  <script>
        //------- 전역 객체(기본적으로 window)의 범위? --------------       
        // 내가 정리 : 전역객체가 새로운 함수로 범위를 묶어버려도 전역객체의 범위를 없애진 않는다.
        // ** 최종 정리 : 다른 함수가 사용되어도 전역객체를 사용할 수 있다.
        var f1 = function() {
            a = 1;
            console.log(window.a);
        }

        f1();

        // *** 이렇게 자바스크립트는 자유도가 높다.

        // -----------------------------
        var f2 = function(){
            a=1;
            var a;
            
            console.log(window.a);      // 1이 출력된다. 공간이 다르게 선언된다.(전역 객체 vs 스택에 변수)
            
        }
        
        f2();

        // ------------------------------
        var f3 = function(){
            a=1;
            
            console.log(window.a);
            
            var a;                // 변수 선언이 밑에 있지만 코드를 저장하면서 먼저 stack에 쌓여 있어서 
        }                         // window.a는 다른 공간이다. 
        f3();
  </script>


4) 변수의 재선언 및 지역화 개념

    <script>

        // ------------------------------
        var a1 = 1;
        
        
        
        
        
        
        var a1 = 2;                 // 코드가 길어져도 아래에서 다시 재선언해도 에러가 안난다.(자바에서는 에러가 난다.)
                                    // ES6에서는 이러한 문제점이 해결되었지만, TypeScript가 컴파일러 과정을 만들어줘서 에러나게 해준다.


        alert(a1);


        // ----------- 중괄호가 사용하는 경우(지역화 X) ---------
        
        
        {
            var a = 1;
        }

        alert(a);           // 지역 변수를 지정할 수 없다.
                            // 즉, 스크립트 파일을 100개로 만들어도 된다. 하나의 공간을 바라보기 때문이다.
                            // *** 따라서, 이러한 문제점을 해결하기 위해서 ES6가 만들어졌다.



        // ----------------- 지역화 O ----------------
        // 자바 스크립트에서는 지역화를 함수 내부에서만 가능(var로 변수를 생성하면, scope 영역이 function로 한정된다!!, 나중에 let, const 개념도 확인할 것)
        function f4() {
            var a = 1;
        }
        alert(a);				// 에러 발생


        function f5() {
            a = 1;
        }
        alert(a);				// 1이 출력(a는 전역객체의 변수이다.)

  </script>


5) 함수의 중복 선언

    <script>
    
        // ----------------- 함수 중복 선언 가능(JS 특징) ----------------
        function f6() {
            a = 1;
            f2();
            function f7() {
                a = 2;
                f3();
                function f8() {
                a = 3;
                }
            }
            console.log(a);     // f1 함수 내부에서 출력.
        }

  </script>


6) 함수의 중복 선언 및 outer 변수 개념

    <script>
    
        // --------- outer 변수 개념 ------------------
        function func1() {
            var b = 10;

            func2();

            console.log(b);     // f1 함수 내부에서 출력가능   // 20 출력
            
            function func2() {
                b = 20;
            }  
        }

        function func1() {
            var b = 10;

            func2();

            console.log(b);     // 불가능   // 10이 출력
            
            var func2 = function func2() {
                var b = 20;
            }
            
        }

        // --------- outer 변수 적용 ------------------
        function func1() {
            var b = 10;

            var func2 = function func2() {
                b = 20;
            }

            func2();
            console.log(b);     // 가능
                                // outer 변수 : func1이 전체 범위라고 했을 때, func2에서 b가 var func2에 담겨져서 밖으로 나갈 수 있는데 이것을 outer 변수라고 부른다.
                                // 원래는 변수 범위가 끝나야 하는데 선언 안 한 b이기 때문에 밖의 var b도 있어서 그것을 덮어씌워주는 역할을 해준다.    
        }                       // 그래서 결과가 20이 나온다.

                                // **** 변수를 선언하지 않았으면(var), 남의 함수를 쓰는 것이다.
        function func1() {
            var b = 10;

            var func2 = function func2() {
                var b = 20;                      // 얘는 여기서 만들어지고 사라지므로 20이 사라진다.
            }

            func2();
            console.log(b);                     // 그래서 결과가 10이 나온다.
                               
            
        }


        var funca;
        function funa(){
            var a = 10;

            var funb = function(){
                a++;
            }
            f2();

            
            console.log(a);
        }
    </script>


7) var의 깊은 의미 및 window 전역 객체의 클로저 초반 개념

    <script>
    
    var f3 = function(){
        a=1;

        console.log(a);          // 1이 출력(window가 아니라 var a로 인식한다.)

        console.log(window.a);   // undefined 출력(window로부터 값을 가져와야하는데 a를 var a로 인식해서 undefined)
        
        var a;                 // 변수 선언이 밑에 있지만 코드를 저장하면서 먼저 stack에 쌓여 있어서 a(여기선, a가 var a를 의미)와 window.a는 다른 공간에 있다.
    };                         // window.a는 다른 공간이다. 
    f3();


    var func3;
    function func1(){
        var a = 10;

        var func2 = function(){
            a++;
        };
        func2();

        console.log(a);     // 11이 출력
    }
  </script>


8) 클로저의 문제점

이미지

  • 추가 질문 : f1 함수가 변수에 의해서 참조되고 있어서 자원 반납을 하지 못 하는 상황이라고 말씀하셨는데 그 말은 곧 f1함수가 return을 하였음에도 스택 메모리에서 사라지지 않고 있는 상황이라고 이해를 해도 될까요?
  • 추가 정답 : f1 변수는 스택에 있고 그 변수가 클로저를 참조하고 있는 한 클로저가 사용하는 outer 변수들은 사라지지 못합니다.


    <script>
    
    // ---------------- outer 변수의 메모리 누수 문제(함수의 return이 없어서) -------------
    var func6;

    function func4(){
        var a = 10;

        var func5 = function(){
            a++;
        };
        func5();                // func4가 메모리에서 사리지지 않는다. func6 때문에 사라지지 않는다.
                               
        func6 = func5;

        console.log(a);         // 11이 출력 
                                // 차이가 없어 보이지만, 전역이라서 변수가 사라지지 않아서 메모리 누수가 생겨서 stack에서 f1, f2가 사라지지 않는다.
    }

    func4();



    // 이 부분은 중간 사이의 코드가 길게 있다고 가정한다.

                                 // *** 최종 정리 : 
    func4();                     // func4 재호출 시, func4는 여전히 구형으로 살아있고(살아 있는 이유 : 함수에 return이 없어서!!)
                                 // func5, func6는 신형으로 다시 만들어져서 살아 있다. 결국 메모리 누수!!
  </script>


9) 클로저를 이해하는 과정 :

  • 함수를 선언할 때, 환경(Lexical 환경)이 구성되면서 closure와 결합되면서 다양한 결합 가능
  • 여전히 outer 함수를 물고 있어서 closure라고 부른다.
  • 안쪽에 있는 함수가 사라지기 전까지 생명선이 존재한다.
  • 이것은 나중에 JS에서 은닉화에 성공하여 캡슐화로 사용되고 변수를 공유하는 역할을 해준다.


    <script>
    
    // ----- [Closure]를 이해하는 과정 ---------
    var funcs = [];

    for(var i =0; i<3; i++){
        funcs[i] = function(){
            console.log(i);
        };
    }

    // funcs[0]();


    for(var i =0; i<3; i++){        // 아까 죽지 못한 변수가 살아남아서 대체 되었고
        funcs[i]();                 // 새로 대체되어서 1, 2, 3 출력!!
    }

    for(var a =0; a<3; a++){        // 앞에 있는 변수가 죽지 못하고 다르게 바뀐 배열 인덱스가 대체되어지지 않고 
                                    // 그대로 이전 함수의 마지막 값과 연결되어서 3,3,3 출력
        funcs[a]();
    }

    // 함수가 죽지 못해 살아 남는 과정 ******

    </script>



10. 자바스크립트 객체 특징 정리

    <script>
        // ------- 1. 객체를 삭제하는 방법
        exam = null;

        // ------- 2. 객체 속성 제거하는 방법(JS의 모든 객체는 속성을 갖고 있고 삭제할 수 있다.)
        delete exam.kor;
        delete exam.kor;
        
        // ------- 3. JS 기본 객체 사용법
        var ar = [];
        ar.papa = function(){
            console.log(ar);
        }
        ar.papa();
    
        // ------- 4. JS 클래스의 Expand 기능 지원 X 
        var name = new String("newlec");
        name.kor = 20;
        console.log(name.kor);     //에러가 발생한다.

        // 확장을 가능하게 할 것인지 말건지 할 수 있다.
        // 자바스크립트에서는 Wrapper 클래스가 기본형이라서, Primitive 클래스(자바스크립트에서는 Wrraper클래스가 Primitive 클래스이다.)는 Expand가 지원하지 않는다.



        // ------- 5-1. 객체 사용법(new의 의미)   
        function Exam(){
            kor = 30;
        }

        var exam1 = Exam(); // 이것은 함수를 호출하기만 하는 것이고 return이 없어서 받을 수는 없다.
        
        console.log(exam1);
        console.log(exam1.kor);

        // ------- 5-2. 객체 사용법(new의 의미)   

        function Exam(){
            kor = 30;
        }

        var exam1 = new Exam(); // new로 함수를 호출하는 것이 아니라 객체를 만들줘서 값을 참조해주면, 값을 출력할 수 있다?
                                // 앞에 new를 쓰면, 객체를 만드는게 이것을 함수가 먹어서 함수 내에서 사용할 수 있고 속성을 추가할 수 있다.(사용자가 임의로 바꿀수 있고 생성자를 의미한다.)
                                // 즉, 데이터 초기화하려고 대문자로 사용한다.
        console.log(exam1);
        console.log(exam1.kor); 
        
        // ----------- 6. this의 의미 -------------
        function Exam(){
            this.kor = 30;      // this라는 것은 자기가 사용할 수 있는 기본객체
            console.log(kor);   // 에러가 발생한다. why? 자바스크립트에서는 this를 이용해서 변수를 만들면 출력시에도 this를 써주어야 한다.
        }
        new Exam();             // 새로운 객체 생성!(자기만의 객체이며 this이용)

        Exam();                 // 앞에 this가 생략 되어있다.
                                // 앞에 new를 하면, 자기만의 객체이고 new를 빼면, 전역객체이다.                     


        // ----- 7. 자바스크립도 자기만의 객체 생성 가능(this + new 이용) : 약갼의 객체지향스러운 모습이 있지만 은닉성을 보장 못한다. -------
        function Exam(){
            this.kor = 30;
            this.eng = 20;
            this.math = 40;

            this.total = function(){
                return this.kor+this.eng+this.math; // this를 넣으면 값이 나온다. this를 빼면 에러 발생!!
            }
        }

        var exam = new Exam();                      // 자기만의 객체 이용가능.
        console.log(exam.total());
         
        // 나중에 ES6에서 사용하지 않는 이유를 알기 위해서 이렇게 배운다
        // 나중에는 람다 함수 사용하지 말기, 익명 함수?



        // ----- 8. 객체 생성을 위한 new의 의미 -------
        function Exam(){
            this.kor = 30;
            this.eng = 20;
            this.math = 40;

            this.total = function(){
                return this.kor+this.eng+this.math; // this를 넣으면 값이 나온다. this를 빼면 에러 발생!!
                                                    // 하지만, 이렇게 쓴 코드도 에러가 있다! ES6와 차이가 있을 것이며 자바코드와도 차이가 있을 것이다.
            }
        }

        var exam = new Exam();              // 자기만의 객체 이용가능.
        console.log(exam.total());
 
        var exam1 = new Exam();             // new로 객체가 새로 만들어지기 때문에 또 새로 만들어진다.
        console.log(exam1.total()); 

</script>