<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hj_ki.log</title>
        <link>https://velog.io/</link>
        <description>Development log</description>
        <lastBuildDate>Fri, 20 May 2022 09:02:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. hj_ki.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hj_ki" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[JS___2]]></title>
            <link>https://velog.io/@hj_ki/js2</link>
            <guid>https://velog.io/@hj_ki/js2</guid>
            <pubDate>Fri, 20 May 2022 09:02:08 GMT</pubDate>
            <description><![CDATA[<p>5.20</p>
<h2 id="javascript">Javascript</h2>
<p><strong>객체 기반</strong>의 <strong>스크립트 프로그래밍 언어</strong>
<strong>웹 브라우저</strong> 내에서 주로 사용하며, 다른 응용 프로그램의 내장 객체에도 접근할 수 있는 기능을 가지고 있다. 또한 Node.js와 같은 런타임 환경과 같이 서버 프로그래밍에도 사용되고 있다.
<strong>느슨한 타입(loosely typed)의 동적(dynamic) 언어</strong>입니다.
JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며,
모든 타입의 값으로 할당 (및 재할당) 가능합니다.</p>
<h2 id="javascript-자료형">Javascript 자료형</h2>
<h3 id="숫자형--number-">숫자형 ( number )</h3>
<p><code>정수 및 부동소수점 숫자(foationg point number)</code>를 나타낸다.
숫자형엔 일반적인 숫자 외에 
Infinity, -Infinity, <strong>NaN</strong>같은 &#39;특수 숫자 값(special numeric value)&#39;이 포함된다.
<strong>Nan</strong> : 계산 중 에러가 발생했다는 것을 나타내주는 값</p>
<pre>
ex :: 문자열 / 숫자

et s = "가";
et n = 123;
console.log(s/n) ---> NaN
</pre>

<h3 id="bigint">BigInt</h3>
<p>표준으로 채택된 지 얼마 안 된 자료형으로, 길이에 상관없이 정수를 나타낼 수 있다.
정수 리터럴 끝에 n을 붙이면 만들 수 있다.</p>
<pre>
const bigInt = 1234343143432353312545325345n;
</pre>

<h3 id="문자형--string-">문자형 ( string )</h3>
<p>문자열을 따옴표로 묶는다.
큰따옴표: &quot;Hello&quot;
작은따옴표: &#39;Hello&#39;
역 따옴표(백틱, backtick): <code>hello</code>
역 따옴표로 변수나 표현식을 감싼 후 <code>${…}</code>안에 넣어주면, 아래와 같이 원하는 변수나 표현식을 문자열 중간에 쉽게 넣을 수 있습니다.</p>
<pre>
let name = "John";

// 변수를 문자열 중간에 삽입
alert( `Hello, ${name}!` ); // Hello, John!

// 표현식을 문자열 중간에 삽입
alert( `the result is ${1 + 2}` ); // the result is 3
</pre>

<h3 id="불린형--boolean-">불린형 ( boolean )</h3>
<p>불린형(논리 타입)은 true와 false 두 가지 값밖에 없는 자료형입니다.
불린형은 긍정(yes)이나 부정(no)을 나타내는 값을 저장할 때 사용합니다.
<strong>true</strong>는 <strong>긍정</strong>, <strong>false</strong>는 <strong>부정</strong>을 의미합니다.</p>
<pre>
let isGreater = 4 > 1;

alert( isGreater ); // true (비교 결과: "yes")
</pre>

<h3 id="null">null</h3>
<p><code>null</code> 값은 지금까지 소개한 자료형 중 어느 자료형에도 속하지 않는 값입니다.
<code>null</code> 값은 오로지 <code>null</code> 값만 포함하는 별도의 자료형을 만듭니다.</p>
<pre>
let age = null;
</pre>
<p><code>let age = null;</code>은 <code>나이(age)</code>를 알 수 없거나 그 값이 비어있음을 보여줍니다.</p>
<h3 id="undefined">undefined</h3>
<p>undefined는 &#39;<strong>값이 할당되지 않은 상태</strong>’를 나타낼 때 사용합니다.
undefined 값도 null 값처럼 자신만의 자료형을 형성합니다.
변수는 선언했지만, <code>값을 할당하지 않았다면</code> 해당 변수에 undefined가 자동으로 할당됩니다.</p>
<pre>
let age;

alert(age); // 'undefined'가 출력됩니다.
</pre>

<p>개발자가 변수에 undefined를 명시적으로 할당하는 것도 가능하긴 합니다. ( <strong>권장하지 않음</strong> )</p>
<pre>
let age = 100;

// 값을 undefined로 바꿉니다.
age = undefined;

alert(age); // "undefined"
</pre>

<h3 id="객체형--object-">객체형 ( object )</h3>
<p>객체(object)형은 특수한 자료형입니다.
객체형을 제외한 <strong>다른 자료형은 문자열이든 숫자든 한 가지만 표현할 수 있기 때문에
 <code>원시(primitive) 자료형</code></strong>이라 부릅니다. </p>
<p>반면 객체는 데이터 컬렉션이나 복잡한 개체(entity)를 표현할 수 있습니다.</p>
<p><strong>원시값</strong> : 객체를 제외한 모든 타입은 불변 값(변경할 수 없는 값)을 정의합니다.
(C언어와는 달리) 문자열은 불변합니다. 이런 일련의 타입을 &quot;원시값&quot;이라고 합니다.</p>
<h3 id="심볼형--symbol-">심볼형 ( symbol )</h3>
<p>심볼(symbol)형은 객체의 고유한 식별자(unique identifier)를 만들 때 사용됩니다.</p>
<hr>
<h3 id="undefined--null">undefined , null</h3>
<p>undefined -- 변수 선언 후, 값을 할당하지 않은 상태 ( 자료형이 없는 상태 )</p>
<ul>
<li>선언만 하고 초기화 되지 않은 변수의 타입이나 값 </li>
<li>객체에 정의 되지않은 속성의 타입이나 값</li>
</ul>
<p>null -- 변수 선언 후, 빈 값을 할당한 상태 ( 빈 객체 )</p>
<ul>
<li>명시적으로 아무것도 없는 비어있는 상태를 나타낸다.</li>
<li>typeof = Object이며 값은 null 이다.</li>
</ul>
<h3 id="--"><strong>== , ===</strong></h3>
<p><code>==</code> )) <strong>value와 value</strong>를 비교한다
<code>===</code> )) <strong>value와 data type</strong>을 비교한다</p>
<pre>
let a = 5; 
a = 5 // true
a = "5" // true

a === 5 // true
a === "5" // false
</pre>
<p>++ <strong>typeof 연산자</strong>
typeof 연산자는 인수의 자료형을 반환합니다. 
자료형에 따라 처리 방식을 다르게 하고 싶거나 변수의 자료형을 빠르게 알아내고자 할 때 유용합니다.
typeof 연산자는 두 가지 형태의 문법을 지원합니다.</p>
<p><code>연산자: typeof x</code>
<code>함수: typeof(x)</code></p>
<pre>
ypeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol"

typeof Math // "object"  (1)

typeof null // "object"  (2)

typeof alert // "function"  (3)
</pre>

<ul>
<li><p>Math는 수학 연산을 제공하는 <strong>내장 객체</strong>이므로 &quot;object&quot;가 출력됩니다. </p>
</li>
<li><p>typeof null의 결과는 &quot;object&quot;입니다. 
null은 별도의 고유한 자료형을 가지는 특수 값으로 객체가 아니지만, 
하위 호환성을 유지하기 위해 이런 오류를 수정하지 않고 남겨둔 상황입니다.</p>
</li>
<li><p><em>언어 자체의 오류*</em>이므로 null이 객체가 아님에 유의합니다.</p>
</li>
<li><p>typeof는 피연산자가 함수면 &quot;function&quot;을 반환합니다. 
그러므로 typeof alert는 &quot;function&quot;을 출력해줍니다. </p>
</li>
<li><p><em>그런데 &#39;함수’형은 따로 없습니다. 함수는 객체형에 속합니다. *</em>
하위 호환성을 유지하기 위해 이런 오류를 수정하지 않고 남겨둔 상황입니다.</p>
</li>
</ul>
<hr>
<h2 id="javascript-문제점">Javascript 문제점</h2>
<ol>
<li><p><code>브라우저에 종속적</code>
브라우저에서 돌아가는 Javascript는 브라우저에 종속적일 수 밖에 없다.
내가 작성한 Javascript 코드가 어떤 브라우저에서 돌아가느냐에 따라
개별적으로 신경써줘야할 부분이 많다는 것을 의미한다.
문제가 없던 코드도 브라우저의 정책이나 지원에 따라 다르게 작동할 수 있다는 것이다.</p>
</li>
<li><p><code>불변성을 제공해주지 않는다는 것</code>
함수형 프로그래밍을 지원하는 것이 장점인 Javascript,
함수형과 밀접한 관계인 불변성을 지원하지 않는다는 건 꽤 모순적이다.
함수형이 대세로 떠오르는 요즘 같은 때에는 치명적인 단점이라고 볼 수 있다.</p>
</li>
<li><p><code>동적</code>
언제든 속성을 추가, 삭제, 수정할 수 있다.
클래스 밖에서도 언제든 클래스의 속성을 바꿀 수 있다.
함수형 프로그래밍에서 불변성은 아주 중요한 개념인데,
Javascript는 너무 쉽게 객체를 변경시킬 수 있다.</p>
</li>
</ol>
<p><strong>const</strong>라는 키워드만으로는 함수형 프로그래밍이 요구하는 수준의 불변성을 실현하기 어렵다.</p>
<p> <em>const*</em>로 객체 선언 후 객체의 주소값 자체를 변경시킬 수는 없지만,
객체 내부의 속성이 변경되는 것 까지는 막지 못한다.</p>
<p> 객체의 속성값에 어떤 값이 추가되든 수정되든 기존 객체의 주소값은 동일한데,
그것까지 <strong>const</strong>가 캐치할 수 없다.
 <strong>정확히 얘기하면 const는 할당된 값이 상수가 되는 것이 아니고, 바인딩 된 값이 상수가 되는 것</strong></p>
<hr>
<h2 id="javascript-객체-불변성">Javascript 객체, 불변성</h2>
<p><code>Immutability(변경불가성)</code>는 객체가 생성된 이후 그 상태를 변경할 수 없는 디자인 패턴을 의미한다. Immutability은 <code>함수형 프로그래밍의 핵심 원리</code>이다.</p>
<p><strong>객체</strong>는 참조(reference) 형태로 전달하고 전달 받는다.
의도하지 않은 객체의 변경이 발생하는 원인의 대다수는 “레퍼런스를 참조한 다른 객체에서 객체를 변경”하기 때문이다.</p>
<pre>
var str = 'Hello';
str = 'world';
</pre>
<ul>
<li>‘Hello’를 수정하는 것이 아니라 새로운 문자열 ‘world’를 메모리에 생성하고 
식별자 str은 이것을 가리킨다. 
이때 문자열 ‘Hello’와 ‘world’는 모두 메모리에 존재하고 있다. 
변수 str은 문자열 ‘Hello’를 가리키고 있다가 문자열 ‘world’를 가리키도록 변경되었을 뿐이다.</li>
</ul>
<h2 id="데이터-타입--기본형--참조형-"><strong>데이터 타입 ( 기본형 , 참조형 )</strong></h2>
<p><strong>기본(원시)형</strong> : <code>Number</code>, <code>String</code>, <code>Boolean</code>, <code>null</code>, <code>undefined</code>, <code>Symbol</code>
기본형 데이터들은 그 자체로 비교가 가능하다.</p>
<p><strong>참조형</strong> : 대표적으로 <code>객체(Object)</code>
그 하위에 <code>배열(Array)</code>, <code>함수(Function)</code>, <code>정규표현식(RegExp)</code>, <code>Map</code>, <code>Set</code>, <code>WeakMap</code>, <code>WeakSet</code>
참조형 데이터들은 프로퍼티(property)와 데이터(data), 즉 <code>key = value</code>로 묶인 쌍들로 
이루어져 있습니다. 프로퍼티명은 변수와 비슷한 성질을 지니고 있고 변수명과 실제 데이터는 
주소값을 통하여 연결되어 있는데 프로퍼티와 데이터 사이에서도 같은 동작을 합니다.</p>
<p><strong>두 타입의 가장 대표적인 차이</strong></p>
<ul>
<li><strong>기본형</strong>에는 바로 <strong>값을 그대로 할당</strong>한다는 것</li>
<li><strong>참조형</strong>에는 <strong>값이 저장된 주소값을 할당(참조)</strong> 한다는 것</li>
</ul>
<h2 id="javascript-형변환--원시형의-형변환-">Javascript 형변환 ( 원시형의 형변환 )</h2>
<p>함수와 연산자에 전달되는 값은 대부분 적절한 자료형으로 자동 변환 된다.
이런 과정을 <code>형 변환</code>이라고 한다.
<strong>ex ::</strong> aleat가 전달받은 값의 자료형과 관계없이
이를 문자열로 자동 변환하여 보여주는 것
<strong>ex ::</strong> 산술 연산을 위해 전달받은 값을 숫자로 변환하는 경우</p>
<hr>
<h4 id="문자형-변환"><strong>문자형 변환</strong></h4>
<p>String(value) 함수를 호출해 전달받은 값을 문자열로 변환 할 수도 있습니다.</p>
<pre>
let value = true;
alert(typeof value); // boolean

value = String(value); // 변수 value엔 문자열 "true"가 저장됩니다.
alert(typeof value); // string
</pre>

<hr>
<h4 id="숫자형-변환">숫자형 변환</h4>
<p>Number(value) 함수를 사용하면 주어진 값(value)을 숫자형으로 명시해서 변환할 수 있습니다.</p>
<pre>
let str = "123";
alert(typeof str); // string

let num = Number(str); // 문자열 "123"이 숫자 123으로 변환됩니다.

alert(typeof num); // number
</pre>

<ul>
<li>숫자형 값를 사용해 무언가를 하려고 하는데 그 값을 문자 기반 폼(form)을 통해 입력받는 경우엔, 이런 명시적 형 변환이 필수입니다.</li>
<li><strong>null과 undefined은 숫자형으로 변환 시 결과가 다르다는 점에 유의하시기 바랍니다.
null은 0이 되고 undefined는 NaN이 됩니다.</strong></li>
</ul>
<hr>
<h4 id="불린형-변환"><strong>불린형 변환</strong></h4>
<p>이 형 변환은 논리 연산을 수행할 때 발생합니다
숫자 <code>0</code>, 빈 문자열, <code>null</code>, <code>undefined</code>, <code>NaN</code>과 같이 직관적으로도 
“비어있다고” 느껴지는 값들은 false가 됩니다.
그 외의 값은 <code>true</code>로 변환됩니다.</p>
<pre>
alert( Boolean(1) ); // 숫자 1(true)
alert( Boolean(0) ); // 숫자 0(false)

alert( Boolean("hello") ); // 문자열(true)
alert( Boolean("") ); // 빈 문자열(false)
</pre>

<hr>
<h3 id="불변-객체를-만드는-방법"><strong>불변 객체를 만드는 방법</strong></h3>
<p><strong>어떤 객체 내부의 프로퍼티들을 변경할 수 없도록 되어있는 객체</strong></p>
<p><code>Object.freeze()</code></p>
<p>Javascript에서 기본적으로 제공하는 메소드인 Object.freeze() 메소드
공식 문서에서는 &quot;객체를 동결하기 위한 메소드&quot;라고 적혀있다.</p>
<pre>
let test = {
    name : 'kim'
}
Object.freeze(test);
</pre>

<p><code>test변수</code>에<code>key value</code>를 가진 객체를 바인딩 후 <code>Object.freeze(test)</code>를 사용해
바인딩 된 변수를 동결 객체로 만들었다. 때문에 test 객체는 객체의 속성을 변경하는 시도가 불가능하다.</p>
<pre>
test.name = 'Jung';
console.log(test) // {name: 'kim'}
</pre>

<p>▲▲▲위와 같은 속성을 변경하는 시도는 무시된다.</p>
<p>하지만... 객체의 재할당이 가능하다.</p>
<pre>
test = {
    age : 15
};
console.log(test); 
</pre>

<ul>
<li>때문에 Object.freeze()도 불변 객체라고 할 수는 없다..</li>
</ul>
<hr>
<h4 id="const와-objectfreeze를-조합한다면"><strong>const와 Object.freeze()를 조합한다면...?</strong></h4>
<p><code>const(재할당 불가)</code> + <code>Object.freeze() (개체속성 변경불가)</code></p>
<p>▼▼▼ 이렇게 사용 가능하다.</p>
<pre>
const test = {
    'name' : 'jung'
};

Object.freeze(test);
</pre>

<p>객체의 재할당, 객체의 속성 변경을 금지하는 불변 객체가 된다.</p>
<hr>
<h2 id="얕은-복사-깊은-복사"><strong>얕은 복사, 깊은 복사</strong></h2>
<p><code>얕은 복사</code>
<strong>객체를 복사할 때 기존 값과 복사된 값이 같은 참조를 가리키고 있는 것을 말한다.</strong>
객체 안에 객체가 있는 경우 한 개의 객체라도 기존 변수의 객체를 참조하고 있다.</p>
<pre>
const a = 'a';
let b = 'b';
b = 'c';
console.log(a); // 'a';
console.log(b); // 'c';
</pre>
<ul>
<li><strong>기존 값에 영향을 끼치지 않는다.</strong></li>
</ul>
<hr>
<p><code>깊은 복사</code>
객체의 실제 값을 복사
<strong>깊은 복사된 객체는 객체 안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체</strong>이다.</p>
<pre>
const object = {
a: "a",
number: {
one: 1,
two: 2,
},
arr: [1, 2, [3, 4]],
};
const copy = JSON.parse(JSON.stringify(object));
copy.number.one = 3;
copy.arr[2].push(5);
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // false
console.log(object.arr === copy.arr); // false
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }

출처: https://bbangson.tistory.com/78 [뺑슨 개발 블로그]
</pre>


<hr>
<h2 id="호이스팅-tdz"><strong>호이스팅, TDZ</strong></h2>
<p><code>호이스팅</code>이란?
인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것</p>
<ul>
<li><p><code>var</code>로 선언한 변수의 경우 호이스팅 시 <code>undefined</code>로 변수를 초기화한다.</p>
</li>
<li><p><code>let</code>, <code>const</code>로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않는다.</p>
</li>
</ul>
<p>다만, <strong>선언과 초기화를 함께 수행하는 경우</strong>
<strong>선언 코드까지 실행해야 변수가 초기화된 상태가 됨을 주의해야 한다</strong>.</p>
<pre>
function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

catName("호랑이");

/*
결과: "제 고양이의 이름은 호랑이입니다"
*/
</pre>


<p><code>↑  결과는 같다 ↓</code></p>
<pre>
catName("클로이");

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

/*
결과: "제 고양이의 이름은 클로이입니다"
*/
</pre>

<hr>
<h4 id="선언만-호이스팅-대상">선언만 호이스팅 대상</h4>
<p>JavaScript는 <strong>초기화를 제외한 선언만 호이스팅</strong>합니다.
<strong>변수를 먼저 사용하고 그 후에 선언 및 초기화가 나타나면</strong>, 사용하는 시점의 변수는 
<strong>기본 초기화 상태</strong>(var 선언 시 undefined, 그 외에는 초기화하지 않음)입니다.</p>
<pre>
console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화
</pre>

