와플스튜디오 세미나에 오신 것을 환영합니다!¶
웹 개발 세미나 (React & Django-REST)¶
0. Introduction¶
본 세미나에서는 웹 개발에 필요한 기본 지식들과 함께 React, Django-REST의 기본 개념 및 사용법을 같이 공부해보고, 실제로 간단한 웹앱을 만들어볼 것입니다. 웹 개발이라는 분야는 정말 방대하기 때문에 세미나에서는 핵심적인 개념들만을 주로 가르치고, 그 외에 필요한 부가적인 내용들은 실제 개발을 통해 스스로 찾아보면서 공부할 수 있도록 하는 것이 목적입니다. 공부하면서 어려운 것이 있으면 멘토분들이 적극적으로 도와주실 것이니 그런 기회를 잘 활용해서 모두가 나중에 있을 프로젝트에 같이 참여할 수 있는 실력을 쌓을 수 있기를 바랍니다.
세미나 진행방식¶
총 6개의 섹션으로 진행될 예정이고, 매 섹션마다 스스로 공부할 수 있도록 간단한 개발 과제가 나갈 것입니다. 그리고 마지막으로 공부했던 내용들을 모두 활용하여 실제로 사용 가능한 수준의 간단한 웹앱을 개발하는 프로젝트 과제가 나갈 것입니다. 이 과제들을 성실히 수행하시면 이후 프로젝트에 참여할 수 있는 자격을 가지게 됩니다.
또한 조마다 주기적으로 스터디 모임을 가져 과제하면서 어려운 것들을 도와줄 수 있도록 할 것입니다.
세미나 일정¶
- 9.15 : Introduction
- 9.22 : HTML & CSS
- 9.29 : Javascript & React 입문
- 10.13 : React
- 11.3 : Redux & Redux-saga
- 11.17 : Django REST
- 12.1 : Django REST 심화 및 웹앱 개발
웹앱(web app)이란?¶
데스크탑 앱이나 모바일 앱과 같은 기능을 제공하는 웹 서비스를 웹앱이라고 부릅니다. 보통 단순히 정보를 나열하면 웹사이트, 유저와의 인터랙션이 많으면 웹앱이라고 합니다. (ex. 페이스북)
프론트엔드/백엔드란?¶
웹 개발은 크게 프론트엔드(frontend) 개발과 백엔드(backend) 개발로 나눌 수 있습니다. 두 용어의 차이를 간단하게 얘기하면, 프론트엔드는 실제로 유저들이 보는 영역을 다루고, 백엔드는 서비스가 제대로 돌아갈 수 있도록 데이터를 저장, 가공, 제공하는 기능을 다루는 분야라 할 수 있습니다.
페이스북을 예로 들어봅시다.
프론트엔드:
- 유저가 실제로 보는 화면
- 유저가 뉴스피드를 스크롤할 때 서버(백엔드)에서 데이터를 받아와 유저에게 보여주는 기능
백엔드:
- 프론트엔드에서 데이터(ex. 뉴스피드 데이터)를 요쳥하면 그것을 데이터베이스에서 가져와 전달해주는 기능
- 유저의 데이터를 바탕으로 유저가 좋아할만한 글들을 골라주는 기능
- 누군가 댓글을 남겼을 때 유저한테 알림을 전달해주는 기능
개발 입문자를 위한 팁¶
- 구글링을 자주 합시다! 개발하면서 겪는 거의 대부분의 어려움들은 구글을 통해 해결할 수 있습니다...
- API 문서 읽는 연습을 합시다!
- 되도록이면 영어로 문서를 읽어버릇 합시다! 한글로 된 문서들도 어느정도 있긴 하지만 결국 언젠가는 영어 문서를 읽게 됩니다...
- Best Practice들을 자주 참고합시다! 어떤 문제를 해결하는데는 더 나은 해결책들이 있기 마련입니다. 입문자라면 best practice들을 자주 보고 참고하도록 합시다.
프로그래밍이 처음이라면?¶
1. HTML & CSS¶
이번 세션에서는 웹 개발의 가장 기본이 되는 HTML과 CSS에 대해 다뤄볼 것입니다. 처음에는 어디서부터 공부해야될지 감이 잘 안 올 수도 있지만 열심히 구글링하면서 개발하다보면 어느샌가 숙련되어있는게 HTML과 CSS입니다... (화이팅)
HTML이 뭔가요?¶
HTML은 간단하게 설명하자면 웹 페이지가 어떤 구조로 만들어져있는지를 설명해주는 언어라고 할 수 있습니다. 예를 들어, 어떤 문서를 웹 페이지로 만든다고 했을 때 그 문서의 제목, 부제목은 무엇인지, 문단의 내용은 무엇인지, 혹은 어떤 이미지가 있는지에 대한 정보를 담고 있는 언어라고 할 수 있습니다.
HTML이 어떻게 생겼는지를 대충 보여드리면 아래와 같습니다. (곧 익숙해질 것입니다)