<hr>
<pre>
console.log(num); // ReferenceError
num = 6; // 초기화
</pre>
<ul>
<li><strong>선언 없이 초기화만 존재하기 때문에 호이스팅이 없고,
변수를 읽으려는 시도에서</strong> <code>ReferenceError</code> <strong>예외가 발생</strong></li>
</ul>
<hr>
<h2 id="tdz"><strong>TDZ</strong></h2>
<p><strong>스코프의 시작 지점부터 초기화 시작 지점까지의 구간</strong> ( <strong>T</strong>emporal <strong>D</strong>ead <strong>Z</strong>one )</p>
<p>변수 선언 3단계
<strong>선언 단계(Declaration phase)</strong><br><code>공간을 확보하고 변수명과 주소를 매칭시키는 과정</code>
변수를 실행 컨텍스트의 변수 객체에 등록하는 단계를 의미합니다. 
이 변수 객체는 스코프가 참조하는 대상이 됩니다.</p>
<p><strong>초기화 단계(Initialization phase)</strong>
실행 컨텍스트에 존재 하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계 입니다.
 이 단계에서 할당된 메모리에는 undefined로 초기화 됩니다.</p>
<p><strong>할당 단계(Assignment phase)</strong>
<code>해당 변수가 가리키는 주소의 공간에 데이터를 저장하는 과정</code>
사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계 입니다.</p>
<hr>
<h2 id="함수-선언식-함수-표현식"><strong>함수 선언식, 함수 표현식</strong></h2>
<p><strong>함수 선언식</strong>
함수명이 정의되어 있고, 별도의 할당 명령이 없는 것</p>
<p><strong>함수 표현식</strong>
정의한 function을 별도의 변수에 할당하는 것</p>
<p>함수 선언식과 함수 표현식의 차이 (호이스팅)</p>
<p><strong>함수 선언식</strong>은 <strong>함수 전체를 호이스팅</strong> 합니다.
정의된 범위의 맨 위로 호이스팅 돼서 함수 선언 전에 함수를 사용할 수 있다는 것</p>
<p><strong>함수 표현식</strong>은 <strong>별도의 변수에 할당</strong>하게 됩니다.
변수는 선언부나 할당부를 나누어 호이스팅 하게 됩니다.</p>
<p>:: ex</p>
<pre>
sum(50, 50); // 100
minus(100, 50) // Uncaught TypeError: minus is not a function

function sum(a, b) { // 함수 선언식
  return a + b;
}

var minus = function (a,b) { // 함수 표현식
  return a - b;
}
</pre>

<hr>
<pre>
var minus = function (a,b) { // 함수 표현식
  return a - b;
}

sum(50, 50); // 100
minus(100, 50) // 50

function sum(a, b) { // 함수 선언식
  return a + b;
};
</pre>

<ul>
<li>함수 선언식으로 작성한 함수는, 함수 전체가 호이스팅 된다고 하였는데,
전역적으로 선언하게 되면, 중복적으로 동명의 함수를 쓰게 될 수 있다.
이를 방지하려면 함수 표현식으로 작성하면 된다.</li>
</ul>
<hr>
<h3 id="var-변수-라이프사이클-▼▼▼">var 변수 라이프사이클 ▼▼▼</h3>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/fe547dc2-e0dd-45b5-8e12-b4b207354ecc/image.png" alt=""></p>
<p>var 키워드 변수는 변수를 선언하기 전에 <strong>선언 단계와 초기화 단계를 동시에 진행</strong>한다.</p>
<p>그래서 Javascript는 실행 컨텍스트 변수 객체의 변수를 등록하고 메모리를 
undefined로 만들어 버린다.</p>
<p>그렇기 때문에 변수를 선언하기 전에 호출을 해도 undefined로 호출이 되는 
호이스팅이 발생한다.</p>
<hr>
<h3 id="let-변수-라이프사이클-▼▼▼">let 변수 라이프사이클 ▼▼▼</h3>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/3e02802b-e76c-4ce6-aab4-8982df191b8f/image.png" alt=""></p>
<p>let으로 선언된 변수는 var 키워드와는 다르게,
<strong>선언 단계와 초기화 단계가 분리되어서 진행</strong>된다.</p>
<p>그렇게 때문에 실행 컨텍스트에 변수를 등록했지만,
메모리가 할당 되지 않아 접근할 수 없어 참조 에러(ReferenceError)가 발생한다.
이것을 보고 우리는 호이스팅이 되지 않는다고 오해할 수 있었다.</p>
<p>let 또한 선언 전, 실행 컨텍스트 변수 객체에 등록이 되어 호이스팅이 되지만,
TDZ 구간에 의해 메모리가 할당되지 않아서 참조 에러(ReferenceError)가 발생하는 것이다.</p>
<h3 id="실행-컨텍스트--콜-스택">실행 컨텍스트 &amp; 콜 스택</h3>
<p>실행할 코드에 제공할 환경 정보들을 모아놓은 객체
Javascript의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이다.</p>
<p>Javascript는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생한다.</p>
<ul>
<li>호이스팅 발생 ( 선언된 변수를 위로 끌어올린다 )</li>
<li>외부 환경 정보를 구성</li>
<li>this 값을 설정</li>
</ul>
<p>이로 인해 다른 언어에서 발견할 수 없는 특이한 현상들이 발생한다.</p>
<p>실행 컨텍스트 구성</p>
<ul>
<li><code>전역공간</code>은 자동으로 컨텍스트로 구성</li>
<li><code>함수</code>를 실행</li>
<li><code>eval()</code> 함수를 실행</li>
<li><code>block</code>을 생성
▲▲▲▲▲ 위의 것을 이용하면 <code>call stack</code>에 쌓이게 된다.</li>
</ul>
<pre>
var a = 1; // 전역 컨텍스트
function outer () { // outer 컨텍스트
  function inner () { // inner 컨텍스트
    console.log(a); // undefined
    var a = 3;
    console.log(a); // 3
  }
  inner();
  console.log(a); // 1
}
outer();
console.log(a); // 1
</pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[항해99 1주차 회고록]]></title>
            <link>https://velog.io/@hj_ki/week1</link>
            <guid>https://velog.io/@hj_ki/week1</guid>
            <pubDate>Sun, 15 May 2022 14:45:16 GMT</pubDate>
            <description><![CDATA[<p>5.9 ~ 5.12</p>
<h4 id="1-미니프로젝트">1. 미니프로젝트</h4>
<p>첫 미니프로젝트라 걱정이 됐지만, 한편으로는 설레는 마음으로 한 주를 시작했다. 
이런 복잡한 마음들 속에서 첫 팀원들을 만났고, 그렇게 프로젝트는 시작되었다.
시작하기 전에 토론을 하며 각자 아이디어를 늘어놓았다.
사전 공부를 할 때 한번씩 만들어봤던 &#39;<strong>영화 포스터 리뷰 웹 사이트</strong>&#39;를 구현하기로 결정했다.
프로젝트 결정 후, 와이어프레임을 작성하며 웹 페이지의 경로? 동작 방식을 작성했다.
미니 프로젝트의 내용은 이렇다.
네이버 영화의 url을 입력하여 영화 포스터를 등록할 수 있고 
회원과 비회원을 구분하여 포스터 등록 및 리뷰 작성을 제한하는 main.html 페이지,
해당 포스터를 클릭했을 때 리뷰를 작성할 수 있는 detail.html 상세 페이지,
ID, PASSWORD를 입력하여 중복확인 및 회원가입을 할 수 있는 signup.html 페이지,
DB에 저장되어있는 회원정보를 비교하여 
정보가 같은 회원만 로그인할 수 있는 login.html 페이지
총 4개의 html 페이지와 post, get 방식으로 사용자의 정보를 저장하고 전달하는 app.py python파일로 나누어져 있다. 
css는 부트스트랩을 이용해 해결하였고 필요한 이미지는 직접 img폴더에 저장해서 사용하였다.
4일동안 팀원들 모두 열정적으로 프로젝트에 임했고, 
그 결과는 우리 모두를 뿌듯하게 만들어 주었다.
아쉬웠던 점은
구글링하며 필요한 기능을 찾고 에러가 나는 부분에서는 몇 시간이 걸려도 해결이 안될 때가 있었다.
완성하는 것에 너무 중점을 둬서, 중간 중간에 완벽하게 이해하지 못한 부분도 넘어가는 경우가 종종 있었고, 프로젝트가 끝난 시점에서 생각해보면 github 사용에 미숙한 부분도 많이 느껴졌다.
하지만 서툴고 부족했던 지식 덕분에 보완해야 될 부분들이 잘 부각되어서, 큰 성과를 얻었다고 생각한다.
미니 프로젝트를 경험으로, 앞으로 만들게 될 프로젝트는 더 나아질 것이라고 확신한다.</p>
<p><strong>main.html</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/1dfe58f8-9476-491a-9609-ecf67dc42ebd/image.png" alt=""></p>
<p><strong>login.html</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/57a801d9-ee27-4cec-88e7-907913460c70/image.png" alt=""></p>
<p><strong>signup.html</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/3c5810c5-0509-47da-a8b1-56a4feba19fc/image.png" alt=""></p>
<p><strong>detail.html</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/d0a0b2b8-6316-4e62-9c31-c37663f6afb5/image.png" alt=""></p>
<p>Github link
:</p>
<p>5.13 ~ 5.14</p>
<h4 id="2-javascript-기초-및-알고리즘-문제해결--코딩-문제-해결-및-풀이-">2. Javascript 기초 및 알고리즘 문제해결 ( 코딩 문제 해결 및 풀이 )</h4>
<p>React 주특기를 배우기 전, 같은 주특기를 선택한 팀원들과 새로운 학습을 시작하였다.
VSCODE를 설치하여 개발환경을 세팅했고 Javascript의 간단한 기초 문법들을 공부하며,
프로그래머스 1단계 난이도에 해당하는 문제들을 풀어보았다. 
얼마 전까지만 해도 파이썬 언어의 문법이 익숙해졌었는데, 그것도 아주 잠깐이었다.
프론트엔드 개발자가 되기 위해 React를 선택한 나로서는 파이썬 언어의 문법 보다는<br>Javascript의 문법과 메서드 등을 공부하여, 
Javascript 형식으로 코딩 문제를 푸는 것이 효율적이라고 판단하였다.
이때까지 문제를 풀면서 느낀 점은, 
문제 해결을 하는 것보다 Javascript에 대한 지식이 나에겐 더 필요하다고 느껴진다.<br>문법이나 메소드를 알지 못하면 코드가 간결하지 못하고, 문제를 푸는데 있어서 어려움을 느낀다.
가끔 자신있게 풀었던 문제도 있지만, 어떤 문제는 해석만 하고 건드리지 못한 문제도 있었다.
다음 문제로 넘어갈 때, 늘 새로움을 느낀다는 것은 아직 풀어야 될 문제가 많이 남았다는 뜻이기도 하다. 
꾸준히 문제를 풀어보고 익숙해져야겠다,,</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS___1]]></title>
            <link>https://velog.io/@hj_ki/js1</link>
            <guid>https://velog.io/@hj_ki/js1</guid>
            <pubDate>Fri, 13 May 2022 11:59:32 GMT</pubDate>
            <description><![CDATA[<p>5.13(금)</p>
<h2 id="실습환경-만들기">실습환경 만들기</h2>
<p>개발환경 세팅 !
React - Node.js를 이용한 VSCode JS 실행하기 : </p>
<p><strong>Node.js 설치</strong>
먼저, 아래 사이트에서 최신 버전 Node.js를 다운로드 한다
<a href="https://nodejs.org/ko/">https://nodejs.org/ko/</a> </p>
<p><strong>VS Code (Visual Studio Code) 설치</strong>
다음으로는 Node.js의 가장 많이 사용되는 개발 툴인 VS Code를 설치합니다.
MS사에서 만든 오픈소스 IDE로 설치도 간편하고 가볍고 사용이 편리합니다. 
아래의 공식 사이트에서 자신의 OS에 맞는 설치 파일을 다운로드합니다.
<a href="https://code.visualstudio.com/download">https://code.visualstudio.com/download</a></p>
<hr>
<p><strong>Node.js 프로젝트 생성 및 실행</strong></p>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/82fd097a-7f9b-4e00-ac57-4d6fe94c8bed/image.png" alt=""></p>
<hr>
<p>VS Code 프로그램으로 가서 상단 메뉴에 File &gt; Open Folder를 선택하여, 방금 생성한 폴더를 선택합니다.
<img src="https://velog.velcdn.com/images/hj_ki/post/e3c39f91-4d38-4595-849d-aca6c3f11e23/image.png" alt=""></p>
<hr>
<p>아래와 같이 Explorer 탭이 오픈이 되고, 방금 내가 오픈한 폴더가 리스트에 있는 것을 확인하실 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/9cfbb4b6-aaee-4115-a088-b92ea017e9bd/image.png" alt=""></p>
<hr>
<p>상단 메뉴바에서 View &gt; Terminal을 눌러서 터미널을 오픈해줍니다.
아래와 같이 하단에 터미널이 오픈이 됩니다.
이렇게 터미널을 보면서 VS CODE 내에서 진행을 하는 것이 창이동 없이 더 편합니다.
<img src="https://velog.velcdn.com/images/hj_ki/post/597694ff-75b4-4e81-aecc-bbb821ad2dfe/image.png" alt=""></p>
<hr>
<p>터미널 오픈 화면</p>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/5bd3342b-bb2c-4193-b7f4-3fe5853facd0/image.png" alt=""></p>
<p>이제 Node.js를 설치할 때 자동으로 설치되는 자바 패키지 관리 모듈인 NPM을 이용해서 프로젝트의 package.json 파일을 생성합니다.
package.json 파일은 Node.js의 프로젝트 기본 정보, 의존성 정보 등을 저장하는 json 파일로 JAVA Maven 프로젝트의 pom.xml과 유사한 역할이라고 생각하시면 됩니다.</p>
<p>하단 터미널 창에 NPM init이라는 명령을 치면, 프로젝트의 기본정보를 작성하도록 여러 항목들이 나옵니다. 실제로 작성을 하셔도 되고, 엔터를 계속 클릭하셔서 Default 값으로 세팅된 파일을 만들도록 해도 됩니다.</p>
<p>다 작성이 되면 프로젝트 폴더에 package.json 파일이 생성됩니다.</p>
<hr>
<p><strong>npm init</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/6bce1cad-0e01-4709-b848-62bd7296c380/image.png" alt=""></p>
<hr>
<p>프로젝트 최초 실행 자바스크립트 파일인 index.js 파일을 생성
<img src="https://velog.velcdn.com/images/hj_ki/post/b8acb7fe-f1dc-40fe-a163-fabb2f764562/image.png" alt=""></p>
<hr>
<p>생성된 index.js을 열어서 아래와 같이 콘솔 로그를 찍도록 간단히 코드를 작성
console.log(&quot;노드js 프로젝트 시작!!&quot;)
<img src="https://velog.velcdn.com/images/hj_ki/post/6d7ac6ed-6f62-47ea-8a33-433098228ef1/image.png" alt=""></p>
<hr>
<p>우측 Run and Debug 탭으로 이동을 하면, VS code에서 프로젝트 실행에 필요한 launch.json 파일이 아직 없기 때문에, 아래와 같이 create a launch.json file이라는 버튼이 보입니다. 
이 버튼을 클릭하여 launch.json을 생성합니다
<img src="https://velog.velcdn.com/images/hj_ki/post/88b16121-3b33-45ab-9a61-8e69945b2c7b/image.png" alt=""></p>
<hr>
<p>그러면 아래와 같이 Launch Type을 선택하도록 되어 있는데, 당연히 Node.js를 선택합니다. 그러면 launch.json 파일이 생성되는 것을 확인할 수 있습니다.
<img src="https://velog.velcdn.com/images/hj_ki/post/1803086c-824d-498e-8398-1c83f6c9b45c/image.png" alt=""></p>
<hr>
<p>이제 VS code에서 프로젝트 실행은 Run and Debug 탭으로 이동하여 해당 Launch name을 선택 후 F5 버튼 혹은 아래 화살표 버튼을 클릭하면 Node.js 프로젝트가 정상적으로 실행이 되는 것을 확인할 수 있습니다.
<img src="https://velog.velcdn.com/images/hj_ki/post/21051fe6-4ba2-4350-8a82-e1ef3408d4d8/image.png" alt=""></p>
<h3 id="javascript-실습-코딩문제-풀기"><strong>JavaScript</strong> 실습 (코딩문제 풀기)</h3>
<h4 id="문제1-두-개의-정수-n-m을-입력-별문자를-이용해-가로길이-n-세로길이-m인-직사각형-형태를-출력하기"><strong>문제1</strong>) 두 개의 정수 n, m을 입력, 별(*)문자를 이용해 가로길이 n, 세로길이 m인 직사각형 형태를 출력하기</h4>
<pre>
process.stdin.setEncoding('utf8');
process.stdin.on('data', data => { 
    const n = data.split(" "); // 입력값에 공백으로 구분

    const a = Number(n[0]); // 입력값 5
    const b = Number(n[1]); // 입력값 3

    const star = "*".repeat(a) // a 입력값만큼 *을 반복

    for(let i = 0; i < b; i++){
        console.log(star)
    }
});
</pre>
<p><strong>실행 결과</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/01d75b48-88ee-4806-9dbf-f5939425d1b7/image.png" alt=""></p>
<ul>
<li>&quot;*&quot;.<strong>repeat</strong>(a) 메서드 : 주어진 횟수만큼 반복해 새로운 문자열 반환 !</li>
</ul>
<hr>
<h4 id="문제2-정수num이-짝수일-경우-even을-반환-홀수인-경우-odd를-반환하는-함수-작성하기"><strong>문제2) 정수num이 짝수일 경우 &quot;Even&quot;을 반환, 홀수인 경우 &quot;Odd&quot;를 반환하는 함수 작성하기</strong></h4>
<pre>
function solution(num) {
    var answer = '';
    if(num % 2 == 0){
        return answer = "Even"
    } else {
        return answer = "Odd"
    }
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/a1ca4096-e3e7-4e62-a8fc-7ab82345ca22/image.png" alt=""></p>
<ul>
<li>num <strong>%</strong> 2 == 0 : 나머지 값을 구하는 산술 연산 !</li>
</ul>
<hr>
<p><strong>문제3) 단어 s의 가운데 글자를 반환하는 함수, solution을 만들기
단어의 길이가 짝수라면 가운데 두글자를 반환</strong></p>
<pre>
function solution(s) {
    var answer = '';
    if(s.length % 2 == 0) { 
        answer = s[s.length / 2 -1] + s[s.length / 2];
    } else { 
        answer = s[Math.floor(s.length / 2)]
    }
    return answer;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/26331acc-744a-40fe-8e26-86afa74d4458/image.png" alt=""></p>
<ul>
<li>% 연산으로 홀수/짝수 구분 !</li>
<li>짝수 == 반으로 나눈 값과 그 값의 -1인덱스값을 함께 출력 ! ( <strong>4 : 1,2</strong> ) </li>
<li>홀수 == <strong>Math.floor</strong>를 사용해 반으로 나눈 값의 소수점을 반내림한다. ( <strong>3 : 1</strong> )</li>
</ul>
<hr>
<p><strong>문제4) 두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수 완성하기
예를 들어 a = 3, b = 5인 경우, 3 + 4 + 5 = 12이므로 12를 리턴합니다.</strong></p>
<pre>
function solution(a, b) {
    var sum = 0;
    if(a < b){
        for(let i = a; i <= b; i++){ // 입력값a ~~ 입력값b 까지 반복 
            sum = sum + i; // a ~ b 값 sum에 더하기
        }
    } else if(a > b) { // 입력값b ~~ 입력값a 까지 반복
        for(let i = b; i <= a; i++){
            sum = sum + i; // a ~ b 값 sum에 더하기
        }
    } else {
        sum = a; // 같은 경우 a 출력
    }
    return sum;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/60ea39c7-2904-4607-be5f-3267611017bc/image.png" alt=""></p>
<ul>
<li>간단하게 if문 안에 for문을 넣어 작성했다.</li>
</ul>
<hr>
<p><strong>문제5) 문자열 s를 숫자로 변환하는 함수 작성하기</strong></p>
<pre>
function solution(s) {
    var answer = 0;
    var answer = Number(s);
    return answer;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/92817c5f-f2d7-4e39-830f-1f9f97cbbf60/image.png" alt=""></p>
<hr>
<h4 id="문제6-없는-숫자-더하기">문제6) 없는 숫자 더하기</h4>
<p>0부터 9까지의 숫자 중 일부가 들어있는 정수 배열 numbers가 매개변수로 주어집니다. numbers에서 찾을 수 없는 0부터 9까지의 숫자를 모두 찾아 더한 수를 return 하도록 solution 함수를 완성해주세요.</p>
<pre>
function solution(numbers) {
    var sum = 0;

    for(let i =0; i<=9; i++){
        if(!numbers.includes(i)) {  // numbers.includes(a) = numbers 안에 a가 포함되어 있는지 체크
            sum = sum + i;
        }
    }
    return sum;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/f85cc131-3d37-4951-bcde-7943d4cd1931/image.png" alt=""></p>
<ul>
<li><strong>.includes</strong>() = 괄호 안의 값을 포함하는지 확인한다 true , false 반환</li>
</ul>
<hr>
<p>5.14(토)</p>
<h4 id="문제7-음양-더하기"><strong>문제7) 음양 더하기</strong></h4>
<p>어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.</p>
<pre>
function solution(absolutes, signs) {
    var answer;
    var sum = 0;
    for(let i =0; i < absolutes.length; i++) { // absolutes의 값 읽기
        if(signs[i] == true) { // signs[index] 가 true이면
            sum = sum + absolutes[i]; // 변수 sum에 absolutes[index] 더하기
        } else { // false이면
            sum = sum - absolutes[i]; // 변수 sum에 absolutes[index] 빼기 
        }
    }
    return sum;
}
</pre>

<p><img src="https://velog.velcdn.com/images/hj_ki/post/127f8a2d-6a47-4d1f-9868-a166d7495e83/image.png" alt=""></p>
<ul>
<li>입력값이 가지는 타입을 정확히 파악하기</li>
</ul>
<hr>
<p><strong>문제8) 평균 구하기</strong>
정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.</p>
<p>function solution(arr) {
    var answer = 0;
    let sum = 0;
    let avg = 0;
    for(let i =0; i&lt;arr.length; i++){
        sum = sum + arr[i]
    }
    avg = sum / arr.length;
    return avg;
}</p>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/10f8f79b-3071-4c94-867c-c008dd28d828/image.png" alt=""></p>
<hr>
<h4 id="문제9-핸드폰-번호-가리기">문제9) 핸드폰 번호 가리기</h4>
<p>프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 
고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 
전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.</p>
<pre>
function solution(phone_number) {
    var answer='';
    for(let i = 0; i < phone_number.length; i++){
        if(answer.length < phone_number.length-4){
            answer = answer + "*";
        }
        else {
            answer = answer + phone_number[i];
        }
    }
    return answer;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/e8661d60-255e-4a16-94c2-3f94c794c8b9/image.png" alt=""></p>
<ul>
<li>길이를 -연산으로 구분하여 영역 나누기 / + repeat함수 사용 가능 ( * )</li>
</ul>
<hr>
<h4 id="문제10-행렬의-덧셈"><strong>문제10) 행렬의 덧셈</strong></h4>
<p>행렬의 덧셈은 행과 열의 크기가 같은 두 행렬의 같은 행, 같은 열의 값을 서로 더한 결과가 됩니다. 
2개의 행렬 arr1과 arr2를 입력받아, 행렬 덧셈의 결과를 반환하는 함수, solution을 완성해주세요.</p>
<p>function solution(arr1, arr2) {
    var answer = [];
    for(let i =0; i&lt;arr1.length; i++){ // [1,2][2,3]
        let sum = []; // 값을 합할 배열 생성
        for(let j=0; j&lt;arr1[i].length; j++) { // [1,2]
            sum.push(arr1[i][j]+arr2[i][j]) // [1,2] + [3,4] 
        }
        answer.push(sum)
    }
    return answer;
}
<img src="https://velog.velcdn.com/images/hj_ki/post/24a1f182-02d0-4152-9428-f7f58c5de804/image.png" alt=""></p>
<ul>
<li>행과 열을 잘 구분하여 헷갈리지 않기 !</li>
</ul>
<hr>
<h4 id="문제11-x만큼-간격이-있는-n개의-숫자">문제11) x만큼 간격이 있는 n개의 숫자</h4>
<p>함수 solution은 정수 x와 자연수 n을 입력 받아, x부터 시작해 x씩 증가하는 숫자를 n개 지니는 리스트를 리턴해야 합니다. 다음 제한 조건을 보고, 조건을 만족하는 함수, solution을 완성해주세요.</p>
<pre>
function solution(x, n) {
    var answer = [];
    for(let i = 1; i<=n; i++){
        answer.push(x*i);
    }
    return answer;
}
</pre>

<p><img src="https://velog.velcdn.com/images/hj_ki/post/295fdf69-eab2-4438-87f3-6a6654286ce8/image.png" alt=""></p>
<ul>
<li>.*<em>push() *</em>: 괄호 안의 값을 배열에 추가</li>
</ul>
<hr>
<h4 id="문제12-부족한-금액-계산하기"><strong>문제12) 부족한 금액 계산하기</strong></h4>
<p>새로 생긴 놀이기구는 인기가 매우 많아 줄이 끊이질 않습니다. 
이 놀이기구의 원래 이용료는 price원 인데, 
놀이기구를 N 번 째 이용한다면 원래 이용료의 N배를 받기로 하였습니다. 
즉, 처음 이용료가 100이었다면 2번째에는 200, 3번째에는 300으로 요금이 인상됩니다.</p>
<h4 id="놀이기구를-count번-타게텍스트-되면-현재-자신이-가지고-있는-금액에서-얼마가-모자라는지를">놀이기구를 count번 타게<strong>텍스트</strong> 되면 현재 자신이 가지고 있는 금액에서 얼마가 모자라는지를</h4>
<p>return 하도록 solution 함수를 완성하세요.
단, 금액이 부족하지 않으면 0을 return 하세요</p>
<pre>
function solution(price, money, count) {
    var result = 0;
    var price_sum = 0;
    for(let i = 1; i <= count; i++){
        price_sum = price_sum + i * price;
    }
    if(price_sum > money) {
        result = price_sum - money;
        return result;
    }

    return result;
}
</pre>

<p><img src="https://velog.velcdn.com/images/hj_ki/post/eb0d599a-9b78-4c16-b53c-42aaf015ba66/image.png" alt=""></p>
<ul>
<li><strong>입력값 구분, 계산, 결과값 정리해서 풀기</strong></li>
</ul>
<hr>
<p>5/16(월)</p>
<h4 id="문제14-나누어-떨어지는-숫자-배열"><strong>문제14) 나누어 떨어지는 숫자 배열</strong></h4>
<p>array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요.
divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.</p>
<pre>
function solution(arr, divisor) {
    var answer = [];
    for(let i = 0; i < arr.length; i++){
        if(arr[i] % divisor == 0){ // 나눈 값의 나머지가 0이면 배열에 넣기
            answer.push(arr[i]);
        }
    }
    if(answer.length == 0) { // 배열에 값이 없다면 -1 넣기
        answer.push(-1);
    }
    answer.sort((a,b) => a - b); // answer 배열 오름차순 
    return answer;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/1ce86884-f0da-45da-9889-5f69e10e6c34/image.png" alt=""></p>
<ul>
<li><strong>.push()</strong></li>
<li><strong>.sort((a,b) =&gt; a - b)</strong> 오름차순 정렬</li>
</ul>
<hr>
<h4 id="문제15-내적"><strong>문제15) 내적</strong></h4>
<p>길이가 같은 두 1차원 정수 배열 a, b가 매개변수로 주어집니다.
a와 b의 내적을 return 하도록 solution 함수를 완성해주세요.</p>
<p>이때, a와 b의 내적은 a[0]<em>b[0] + a[1]</em>b[1] + ... + a[n-1]*b[n-1] 입니다. (n은 a, b의 길이)</p>
<pre>
function solution(a, b) {
    var answer = 0;
    for(let i = 0; i < a.length; i++){
        answer = answer + a[i] * b[i] // a[i] * b[i] --> answer에 누적
    }
    return answer;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/2bdc8617-2f14-47be-80f3-c68dfb636305/image.png" alt=""></p>
<ul>
<li>*<em>각 배열의 인덱스 값을 곱하여 더하기 a[0] b[0] + a[1] b[1] *</em></li>
</ul>
<hr>
<h4 id="문제16-문자열-내-p와-y의-개수"><strong>문제16) 문자열 내 p와 y의 개수</strong></h4>
<p>대문자와 소문자가 섞여있는 문자열 s가 주어집니다.
s에 &#39;p&#39;의 개수와 &#39;y&#39;의 개수를 비교해 같으면 True, 다르면 False를 return 하는 solution를 완성하세요.
 &#39;p&#39;, &#39;y&#39; 모두 하나도 없는 경우는 항상 True를 리턴합니다.
 단, 개수를 비교할 때 대문자와 소문자는 구별하지 않습니다.</p>
<p>예를 들어 s가 &quot;pPoooyY&quot;면 true를 return하고 &quot;Pyy&quot;라면 false를 return합니다.</p>
<pre>
function solution(s){
    var answer = true;
    var p = 0;
    var y = 0;
    for(let i = 0; i < s.length; i++) {
        if(s[i] == 'p' || s[i] == 'P') {
            p = p + 1;
        }
        else if(s[i] == 'y' || s[i] == 'Y') {
            y = y + 1;
        }
    }
    return (p == y) ? true : false;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/177fe610-1fc1-4577-a3f0-c7dc068b3afa/image.png" alt=""></p>
<ul>
<li><strong>for문을 이용해서 p,P y,Y 값 변수에 담아주기</strong></li>
<li><strong>( p == y ) ? true : false</strong> ::** [조건] ? [true] : [false] **</li>
</ul>
<hr>
<h4 id="문제17-문자열-다루기-기본"><strong>문제17) 문자열 다루기 기본</strong></h4>
<p>문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요.
예를 들어 s가 &quot;a234&quot;이면 False를 리턴하고 &quot;1234&quot;라면 True를 리턴하면 됩니다.</p>
<pre>
function solution(s) {
    var answer = parseInt(s);

    if((s.length == 4 || s.length == 6) && s == answer) {
        return true;
    } else {
        return false;
    }
    return answer;
}
</pre>