HTML의 구조를 파헤쳐봅시다¶
HTML은 여러 개의 element로 구성되어있습니다. 먼저 간단한 HTML element의 예시를 살펴봅시다.
<p>Wafflestudio</p>
모든 element는 opening tag와 closing tag로 감싸져 있습니다. 여기서는 <p>가 opening tag, </p>가 closing tag에 해당됩니다.
또한 element는 tag의 종류에 따라서 다른 의미를 가집니다. 여기서 사용하고 있는 것은 p tag이며 text paragraph를 의미합니다. html tag는 이 외에도 굉장히 많으며 대표적으로는 div(다른 html element들을 포함하는 container), a(어떤 웹페이지/이메일/url을 가리키는 하이퍼링크), input(유저가 텍스트를 입력할 수 있는 창), button(클릭할 수 있는 버튼) 등이 있습니다.
opening tag와 closing tag 안에 있는 것은 content라고 부르며, 여기서는 text로만 이루어져있습니다.
또한 element는 attribute들을 가지기도 합니다. attribute는 해당 element에 담겨있는 추가적인 정보를 의미합니다. attribute의 대표적인 예시로는 class나 id가 있는데 이것이 어떤 쓸모가 있는지는 조만간 알게 될 것입니다.
<p class="paragraph" id="waffle">Wafflestudio</p>
element 안에 element를 넣을 수도 있습니다.
<p>와플스튜디오 <strong>세미나</strong>에 오신 것을 환영합니다.</p>
어떤 element들은 content를 안 가지기도 합니다. 대표적으로는 img tag가 있습니다.
<img src="assets/wafflestudio-logo.png">
조금 복잡한 구조를 살펴봅시다.
<html>
<head>
<meta charset="utf-8">
<title>Wafflestudio Seminar</title>
</head>
<body>
<div>
<h1>세미나 일정</h1>
<p>다음은 앞으로의 세미나 일정입니다. 추후에 변경될 수 있습니다.</p>
<ul>
<li>9.15 : Introduction</li>
<li>9.22 : HTML, CSS</li>
<li>9.29 : Javascript</li>
</ul>
<img src="wafflestudio-logo.png">
</div>
</body>
</html>
- <html> : html element. 웹페이지의 모든 것들을 담고 있는 element이며 root element라고 부르기도 함.
- <head> : head element. 유저에게 보여지는 content를 담고 있지는 않지만 웹페이지에 필요한 정보 등을 담고 있음.
- <body> : body element. 실제로 유저에게 보여지는 content를 담고 있음.
- <meta charset="utf-8"> : document가 사용하는 charcter set을 utf-8로 정의. 한글을 제대로 표시하려면 이것을 head에 포함해야함.
- <title> : 현재 페이지의 title. 보통 브라우저에서 탭에 띄워주는 문구.
- <div> : content를 div로 감싸고 있음.
- <h1> : heading 제목.
- <p> : paragraph.
- <ul> : bullet list.
- <li> : bullet list의 item
- <img> : image.
이 html 파일을 index.html로 저장하고 웹 브라우저에서 열면 다음과 같이 보일 것입니다. (이미지는 아무거나 넣고 img element에서 src를 그 파일명으로 수정해주시면 됩니다)

CSS가 뭔가요?¶
CSS는 HTML로 만든 웹페이지에 스타일을 씌워줘서 좀 더 보기 좋게 만들어주는 언어라고 생각하면 됩니다. 예를 들어, 어떤 글자의 색깔을 바꾸고 싶다던지, 폰트를 바꾸고 싶다던지, 혹은 이미지의 배치를 바꾸고 싶다던지 할 때 쓰는 언어입니다.
CSS 쓰는 법을 알아봅시다.¶
CSS를 쓰려면 일단 HTML에서 link를 해줘야 합니다. styles 폴더 안에 style.css라는 파일을 만들어서 html의 head tag 안에 다음 줄을 붙여넣어 봅시다. 참고로 href="styles/style.css"라고 한 것은 현재 경로를 기준으로 styles라는 폴더 안에 있는 style.css라는 파일을 의미합니다. 경로만 잘 설정해준다면 파일을 어디에 넣던지, 어떤 이름으로 만들어주던지 상관 없습니다.
<link href="styles/style.css" rel="stylesheet" type="text/css">
style.css에 다음 코드를 붙여넣어 봅시다.
p {
color: blue;
}
이제 index.html을 브라우저에서 열면 다음과 같이 보일 것입니다.