<p><img src="https://velog.velcdn.com/images/hj_ki/post/d39d7755-16fa-4d8e-972d-661120875124/image.png" alt=""></p>
<ul>
<li><strong>parseInt(s) : 문자열을 파싱하여 문자열에 포함된 숫자를 찾아서 number로 형변환, 
문자열이 숫자로 시작한다면 숫자로 리턴,
숫자로 시작하거나, 숫자를 포함하지 않는 문자열의 경우는 NaN으로 반환</strong></li>
</ul>
<hr>
<h4 id="문제18-서울에서-김서방-찾기"><strong>문제18) 서울에서 김서방 찾기</strong></h4>
<p>String형 배열 seoul의 element중 &quot;Kim&quot;의 위치 x를 찾아, &quot;김서방은 x에 있다&quot;는 String을 반환하는 함수, solution을 완성하세요. seoul에 &quot;Kim&quot;은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.</p>
<pre>
function solution(seoul) {
    let kim = 0;
    for(let i = 0; i < seoul.length; i++){
        if(seoul[i] == "Kim"){
            kim = kim + i;
        }
    }
    var answer = '김서방은 ' + kim + '에 있다';
    return answer;
}
</pre>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/b36e1718-4af5-4502-a559-91a78a5c5f7c/image.png" alt=""></p>
<ul>
<li><strong>&quot;kim&quot; 문자를 찾는다면 해당 인덱스값을 변수에 저장</strong></li>
<li><strong>간결하게 하려면 indexOf() 사용할 것</strong></li>
<li><strong>indexOf() : 특정 문자 위치 찾기</strong></li>
</ul>
<hr>
<p>5.17(화)</p>
<h2 id="javascript-기초"><strong>Javascript 기초</strong></h2>
<h4 id="입력-및-메세지"><strong>입력 및 메세지</strong></h4>
<pre>
console.log(name);
alert(age);
prompt('생년월일 입력하세요.');
confirm('삭제 하시겠습니까?);
</pre>

<h4 id="조건문"><strong>조건문</strong></h4>
<pre>
if(user.name && user.age > 19){
    console.log('성인 입니다');
    } else {
        return false;
}
</pre>

<h4 id="반복문"><strong>반복문</strong></h4>
<pre>
for(let i = 0; i < 10; i++){
   console.log(i);
}
</pre>

<h4 id="함수"><strong>함수</strong></h4>
<pre>
function add(num1, num2) {
    console.log(num1+num2);
}
</pre>

<h4 id="object">Object</h4>
<pre>
const user = {
    name : 'Mike',
    age : 30,
}
</pre>

<h4 id="배열"><strong>배열</strong></h4>
<pre>
const users = ['Mike', 'Jane'];
</pre>

<h4 id="-함수-표현식">** 함수 표현식**</h4>
<pre>
let showError = function() {
  console.log('error');
}
</pre>

<h4 id="함수-선언문">함수 선언문</h4>
<pre>
function showError() {
   console.log('error');
}
</pre>
<h4 id="화살표-함수">화살표 함수</h4>
<pre>
let showError = () => {
   console.log('error');
}
</pre>


<h3 id="변수의-생성과정"><strong>변수의 생성과정</strong></h3>
<ol>
<li>선언 단계</li>
<li>초기화 단계</li>
<li>할당 단계</li>
</ol>
<p><strong>var ( 함수 스코프 - function-scoped )</strong></p>
<ol>
<li>선언 및 초기화 단계</li>
<li>할당 단계</li>
</ol>
<p><strong>let ( 블록 스코프 - block=scoped )</strong> </p>
<ol>
<li>선언 단계</li>
<li>초기화 단계</li>
<li>할당 단계</li>
</ol>
<p><strong>const ( 블록 스코프 - block=scoped )</strong></p>
<ol>
<li>선언 + 초기화 + 할당</li>
</ol>
<p><strong>코드 블록</strong>
함수, if문, for문, while문, try/catch 문 등 안에서만 사용 가능 ( 지역변수 )</p>
<p><strong>let</strong> = &quot;변하는 변수&quot;
<strong>const</strong> = &quot;상수&quot; ( 대문자로 표현할 것 )
<strong>prompt</strong> = &quot;값을 입력받을 때 사용&quot;  prompt( &quot;예약일을 입력하세요&quot; , &quot;2020-10-&quot; ) <strong>default</strong> 값 입력가능
입력 없이 취소할 경우 null 값을 반환
<strong>confirm</strong> = &quot;뭔가 확인 받을 때 사용&quot;  // 확인(true) 취소(false) 메세지박스 </p>
<p><strong>호이스팅</strong> : 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것처럼 행동</p>
<hr>
<p>5.18(수)</p>
<h2 id="null-undefined-">*<em>null, undefined *</em></h2>
<p><strong>undefined</strong> - 아무 값도 할당받지 않은 상태
<strong>null</strong> - 비어잇는, 존재하지 않는 값 ( 값의 부재 )</p>
<h3 id="객체-함수"><strong>객체, 함수</strong></h3>
<p><strong>함수(Function)</strong> - 여러 개의 프로그램 명령들을 모아 놓은 것
<strong>객체(Object)</strong> - 프로그램이 실행 중 사용하는 데이터,
객체의 크기와 종류는 다양하다. 한편으론 값이 들어있는 즉 공간을 말하기도 한다.</p>
<p>*<em>함수에 return 값을 주면 값을 반환하여 그 값을 
다른 코드에서 사용할 수 있다. *</em></p>
<pre>
const caculator = {
    add: function(a,b){
        console.log(a+b);
    },
    minus: function(a,b){
        console.log(a-b);
    },
    times: function(a,b){
        console.log(a*b);
    },
    divide: function(a,b){
        console.log(a/b);
    },
    power: function(a,b){
        console.log(a**b);
    }
};
caculator.power(3,9);
caculator.divide(10,3);
caculator.add(4,5);

const plusResult = caculator.add(2,3); // 5
const minusResult = caculator.minus(plusResult, 3); // 5 - 3
const powerResult = caculator.power(plusResult, 2); // 5 * 5
const timesResult = caculator.times(minusResult, powerResult); // 2 * 25
console.log(plusResult, minusResult, powerResult, timesResult);
</pre>

<h4 id="객체-안의-함수를-호출"><strong>객체 안의 함수를 호출</strong></h4>
<pre>
console.log()
player.msg()
caculator.add(1,2)
</pre>

<h3 id="함수와-메서드의-차이">함수와 메서드의 차이</h3>
<p>함수(function)라는 것은 어떠한 기능을 수행하는 친구이다.
각 함수마다 나름의 기능을 가지고 있다.
지금도 누군가 함수를 만들고 있기 때문에, 함수의 수는 절대 셀 수 없다.
메소드(method)는 함수처럼 어떠한 기능을 수행하는 친구이다.
하지만 <strong>메서드</strong>는 <strong>클래스 및 객체(object)와 연관되어 있는 함수</strong>이다.
클래스 내에 선언되어 있는 함수가 바로 메소드이다.</p>
<ul>
<li><strong>클래스 및 객체와 연관되어 있는 것이라면 메소드, 그것들과 상관없이 독립적으로
존재하는 것은 함수이다.</strong>
함수가 메소드보다 더 큰 개념이라고 생각할 수 있다.</li>
</ul>
<hr>
<h2 id="this">This</h2>
<p>Javascript 예약어</p>
<ul>
<li>자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 <strong>자기 참조 변수</strong>이다.</li>
<li>this를 통해 자신이 속한 객체 또는 자신이 생성할 <strong>인스턴스의 프로퍼티나 메서드를 참조</strong>할 수 있다.</li>
<li>this는 Javascript 엔진에 의해 <strong>암묵적으로 생성</strong>된다.</li>
<li>this는 <strong>코드 어디서는 참조</strong>할 수 있다.</li>
<li>하지만 this는 객체의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이므로
일반적으로 <strong>객체의 메서드 내부 또는 생성자 함수 내부에서만 의미가 있다</strong>.</li>
<li>함수를 호출하면 <strong>인자와 this가 암묵적으로 함수 내부에 전달</strong>된다.</li>
<li>함수 내부에서 인자를 지역 변수처럼 사용할 수 있는 것처럼, this도 <strong>지역 변수처럼 사용</strong>할 수 있다.</li>
<li>단, this가 가리키는 값, 즉 <strong>this 바인딩은 함수 호출 방식에 의해 동적으로 결정</strong>된다.</li>
<li>크게 <strong>전역에서 사용할 때</strong>와 <strong>함수안에서 사용할 때</strong>로 나눌 수 있다.</li>
</ul>
<h3 id="👉-바인딩이란">👉 바인딩이란?</h3>
<ul>
<li><strong>식별자와 값을 연결하는 과정을 말한다.</strong></li>
<li><strong>변수선언은 변수 이름과 확보된 메모리 공간의 주소를 바인딩하는 것이다.</strong></li>
<li><strong>this 바인딩은 this(</strong>키워드로 분류되지만 식별자의 역할을 한다<strong>)와 this가 가리킬 객체를 바인딩하는 것이다.</strong></li>
</ul>
<h3 id="❗️this를-전역에서-사용한-경우"><strong>❗️this를 전역에서 사용한 경우</strong></h3>
<ul>
<li>브라우저라는 Javascript 런타임의 경우에 <strong>this는 항상 window라는 전역 객체를 참조</strong>한다.</li>
<li>전역 객체란 <strong>전역 범위에 항상 존재하는 객체를 의미</strong>한다. (Node.js에서 전역 객체는 global)</li>
<li>브라우저라는 Javascript 런타임에서 <strong>모든 변수, 함수는 window라는 객체의 프로퍼티와 메소드</strong>이다.
<img src="https://velog.velcdn.com/images/hj_ki/post/618b475f-f5a7-4958-9584-2929a338440f/image.png" alt=""></li>
</ul>
<h3 id="❗️this를-함수-내부에서-사용한-경우">❗️this를 함수 내부에서 사용한 경우</h3>
<ul>
<li>함수는 <strong>전역에 선언된 일반 함수</strong>와 <strong>객체 안에 메소드</strong>로 크게 구분할 수 있다.</li>
<li>객체안에 선언된 함수를 전역에 선언된 함수와 구분하기 위해 <strong>메소드</strong>라고 한다.</li>
<li>그런데 <strong>전역에 선언된 일반 함수도 결국 window 전역 객체의 메소드</strong>다.</li>
<li><strong>즉, 모든 함수는 객체 내부에 있다.</strong></li>
<li>이때 this는 <strong>현재 함수를 실행하고 있는 그 객체를 참조</strong>한다.</li>
<li>정리하면 <strong>함수 내부에서 this의 값은 함수를 호출하는 방법에 의해 바뀐다.</strong></li>
<li>그리고 또한 <strong>엄격 모드 여부에 따라 참조 값이 달라진다.</strong></li>
<li><strong>엄격 모드에서 일반 함수 내부의 this는 undefinded 가 바인딩 된다.</strong></li>
</ul>
<h3 id="⚡️-this의-사용">⚡️ this의 사용</h3>
<h4 id="❗️전역에-선언된-함수에서-this">❗️전역에 선언된 함수에서 this</h4>
<pre>
function myFn () {
    return this;
}

myFn(); // window 객체 출력
</pre>

<hr>
<ul>
<li><strong>new 연산자를 사용해서 생성자 함수방식으로 인스턴스를 생성한 경우</strong></li>
<li><strong>생성자 함수 MyFn가 빈 객체를 만들고 이 생성자 함수에서 this가 이 빈 객체를 가리키도록 설정</strong><pre>
function MyFn() {
this.title = 'Hello World!';
return this;
}
// new 연산자를 이용해서 새로운 객체를 얻는다.
const myfn = new MyFn();
myfn // MyFn {title: 'Hello World!'}
</pre>

</li>
</ul>
<h4 id="❗️객체의-메소드-함수에서-this">❗️객체의 메소드 함수에서 this</h4>
<ul>
<li><p><strong>method → obj 인 경우이다.</strong></p>
</li>
<li><p><strong>showTitle() 메소드는 fn 객체의 메소드이기 때문에 this는 fn 객체를 참조</strong></p>
<pre>
const fn = {
title: 'Hello World!',
showTitle() {
  console.log(this.title);
}
};
fn.showTitle(); // 'Hello World!'
</pre>
</li>
<li><p><strong>고차 함수의 콜백함수 안에서 this는 콜백함수가 일반 함수이기 때문에 전역 객체를 참조</strong></p>
<pre>
const fn = {
title: 'Hello World!',
tags: [1, 2, 3, 4],
showTags() {
  this.tags.forEach(function(tag) {
    console.log(tag);
    console.log(this); // window
  });
}
}
fn.showTags();
// 1
// window 객체 출력
// 2
// window 객체 출력
// 3
// window 객체 출력
// 4
// window 객체 출력
</pre>
</li>
<li><p><strong>콜백함수 다음 인자로 참조할 객체를 전달</strong></p>
<pre>
const fn = {
title: 'Hello World!',
tags: [1, 2, 3, 4],
showTags() {
  this.tags.forEach(function(tag) {
    console.log(tag);
    console.log(this); // fn
  }, this); // 여기는 일반 함수 바깥, fn 객체를 참조할 수 있다.
}
}
fn.showTags();
// 1
// fn 객체 출력
// 2
// fn 객체 출력
// 3
// fn 객체 출력
// 4
// fn 객체 출력
</pre>
</li>
<li><p>function 키워드로 생성한 <strong>일반함수</strong>와 <strong>화살표 함수</strong>의 <strong>가장 큰 차이점</strong>이 바로 <strong>this</strong>이다.</p>
</li>
<li><p>이를 Lexical this(렉시컬 this) 라고 한다.</p>
</li>
<li><p>화살표 함수 안에서 this는 언제나 상위 스코프의 this를 가리킨다.</p>
</li>
<li><p>일반 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정되지 않고, 함수를 호출 할 때 함수가 어떻게 호출 되는지에 따라 this에 바인딩할 객체가 동적으로 결정된다.</p>
</li>
<li><p>화살표 함수는 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정된다.</p>
</li>
<li><p>화살표 함수의 this 바인딩 객체 결정 방식은 함수의 상위 스코프를 결정하는 방식인 렉시컬 스코프와 유사하다.</p>
</li>
<li><p>화살표 함수는 call, apply, bind 메소드를 사용하여 this를 변경할 수 없다.</p>
</li>
</ul>
<pre>
const fn = {
  title: 'Hello World!',
  tags: [1, 2, 3, 4],
  showTags() {
    this.tags.forEach((tag) => {
      console.log(tag);
      console.log(this); // fn
    });
  }
}
fn.showTags();
// 1
// fn 객체 출력
// 2
// fn 객체 출력
// 3
// fn 객체 출력
// 4
// fn 객체 출력
</pre>


<h3 id="⚡️-결론">⚡️ 결론</h3>
<ul>
<li>this는 이처럼 어떤 위치에 있느냐, 어디에서 호출하느냐, 어떤 함수에 있느냐에 따라
참조 값이 달라지는 특성이 있다.</li>
<li>그래서 사용할 때 주의해야 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[항해99 2조 미니프로젝트 #1]]></title>
            <link>https://velog.io/@hj_ki/2mini</link>
            <guid>https://velog.io/@hj_ki/2mini</guid>
            <pubDate>Mon, 09 May 2022 05:46:36 GMT</pubDate>
            <description><![CDATA[<p>5.9 ~ 5.13</p>
<h3 id="1-프로젝트-제목">1) 프로젝트 제목</h3>
<p>너의 영화는 ?</p>
<h3 id="2-소개">2) 소개</h3>
<p>내가 봤던 영화를 올리고 리뷰를 작성해본다.
카테고리로 구분된 장르를 확인하고 관심있는 장르의 영화를 찾아본다.
여러 사람들의 리뷰, 전체 평점 순위를 참고한다.</p>
<hr>
<h3 id="3-와이어-프레임">3) 와이어 프레임</h3>
<ol>
<li><p>main 페이지
<img src="https://velog.velcdn.com/images/hj_ki/post/e68d392b-a0b5-436a-ba0e-035948e78734/image.png" alt=""></p>
</li>
<li><p>회원가입 페이지
<img src="https://velog.velcdn.com/images/hj_ki/post/356be180-0e8a-47ef-9b89-474124f92491/image.png" alt=""></p>
</li>
<li><p>로그인 페이지
<img src="https://velog.velcdn.com/images/hj_ki/post/bf587af4-75f7-4bb2-bd19-b160ee32d12a/image.png" alt=""></p>
</li>
<li><p>포스터 페이지
<img src="https://velog.velcdn.com/images/hj_ki/post/0d7fb158-0621-41db-b4d6-8255961b2b41/image.png" alt=""></p>
</li>
</ol>
<hr>
<h3 id="4-개발해야-하는-기능들">4) 개발해야 하는 기능들</h3>
<h4 id="1-main-페이지">1. main 페이지</h4>
<ul>
<li>DB (GET) (/main) (url) (전체 리스트)</li>
<li>카테고리 네비게이션 ( 해당 장르의 포스터만 모아서 보여준다 )</li>
<li>로그인 버튼 및 회원가입 버튼</li>
<li>url 입력란 ( 회원과 비회원을 구분하여 활성화하기, 포스터 등록 )</li>
<li>생성된 포스터 버튼 ( 리뷰 등록 페이지 열기 )</li>
<li>현재 평점 순위 ( movies[&#39;rank&#39;] get )</li>
<li>(장르별 조회) (GET) (/main/genre) (genre)<h4 id="2-회원가입-페이지-post--회원정보를-입력-db에-등록-">2. 회원가입 페이지 [POST] ( 회원정보를 입력, DB에 등록 )</h4>
</li>
<li>(아이디중복확인) (POST) (/signup/check) (id, pw) 
(사용가능 메시지 + 회원가입 확인 버튼 활성화)</li>
<li>DB (POST) (/signup) </li>
<li>완료 시 (가입 완료 메시지)</li>
</ul>
<h4 id="3-로그인-페이지-get--db내용과-입력값을-비교하여-main-페이지로-이동한다-텍스트">3. 로그인 페이지 [GET] ( db내용과 입력값을 비교하여 main 페이지로 이동한다 )<strong>텍스트</strong></h4>
<ul>
<li>DB POST (POST) (/login)</li>
<li>완료 시 (로그인 완료 메시지)</li>
</ul>
<h4 id="4-포스터-페이지">4. 포스터 페이지</h4>
<ul>
<li>DB (POST) (/detail/review) (comment) ()</li>
</ul>
<hr>
<ul>
<li>public github repo 주소 : <a href="https://github.com/gaius365/hh99_mini1">https://github.com/gaius365/hh99_mini1</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[5주차 웹 개발]]></title>
            <link>https://velog.io/@hj_ki/web5</link>
            <guid>https://velog.io/@hj_ki/web5</guid>
            <pubDate>Mon, 25 Apr 2022 21:18:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hj_ki/post/f77f9b99-4cc0-4ee5-beeb-ea8ead5f117b/image.png" alt=""></p>
<h2 id="filezilla-설치--가비아-가입하기--도메인-구입"><strong>Filezilla 설치 &amp; 가비아 가입하기 + 도메인 구입</strong></h2>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/bc742287-8b1a-484b-a897-6cee8b173b22/image.png" alt=""></p>
<ul>
<li>다운로드 클릭 후 가장 기본 버전 다운로드!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/2fe6593c-fc80-4da0-bdc1-7d112f9af0ff/image.png" alt=""></p>
<ul>
<li>가비아에서 할인이벤트(500원/1년)를 진행하는 도메인을 구매해서 진행
<img src="https://velog.velcdn.com/images/hj_ki/post/664346fe-ef67-4f50-b2ab-903a41590095/image.png" alt=""></li>
</ul>
<hr>
<h1 id="1-프로젝트-세팅"><strong>1) 프로젝트 세팅</strong></h1>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/e4156e8b-8365-4f39-93a2-98c5f5159115/image.png" alt="">
<strong>bucket 폴더 안에 static, templates, app.py 만들기!</strong></p>
<ul>
<li>패키지 설치 : <strong>flask</strong>, <strong>pymongo</strong>, <strong>dnspython</strong></li>
</ul>
<h3 id="뼈대-준비">뼈대 준비</h3>
<p><strong>index.html</strong>, <strong>app.py</strong> 준비하기</p>
<h3 id="indexhtml">index.html</h3>
<ul>
<li>버킷리스트 페이지</li>
</ul>
<h3 id="apppy">app.py</h3>
<ul>
<li>DB, 프레임워크 패키지 임포트</li>
<li><strong>POST</strong>, GET 세팅</li>
</ul>
<h3 id="mongodb-atlas"><strong>mongoDB Atlas</strong></h3>
<p>POST, GET을 이용하기 전 DB 준비</p>
<hr>
<h1 id="2-post-기록"><strong>2) POST (기록)</strong></h1>
<ol>
<li>요청 정보 :  URL= <code>/bucket</code>, 요청 방식 = <code>POST</code></li>
</ol>
<ol start="2">
<li><p>클라(ajax) → 서버(flask) : <code>bucket</code></p>
</li>
<li><p>서버(flask) → 클라(ajax) : 메시지를 보냄 (기록 완료!)</p>
</li>
</ol>
<p>단! 서버에서 한 가지 일을 더 한다.
→ <strong>번호를 만들어 함께 넣어주는 것</strong>. <strong>그래야 업데이트가 가능!</strong></p>
</aside>