위에서 붙여넣은 코드에서 중괄호 앞에 있는 p는 p tag들에 해당 style을 적용한다는 것을 의미합니다.(selector라고 부름) 그리고 중괄호 안에 있는 color: blue는 p tag 안에 있는 text의 색깔을 blue로 지정해준다는 것을 의미합니다. (color는 property, blue는 property value라고 부름)
색깔 외에도 몇 가지 성질들을 더 추가해볼 수 있습니다.
p {
color: blue;
border: 1px solid black;
background-color: #ccffcc;
}
border: 1px solid black은 1px 크기의 검은색 경계선을 만든다는 의미이고, background-color: #ccffcc는 배경 색깔을 #ccffcc(색깔 hex code)로 만든다는 의미입니다. 이것을 브라우저에서 열면 다음과 같이 보입니다.

selector에는 tag selector 이외에도 여러 종류가 있는데, 대표적으로는 id selector와 class selector가 있습니다. 작업하던 html의 h1 tag에 다음과 같이 class를 추가해봅시다.
<h1 class="heading">세미나 일정</h1>
style.css에 다음과 같은 코드를 추가해봅시다. 이 코드는 heading이라는 class를 가진 element들의 color를 red로 만들어주는 것을 의미합니다. class selector는 class 이름 앞에 .을 붙이면 됩니다.(id selector는 앞에 #을 붙이면 됨)
.heading {
color: red;
}
이제 브라우저에서 띄우면 다음과 같이 보일 것입니다.

CSS box model에 대해 알아봅시다¶
앞에서는 CSS를 이용해 글자의 색깔, border의 색깔 등을 바꾸는 방법을 알아보았습니다. 그런데 element간의 간격이나 배치 등을 바꾸기 위해서는 어떻게 해야할까요? 그래서 필요한 것이 css box model입니다.

브라우저의 rendering engine은 모든 element를 직사각형 box로 취급합니다. 가장 안쪽에는 content area(실제 content가 들어있는 영역)가 있고, 그 밖에는 padding area(여백 영역), 그 다음에는 border area(경계선), 그리고 마지막으로 margin area(다른 element와 겹치지 않는 영역)가 있습니다.
실제로 style.css에 적용을 해봅시다. margin: 20px는 margin을 모두 20px로 준다는 의미이고, padding: 30px 5px 10px 5px(차례대로 top, right, down, left)은 위쪽 padding은 30px, 양옆 padding은 5px, 아래쪽 padding은 10px로 준다는 의미입니다.
p {
color: blue;
border: 1px solid black;
background-color: #ccffcc;
margin: 20px;
padding: 30px 5px 10px 5px;
}
이제 브라우저에서 띄우면 다음과 같이 보일 것입니다.

Flexbox (보충)¶
div element 여러 개를 앞쪽에 배치하고 싶다던지, 뒤쪽에 배치하고 싶다던지, 혹은 중간에 배치하고 싶을 때는 어떻게 할까요? 그래서 나온 것이 flexbox입니다.
그럼 flexbox를 이용한 간단한 예시를 살펴보겠습니다.
<html>
<head>
<meta charset="utf-8">
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<!-- class="container container-1"은 container, container-1 class를 동시에 가지고 있는 것을 의미합니다.
중간에 공백으로 구분해주면 이렇게 여러 개의 class를 넣을 수도 있습니다. -->
<div class="container container-1">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
<div class="container container-2">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
<div class="container container-3">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
<div class="container container-4">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
<div class="container container-5">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
</body>
</html>
.item {
width: 100px;
border: 1px solid black;
}
.container {
margin: 20px 0px;
border: 1px solid red;
display: flex; /* 이렇게 display를 flex로 설정해주면 해당 element는 flex container가 됩니다. */
}
.container-1 {
justify-content: flex-end; /* 뒤에부터 차곡차곡 쌓기 */
}
.container-2 {
justify-content: flex-start; /* 처음부터 차곡차곡 쌓기 */
}
.container-3 {
justify-content: center; /* 중간에 배치 */
}
.container-4 {
justify-content: space-between; /* item 사이의 간격을 일정하게 */
}
.container-5 {
justify-content: space-around; /* item 사이와 양 끝의 간격을 일정하게 */
}
위의 html과 css를 각각 저장하고 브라우저에서 열어보면 다음과 같이 보일 것입니다.

이렇게 display: flex로 flex container를 만들어주고 justify-content를 적절히 설정해주면 원하는 레이아웃대로 배치할 수 있습니다. 한 번씩 시도해보시기 바랍니다. flexbox를 더 자세히 알아보고 싶다면 아래 읽을거리에 첨부한 사이트들을 참고해주세요.
(IE 브라우저에서는 flexbox가 잘 작동하지 않을 수도 있습니다. 대응하는 방법도 있긴 하지만 많이 귀찮으니 Chrome이나 Edge 등 다른 브라우저를 사용하길 권장합니다)
읽을거리¶
과제¶
HTML과 CSS만을 이용해서 구글 홈페이지 목업 만들기

필요한 이미지는 구글 홈페이지에서 직접 다운받을 수 있습니다.
과제를 하려면 세미나에서 다룬 내용 외에 직접 찾아보면서 공부해야할 것들도 좀 있을 것입니다. 위에 추가된 flexbox 보충자료와 읽을거리를 참고해주세요. (하단 바를 어떻게 구현해야할지 모르겠다면 CSS Layout - The position Property를 읽어보세요)
2. Javascript¶
이번 세션에서는 Javascript에 대해 다뤄볼 것입니다. 이미 하나 이상의 언어로 프로그래밍 경험이 있다고 생각하고 진행되기 때문에 아직 프로그래밍이 익숙하지 않은 분들은 따로 공부를 해주시길 바랍니다. (프로그래밍이 처음이라면? 참고)
Javascript가 뭔가요?¶
Javascript는 웹페이지에 좀 더 다이내믹한 기능을 제공하기 위해서 개발된 언어입니다. Javascript를 활용하면 유저로부터 인풋을 받아 필요한 작업을 수행할 수도 있고, 웹페이지를 더 다이내믹하게 만들 수도 있습니다. 웹앱을 개발하기 위해서는 필수적이라고 할 수 있습니다. 또한 최근에는 웹을 벗어나서 다양하게 사용이 되고 있는 추세이므로 배워두면 여러모로 쓸모가 있을 것입니다.
Hello World!¶
Javascript를 이용해 화면에 Hello World를 띄워봅시다.
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1 id="header"></h1>
<!-- onClick의 value를 what()으로 넣어주면 click할 때 what 함수를 실행 -->
<button onClick="what()">click!</button>
<!-- 이렇게 script를 link해줘야 script가 실행됨. css를 link하는 것과 비슷.
보통은 body tag가 끝나기 직전에 넣어주는 것이 좋음.
그 이유는 더 앞쪽에서 넣어줄 경우 document가 다 로드되지 않아 스크립트에서 어떤 document 정보에 접근하지 못할 수도 있기 때문.-->
<script src="index.js"></script>
</body>
</html>
function what() { // what이라는 함수를 정의. 인자는 아무것도 받지 않음.
var header = document.getElementById('header'); // header라는 id를 가진 element를 찾음
header.textContent = 'Hello world!'; // header의 text content를 'Hello world'로 바꾼다.
}
위의 html 파일을 index.html로 저장하고, 밑에 javasciprt 파일을 index.js로 같은 폴더에 저장하고 index.html을 브라우저에서 열어봅시다. 그리고 click 버튼을 눌러보면 아래 사진처럼 Hello World가 뜨는 것을 확인할 수 있을 것입니다.

무슨 일이 일어난 것인지 정리해보자면 다음과 같습니다. index.js가 실행이 되면서 what()이라는 함수를 정의했고, 이 함수가 하는 일은 header라는 id를 가진 element를 찾아 그 element의 내용을 'Hello World!'로 바꾸는 것입니다. 그리고 index.html에서는 button의 onClick attribute에 what()을 넣어줘서, button이 클릭되었을때 what()을 실행시킬 수 있도록 연결해주었습니다. 따라서 button을 누르면 what()이 실행되면서 h1 tag의 content를 `Hello World!`로 바꾼 것입니다.
개발자 도구 콘솔¶
개발자 도구의 콘솔에서도 Javascript를 실행할 수 있습니다. 콘솔 창을 열어서 alert('hello world!')를 입력하면 아래와 같이 경고창이 뜨는 것을 확인할 수 있을 것입니다.

타입과 연산자¶
Javascript에 있는 타입과 연산자들에 대해 알아봅시다.
Javascript는 다른 컴파일 언어와 다르게 어떤 변수가 어떤 타입의 데이터를 가지고 있는지 정해져있지 않습니다. 그냥 코드가 실행될 때 타입이 결정됩니다. 이를 dynamic typing이라고 부르기도 합니다. 변수를 정의하는 방법에는 다음과 같은 것들이 있습니다. (let과 const는 최근 표준이라 몇몇 브라우저에서는 아직 작동하지 않을 수도 있습니다.)
var a // 이렇게 정의하면 스크립트가 실행되기 전에 미리 변수 a가 정의됨. hoisting이라고 부름.
let a // block 안에서만 사용할 수 있게 scoping 됨.
const a // let과 마찬가지로 block scoping이 되지만 다시 대입하는걸 방지함.
Javascript의 기본 타입(primitive type)에는 다음과 같은 것들이 있습니다.
- undefined : 값이 정의되지 않았음을 의미합니다. (변수를 정의하기만 하고 값을 넣어주지 않으면 undefined가 뜹니다)
- null : 값이 없음을 의미합니다. (값이 없다는 의미를 표현하고 싶을 때는 웬만하면 undefined보다는 null을 씁시다)
- boolean : true 혹은 false
- number : 정수, 소수 구분없이 모든 숫자는 number type (ex. 1, 2, 5.4 등등)
- string : 문자열 (ex. 'hello', 'world' 등등)
연산자들에는 다음과 같은 것들이 있습니다. 각자 콘솔에서 이것저것 시험해보시기 바랍니다.
6 + 9 // 15
"Hello " + "world!" // "Hello world!"
9 - 3 // 6
8 * 2 // 16
9 / 3 // 3
var a = 3 // a에 3을 대입
3 === 4 // false
"hello" === "hello" // true
!(false) // true
3 !== 4 // true
true && true // true
true && false // false
true || false // true
Coercion : 연산을 할 때 type이 알아서 바뀌기도 합니다. 유독 Javascript에서는 독특한 특징도 많고 자주 쓰이니 알아두면 좋을 것입니다.
1 + "2" // "12"
false == 0 // true
"" == 0 // true
null == undefined // true
== vs === : ===는 좀 더 strict하게 equality를 체크하는 연산자입니다. ===로 체크하면 coercion이 일어나지 않습니다. coercion을 의도한게 아니라면 항상 ===를 쓰도록 합시다!
조건문과 반복문¶
조건문과 반복문은 다른 언어와 비슷하니 조건문 - 생활코딩과 반복문 - 생활코딩를 참고하시기 바랍니다.
배열(Array)¶
객체(Object)¶
Javascript에서 Object는 name/value pair로 이루어져있습니다.
var tony = {
firstname: 'Tony', // firstname이라는 name에 'Tony'라는 value
lastname: 'Alicea',
address: { // object를 value로 가질 수도 있음.
street: '111 Main St.',
city: 'New York',
state: 'NY'
}
};
console.log(tony.firstname) // 'Tony'
console.log(tony.address.street) // '111 Main St.'
console.log(tony['firstname']) // 'Tony'
tony.lastname = 'Suh' // 이렇게 값을 대입할 수도 있음
console.log(tony.lastname) // 'Suh'
tony['lastname'] = 'Kim'
console.log(tony.lastname) // 'Kim'
tony.age = 20 // 이렇게 새로운 값을 넣어줄 수도 있음
console.log(tony.age) // 20
function greet(person) {
console.log('Hi ' + person.firstname);
}
greet(tony) // 'Hi Tony'
JSON : JavaScript Object Notation. Javascript object를 문자열(string)으로 만든 것으로 서버와 데이터를 주고 받을 때 자주 쓰는 형태입니다.
var obj = JSON.parse('{ "firstname": "Mary", "isAProgrammer": true }')
console.log(obj)
console.log(JSON.stringify(obj))
함수(Function)¶
Javascript에서 함수는 객체로 취급됩니다. 그래서 함수를 변수(variable)에 대입할 수도 있고, 다른 함수에 인자로 전달해줄 수도 있고, 어디서든지 만들 수도 있습니다. 이러한 성질을 first class function이라고 부릅니다.
Statement vs Expression : statement는 어떤 작업을 수행하라는 명령문이고 expression은 결과값이 나오는 코드 단위를 의미합니다. (ex. a = 3 은 expression, if (a == 3) {} 는 statement)
greet();
// function statement
function greet() {
console.log('hi');
}
// function expression
var anonymousGreet = function() { // anonymous function
console.log('hi');
}
anonymousGreet();
function log(a) {
a();
}
log(function() {
console.log('hi');
});
By Value vs By Reference :
- b = a에서 a가 primitive value이면, b는 그 primitive value의 copy를 가리키게 된다(by value)
- b = a에서 a가 object나 function이면, b는 a가 가리키고 있던 object를 가리키게 된다(by reference)
Immediately Invoked Function Expressions :
var greeting = function(name) {
return 'Hello ' + name;
}('John'); // 함수를 만들고 바로 실행
console.log(greeting); // result : Hello John
Closure¶
Javascript는 함수 안에서 함수를 정의할 수도 있습니다.
function a() { // 외부 함수 (outer function)
var name = 'Heesu';
function greet() { // 내부 함수 (inner function)
console.log('Hello, ' + name);
}
greet();
}
a(); // Hello, Heesu
내부 함수는 외부 함수에서 선언된 변수들에 접근할 수 있습니다. 그래서 greet에서 name 변수에 접근할 수 있는 것입니다.
그럼 다음 예제를 살펴봅시다.
function makeGreet(name) { // 함수를 만들어 리턴하는 함수
return function greet() {
console.log('Hello, ' + name);
}
}
var greetHeesu = makeGreet('Heesu'); // greetHeesu는 함수
var greetDonghoon = makeGreet('Donghoon');
greetHeesu(); // Hello, Heesu
greetDonghoon(); // Hello, Donghoon
greetHeesu와 greetDonghoon은 makeGreet에서 만들어진 함수들입니다. greetHeesu는 makeGreet에 'Heesu'를 인자로 넘겨서 나온 함수이고, greetDonghoon은 makeGreet에 'Donghoon'을 인자로 넘겨서 나온 함수입니다. 그런데 언뜻보면 정말 이상합니다. makeGreet 함수의 실행이 끝나고 나면 name 변수에는 더 이상 접근 못하는게 당연할 것 같은데, 어떻게 greetHeesu랑 greetDonghoon은 이전에 전달해준 name variable에 접근할 수 있는 걸까요?
이러한 성질을 Closure라고 부릅니다. 함수 안에서 함수를 정의하면 내부함수는 외부함수의 실행이 끝나고 나서도 외부함수의 변수에 접근할 수 있습니다. 그러니까 makeGreet에서 정의된 name 변수는 어딘가에 남아있어서, greetHeesu에서는 'Heesu'값을 가진 name 변수에 접근할 수 있고, greetDonghoon은 'Donghoon'값을 가진 name 변수에 접근할 수 있는 것입니다.
다음은 Closure를 이용한 다른 예시입니다.
function makeGreeting(language) {
return function(name) {
if (language === 'en') {
console.log('Hello ' + name);
}
if (language === 'ko') {
console.log(name + '님 안녕하세요 ');
}
}
}
var greetEnglish = makeGreeting('en');
var greetKorean = makeGreeting('ko');
greetEnglish('Heesu Suh');
greetKorean('서희수');
과제¶

추석 때 다들 편하게 쉬시라고 이번 과제는 특별히 쉬운걸 준비했습니다.
위의 사진처럼 직각삼각형 모양으로 별을 찍는건데, Add 버튼을 누르면 아래에 한 줄씩 추가하고, Remove 버튼을 누르면 아래에서부터 한 줄씩 삭제해주는 것입니다.
JavaScript HTML DOM Elements와 JavaScript HTML DOM Elements (Nodes)를 참고해주세요.
혹시 마지막 줄을 어떻게 삭제해야할지 모르겠으면 Node.lastChild를 참고하셔도 됩니다.
3. React¶
이번 세션에서는 React라는 라이브러리(라이브러리란?)에 대해 다뤄볼 것입니다. 요새 현업에서 많이 쓰이는 핫한 라이브러리입니다.
React같은 라이브러리를 왜 써야하나요?¶
간단한 웹앱의 경우에는 굳이 라이브러리를 쓰지 않아도 쉽게 개발할 수 있습니다. 하지만 좀만 복잡해지면 React와 같은 라이브러리 없이 개발하는 것은 굉장히 고통스러운 일이 됩니다.
페이스북 댓글창 같은 기능을 생각해봅시다. 어떤 유저가 새로운 댓글을 남기거나, 댓글 더 보기를 누르거나, 혹은 댓글을 숨기거나 하면 댓글창의 View를 업데이트해줘야합니다. 그런데 이걸 appendChild나 removeChild 같은 함수를 이용해서 일일이 해줘야 한다면 개발 시간도 더 오래 걸리고, 코드 관리도 어려워질 것입니다. 거기다가 새로운 기능을 구현하려 한다면 또 그에 맞게 View를 업데이트해주는 함수를 만들어야 하니 규모가 커지면 커질수록 이는 고통스러운 일이 될 것입니다. 그래서 이렇게 View를 업데이트하는 일을 훨씬 간단하게 만들어주고자 React와 같은 라이브러리가 등장한 것입니다.
React 외에도 비슷한 일을 해주는 라이브러리/프레임워크로는 Angular나 Vue 등이 있습니다. 이 라이브러리/프레임워크들 간의 비교는 구글링해보면 많은 자료들이 나오니 궁금하신 분들은 찾아서 보시기 바랍니다.
개발 환경 세팅¶
- Node.js 최신버전을 설치합니다.
- Create React App으로 새로운 React App을 만듭니다.
ES6¶
ES6는 Javascript의 새로운 표준을 말합니다. 기존 표준에 비해 새로운 문법들이 많이 추가되었습니다. 앞으로 ES6의 문법을 많이 사용할 예정입니다. ES6의 새로운 문법에 대해서는 Top 10 ES6 Features Every Busy JavaScript Developer Must Know에 잘 정리되어있으니 참고하시기 바랍니다.
React 기본 개념 : Component¶
Create React App을 이용해 만든 App의 src/App.js 파일을 열어봅시다.
import React from 'react';
import logo from './logo.svg';
import './App.css';
class App extends React.Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;
React에서는 View를 Component단위로 관리합니다. 재사용 가능한 Component로 나눔으로써 코드의 반복도 줄일 수 있고, 또한 특정 기능을 단위로 Component로 나눔으로써 관심사 분리(separation of concern)를 이루어 코드를 좀 더 체계적으로 관리할 수 있게 됩니다.
모든 React Component들은 React.Component를 상속합니다. 그리고 반드시 render 함수를 오버라이딩해야합니다. 이 render 함수는 화면에 어떤 것을 보여줄지를 알려주는 역할을 합니다. React에서는 이 render 함수를 이용해 화면에 어떻게 보여질지를 계산하고 필요한 부분만 효과적으로 업데이트합니다.
React에서는 보통 JSX라는 확장된 문법을 사용합니다.(위에 render 함수 안에서 사용한 문법) 이 문법은 HTML과 비슷하지만 그 안에 Javascript Code를 넣을 수 있는 등 더 다양한 일을 할 수 있습니다. 사용법은 차차 알아보도록 합시다.
React 기본 개념 : State¶
React에서 가장 중요한 기능은 데이터 바인딩(데이터를 업데이트하면 View를 알아서 업데이트)이라고 할 수 있습니다. 이 데이터는 Component의 State 안에 저장될 수도 있고, 부모 Component에서 Props로 전달받을 수도 있습니다. 먼저 State에 대해 알아봅시다.
App.js 파일을 다음과 같이 수정해봅시다.
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = { // 이렇게 state를 정의합니다.
count: 0,
};
this.handleClick = this.handleClick.bind(this); // handleClick 함수 안에서 this가 이 Class를 가리키도록 하려면 bind(this)를 해줘야 합니다.
}
handleClick() {
this.setState({ // setState를 통해 state 값을 업데이트합니다.
count: this.state.count + 1,
});
}
render() {
return (
<div>
<button onClick={this.handleClick} >click!</button>
<p>{this.state.count}</p>
</div>
);
}
}
export default App;
State는 단어 그대로 Component의 상태를 나타낸다고 생각하면 됩니다. State를 사용하려면 constructor에서 this.state로 정의를 해주고, 값을 업데이트하려면 this.setState 함수를 이용하면 됩니다. 위에서는 count 값을 1 증가시키는 handleClick이라는 함수를 만들어서 button의 onClick에 넣어주었습니다. (JSX에서는 {} 안에 Javascript Expression을 사용할 수 있습니다) 그리고 p tag 안에 this.state.count 값을 출력하도록 하였습니다. 브라우저에서 띄워보고 click 버튼을 눌러보세요.
React 기본 개념 : Props¶
Component가 많아지고 점점 구조가 복잡해질수록 상위 Component에서 데이터를 관리해야할 필요를 느낄 것입니다. 그 데이터가 하나의 Component에서만 쓰이는 게 아니라 여러 Component에서 쓰일 때 그렇죠. 그러면 상위 Component에서 데이터를 관리한다고 했을 때 그것을 하위 Component로 전달하려면 어떻게 해야할까요? 그 때 사용하는게 Props입니다.
src 폴더에 Comment.js라는 파일을 만들어서 다음 코드를 붙여넣어 봅시다.
import React from 'react';
class Comment extends React.Component {
render() {
return (
<div style={{display: 'flex', border: '1px solid black', padding: '5px', marginBottom: '5px'}}>
<img src={this.props.avatarUrl} alt={this.props.name} width="50px" height="50px" />
<div style={{marginLeft: '10px'}}>
<div style={{fontWeight: 'bold', marginBottom: '5px'}}>{this.props.name}</div>
<div>{this.props.text}</div>
</div>
</div>
);
}
}
export default Comment;
그리고 App.js 파일을 다음과 같이 수정해봅시다.
import React from 'react';
import Comment from './Comment';
class App extends React.Component {
render() {
return (
<div style={{padding: '10px'}}>
<Comment avatarUrl={'http://via.placeholder.com/50x50'} name={'Mark Zuckerberg'} text={'I want Instagram'} />
<Comment avatarUrl={'http://via.placeholder.com/50x50'} name={'Elon Musk'} text={'Then buy it'} />
</div>
);
}
}
export default App;
위에 App.js 파일에서도 볼 수 있듯이 Component 안에서 Component를 사용할 수 있습니다.(Comment.js 파일에서 Comment Component를 import해서 사용) 그리고 Comment Component에 avatarUrl, name, text라는 prop들을 전달해주고 Comment Component에서 그것을 this.props로 받아서 쓰고 있는 것을 볼 수 있습니다.
아래 코드는 이 데이터를 상위 컴포넌트에서 state로 관리하고 있는 예시입니다.
import React from 'react';
import Comment from './Comment';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
comments: [
{
writer: {
name: 'Mark Zuckerberg',
avatarUrl: 'http://via.placeholder.com/50x50',
},
text: 'I want Instagram',
}, {
writer: {
name: 'Elon Musk',
avatarUrl: 'http://via.placeholder.com/50x50',
},
text: 'Then buy it',
}
]
}
}
render() {
return (
<div style={{padding: '10px'}}>
{
this.state.comments.map((comment, index) => (
<Comment key={index} avatarUrl={comment.writer.avatarUrl} name={comment.writer.name} text={comment.text} />
))
}
</div>
);
}
}
export default App;
map 함수에 대해서는 Array.prototype.map() - MDN을 참고하세요.
React Tutorial : Tic Tac Toe¶
기본적인 개념들을 살펴보았으니 이제 React 공식 튜토리얼을 따라가면서 더 알아보도록 합시다.
기본 뼈대 코드는 https://www.dropbox.com/s/ywaw6xo5z8jkdwq/tic-tac-toe.zip?dl=0 에 올려놓았으니 참고하시기 바랍니다.
세미나에서는 Storing a History 전까지만 다룰 예정이지만, 그 이후 내용도 혼자서 해보시면 좋을 것 같습니다.
과제¶
간단한 To-Do List 만들기
기본 화면은 아래와 같이 생겼습니다.

아이템을 클릭하면 아래와 같이 완료되었다는 표시를 해줍니다.

Show: 에서 Active를 클릭하면 아직 완료되지 않은 아이템들만을 보여줍니다.

Show: 에서 Completed를 클릭하면 완료된 아이템들만을 보여줍니다.

인풋창에 텍스트를 입력하고 Add Todo 버튼을 누르면 새로운 아이템을 추가해줍니다.

Delete 버튼을 누르면 아이템을 삭제해줍니다.

4. Redux & Redux-saga¶
이번 세션에서는 Redux라는 라이브러리에 대해 다뤄볼 것입니다.
세미나 진행은 공식 튜토리얼을 따라가면서 할 예정입니다. 자료는 공식 홈페이지를 참고해주세요. (한글 번역판도 있습니다. 참고)
과제¶
저번에 과제로 만들었던 To-Do List를 Redux를 이용해서 만들어봅시다. 그리고 추가로 '완료된 항목 삭제' 기능을 만들어봅시다.
아래 화면에서 Clear Completed 버튼을 누르면 완료된 항목들을 삭제해주면 됩니다.
심심하면 기능도 더 추가하고 디자인도 바꿔보세요.