<hr>
<h2 id="클라이언트와-서버-연결-확인"><strong>클라이언트와 서버 연결 확인</strong></h2>
<h4 id="서버-코드-apppy"><strong>서버 코드</strong> app.py</h4>
<pre><code class="language-python">@app.route(&quot;/bucket&quot;, methods=[&quot;POST&quot;])
def bucket_post():
    sample_receive = request.form[&#39;sample_give&#39;]
    print(sample_receive)
    return jsonify({&#39;msg&#39;: &#39;POST(기록) 연결 완료!&#39;})</code></pre>
<hr>
<h4 id="클라이언트-코드-indexhtml"><strong>클라이언트 코드 index.html</strong></h4>
<pre><code class="language-jsx">function save_bucket(){
    $.ajax({
        type: &quot;POST&quot;,
        url: &quot;/bucket&quot;,
        data: {sample_give:&#39;데이터전송&#39;},
        success: function (response) {
            alert(response[&quot;msg&quot;])
        }
    });
}

&lt;button onclick=&quot;save_bucket()&quot; type=&quot;button&quot; class=&quot;btn btn-outline-primary&quot;&gt;기록하기&lt;/button&gt;</code></pre>
<hr>
<h2 id="서버부터-만들기--bucket-정보를-받아서-저장-">서버부터 만들기 ( bucket 정보를 받아서 저장 )</h2>
<ul>
<li><strong>버킷 번호와 완료여부를 함께 넣어줄 것 !!</strong></li>
</ul>
<pre><code class="language-jsx">count = list(db.bucket.find({},{&#39;_id&#39;:False}))
num = len(count) + 1

vs

count = db.bucket.find({},{&#39;_id&#39;:False}).count()
num = count + 1</code></pre>
<pre><code class="language-python">@app.route(&quot;/bucket&quot;, methods=[&quot;POST&quot;])
def bucket_post():
    bucket_receive = request.form[&quot;bucket_give&quot;]

    count = db.bucket.find({},{&#39;_id&#39;:False}).count()
    num = count + 1

    doc = {
        &#39;num&#39;:num,
        &#39;bucket&#39;: bucket_receive,
        &#39;done&#39;:0
    }

    db.bucket.insert_one(doc)
    return jsonify({&#39;msg&#39;:&#39;등록 완료!&#39;})</code></pre>
<hr>
<h2 id="클라이언트-만들기--bucket-정보만-보내주기-"><strong>클라이언트 만들기 ( bucket 정보만 보내주기 )</strong></h2>
<pre><code class="language-jsx">function save_bucket(){
    let bucket = $(&#39;#bucket&#39;).val()
    $.ajax({
        type: &quot;POST&quot;,
        url: &quot;/bucket&quot;,
        data: {bucket_give:bucket},
        success: function (response) {
            alert(response[&quot;msg&quot;])
            window.location.reload()
        }
    });
}</code></pre>
<hr>
<h2 id="완성-확인하기-">*<em>완성 확인하기 *</em></h2>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/821b132d-c2b4-4dc7-8695-14d5d48c1311/image.png" alt=""></p>
<hr>
<h1 id="3-get-보여주기"><strong>3) GET (보여주기)</strong></h1>
<ol>
<li><p>요청 정보 :  URL= <code>/bucket</code>, 요청 방식 = <code>GET</code></p>
</li>
<li><p>클라(ajax) → 서버(flask) : (없음)</p>
</li>
<li><p>서버(flask) → 클라(ajax) : 전체 버킷리스트를 보여주기</p>
</li>
</ol>
<hr>
<h2 id="클라이언트와-서버-연결-확인하기"><strong>클라이언트와 서버 연결 확인하기</strong></h2>
<h4 id="서버-코드-apppy-1"><strong>서버 코드 app.py</strong></h4>
<pre><code class="language-python">@app.route(&quot;/bucket&quot;, methods=[&quot;GET&quot;])
def bucket_get():
    return jsonify({&#39;msg&#39;: &#39;GET 연결 완료!&#39;})</code></pre>
<hr>
<h4 id="클라이언트-코드-indexhtml-1"><strong>클라이언트 코드 index.html</strong></h4>
<pre><code class="language-jsx">$(document).ready(function () {
    show_bucket();
});
function show_bucket(){
    $.ajax({
        type: &quot;GET&quot;,
        url: &quot;/bucket&quot;,
        data: {},
        success: function (response) {
            alert(response[&quot;msg&quot;])
        }
    });
}</code></pre>
<hr>
<h2 id="서버부터-만들기--받을-것-없이">서버부터 만들기 ( 받을 것 없이</h2>
<h2 id="buckets에-주문정보-담아서-내려주기-">buckets에 주문정보 담아서 내려주기 )</h2>
<pre><code class="language-python">@app.route(&quot;/bucket&quot;, methods=[&quot;GET&quot;])
def bucket_get():
    buckets_list = list(db.bucket.find({},{&#39;_id&#39;:False}))
    return jsonify({&#39;buckets&#39;:buckets_list})</code></pre>
<hr>
<h2 id="클라이언트-만들기--응답을-잘받아서-for-문으로-붙여주기-"><strong>클라이언트 만들기 ( 응답을 잘받아서 for 문으로 붙여주기 )</strong></h2>
<pre><code class="language-jsx">function show_bucket(){
    $(&#39;#bucket-list&#39;).empty()
    $.ajax({
        type: &quot;GET&quot;,
        url: &quot;/bucket&quot;,
        data: {},
        success: function (response) {
            let rows = response[&#39;buckets&#39;]
            for (let i = 0; i &lt; rows.length; i++) {
                let bucket = rows[i][&#39;bucket&#39;]
                let num = rows[i][&#39;num&#39;]
                let done = rows[i][&#39;done&#39;]

                let temp_html = ``
                if (done == 0) {
                    temp_html = `&lt;li&gt;
                                    &lt;h2&gt;✅ ${bucket}&lt;/h2&gt;
                                    &lt;button onclick=&quot;done_bucket(${num})&quot; type=&quot;button&quot; class=&quot;btn btn-outline-primary&quot;&gt;완료!&lt;/button&gt;
                                &lt;/li&gt;`
                } else {
                    temp_html = `&lt;li&gt;
                                    &lt;h2 class=&quot;done&quot;&gt;✅ ${bucket}&lt;/h2&gt;
                                &lt;/li&gt;`
                }
                $(&#39;#bucket-list&#39;).append(temp_html)
            }
        }
    });
}</code></pre>
<hr>
<h2 id="완성-확인하기"><strong>완성 확인하기</strong></h2>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/e7df89a1-0e89-426c-9408-5dd3f4086d96/image.png" alt=""></p>
<hr>
<h1 id="4-post--완료하기-"><strong>4) POST ( 완료하기 )</strong></h1>
<ol>
<li><p>요청 정보 :  URL= <code>/bucket/done</code>, 요청 방식 = <code>POST</code></p>
</li>
<li><p>클라(ajax) → 서버(flask) : <code>num</code> (버킷 넘버)</p>
</li>
<li><p>서버(flask) → 클라(ajax) : 메시지를 보냄 (버킷 완료!)</p>
</li>
</ol>
<hr>
<h2 id="클라이언트와-서버-연결-확인하기-1"><strong>클라이언트와 서버 연결 확인하기</strong></h2>
<h4 id="서버-코드-apppy텍스트">서버 코드 app.py<strong>텍스트</strong></h4>
<pre><code class="language-python">@app.route(&quot;/bucket/done&quot;, methods=[&quot;POST&quot;])
def bucket_done():
    sample_receive = request.form[&#39;sample_give&#39;]
    print(sample_receive)
    return jsonify({&#39;msg&#39;: &#39;POST(완료) 연결 완료!&#39;})</code></pre>
<hr>
<h4 id="클라이언트-코드-indexhtml-2"><strong>클라이언트 코드 index.html</strong></h4>
<pre><code class="language-jsx">function done_bucket(num){
    $.ajax({
        type: &quot;POST&quot;,
        url: &quot;/bucket/done&quot;,
        data: {sameple_give:&#39;데이터전송&#39;},
        success: function (response) {
            alert(response[&quot;msg&quot;])
        }
    });
}

&lt;button onclick=&quot;done_bucket(5)&quot; type=&quot;button&quot; class=&quot;btn btn-outline-primary&quot;&gt;완료!&lt;/button&gt;</code></pre>
<hr>
<h2 id="서버부터-만들기">서버부터 만들기</h2>
<ul>
<li><strong>버킷 번호를 받아서, 업데이트 할 것</strong></li>
<li><strong>num_receive는 문자열로 들어오기 때문에 숫자로 바꿔줄 것 !! ( int )</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/289d590e-915c-46a8-920a-c0ec43e26683/image.png" alt=""></p>
<pre><code class="language-python">@app.route(&quot;/bucket/done&quot;, methods=[&quot;POST&quot;])
def bucket_done():
    num_receive = request.form[&quot;num_give&quot;]
    db.bucket.update_one({&#39;num&#39;: int(num_receive)}, {&#39;$set&#39;: {&#39;done&#39;: 1}})
    return jsonify({&#39;msg&#39;: &#39;버킷 완료!&#39;})</code></pre>
<hr>
<h2 id="클라이언트-만들기--버킷-넘버를-보여주기-"><strong>클라이언트 만들기 ( 버킷 넘버를 보여주기 )</strong></h2>
<pre><code class="language-jsx">function done_bucket(num){
    $.ajax({
        type: &quot;POST&quot;,
        url: &quot;/bucket/done&quot;,
        data: {&#39;num_give&#39;:num},
        success: function (response) {
            alert(response[&quot;msg&quot;])
            window.location.reload()
        }
    });
}</code></pre>
<hr>
<h2 id="완성-확인하기--선-그어진-것-"><strong>완성 확인하기 ( 선 그어진 것 )</strong></h2>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/2f61e56e-454a-4058-b5ad-0112c7409c84/image.png" alt=""></p>
<h1 id="5-내-프로젝트를-서버에-올리기"><strong>5) 내 프로젝트를 서버에 올리기</strong></h1>
<h3 id="웹-서비스-런칭"><strong>웹 서비스 런칭</strong></h3>
<ul>
<li>웹 서비스를 런칭하기 위해 클라이언트의 요청에 항상 응답해줄 수 있는 서버에 
프로젝트를 실행시켜줘야 한다.</li>
</ul>
<h3 id="항상-요청에-응답하려면"><strong>항상 요청에 응답하려면</strong></h3>
<ul>
<li>컴퓨터가 항상 켜져있고 프로그램이 실행되어 있어야하고,</li>
<li>모두가 접근할 수 있는 공개 주소인 공개 IP 주소(Public Address)로
나의 웹 서비스에 접근할 수 있도록 해야한다.</li>
<li>서버는 그냥 컴퓨터이다. </li>
<li>외부 접속이 가능하게 설정한다면 내 컴퓨터를 서버로 사용할 수도 있다.</li>
<li>AWS라는 <strong>클라우드 서비스</strong>에서 편하게 서버를 관리하기 위해서
항상 켜 놓을 수 있는 컴퓨터인 EC2 사용권을 구입해 서버로 사용한다.</li>
</ul>
<hr>
<h1 id="6-aws-서버-구매하기"><strong>6) AWS 서버 구매하기</strong></h1>
<h2 id="awe-ec2-서버-사기"><strong>AWE EC2 서버 사기</strong></h2>
<ul>
<li>클릭 만으로 내가 원하는 서버(컴퓨터)의 설정을 정하고, 거기에 컴퓨터를 실행시키기 위해
운영체제(OS)를 설치한다.</li>
<li>OS는 리눅스의 Ubuntu를 설치한다.</li>
<li>윈도우와 같이, OS는 여러개 존재한다.</li>
<li>리눅스도 그 중의 하나, 오픈소스로 발전되는 OS이다.</li>
</ul>
<hr>
<ul>
<li><strong>Ubuntu Server 18.04 또는 20.04 버전을 구매한다.</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/7f82c4cb-28fb-442d-a339-038f8000edf7/image.png" alt=""></p>
<hr>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/05b8c1b8-666f-48e2-a908-559f6961362f/image.png" alt=""></p>
<hr>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/0c3476b3-bff4-4a53-8bcb-ca574b4e9981/image.png" alt=""></p>
<hr>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/a9f73e78-1ff2-4c64-8c09-abac6c2ba482/image.png" alt=""></p>
<hr>
<h2 id="ec2-서버-종료하는-방법-1년-후-자동결제-방지-"><strong>EC2 서버 종료하는 방법( 1년 후 자동결제 방지! )</strong></h2>
<p><strong>대상 인스턴스에 마우스 우클릭 후 인스턴스 상태를 &#39;중지&#39; 또는 &#39;종료&#39; 할 것</strong></p>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/360b21f5-3dcd-4ed6-9b74-1ca1f9510616/image.png" alt=""></p>
<hr>
<h2 id="ec2-접속하기-aws-ec2"><strong>EC2 접속하기 (AWS EC2)</strong></h2>
<h3 id="sshsecure-shell-protocol"><strong>SSH(Secure Shell Protocol)</strong></h3>
<ul>
<li>다른 컴퓨터에 접속할 때 쓰는 프로그램이다.</li>
<li>다른 것들 보다 보안이 상대적으로 뛰어나다.</li>
<li>접속할 컴퓨터가 22번 포트가 열려있어야 접속이 가능하다.
AWS E22의 경우, 이미 22번 포트가 열려있다. (확인)
<img src="https://velog.velcdn.com/images/hj_ki/post/0dc4b614-9780-4703-8722-a53be31ff4bb/image.png" alt=""></li>
</ul>
<hr>
<h3 id="aws-ec2에-접속하기"><strong>AWS EC2에 접속하기</strong></h3>
<ul>
<li>Mac OS : Mac은 ssh가 있어서, 명령어로 바로 접근 가능!</li>
<li>Windows : ssh가 없으므로, <strong>gib bash</strong>라는 프로그램을 이용!</li>
</ul>
<p><strong>git bash를 실행하고, 아래를 입력한다</strong>!</p>
<pre><code class="language-bash">ssh -i 받은키페어를끌어다놓기 ubuntu@AWS에적힌내아이피</code></pre>
<pre><code class="language-bash">ssh -i /path/my-key-pair.pem ubuntu@13.125.250.20</code></pre>
<ul>
<li>Key fingerprint 관련 메세지가 나올 경우 Yes를 입력</li>
<li>gib bash를 종료할 때는 exit 명령어를 입력하여 ssh 접속을 먼저 끊을 것</li>
</ul>
<hr>
<h3 id="간단한-리눅스-명령어-연습하기"><strong>간단한 리눅스 명령어 연습하기</strong></h3>
<ul>
<li><p>리눅스는 윈도우 같지 않아서, 
&#39;<strong>쉘 명령어</strong>&#39;를 통해 OS를 조작한다 ( 마우스 역할 )</p>
</li>
<li><p><strong>가장 많이 쓰는 몇 가지 명령어</strong></p>
<pre><code class="language-bash">ls: 내 위치의 모든 파일을 보여준다.
</code></pre>
</li>
</ul>
<p>pwd: 내 위치(폴더의 경로)를 알려준다.</p>
<p>mkdir: 내 위치 아래에 폴더를 하나 만든다.</p>
<p>cd [갈 곳]: 나를 [갈 곳] 폴더로 이동시킨다.</p>
<p>cd .. : 나를 상위 폴더로 이동시킨다.</p>
<p>cp -r [복사할 것] [붙여넣기 할 것]: 복사 붙여넣기</p>
<p>rm -rf [지울 것]: 지우기</p>
<p>sudo [실행 할 명령어]: 명령어를 관리자 권한으로 실행한다.
sudo su: 관리가 권한으로 들어간다. (나올때는 exit으로 나옴)</p>
<pre><code>
---

# **7) 서버 세팅하기**

**서버 환경 통일하기 ( 구매한 컴퓨터 세팅 )**

## **EC2 한번에 세팅하기**

```jsx
# python3 -&gt; python
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10

# pip3 -&gt; pip
sudo apt-get update
sudo apt-get install -y python3-pip
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1

# port forwarding
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000</code></pre><hr>
<h2 id="filezilla를-이용해서-간단한-python-파일-올려보기"><strong>filezilla를 이용해서, 간단한 python 파일 올려보기</strong></h2>
<ul>
<li><p><strong>서버에 업로드 할 간단한 파일을 작성</strong></p>
</li>
<li><p><strong>파일질라 실행, 다음과 같이 설정</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/a5c7b627-7719-4f67-b989-7b0c427822db/image.png" alt=""></p>
</li>
</ul>
<hr>
<ul>
<li><strong>정보들을 입력하고, ok 누르면 서버의 파일들을 볼 수 있다
(Host : 내 EC2 서버의 ip // User: ubuntu로 입력)</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/212e17d9-c401-4187-9fb9-6fabef06db2b/image.png" alt=""></p>
<hr>
<ul>
<li><strong>마우스로 드래그 해서 파일을 업로드/다운로드하면 된다!
왼쪽이 내 컴퓨터 vs 오른쪽이 내가 방금 산 컴퓨터</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/baa7e680-6aa3-4c34-8dc6-a0fc5abeb534/image.png" alt=""></li>
</ul>
<hr>
<h1 id="8-파이썬-파일-실행해보기"><strong>8) 파이썬 파일 실행해보기</strong></h1>
<h4 id="python-testpy"><strong>python test.py</strong></h4>
<h2 id="서버-환경-세팅"><strong>서버 환경 세팅</strong></h2>
<p><strong>1) 파이썬(python3 -&gt; python)</strong></p>
<ul>
<li>python3 명령어를 python으로 사용할 수 있게 하는 명령어</li>
</ul>
<p>*<em>2) pip(pip3 -&gt; pip)
*</em></p>
<ul>
<li><p>pip3 설치
sudo apt-get update
sudo apt-get install -y python3-pip</p>
</li>
<li><p>pip3 명령어를 pip으로 사용할 수 있게 하는 명령어
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1</p>
</li>
<li><p>한 줄 씩 복사 붙여넣기!</p>
</li>
</ul>
<p><strong>3) 포트포워딩(80포트 -&gt; 5000포트)</strong></p>
<ul>
<li><strong>80포트</strong>로 들어오는 요청을 <strong>5000포트</strong>로 넘겨주는 명령어
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1</li>
</ul>
<hr>
<h2 id="flask-서버-실행"><strong>Flask 서버 실행</strong></h2>
<p><strong>1) 팬명록 완성본을 filezilla로 EC2에 업로드 하기</strong></p>
<ul>
<li><p>파일질라에서 homework 폴더 째로 드래그 드롭으로 EC2 인스턴스의 home/ubuntu 폴더에 업로드</p>
</li>
<li><p>실행 - python app.py</p>
</li>
</ul>
<p><strong>2) pip로 패키지 설치</strong></p>
<ul>
<li>pip install flask</li>
</ul>
<p><strong>3) 그 외 패키지들 설치</strong></p>
<ul>
<li>pip install pymongo dnspython</li>
</ul>
<p><strong>4) 다시 flask 서버 실행</strong></p>
<ul>
<li>아래 명령어로 flask 서버 실행</li>
<li><em>python app.py*</em></li>
</ul>
<p>서버 실행이 되면, 크롬에서 접속해보기</p>
<ul>
<li>크롬 브라우저 창에 입력 - http://내 EC2 IP : 5000/</li>
<li>아직 작동하지 않는다 ( AWS에서 5000포트를 열어줘야 함 )</li>
</ul>
<p><strong>5) AWS에서 5000포트를 열어주기</strong></p>
<ul>
<li><p>EC2서버( 가상의 내 컴퓨터 )에서 포트를 따로 설정하는 것 외에도, 
AWS EC2에서도 자체적으로 포트를 열고/닫을 수 있게 관리를 하고 있다.</p>
</li>
<li><p>-&gt; 그래서 AWS EC2 Security Group에서 인바운드 요청 포트를 열어줘야 한다.</p>
</li>
<li><p>EC2 관리 콘솔로 들어간다. 그리고 보안그룹( 영문:Security Group )을 눌러 들어간다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/41b62419-2475-48a4-ae6c-9008122e68dc/image.png" alt=""></p>
<hr>
<ul>
<li>해당 보안그룹을 클릭</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/c20660ae-4235-4f27-ae40-b42875dbf56d/image.png" alt=""></p>
<hr>
<ul>
<li>Edit inbound rules를 선택</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/59f4a6f7-9c6c-48a7-8a89-1a71a779b633/image.png" alt=""></p>
<hr>
<ul>
<li>두 가지 포트를 추가 / Anywhere-IPv4를 클릭</li>
<li>80포트 : HTTP 접속을 위한 기본포트</li>
<li>5000포트 : flask 기본포트</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/ec671368-67f0-41d0-b818-e9f00f418a26/image.png" alt=""></p>
<hr>
<h4 id="6-포트-번호-없애기--기본-개념-"><strong>6) 포트 번호 없애기 ( 기본 개념 )</strong></h4>
<ul>
<li>현재 5000포트에서 웹 서비스가 실행되고 있다. 그래서 매번 :5000 이라고 뒤에 붙여줘야 한다.</li>
<li>http 요청에서는 80포트가 기본이기 때문에, 굳이 :80을 붙이지 않아도 자동 연결이 된다.</li>
<li>포트 번호를 입력하지 않아도 자동으로 접속되기 위해, 우리는 80포트로 오는 요청을 5000 포트로  전달하게 하는 포트포워딩(port forwarding) 을 사용 </li>
<li>리눅스에서 기본으로 제공해주는 포트포워딩을 사용</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/1440ef50-1ae6-48aa-87cf-a9617a29286d/image.png" alt=""></p>
<hr>
<h4 id="7-다시-접속해보기"><strong>7) 다시 접속해보기</strong></h4>
<ul>
<li>http://내아이피</li>
<li>이제 app.py파일을 수정하고, 다듬어서 올리면 된다</li>
</ul>
<hr>
<h2 id="nohup-설정하기"><strong>nohup 설정하기</strong></h2>
<p><strong>SSH 접속을 끊어도 서버가 계속 돌게 하기!</strong></p>
<ul>
<li><p>현재 상황
Git bash 또는 맥의 터미널을 종료하면 (=즉, SSH 접속을 끊으면) 프로세스가 종료되면서, 
서버가 돌아가지 않고 있다.</p>
</li>
<li><p>원격 접속을 종료하더라도 서버가 계속 돌아가게 하기</p>
</li>
<li><p><em>nohup python app.py &amp;*</em></p>
</li>
<li><p>서버 종료하기 ( 강제종료하는 방법 )</p>
</li>
<li><p><em>ps -ef | grep &#39;python app.py&#39; | awk &#39;{print $2}&#39; | xargs kill*</em></p>
</li>
</ul>
<hr>
<h1 id="9-도메인-구입--연결-">*<em>9) 도메인 구입 / 연결 *</em></h1>
<h4 id="도메인-구입--연결"><strong>도메인 구입 / 연결</strong></h4>
<p>도메인을 구매한다는 것은, 네임서버를 운영해주는 업체에, IP와 도메인 매칭유지비를 내는 것
한국 또는 글로벌 업체 어디든 상관 없지만, 우리는 한국의 &#39;가비아&#39;라는 회사에서 구입해본다.</p>
<hr>
<h4 id="dns-설정-클릭"><strong>DNS 설정 클릭</strong></h4>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/170d47a4-805f-422c-8ee9-613d33984c00/image.png" alt=""></p>
<hr>
<h4 id="호스트-이름에--ip주소에-ip주소를-입력"><strong>호스트 이름에 @, IP주소에 IP주소를 입력</strong></h4>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/b00abed1-7341-4470-bf07-9cf9367a37c0/image.png" alt=""></p>
<hr>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/93a7009e-beb1-411c-94be-e444becc506f/image.png" alt=""></p>
<hr>
<h4 id="ip주소로-접근해보기"><strong>IP주소로 접근해보기</strong></h4>
<p><strong>http://내AWS아이피/</strong> ---&gt;** http://내도메인/**</p>
<hr>
<h1 id="10-og태그"><strong>10) og태그</strong></h1>
<h4 id="og-태그-만들기"><strong>og 태그 만들기</strong></h4>
<p><strong>og:image</strong>, <strong>og:title</strong>, <strong>og:description</strong> 
<img src="https://velog.velcdn.com/images/hj_ki/post/fb22e2fe-32e6-4a28-a95b-e42c87f338ed/image.png" alt=""></p>
<ul>
<li>static 폴더 아래에 이미지 파일을 넣고, 
각자 프로젝트 HTML의 <strong>head&gt;~/head&gt;</strong> 사이에 아래 내용을 작성하면 
og 태그를 개인 프로젝트에 사용할 수 있다.</li>
</ul>
<p><strong>meta property=&quot;og:title&quot; content=&quot;내 사이트의 제목&quot; /&gt;
meta property=&quot;og:description&quot; content=&quot;보고 있는 페이지의 내용 요약&quot; /&gt;
meta property=&quot;og:image&quot; content=&quot;이미지URL&quot; /&gt;</strong></p>
<hr>
<ul>
<li><p><strong>참고</strong>
이미지를 바꿨는데 이전 ogimage가 그대로 나오는 것은
페이스북 / 카카오톡 등에서 처음 것을 한동안 저장해놓기 때문이다.</p>
</li>
<li><p>페이스북 og 태그 초기화 하기 : <a href="https://developers.facebook.com/tools/debug/">https://developers.facebook.com/tools/debug/</a></p>
</li>
<li><p>카카오톡 og 태그 초기화 하기 : <a href="https://developers.kakao.com/tool/clear/og">https://developers.kakao.com/tool/clear/og</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[4주차 웹 개발]]></title>
            <link>https://velog.io/@hj_ki/web4</link>
            <guid>https://velog.io/@hj_ki/web4</guid>
            <pubDate>Wed, 20 Apr 2022 22:39:08 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hj_ki/post/8826549a-b363-4327-bcc2-d2259f92a4b8/image.png" alt=""></p>
<h1 id="1-flask">1) Flask</h1>
<p>projects 폴더 아래에, 다섯개 만들고 시작</p>
<h3 id="flask-시작하기---서버만들기">Flask 시작하기 - 서버만들기</h3>
<p><strong>1) new project → prac 폴더를 선택하고 
 create 를 클릭</strong>
 <img src="https://velog.velcdn.com/images/hj_ki/post/91899b44-811c-4f84-8d0e-4837650ba4f8/image.png" alt=""></p>
<p><strong>2) Flask 패키지 설치하고 시작!</strong>
패키지 설치 화면 진입하기
윈도우 : 좌상단File → setting → Python interpreter
맥 : 좌상단Pycharm → Preference → Python Interpreter</p>
<p><strong>flask로 검색한 후, Install package 클릭</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/b318008f-03c5-4b87-983a-a2a94c270b4d/image.png" alt=""></p>
<h3 id="1-flask-프레임워크">1) Flask 프레임워크</h3>
<p>서버를 구동시켜주는 편한 코드 모음. 
서버를 구동하려면 필요한 복잡한 일들을 쉽게 가져다 쓸 수 있다.</p>
<ul>
<li>app.py 파일을 만들어 아래 코드를 붙여본다.</li>
<li>파일 이름은 아무렇게나 해도 상관없지만, 
통상적으로 flask 서버를 돌리는 파일은 app.py라고 이름 짓는다!</li>
</ul>
<p>from flask import Flask
app = Flask(<strong>name</strong>)</p>
<p>@app.route(&#39;/&#39;)
def home():
   return &#39;This is Home!&#39;</p>
<p>if <strong>name</strong> == &#39;<strong>main</strong>&#39;:<br>   app.run(&#39;0.0.0.0&#39;,port=5000,debug=True)
<img src="https://velog.velcdn.com/images/hj_ki/post/96882aa6-dbaa-4a21-815c-76e3f271359d/image.png" alt=""></p>
<p>터미널에 아래와 같은 메시지가 뜨면 실행 성공!</p>
<p>크롬에서 <a href="http://localhost:5000/">http://localhost:5000/</a> 으로 접속!</p>
<p>--&gt; <strong>터미널 창을 클릭하고 ctrl+c 누르면 서버를 종료할 수 있다.</strong></p>
<p>--&gt; <strong>url 별로 함수명이 같거나, route(&#39;/&#39;)내의 주소가 같으면 안된다.</strong></p>
<p>from flask import Flask
app = Flask(<strong>name</strong>)</p>
<p>@app.route(<strong>&#39;/&#39;</strong>)
def home():
   return &#39;This is Home!&#39;</p>
<p>@app.route(<strong>&#39;/mypage&#39;</strong>)
def mypage():<br>   return &#39;This is My Page!&#39;</p>
<p>if <strong>name</strong> == &#39;<strong>main</strong>&#39;:<br>   app.run(&#39;0.0.0.0&#39;,port=5000,debug=True)</p>
<h3 id="flask-시작하기---html-파일-주기"><strong>Flask 시작하기 - HTML 파일 주기</strong></h3>
<p>Flask 서버를 만들 때, 항상,</p>
<p>프로젝트 폴더 안에,
 ㄴ<strong>static 폴더</strong> (이미지, css파일을 넣어둔다)
 ㄴ<strong>templates 폴더</strong> (html파일을 넣어둔다)
 ㄴ<strong>app.py 파일</strong></p>
<p>이렇게 세 개를 만들어두고 시작한다</p>
<hr>
<p><strong>templates 폴더의 역할</strong></p>
<p>1) 간단한 index.html 파일을 templates 안에 만들기
2) html 파일 불러오기</p>
<p>from flask import Flask, render_template
app = Flask(<strong>name</strong>)</p>
<p>@app.route(&#39;/&#39;)
def home():
   return render_template(<strong>&#39;index.html&#39;</strong>)</p>
<p>if <strong>name</strong> == &#39;<strong>main</strong>&#39;:
   app.run(&#39;0.0.0.0&#39;, port=5000, debug=True)</p>
<p>--&gt; <strong>flask 내장함수 render_template를 이용 ( 프레임워크의 효율성 )</strong></p>
<hr>
<h1 id="2-get--post"><strong>2) GET , POST</strong></h1>
<h3 id="flask-시작하기---본격-api-만들기">Flask 시작하기 - 본격 API 만들기</h3>
<p>👉 <strong>GET, POST 방식</strong></p>
<ul>
<li><p>*<em>GET *</em>       →      통상적으로! 데이터 조회(Read)를 요청할 때</p>
<pre><code>                     예) 영화 목록 조회
            →     **데이터 전달** : URL 뒤에 물음표를 붙여 key=value로 전달
            →     예: google.com?q=북극곰</code></pre></li>
<li><p><strong>POST</strong>     →      통상적으로! 데이터 생성(Create), 변경(Update), 삭제(Delete) 요청 할 때</p>
<pre><code>                     예) 회원가입, 회원탈퇴, 비밀번호 수정
            →     **데이터 전달 :** 바로 보이지 않는 HTML body에 key:value 형태로 전달</code></pre></li>
</ul>
<p><strong>Jquery 임포트</strong>
script src=&quot;<a href="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js&quot;&gt;">https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js&quot;&gt;</a> /script&gt;</p>
<hr>
<p><strong>GET 요청 API코드</strong></p>
<p>@app.route(&#39;/test&#39;, methods=[&#39;GET&#39;])
def test_get():
   title_receive = request.args.get(&#39;title_give&#39;)
   print(title_receive)
   return jsonify({&#39;result&#39;:&#39;success&#39;, &#39;msg&#39;: &#39;이 요청은 GET!&#39;})</p>
<hr>
<p><strong>GET 요청 확인 Ajax코드</strong></p>
<p>$.ajax({
    type: &quot;GET&quot;,
    url: &quot;/test?title_give=봄날은간다&quot;,
    data: {},
    success: function(response){
       console.log(response)
    }
  })</p>
<hr>
<p><strong>POST 요청 API코드</strong></p>
<p>@app.route(&#39;/test&#39;, methods=[&#39;POST&#39;])
def test_post():
   title_receive = request.form[&#39;title_give&#39;]
   print(title_receive)
   return jsonify({&#39;result&#39;:&#39;success&#39;, &#39;msg&#39;: &#39;이 요청은 POST!&#39;})</p>
<hr>
<p><strong>POST 요청 확인 Ajax코드</strong></p>
<p>$.ajax({
    type: &quot;POST&quot;,
    url: &quot;/test&quot;,
    data: { title_give:&#39;봄날은간다&#39; },
    success: function(response){
       console.log(response)
    }
  })</p>
<hr>
<h3 id="post-연습주문-저장"><strong>POST 연습(주문 저장)</strong></h3>
<p>API 만들고 사용하기 - 이름, 주소, 평수 저장하기(Create → POST)</p>
<ol>
<li>요청 정보 :  URL= <code>/mars</code>, 요청 방식 = <code>POST</code>  </li>
<li>클라(ajax) → 서버(flask) : <code>name</code>, <code>address</code>, <code>size</code></li>
<li>서버(flask) → 클라(ajax) : 메시지를 보냄 (주문 완료!)</li>
</ol>
<p><strong>1) 클라이언트와 서버 연결 확인하기</strong></p>
<p>[서버 코드 - <strong><code>app.py</code></strong>]
@app.route(&quot;/mars&quot;, methods=[&quot;POST&quot;])
def mars_post():
    sample_receive = request.form[&#39;sample_give&#39;]
    print(sample_receive)
    return jsonify({&#39;msg&#39;: &#39;POST 연결 완료!&#39;})</p>
<p>[클라이언트 코드 - <strong><code>index.html</code></strong>]
function save_order() {
    $.ajax({
        type: &#39;POST&#39;,
        url: &#39;/mars&#39;,
        data: { sample_give:&#39;데이터전송&#39; },
        success: function (response) {
            alert(response[&#39;msg&#39;])
        }
    });
}</p>
<p>button onclick=&quot;save_order()&quot; type=&quot;button&quot; class=&quot;btn btn-warning mybtn&quot;&gt;주문하기/button&gt;</p>
<hr>
<p><strong>2) 서버부터 만들기</strong></p>
<p><strong>name, address, size 정보를 받아서, 저장</strong>
@app.route(&quot;/mars&quot;, methods=[&quot;POST&quot;])
def mars_post():
    name_receive = request.form[&#39;name_give&#39;]
    address_receive = request.form[&#39;address_give&#39;]
    size_receive = request.form[&#39;size_give&#39;]</p>
<pre><code>doc = {
    &#39;name&#39;: name_receive,
    &#39;address&#39;: address_receive,
    &#39;size&#39;: size_receive
}

db.orders.insert_one(doc)

return jsonify({&#39;msg&#39;: &#39;주문 완료!&#39;})</code></pre><hr>
<p><strong>3) 클라이언트 만들기</strong></p>
<p><strong>name, address, size 정보를 보내기</strong>
function save_order() {
    let name = $(&#39;#name&#39;).val()
    let address = $(&#39;#address&#39;).val()
    let size = $(&#39;#size&#39;).val()</p>
<pre><code>$.ajax({
    type: &#39;POST&#39;,
    url: &#39;/mars&#39;,
    data: { name_give:name, address_give:address, size_give:size },
    success: function (response) {
        alert(response[&#39;msg&#39;])
        window.location.reload()
    }
});</code></pre><p>}</p>
<hr>
<p><strong>4) DB에 잘 들어갔는지 확인</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/0f67b87b-55ad-47b2-9df0-14f6179dcf6a/image.png" alt=""></p>
<hr>
<h3 id="get-연습주문-보여주기"><strong>GET 연습(주문 보여주기)</strong></h3>
<p><strong>API 만들고 사용하기 - 저장된 주문을 화면에 보여주기(Read → GET)</strong></p>
<ol>
<li>요청 정보 :  URL= /mars, 요청 방식 = GET</li>
<li>클라(ajax) → 서버(flask) : (없음)</li>
<li>서버(flask) → 클라(ajax) : 전체 주문을 보내주기</li>
</ol>
<h3 id="1-클라이언트와-서버-확인하기"><strong>1) 클라이언트와 서버 확인하기</strong></h3>
<p>[서버 코드 - <strong><code>app.py</code></strong>]
@app.route(&quot;/mars&quot;, methods=[&quot;GET&quot;])
def mars_get():
    return jsonify({&#39;msg&#39;: &#39;GET 연결 완료!&#39;})</p>
<p>[클라이언트 코드 - <strong><code>index.html</code></strong>]
$(document).ready(function () {
    show_order();
});
function show_order() {
    $.ajax({
        type: &#39;GET&#39;,
        url: &#39;/mars&#39;,
        data: {},
        success: function (response) {
            alert(response[&#39;msg&#39;])
        }
    });
}</p>
<hr>
<h3 id="2-서버부터-만들기"><strong>2) 서버부터 만들기</strong></h3>
<p>받을 것 없이 orders 에 주문정보를 담아서 내려주기만 하면 된다!</p>
<p>@app.route(&quot;/mars&quot;, methods=[&quot;GET&quot;])
def mars_get():
    orders_list = list(db.orders.find({},{&#39;_id&#39;:False}))
    return jsonify({&#39;orders&#39;:orders_list})</p>
<hr>
<h3 id="3-클라이언트-만들기"><strong>3) 클라이언트 만들기</strong></h3>
<p>응답을 잘 받아서 for 문으로! 붙여주면 끝!</p>
<p>function show_order() {
    $(&#39;#order-box&#39;).empty()
    $.ajax({
        type: &#39;GET&#39;,
        url: &#39;/mars&#39;,
        data: {},
        success: function (response) {
            let rows = response[&#39;orders&#39;]
            for (let i = 0; i &lt; rows.length; i++) {
                let name = rows[i][&#39;name&#39;]
                let address = rows[i][&#39;address&#39;]
                let size = rows[i][&#39;size&#39;]</p>
<pre><code>            let temp_html = `&lt;tr&gt;
                                &lt;td&gt;${name}&lt;/td&gt;
                                &lt;td&gt;${address}&lt;/td&gt;
                                &lt;td&gt;${size}&lt;/td&gt;
                              &lt;/tr&gt;`
            $(&#39;#order-box&#39;).append(temp_html)
        }

    }
});</code></pre><p>}</p>
<hr>
<h1 id="3-메타-태그--크롤링"><strong>3) 메타 태그 + 크롤링</strong></h1>
<h3 id="조각-기능-구현해보기"><strong>조각 기능 구현해보기</strong></h3>
<p>1) 프로젝트 준비 - URL에서 페이지 정보 가져오기 (<strong>meta태그 스크래핑</strong>)
URL만 입력했는데, 자동으로 불러와지는 부분들 &#39;제목&#39;, &#39;썸네일 이미지&#39;, &#39;내용&#39;
<img src="https://velog.velcdn.com/images/hj_ki/post/aa726572-f147-49d9-b778-e69514b51356/image.png" alt=""></p>
<p><strong>메타 태그</strong>
head&gt;/head&gt; 부분에 들어가는, 
눈으로 보이는 것(body) 외에 사이트의 속성을 설명해주는 태그들입니다.
예) 구글 검색 시 표시 될 설명문, 사이트 제목, 카톡 공유 시 표시 될 이미지 등</p>
<ul>
<li>그 중 <strong>og:image *<em>/ *</em>og:title *<em>/ *</em>og:description</strong> 을 크롤링</li>
</ul>
<hr>
<p><strong>크롤링 기본 코드</strong>
import <strong>requests</strong>
from <strong>bs4</strong> import <strong>BeautifulSoup</strong></p>
<p>url = &#39;<a href="https://movie.naver.com/movie/bi/mi/basic.naver?code=191597&#39;">https://movie.naver.com/movie/bi/mi/basic.naver?code=191597&#39;</a></p>
<p>headers = {&#39;User-Agent&#39; : &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36&#39;}
data = requests.get(url,headers=headers)
soup = BeautifulSoup(data.text, &#39;html.parser&#39;)</p>
<hr>
<p><strong>select_one을 이용해 meta tag를 먼저 가져오기</strong>
og_image = soup.select_one(&#39;meta[property=&quot;og:image&quot;]&#39;)
og_title = soup.select_one(&#39;meta[property=&quot;og:title&quot;]&#39;)
og_description = soup.select_one(&#39;meta[property=&quot;og:description&quot;]&#39;)</p>
<p>print(og_image)
print(og_title)
print(og_description)</p>
<hr>
<p><strong>가져온 meta tag의 content를 가져오기</strong>
image = og_image[&#39;content&#39;]
title = og_title[&#39;content&#39;]
description = og_description[&#39;content&#39;]</p>
<p>print(image)
print(title)
print(description)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3주차 웹 개발]]></title>
            <link>https://velog.io/@hj_ki/web3</link>
            <guid>https://velog.io/@hj_ki/web3</guid>
            <pubDate>Wed, 20 Apr 2022 15:58:53 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hj_ki/post/0862bf36-78ac-4e4e-98ec-9e19b5a3a043/image.png" alt=""></p>
<h1 id="1-파이썬-시작하기">1) 파이썬 시작하기</h1>
<p>파이썬 설치의 의미
파이썬 문법으로 된 것을 변환해줄 수 있도록, 번역 패키지를 설치하는 것</p>
<h3 id="파이썬-기초">파이썬 기초</h3>
<h3 id="변수--기본연산"><strong>변수 &amp; 기본연산</strong></h3>
<ul>
<li><p>a = 3      --&gt; 3을 a에 넣는다</p>
</li>
<li><p>b = a      --&gt; a를 b에 넣는다</p>
</li>
<li><p>a = a + 1  --&gt; a+1을 다시 a에 넣는다</p>
</li>
<li><p>num1 = a<em>b --&gt; a</em>b의 값을 num1이라는 변수에 넣는다</p>
</li>
<li><p>num2 = 99 --&gt; 99의 값을 num2이라는 변수에 넣는다</p>
</li>
</ul>
<h3 id="숫자-문자형"><strong>숫자, 문자형</strong></h3>
<p>name = &#39;bob&#39; # 변수에는 문자열이 들어갈 수도 있고,
num = 12 # 숫자가 들어갈 수도 있고,</p>
<p>is_number = True # True 또는 False -&gt; &quot;Boolean&quot;형이 들어갈 수도 있습니다.</p>
<h3 id="리스트-형javascript의-배열형과-동일"><strong>리스트 형(Javascript의 배열형과 동일)</strong></h3>
<p>a_list = []
a_list.append(1)     # 리스트에 값을 넣는다
a_list.append([2,3]) # 리스트에 [2,3]이라는 리스트를 다시 넣는다</p>
<p> a_list의 값 : <strong>[1,[2,3]]</strong>
a_list[0]의 값 : <strong>1</strong>
a_list[1]의 값 : <strong>[2,3]</strong>
a_list[1][0]의 값 : <strong>2</strong></p>
<h3 id="dictionary-형-javascript의-dictionary형과-동일">Dictionary 형 (Javascript의 dictionary형과 동일)</h3>
<p>a_dict = {}
a_dict = {&#39;name&#39;:&#39;bob&#39;,&#39;age&#39;:21}
a_dict[&#39;height&#39;] = 178</p>
<p> a_dict의 값 : {&#39;name&#39;:&#39;bob&#39;,&#39;age&#39;:21, &#39;height&#39;:178}
 a_dict[&#39;name&#39;]의 값 :** &#39;bob&#39;**
 a_dict[&#39;age&#39;]의 값 : <strong>21</strong>
 a_dict[&#39;height&#39;]의 값 :** 178**</p>
<h3 id="dictionary-형과-list형의-조합">Dictionary 형과 List형의 조합</h3>
<p>people = [{&#39;name&#39;:&#39;bob&#39;,&#39;age&#39;:20},{&#39;name&#39;:&#39;carry&#39;,&#39;age&#39;:38}]</p>
<p> people[0][&#39;name&#39;]의 값 : <strong>&#39;bob&#39;</strong>
 people[1][&#39;name&#39;]의 값 : <strong>&#39;carry&#39;</strong></p>
<p>person = {&#39;name&#39;:&#39;john&#39;,&#39;age&#39;:7}
people.<strong>append</strong>(person)</p>
<p>people의 값 : <strong>[{&#39;name&#39;:&#39;bob&#39;,&#39;age&#39;:20},{&#39;name&#39;:&#39;carry&#39;,&#39;age&#39;:38},{&#39;name&#39;:&#39;john&#39;,&#39;age&#39;:7}]</strong>
 people[2][&#39;name&#39;]의 값 : <strong>&#39;john&#39;</strong></p>
<h2 id="2-함수">2) 함수</h2>
<p><strong>수학문제에서</strong>
f(x) = 2*x+3
y = f(2)
y의 값 : 7</p>
<p><strong>참고: 자바스크립트에서</strong>
function f(x) {
    return 2*x+3
}</p>
<p><strong>파이썬에서</strong>
def f(x):
    return 2*x+3</p>
<p>y = f(2)
y의 값 : 7</p>
<h3 id="함수의-응용">함수의 응용</h3>
<p>def sum_all(a,b,c):
    return a+b+c</p>
<p>def mul(a,b):
    return a*b</p>
<p>result = sum_all(1,2,3) + mul(10,10)</p>
<h3 id="조건문">조건문</h3>
<p><strong>if / else 로 구성</strong>
def oddeven(num):  --&gt; <strong>oddeven이라는 이름의 함수를 정의한다. num을 변수로 받는다.</strong>
    if num % 2 == 0: --&gt; num을 2로 나눈 나머지가 0이면
         return True   --&gt; True (참)을 반환한다.
    else:           --&gt; 아니면,
         return False  --&gt; False (거짓)을 반환한다.</p>
<p>result = oddeven(20)</p>
<hr>
<p>def is_adult(age):
    if age &gt; 20:
        print(&#39;성인입니다&#39;)    --&gt; 조건이 참이면 성인입니다를 출력
    else:
        print(&#39;청소년이에요&#39;)  --&gt; 조건이 거짓이면 청소년이에요를 출력</p>
<p>is_adult(30)</p>
<h3 id="반복문">반복문</h3>
<p><strong>파이썬에서의 반복문은, 리스트의 요소들을 하나씩 꺼내쓰는 형태</strong></p>
<p>fruits = [&#39;사과&#39;,&#39;배&#39;,&#39;감&#39;,&#39;귤&#39;]</p>
<p>for fruit in fruits:
    print(fruit)</p>
<p><strong>사과, 배, 감, 귤 하나씩 꺼내어 찍힙니다.</strong></p>
<hr>
<p>fruits = [&#39;사과&#39;,&#39;배&#39;,&#39;배&#39;,&#39;감&#39;,&#39;수박&#39;,&#39;귤&#39;,&#39;딸기&#39;,&#39;사과&#39;,&#39;배&#39;,&#39;수박&#39;]</p>
<p>count = 0
for fruit in fruits:
    if fruit == &#39;사과&#39;:
        count += 1</p>
<p>print(count)</p>
<p><strong>사과의 갯수를 세어 보여줍니다.</strong></p>
<hr>
<p>def count_fruits(target):
    count = 0
    for fruit in fruits:
        if fruit == target:
            count += 1
    return count</p>
<p>subak_count = count_fruits(&#39;수박&#39;)
print(subak_count) --&gt; 수박의 갯수</p>
<p>gam_count = count_fruits(&#39;감&#39;)
print(gam_count) --&gt; 감의 갯수</p>
<hr>
<p><strong>딕셔너리 예제</strong>
people = [{&#39;name&#39;: &#39;bob&#39;, &#39;age&#39;: 20}, 
          {&#39;name&#39;: &#39;carry&#39;, &#39;age&#39;: 38},
          {&#39;name&#39;: &#39;john&#39;, &#39;age&#39;: 7},
          {&#39;name&#39;: &#39;smith&#39;, &#39;age&#39;: 17},
          {&#39;name&#39;: &#39;ben&#39;, &#39;age&#39;: 27}]</p>
<p><strong>모든 사람의 이름과 나이를 출력하기</strong></p>
<p>for <strong>person</strong> in people:
    print(<strong>person</strong>[&#39;name&#39;], <strong>person</strong>[&#39;age&#39;])</p>
<hr>
<p><strong>반복문과 조건문을 응용한 함수를 만들기</strong>
<strong>이름을 받으면, age를 리턴해주는 함수</strong></p>
<p>def get_age(<strong>myname</strong>):
    for person in people:
        if person[&#39;name&#39;] == <strong>myname</strong>:
            return person[&#39;age&#39;]
    return &#39;해당하는 이름이 없습니다&#39;</p>
<p>print(get_age(&#39;bob&#39;))
print(get_age(&#39;kay&#39;))</p>
<h3 id="파이썬-패키지-설치">파이썬 패키지 설치</h3>
<p>👉 패키지? 라이브러리? → 
Python 에서 <strong>패키지</strong>는 모듈(일종의 기능들 묶음)을 모아 놓은 단위입니다. 
이런 패키지 의 묶음을 <strong>라이브러리</strong> 라고 볼 수 있습니다. 
지금 여기서는 외부 라이브러리를 사용하기 위해서 패키지를 설치합니다. </p>
<p>즉, 여기서는 <strong>패키지 설치 = 외부 라이브러리 설치</strong>!</p>
<h3 id="가상-환경virtual-environment-이란">가상 환경(virtual environment) 이란?</h3>
<p>같은 시스템에서 실행되는 다른 파이썬 응용 프로그램들의 동작에 영향을 주지 않기 위해, 
파이썬 배포 패키지들을 설치하거나 업그레이드하는 것을 가능하게 하는 <strong>격리된 실행 환경</strong> 입니다.
프로젝트별로 패키지들을 담을 공구함</p>
<h3 id="웹스크래핑크롤링-기초">웹스크래핑(크롤링) 기초</h3>
<p>패키지 추가 설치하기(<strong>beautifulsoup4</strong>) - bs4</p>
<hr>
<h3 id="크롤링-기본-세팅">크롤링 기본 세팅</h3>
<p>import requests
from <strong>bs4</strong> import <strong>BeautifulSoup</strong></p>
<p>타겟 URL을 읽어서 HTML를 받아오고,
<strong>headers *<em>= {&#39;User-Agent&#39; : &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36&#39;}
*</em>data **= requests.</strong>get<strong>(&#39;<a href="https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&amp;date=20210829&#39;,headers=headers">https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&amp;date=20210829&#39;,headers=headers</a>) &lt;&lt; **naver 영화 페이지</strong>
soup = BeautifulSoup(data.text, &#39;html.parser&#39;)</p>
<ul>
<li><strong>HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦</strong></li>
<li><strong>soup이라는 변수에 &quot;파싱 용이해진 html&quot;이 담긴 상태가 됨</strong></li>
<li><strong>#이제 코딩을 통해 필요한 부분을 추출하면 된다.</strong></li>
</ul>
<hr>
<h4 id="select--select_one-영화-제목-가져오기">select / select_one 영화 제목 가져오기</h4>
<p>import requests
from bs4 import BeautifulSoup</p>
<ul>
<li>URL을 읽어서 HTML를 받아오고,</li>
</ul>
<p><strong>headers</strong> = {&#39;User-Agent&#39; : &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36&#39;}
<strong>data **= requests.</strong>get**(&#39;<a href="https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&amp;date=20210829&#39;,headers=headers">https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&amp;date=20210829&#39;,headers=headers</a>)</p>
<ul>
<li><p>HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦</p>
</li>
<li><p><em>soup = BeautifulSoup(data.text, &#39;html.parser&#39;)*</em></p>
</li>
<li><p>select를 이용해서, tr들을 불러오기</p>
</li>
<li><p><em>movies = soup.select(&#39;#old_content &gt; table &gt; tbody &gt; tr&#39;)*</em></p>
</li>
<li><p>movies (tr들) 의 반복문을 돌리기</p>
</li>
<li><p><em>for movie in movies:*</em></p>
<ul>
<li>movie 안에 a 가 있으면,</li>
<li><ul>
<li>a_tag = movie.select_one(&#39;td.title &gt; div &gt; a&#39;)
if a_tag is not None:**<ul>
<li>a의 text를 찍어본다.
<strong>print (a_tag.text)</strong></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="beautifulsoup-내-select에-미리-정의된-다른-방법을-알아보기"><strong>beautifulsoup 내 select에 미리 정의된 다른 방법을 알아보기</strong></h3>
<ul>
<li><strong>선택자를 사용하는 방법 (copy selector)</strong>
soup.select(&#39;태그명&#39;)
soup.select(&#39;.클래스명&#39;)
soup.select(&#39;#아이디명&#39;)
soup.select(&#39;상위태그명 &gt; 하위태그명 &gt; 하위태그명&#39;)
soup.select(&#39;상위태그명.클래스명 &gt; 하위태그명.클래스명&#39;)</li>
</ul>
<ul>
<li><p><strong>태그와 속성값으로 찾는 방법</strong>
soup.select(&#39;태그명[속성=&quot;값&quot;]&#39;)</p>
</li>
<li><p><strong>한 개만 가져오고 싶은 경우</strong>
soup.select_one(&#39;위와 동일&#39;)
<img src="https://velog.velcdn.com/images/hj_ki/post/8e1aa72b-e793-4dd2-bf1e-0e961bef8041/image.png" alt=""></p>
</li>
</ul>
<hr>
<h1 id="3-db">3) DB</h1>
<p><strong>Database의 두 가지 종류</strong>
<img src="https://velog.velcdn.com/images/hj_ki/post/ee68075f-a6be-40ae-9b0f-9a596ad2979c/image.png" alt=""></p>
<p><strong>RDBMS(SQL)</strong>
행/열의 생김새가 정해진 엑셀에 데이터를 저장하는 것과 유사합니다. 
데이터 50만 개가 적재된 상태에서, 갑자기 중간에 열을 하나 더하기는 어려울 것입니다.
그러나, 정형화되어 있는 만큼, 데이터의 일관성이나 / 분석에 용이할 수 있습니다.</p>
<p><strong>No-SQL</strong>
딕셔너리 형태로 데이터를 저장해두는 DB입니다. 
고로 데이터 하나 하나 마다 같은 값들을 가질 필요가 없게 됩니다. 
자유로운 형태의 데이터 적재에 유리한 대신, 일관성이 부족할 수 있습니다.</p>
<ul>
<li>DB의 실체는 우리가 쓰는 프로그램과 같은 것</li>
<li>요새는 <strong>Cloud</strong> 형태로 제공해주는 곳들이 많다</li>
<li>유저가 몰리거나 / DB를 백업해야 하거나 / 모니터링 하기가 아주 용이하기 때문</li>
</ul>
<hr>
<h3 id="mongodb-가입-및-연결"><strong>mongoDB 가입 및 연결</strong></h3>
<p>mongoDB - Atlas 가입</p>
<p>연결 준비하기   </p>
<p>1) Allow Access from Anywhere 클릭 → Add IP address 클릭<br>2) Username, Password를 아래와 같이 입력 → Create Database User 클릭<br>3) Choose a connection method 클릭</p>
<p><strong>mongoDB - Atlas 연결하기</strong></p>
<ul>
<li><p>*<em>pymongo 라이브러리의 역할 *</em>
mongoDB 라는 프로그램을 조작하려면,
특별한 라이브러리, pymongo가 필요!</p>
</li>
<li><p>pymongo, dnspython 패키지 설치 후 잘 연결됐는지 테스트해보기</p>
</li>
</ul>
<p>doc = {
    &#39;name&#39;:&#39;bob&#39;,
    &#39;age&#39;:27
}</p>
<p>db.users.insert_one(doc)
<img src="https://velog.velcdn.com/images/hj_ki/post/d533933e-5912-4a0b-9f8f-6a6f0533981c/image.png" alt=""></p>
<h3 id="pymongo로-db조작하기"><strong>pymongo로 DB조작하기</strong></h3>
<ul>
<li><p><strong>DB연결하기 &amp; 데이터 넣기 (insert_one)</strong>
&#39;users&#39;라는 collection에 {&#39;name&#39;:&#39;bobby&#39;,&#39;age&#39;:21}를 넣습니다.
db.users.<strong>insert_one</strong>({&#39;name&#39;:&#39;bobby&#39;,&#39;age&#39;:21})
db.users.<strong>insert_one</strong>({&#39;name&#39;:&#39;kay&#39;,&#39;age&#39;:27})
db.users.<strong>insert_one</strong>({&#39;name&#39;:&#39;john&#39;,&#39;age&#39;:30})</p>
</li>
<li><p>*<em>모든 결과 값을 보기 (find) *</em></p>
<p>all_users = list(db.users.<strong>find</strong>({},{&#39;_id&#39;:False}))</p>
<p>print(all_users[0])         # <strong>0번째 결과값을 보기</strong>
print(all_users[0][&#39;name&#39;]) # <strong>0번째 결과값의 &#39;name&#39;을 보기</strong></p>
<p>for user in all_users:      # <strong>반복문을 돌며 모든 결과값을 보기</strong>
  print(user)</p>
</li>
<li><p><strong>특정 결과 값을 뽑아 보기 (find_one) **
user = db.users.</strong>find_one**({&#39;name&#39;:&#39;bobby&#39;})
print(user)</p>
</li>
<li><p><strong>수정하기 (update_one)</strong>
db.users.<strong>update_one</strong>({&#39;name&#39;:&#39;bobby&#39;},{&#39;$set&#39;:{&#39;age&#39;:19}})</p>
<p>user = db.users.<strong>find_one</strong>({&#39;name&#39;:&#39;bobby&#39;})
print(user)</p>
<ul>
<li><strong>삭제하기 (거의 안 씀) (delete_one)</strong>
db.users.<strong>delete_one</strong>({&#39;name&#39;:&#39;bobby&#39;})</li>
</ul>
<p>user = db.users.<strong>find_one</strong>({&#39;name&#39;:&#39;bobby&#39;})
print(user)</p>
<hr>
</li>
</ul>
<h2 id="pymongo-사용법--코드요약">pymongo 사용법 : 코드요약</h2>
<ul>
<li><strong>저장 - 예시</strong>
doc = {&#39;name&#39;:&#39;bobby&#39;,&#39;age&#39;:21}
db.users.insert_one(doc)</li>
</ul>
<ul>
<li><p>** 한 개 찾기 - 예시**
user = db.users.find_one({&#39;name&#39;:&#39;bobby&#39;})</p>
</li>
<li><p><strong>여러개 찾기 - 예시 ( _id 값은 제외하고 출력)</strong>
all_users = list(db.users.find({},{&#39;_id&#39;:False}))</p>
</li>
<li><p><strong>바꾸기 - 예시</strong>
db.users.update_one({&#39;name&#39;:&#39;bobby&#39;},{&#39;$set&#39;:{&#39;age&#39;:19}})</p>
</li>
<li><p><strong>지우기 - 예시</strong>
db.users.delete_one({&#39;name&#39;:&#39;bobby&#39;})</p>
</li>
</ul>
<hr>
<h3 id="insert-연습---웹스크래핑-결과를-db에-저장하기">insert 연습 - 웹스크래핑 결과를 DB에 저장하기</h3>
<p><strong>pymongo 기본 세팅</strong></p>
<p>import <strong>requests</strong>
from <strong>bs4</strong> import <strong>BeautifulSoup</strong></p>
<p><strong>from pymongo import MongoClient
client = MongoClient(&#39;mongodb+srv://test:<a href="mailto:sparta@cluster0.55vah.mongodb.net">sparta@cluster0.55vah.mongodb.net</a>/Cluster0?retryWrites=true&amp;w=majority&#39;)
db = client.dbsparta_<em>_</em></strong></p>
<ul>
<li><p>URL을 읽어서 HTML를 받아오고,</p>
</li>
<li><p><em>headers = {&#39;User-Agent&#39; : &#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36&#39;}
data = requests.get(&#39;<a href="https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&amp;date=20210829&#39;,headers=headers">https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&amp;date=20210829&#39;,headers=headers</a>)*</em></p>
</li>
<li><p>HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦</p>
</li>
<li><ul>
<li>soup = BeautifulSoup(data.text, &#39;html.parser&#39;)</li>
</ul>
</li>
<li><p>*</p>
</li>
<li><p>select를 이용해서, tr들을 불러오기</p>
</li>
<li><p>*movies = soup.select(&#39;#old_content &gt; table &gt; tbody &gt; tr&#39;)</p>
</li>
<li><p>*</p>
</li>
<li><p>movies (tr들) 의 반복문을 돌리기</p>
</li>
<li><ul>
<li>for movie in movies:
a_tag = movie.select_one(&#39;td.title &gt; div &gt; a&#39;)
if a_tag is not None:**</li>
<li>img 태그의 alt 속성값을 가져오기</li>
<li><em>rank = movie.select_one(&#39;td:nth-child(1) &gt; img&#39;)[&#39;alt&#39;] *</em></li>
<li>a 태그 사이의 텍스트를 가져오기</li>
</ul>
</li>
<li><ul>
<li>title = a_tag.text **  </li>
<li>td 태그 사이의 텍스트를 가져오기</li>
</ul>
</li>
<li><ul>
<li>star = movie.select_one(&#39;td.point&#39;).text  **              
print(rank,title,star)</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2주차 웹 개발]]></title>
            <link>https://velog.io/@hj_ki/web2</link>
            <guid>https://velog.io/@hj_ki/web2</guid>
            <pubDate>Wed, 13 Apr 2022 09:35:21 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/hj_ki/post/094f3cec-bad5-4dca-9dee-15f7f59e6326/image.png" alt=""></p>
<h2 id="1-jquery">1) JQuery</h2>
<p>HTML의 요소들을 조작하는 편리한 Javascript를 미리 작성해준 것. 라이브러리!
Javascript로도 모든 기능을 구현할 수 있지만,
코드의 복잡도, 브라우저 간 호환성을 고려하여 JQuery라는 라이브러리가 등장하였다.</p>
<p>-<strong>Javascript</strong>-
document.getElementById(&quot;element&quot;).style.display = &quot;none&quot;;</p>
<p>-<strong>JQuery</strong>-
$(&#39;#element&#39;).hide();</p>
<p>JQery 사용하기
미리 작성된 Javascript 코드를 가져오는 것을 &#39;임포트&#39;라고 부른다.</p>
<p>head&gt;
script&gt; src=&quot;<a href="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js&quot;">https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js&quot;</a>
/script&gt;
head&gt;</p>
<p>△△△ JQuery CDN 부분을 참고해서 임포트하기!</p>
<p><strong>* *<em>CSS에서는 선택자로 *</em>class</strong>를 사용하였고**
<strong>* JQuery에서는 **id</strong>값을 통해 특정 버튼/인풋박스/div/.. 등을 가리키게 된다</p>
<p>$(&#39;#id값&#39;).val()</p>
<p>$(&#39;#id값&#39;).hide()</p>
<p>$(&#39;#id값&#39;).show()</p>
<h2 id="2-서버-클라이언트-통신-이해하기">2) 서버 클라이언트 통신 이해하기</h2>
<h3 id="json">JSON</h3>
<p>Key, Value로 이루어져 있다. 자료형 Dictionary와 아주 유사하다.</p>
<p>OpenAPI 접속 후 
크롬 익스텐션 JSONView를 설치하면 좀 더 예쁘게 JSON을 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/hj_ki/post/b2ae3560-6a8d-4d3a-818e-5281ad88bbdb/image.png" alt="">
 RealtimeCityAir라는 키 값에 딕셔너리 형 value가 들어가있고,
그 안에 row라는 키 값에는 리스트형 value가 들어가있습니다.</p>
<h3 id="클라이언트---서버--get-요청-이해하기">클라이언트 -&gt;&gt; 서버 : GET 요청 이해하기</h3>
<p>클라이언트가 요청할 때 &quot;타입&quot;이라는 것이 존재한다</p>
<ul>
<li><p><strong>GET</strong>        →      통상적으로! 데이터 <strong>조회(Read)</strong>를 요청할 때</p>
<pre><code>                     예) 영화 목록 조회</code></pre></li>
<li><p><strong>POST</strong>     →      통상적으로! 데이터 <strong>생성(Create)</strong>, <strong>변경(Update)</strong>, <strong>삭제(Delete)</strong> 요청 할 때</p>
<pre><code>                     예) 회원가입, 회원탈퇴, 비밀번호 수정</code></pre></li>
</ul>
<p>예)
<a href="https://movie.naver.com/movie/bi/mi/basic.nhn?code=161967">https://movie.naver.com/movie/bi/mi/basic.nhn?code=161967</a>
위 주소는 크게 두 부분으로 쪼개진다. 
바로 &quot;<strong>?</strong>&quot;가 쪼개지는 지점
<strong>&quot;?&quot;</strong> 기준으로 앞부분이 <strong>&lt;서버 주소&gt;</strong>, 뒷부분이 <strong>&lt;영화 번호&gt;</strong></p>
<ul>
<li>서버 주소: <strong><a href="https://movie.naver.com/movie/bi/mi/basic.nhn">https://movie.naver.com/movie/bi/mi/basic.nhn</a></strong></li>
<li>영화 정보: <strong>code=161967</strong></li>
</ul>
<p>👉 <strong>GET 방식으로 데이터를 전달하는 방법</strong></p>
<p><strong>?</strong>  : 여기서부터 전달할 데이터가 작성된다는 의미입니다.
<strong>&amp;</strong> : 전달할 데이터가 더 있다는 뜻입니다.</p>
<p>예) <strong>google.com/search?q=아이폰&amp;sourceid=chrome&amp;ie=UTF-8</strong>
위 주소는 google.com의 search 창구에 다음 정보를 전달합니다!
<strong>q</strong> = 아이폰              (<strong>검색어</strong>)
<strong>sourceid</strong> = chrome     (<strong>브라우저 정보</strong>)
<strong>ie</strong> = UTF-8            (<strong>인코딩 정보</strong>)</p>
<h2 id="3-ajax">3) Ajax</h2>
<p><strong>Ajax는 JQuery를 임포트한 페이지에서만 동작 가능하다!</strong></p>
<h3 id="-ajax-골격-">-Ajax 골격-</h3>
<p>$.ajax({
  type: &quot;GET&quot;,
  url: &quot;여기에URL을입력&quot;,
  data: {},
  success: function(response){
    console.log(response)
  }
})</p>
<ul>
<li><strong>type</strong>: &quot;GET&quot; → GET 방식으로 요청한다.</li>
<li><strong>url</strong>: 요청할 url</li>
<li><strong>data</strong>: 요청하면서 함께 줄 데이터 (GET 요청시엔 비워둔다)</li>
</ul>
<pre><code>👉 리마인드
**GET** 요청은, url뒤에 아래와 같이 붙여서 데이터를 가져갑니다.
http://naver.com?param=value&amp;param2=value2 

**POST** 요청은, data : {} 에 넣어서 데이터를 가져갑니다.
data: { param: &#39;value&#39;, param2: &#39;value2&#39; },</code></pre><ul>
<li><strong>success</strong>: 성공하면, response 값에 서버의 결과 값을 담아서 함수를 실행한다.</li>
</ul>
<pre><code>```jsx
success: function(response){ // 서버에서 준 결과를 response라는 변수에 담음
  console.log(response) 
}
```</code></pre><p>&lt;예&gt; 모든 구의 미세먼지 값을 찍어보기
$.ajax({
  type: &quot;GET&quot;, <strong>&lt;&lt;--- GET 방식 요청</strong>
  url: &quot;<a href="http://spartacodingclub.shop/sparta_api/seoulair&quot;">http://spartacodingclub.shop/sparta_api/seoulair&quot;</a>, <strong>&lt;&lt;--- 값을 가져올 url</strong>
  data: {}, <strong>&lt;&lt;--- GET 활용시 비활성화</strong>
  success: function (response) { <strong>&lt;&lt;--- 서버에서 준 결과를 response라는 변수에 담음</strong>
    let mise_list = response[&quot;RealtimeCityAir&quot;][&quot;row&quot;]; <strong>&lt;&lt;--- json 형식의 데이터를 변수 안에 담기</strong>
    for (let i = 0; i &lt; mise_list.length; i++) {
      let mise = mise_list[i];
      let gu_name = mise[&quot;MSRSTE_NM&quot;];
      let gu_mise = mise[&quot;IDEX_MVL&quot;];
      console.log(gu_name, gu_mise);
    }
  }
});</p>
<h4 id="-ajax-추가-연습--이미지-바꾸기-텍스트-바꾸기-">+++ Ajax 추가 연습 ( 이미지 바꾸기, 텍스트 바꾸기 )</h4>
<ul>
<li>이미지 바꾸기 : <code>$(&quot;#아이디값&quot;).attr(&quot;src&quot;, 이미지URL);</code></li>
<li>텍스트 바꾸기 : <code>$(&quot;#아이디값&quot;).text(&quot;바꾸고 싶은 텍스트&quot;);</code></li>
</ul>
<p><strong>* -로딩 후 호출하기- *</strong></p>
<pre><code class="language-jsx">$(document).ready(function(){
    alert(&#39;로딩완료!&#39;)
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1주차 웹 개발]]></title>
            <link>https://velog.io/@hj_ki/web1</link>
            <guid>https://velog.io/@hj_ki/web1</guid>
            <pubDate>Thu, 10 Mar 2022 01:45:28 GMT</pubDate>
            <description><![CDATA[<h1 id="html-css-javascript">HTML, CSS, Javascript</h1>
<h2 id="-1-html과-css의-개념">** 1) HTML과 CSS의 개념**</h2>
<ul>
<li><p>HTML은 구역과 텍스트를 나타내는 코드로, CSS는 잡은 구역을 꾸며주는 것으로 생각합니다. HTML 내 style 속성으로 꾸미기를 할 수 있지만, 긴 세월동안 이것을 한데 모아 볼 수 있는 CSS 파일이 탄생하게 되었습니다. HTML 코드 내에 CSS 파일을 불러와서 적용합니다.</p>
</li>
<li><p>또한 CSS를 잘 사용할 줄 아는 것과, &#39;예쁘게&#39; 만드는 것은 다른 영역이기 때문에(붓을 잡을 줄 아는 것과 그림을 잘 그릴 줄 아는 것의 차이), 많은 경우 웹디자이너나 퍼블리셔에게 의존하게 됩니다.</p>
</li>
<li><p>클라이언트가 서버에 요청하면, 서버가 클라이언트에게 HTML+CSS+Javascript를 준다.</p>
</li>
</ul>
<h2 id="2-html">2) HTML</h2>
<h4 id="html은-크게-head와-body로-구성">HTML은 크게 head와 body로 구성</h4>
<p>head 안에는 페이지의 속성 정보를, body안에는 페이지의 내용을 담습니다.
head 안에 들어가는 대표적인 요소들: meta, script, link, title 등
body 안에 들어가는 대표적인 요소들: h, p, div, span 등</p>
<h2 id="3-css">3) CSS</h2>
<p>head ~ /head 안에 style ~ /style 로 공간을 만들어 작성합니다.
아래 코드를 통해 간단한 사용 방법을 알아봅니다.
mytitle라는 클래스를 가리킬 때, .mytitle { ... } 라고 써줘야 하는 것을 꼭! 기억할 것</p>
<p><strong>자주 쓰이는 CSS</strong>
h1, h5, background-image, background-size, background-position
color, width, height, border-radius, margin, padding
--&gt; 암기X, 필요에 따라 사용할 것</p>
<h4 id="구글-폰트-입히기">구글 폰트 입히기</h4>
<p><a href="https://fonts.google.com/?subset=korean">https://fonts.google.com/?subset=korean</a>
(1) 마음에 드는 폰트를 클릭합니다.
(2) [ + Select this style ]을 클릭합니다.
(3) 우측 상단의 모음 아이콘을 클릭합니다.
(4) Embed 탭을 클릭합니다.
(5) link 태그를 복사해서 <head> ~ </head>사이에, CSS를 복사해서 <style> ~ </style> 사이에 넣습니다.</p>
<h4 id="css-분리">CSS 분리</h4>
<p>style ~ /style 부분이 너무 길어지면, 보기가 어렵습니다.
이럴 땐 아래와 같이 파일을 분리해둘 수 있습니다.
style.css 파일을 같은 폴더에 만들고, head 태그에서 불러오기!
&lt;.link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href = &quot;(css파일이름).css&quot;&gt;</p>
<h4 id="부트스트랩-예쁜-css-모음집">부트스트랩, 예쁜 CSS 모음집</h4>
<p>-bootstrap-
예쁜 CSS를 미리 모아둔 것 (CSS를 다룰 줄 아는 것과, 미적 감각을 발휘하여 예쁘게 만드는 것은 다른 이야기이기 때문에, 현업에서는 미리 완성된 부트스트랩을 가져다 쓰는 경우가 많습니다.)
남이 만들어 둔 것을 쓸 때는 잘 찾아다가 조금씩만 고쳐서 쓰는 게 답!
카테고리에서 원하는 디자인을 찾아 그 코드를 가져올 것</p>
<h2 id="4-javascript">4) Javascript</h2>
<p>프로그래밍 언어 중 하나로, 브라우저가 알아들을 수 있는 언어
head ~ /head 안에 script ~ /script 로 공간을 만들어 작성합니다.
script ~ /script 내에 자바스크립트를 작성</p>
<p>기초문법
<strong>변수 &amp; 기본연산</strong></p>
<p>변수 대입( a = 2 )의 의미: &quot;오른쪽에 있는 것을 왼쪽에 넣는 것!&quot;
(2를 a라는 변수에 넣는다)</p>
<p>let num = 20
num = &#39;Bob&#39;
// 변수는 값을 저장하는 박스
// 한 번 선언했으면, 다시 선언하지 않고 값을 넣습니다.
// 사칙연산, 그리고 문자열 더하기가 기본적으로 가능합니다.
// 쉽게 알아볼 수 있게 쓰는 게 중요
// 다른 특수문자 또는 띄워쓰기는 불가능합니다.</p>
<h4 id="리스트--딕셔너리">리스트 &amp; 딕셔너리</h4>
<ul>
<li><p>리스트: 순서를 지켜서 가지고 있는 형태</p>
<pre><code class="language-jsx">  let a_list = []  // 리스트를 선언. 변수 이름은 역시 아무렇게나 가능!

  // 또는,

  let b_list = [1,2,&#39;hey&#39;,3] // 로 선언 가능

  b_list[1] // 2 를 출력
  b_list[2] // &#39;hey&#39;를 출력

  // 리스트에 요소 넣기
  b_list.push(&#39;헤이&#39;)
  b_list // [1, 2, &quot;hey&quot;, 3, &quot;헤이&quot;] 를 출력

  // 리스트의 길이 구하기
  b_list.length // 5를 출력</code></pre>
</li>
<li><p>딕셔너리: 키(key)-밸류(value) 값의 묶음</p>
<pre><code class="language-jsx">let a_dict = {}  // 딕셔너리 선언. 변수 이름은 역시 아무렇게나 가능!
</code></pre>
</li>
</ul>
<p>// 또는,</p>
<p>let b_dict = {&#39;name&#39;:&#39;Bob&#39;,&#39;age&#39;:21} // 로 선언 가능
b_dict[&#39;name&#39;] // &#39;Bob&#39;을 출력
b_dict[&#39;age&#39;] // 21을 출력</p>
<p>b_dict[&#39;height&#39;] = 180 // 딕셔너리에 키:밸류 넣기
b_dict // {name: &quot;Bob&quot;, age: 21, height: 180}을 출력</p>
<pre><code>- 리스트와 딕셔너리의 조합
```jsx
names = [{&#39;name&#39;:&#39;bob&#39;,&#39;age&#39;:20},{&#39;name&#39;:&#39;carry&#39;,&#39;age&#39;:38}]

// names[0][&#39;name&#39;]의 값은? &#39;bob&#39;
// names[1][&#39;name&#39;]의 값은? &#39;carry&#39;

new_name = {&#39;name&#39;:&#39;john&#39;,&#39;age&#39;:7}
names.push(new_name)

// names의 값은? [{&#39;name&#39;:&#39;bob&#39;,&#39;age&#39;:20},{&#39;name&#39;:&#39;carry&#39;,&#39;age&#39;:38},{&#39;name&#39;:&#39;john&#39;,&#39;age&#39;:7}]
// names[2][&#39;name&#39;]의 값은? &#39;john&#39;</code></pre><p>*** 왜 필요한가?</p>
<p><strong>순서를 표시할 수 있고, 정보를 묶을 수 있습니다.</strong>
👉딕셔너리를 활용한다면 다음과 같이 고객 별로 정보를 묶을 수 있습니다.
let customer_1 = {&#39;name&#39;: &#39;김철수&#39;, &#39;phone&#39;: &#39;010-1234-1234&#39;};
let customer_2 = {&#39;name&#39;: &#39;박민수&#39;, &#39;phone&#39;: &#39;010-4321-4321&#39;};</p>
<p>👉그리고 순서를 나타내기 위해 리스트를 사용하면, 이렇게나 깔끔해집니다.
let customer = [
    {&#39;name&#39;: &#39;김철수&#39;, &#39;phone&#39;: &#39;010-1234-1234&#39;},
    {&#39;name&#39;: &#39;박민수&#39;, &#39;phone&#39;: &#39;010-4321-4321&#39;}
]</p>
<p>✅보기에도 깔끔해지고, 다루기도 쉬워지고, 고객이 새로 한 명 더 오더라도 .push 함수를 이용해 간단하게 대응할 수 있습니다.</p>
<h4 id="함수">함수</h4>
<ul>
<li><p>기본 생김새</p>
<pre><code class="language-jsx">// 만들기
function 함수이름(필요한 변수들) {
  내릴 명령들을 순차적으로 작성
}
// 사용하기
함수이름(필요한 변수들);</code></pre>
</li>
<li><p>예시</p>
<pre><code class="language-jsx">// 두 숫자를 입력받으면 더한 결과를 돌려주는 함수
function sum(num1, num2) {
  console.log(&#39;숫자&#39;, num1, num2);
  return num1 + num2;
}
</code></pre>
</li>
</ul>
<p>sum(3, 5); // 8
sum(4, -1); // 3</p>
<pre><code>
**조건문**
- 20 보다 작으면 작다고, 크면 크다고 알려주는 함수

    ```jsx
    function is_adult(age){
        if(age &gt; 20){
            alert(&#39;성인이에요&#39;)
        } else {
            alert(&#39;청소년이에요&#39;)
        }
    }

    is_adult(25)
    ```

- if, else if, else if, else if else

    ```jsx
    function is_adult(age){
        if(age &gt; 20){
            alert(&#39;성인이에요&#39;)
        } else if (age &gt; 10) {
            alert(&#39;청소년이에요&#39;)
        } else {
            alert(&#39;10살 이하!&#39;)
        }
    }

    is_adult(12)
    ```

**반복문**
- 예를 들어 0부터 99까지 출력해야 하는 상황이라면!

    ```jsx
    console.log(0)
    console.log(1)
    console.log(2)
    console.log(3)
    console.log(4)
    console.log(5)
    ...
    console.log(99)

    // 이렇게 쓰기엔 무리가 있겠다. 그래서, 반복문이라는 것이 존재!
    ```

- 반복문을 이용하면 아래와 같이 단 세줄로, 출력할 수 있습니다.

    ```jsx
    for (let i = 0; i &lt; 100; i++) {
        console.log(i);
    }
    ```

    ```jsx
    for (1. 시작조건; 2. 반복조건; 3. 더하기) {
        4. 매번실행
    }

    1 -&gt; 2체크하고 -&gt; (괜찮으면) -&gt; 4 -&gt; 3
    -&gt; 2체크하고 -&gt; (괜찮으면) -&gt; 4 -&gt; 3
    -&gt; 2체크하고 -&gt; (괜찮으면) -&gt; 4 -&gt; 3
    -&gt; 2체크하고 -&gt; (괜찮으면) -&gt; 4 -&gt; 3

    와 같은 순서로 실행됩니다.
    i가 증가하다가 반복조건에 맞지 않으면, 반복을 종료하고 빠져나옵니다.
    ```

- 그러나 위처럼 숫자를 출력하는 경우보다는, 반복문은 주로 리스트와 함께 쓰입니다.
     **반복문 예제**




    ```jsx
    let people = [&#39;철수&#39;,&#39;영희&#39;,&#39;민수&#39;,&#39;형준&#39;,&#39;기남&#39;,&#39;동희&#39;]

    // i가 1씩 증가하면서, people의 원소를 차례대로 불러올 수 있게 됩니다.
    for (let i = 0 ; i &lt; people.length ; i++) {
        console.log(people[i])
    }
    ```


        ```jsx
        let scores = [
            {&#39;name&#39;:&#39;철수&#39;, &#39;score&#39;:90},
            {&#39;name&#39;:&#39;영희&#39;, &#39;score&#39;:85},
            {&#39;name&#39;:&#39;민수&#39;, &#39;score&#39;:70},
          {&#39;name&#39;:&#39;형준&#39;, &#39;score&#39;:50},
          {&#39;name&#39;:&#39;기남&#39;, &#39;score&#39;:68},
          {&#39;name&#39;:&#39;동희&#39;, &#39;score&#39;:30},
        ]
        ```


    ```jsx
    let scores = [
        {&#39;name&#39;:&#39;철수&#39;, &#39;score&#39;:90},
        {&#39;name&#39;:&#39;영희&#39;, &#39;score&#39;:85},
        {&#39;name&#39;:&#39;민수&#39;, &#39;score&#39;:70},
      {&#39;name&#39;:&#39;형준&#39;, &#39;score&#39;:50},
      {&#39;name&#39;:&#39;기남&#39;, &#39;score&#39;:68},
      {&#39;name&#39;:&#39;동희&#39;, &#39;score&#39;:30},
    ]

    for (let i = 0 ; i &lt; scores.length ; i++) {
        console.log(scores[i]);
    }

    // 이렇게 하면 리스트 내의 딕셔너리를 하나씩 출력할 수 있고,
    ```

    ```jsx
    for (let i = 0 ; i &lt; scores.length ; i++) {
        if (scores[i][&#39;score&#39;] &lt; 70) {
            console.log(scores[i][&#39;name&#39;]);
        }
    }

    // 이렇게 하면 점수가 70점 미만인 사람들의 이름만 출력할 수도 있습니다.
    ```
</code></pre>]]></description>
        </item>
    </channel>
</rss>