• 기술
  • 후기
  • 생각

짧고 개인적인 웹 프론트엔드 성장역사

작성자 프로필이미지문정민
··10분 읽기

웹 성장 역사를 돌아보자🔗

누군가와 함께 커피를 마시는 것이 아니라 혼자서 커피타임을 하고 있으면, 가끔 추억에 젖을 때가 있지 않나요? 근데 하필 코딩을 하다가 추억에 젖어서 그런지, 지금 제가 개발하고 있는 환경과 처음 접한 환경의 차이가 상당히 크다는 것이 생각나 과거로 과거로 꼬리를 좇아가보게 되었습니다. 이 참에 한 번 글로 작성해보려 합니다.

세이클럽에서 웹과의 첫 만남🔗

초등학교때 제가 사는 지역에서는 세이클럽이라는 SNS가 불같이 퍼져갔고, 결국 저도 가입했습니다. 그곳에서 친구들과 쪽지를 보내며 방과후에 공을차며 친구를 직접만나지 않고도 이야기를 이어 나갈 수 있다는 것이 너무 재미있었습니다.

좀 더 나아가서, 세이클럽에는 카페같은 “클럽”이라는 모임이 있었는데, 이것을 기반으로 반모임같은 그룹에 모여서 글도 쓰곤 했습니다. 그런데 이 클럽에 글을 작성하거나 할 때 html을 수정해서 스크립트나 css를 수정할 수 있었습니다. 지금이야 그것은 보안상 굉장히 위험한 일이라는 것을 알지만, 그 당시에 제게는 너무나 혁명적인 기능이었습니다. 마우스에 나뭇잎을 따라다니게 한다거나, 배경에 눈이 내리게 하고, 음악을 넣는 등. 그런 코드 조각을 모아놓은 카페나 클럽에서 긁어서 수정하면 실제로 그렇게 되는 것이 정말 재미있었고, 마치 프로그래머가 된 것 같았습니다.

평범하게 중고등학교에 진학했습니다. 뜬금없게도 저는 음악을 하는 사람이 되고 싶어 보충수업과 야자는 면제받고 입시를 위해 피아노, 청음, 화성학 같은 레슨을 받곤했습니다. 그러나 여전히 내 깊은곳에서 부터의 흥미와 의지는 컴퓨터에 대한 관심으로 꾸준히 기울었고, 변곡점이 있었지만 결국, 소프트웨어공학을 선택합니다.

학부시절에 경험한 웹 프론트엔드🔗

첫 만남을 이야기하기 전에 제 감정을 좇아가다보니 처음에 웹을 바라보았던 저의 시선에 닿았습니다.

웹은 개발자의 영역이 아니야!🔗

아… 부끄럽지만 정말 그렇게 생각했습니다. 세상을 보는 눈이 많이 편협했습니다.

2학년 때 ”웹 프로그래밍”이라는 별도의 수업이 있었지만, 정말 싫었습니다. 컴퓨터과학의 심연을 제대로 느껴 볼 수 있을 것 같은 C/C++은 고귀해 보였고, <div>와 <table>같은 마크업언어로 뭔가 화면에 그리는 것은 필요는 하지만, 재미없으며 근본적으로 개발이 아니라고 생각했습니다. 그 오해는 한동안 계속되어 아마 그간 제가 알지 못했던 많은 기회를 놓쳤을지도 모릅니다.

PHP🔗

2학년이 되어 데이터베이스 수업을 듣게되었습니다. 수업을 들으면 의례 과제도 해야하죠. 데이터베이스는 사실 눈에 보이는 모양이랄 게 없습니다. 그 결과는 하드디스크에 저장되어 있을 뿐이니까요. DB를 설계하고 데이터를 입력하고 조회하고 삭제하고 수정하는 이 과정을 눈으로 확인시키려면 이것을 시각화하는 껍데기가 있어야 합니다.

이 껍데기, 즉 DB의 표현수단은 웹이었습니다. 그게 과제를 하기 위한 필수 요구사항이었는지는 잘 기억나지 않습니다. 그러나 저는 이 과제를 통해 웹을 처음 했습니다. 이때 사용한 것은 PHP였습니다. 그 당시 한참을 노력하고 있었던 언어는 C/C++였고, 그와 비슷한 문법을 사용할 수 있어 가장 편하다고 느꼈습니다.

<?php
// Database 연결 설정
$db_host = "localhost";
$db_user = "user";
$db_password = "password";
$db_name = "my_database";

// MySQL DB 연결
$conn = mysqli_connect($db_host, $db_user, $db_password, $db_name);

// 연결 확인
if(mysqli_connect_errno($conn)){
echo "DB 연결 실패: " . mysqli_connect_error();
}

// 쿼리 작성
$query = "SELECT * FROM students";

// 쿼리 실행
$result = mysqli_query($conn, $query);
?>
<html>
<head>
<title>Untitles</title>
</head>
<body>
<h1>학생 목록</h1>
<table>
<tr>
<th>아이디</th>
<th>이름</th>
<th>전공</th>
</tr>

<?php
// 레코드를 한 줄씩 읽어옴
while($row = mysqli_fetch_assoc($result)) {
?>

<tr>
<td><?php echo $row['id']; ?></td>
<td><?php echo $row['name']; ?></td>
<td><?php echo $row['major']; ?></td>
</tr>

<?php
}
// DB 연결 해제
mysqli_close($conn);
?>

</table>
</body>
</html>
<?php
// Database 연결 설정
$db_host = "localhost";
$db_user = "user";
$db_password = "password";
$db_name = "my_database";

// MySQL DB 연결
$conn = mysqli_connect($db_host, $db_user, $db_password, $db_name);

// 연결 확인
if(mysqli_connect_errno($conn)){
echo "DB 연결 실패: " . mysqli_connect_error();
}

// 쿼리 작성
$query = "SELECT * FROM students";

// 쿼리 실행
$result = mysqli_query($conn, $query);
?>
<html>
<head>
<title>Untitles</title>
</head>
<body>
<h1>학생 목록</h1>
<table>
<tr>
<th>아이디</th>
<th>이름</th>
<th>전공</th>
</tr>

<?php
// 레코드를 한 줄씩 읽어옴
while($row = mysqli_fetch_assoc($result)) {
?>

<tr>
<td><?php echo $row['id']; ?></td>
<td><?php echo $row['name']; ?></td>
<td><?php echo $row['major']; ?></td>
</tr>

<?php
}
// DB 연결 해제
mysqli_close($conn);
?>

</table>
</body>
</html>
엉망이었던 그 시절 코드 재현

이런식으로 작성했던 그 때의 웹 코딩스타일을 떠올려 봅니다. PHP파일 안에서 DB 정보를 하드코딩으로 입력하고 접속했던 것이 너무 재미있네요. 지금도 저렇게 한다면 재앙입니다. 파일명이 곧 URL이었고, 대응되는 URL마다 저렇게 수십개의 파일을 복붙해가며 만들었던 기억이 새록새록납니다.

다시 한 번 글의 목표를 상기해, 추억을 따라 프론트엔드의 변화에 집중하려고 합니다. 사실 위의 코드는 엉망이었던 코드의 예시로 소개했지만, 그럼에도 제게 너무 놀라웠던 것은 반복문을 사용해서 HTML을 만들 수 있다는 것입니다. 그러니 .html 파일이 아닌 .php를 작업하는 것이었고, 서버에서 계산된 결과로 HTML이 생성되는 것이었습니다.

저 경험을 했을때 정말 프로그래밍이라는 수단이 강력하다는 것을 다시 한번 느꼈었지 않았을까 싶습니다.

JSP🔗

또 얼마간의 시간이 흘러 JSP를 접했습니다. 어디서 처음 접하게 되었는지는 정확히는 기억나지 않습니다. 그러나 그 당시 주력하던 Java를 사용하여 역시 HTML을 구성할 수 있었습니다. HTML 구성하는 방식은 PHP와 비슷했습니다. 그럼에도 뭔가 구조적으로 안정되어 있다는 느낌은 많이 받았던 기억이 납니다. 둘은 많이 다르겠지만, 다시한 번 여기서는 HTML의 표현하는 부분에만 집중하겠습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Student List</title>
<style>
.cs {
background-color: lightgreen;
}
.non-cs {
background-color: lightblue;
}
</style>
</head>
<body>
<%
class Student {
String name;
int age;
String major;

Student(String name, int age, String major) {
this.name = name;
this.age = age;
this.major = major;
}
}

ArrayList<Student> students = new ArrayList<Student>();
students.add(new Student("문정민", 20, "컴퓨터공학과"));
students.add(new Student("홍길동", 21, "기계공학과"));
students.add(new Student("존 도", 22, "경영학과"));
%>
<table border="1">
<tr>
<th>Name</th>
<th>Age</th>
<th>Major</th>
</tr>
<%
for (Student student : students) {
String rowClass = student.major.equals("컴퓨터공학과") ? "cs": "non-cs";
%>
<tr class="<%= rowClass %>">
<td><%= student.name %></td>
<td><%= student.age %></td>
<td><%= student.major %></td>
</tr>
<%
}
%>
</table>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Student List</title>
<style>
.cs {
background-color: lightgreen;
}
.non-cs {
background-color: lightblue;
}
</style>
</head>
<body>
<%
class Student {
String name;
int age;
String major;

Student(String name, int age, String major) {
this.name = name;
this.age = age;
this.major = major;
}
}

ArrayList<Student> students = new ArrayList<Student>();
students.add(new Student("문정민", 20, "컴퓨터공학과"));
students.add(new Student("홍길동", 21, "기계공학과"));
students.add(new Student("존 도", 22, "경영학과"));
%>
<table border="1">
<tr>
<th>Name</th>
<th>Age</th>
<th>Major</th>
</tr>
<%
for (Student student : students) {
String rowClass = student.major.equals("컴퓨터공학과") ? "cs": "non-cs";
%>
<tr class="<%= rowClass %>">
<td><%= student.name %></td>
<td><%= student.age %></td>
<td><%= student.major %></td>
</tr>
<%
}
%>
</table>
</body>
</html>

뭔가 발전하고 있었지만 느끼고 있던 답답함🔗

여기까지 순수 PHP, JSP를 경험하고 이것을 이용해 웹을 만들며 답답한 부분들이 생겼습니다. 하고싶은건 많고 웹사이트를 서핑하며 멋진 것은 다 경험했는데, 나는 아직 만들지 못하는 것들이었습니다.

템플릿 문법이 쿨하지 못하다고 느낌🔗

데이터에 맞게 HTML을 표현하려면 JSP같은 서버템플릿 언어를 이용해야 했습니다. 조건에 따라 분기하기 위해 HTML중간에 <% SOMETHING %> 이런 문법을 끼워넣어야 했고 여기에 { 중괄호 같은 단 한글자를 적어야 할 때도 있었습니다.

이런 템플릿 표현이 뭔가 쿨하지 못하다고 생각했습니다. 그렇다고 진지하게 저런 방식이 현재의 템플릿 문법과 다른가? 그렇지 않습니다. 하지만 본능적으로 저런 방법외에 html에 데이터를 더 멋지게 주입하는 방법을 원했습니다. 그냥 개발자로서 생산성이 부족하다고 느낀것이라 생각합니다.

그러나 그런방법을 당시에는 알지 못했고 결국 html을 데이터에 맞게 조작하려는 부분에는 저런식의 조작이 들어가야만 했습니다.

나는 동적인 웹을 만들고 싶음🔗

위에 ToDo 웹을 예시로 작성했습니다.

그런데 여기서 새로운 할 일을 추가하기 위해서 항상 준비된 입력창이 필요합니다. 원래 하고 싶었던 것은 사용자가 버튼을 눌러 요청할 때 입력창이 나오는 것입니다. 요청에 따라 기존의 할일 아래에 빈 입력창을 추가하고 “저장”을 누르면 갱신되도록 할 수 있습니다. 이런 버튼의 동작에 따라 UI가 변화하는 지금은 너무나 당연한 작업이지만, 제 기존 지식으로는 서버를 거쳐 새 UI를 내려주지 않는 한 불가능했습니다.

그런 기능을 위해 서버에서 그런 페이지를 만든다면, 느리고 비효율적입니다.

이런 경험이 프로젝트를 만들때 마다 반복되면서 이전의 경험은 점점 좋지 않은 경험으로 누적되어 갔습니다. 이것은 자연스럽게 물리적으로나 심적으로나 유지보수를 거의 불가능하게 만들고, 복사 붙여넣기 지옥으로 이끌었습니다. 웹개발에 대한 부정적이고 불편한 경험만 누적되어 갔던 것입니다.

이런 불편한 경험들은 더 좋은 구조와 개발방법, 기술을 갈망하게 되었고, 이쯤에서 JavaScript로 HTML을 조작하는 세계에 발을 들이게 되었습니다.

JavaScript🔗

첫느낌: JavaScript 그는 신이야!🔗

드디어 JavaScript를 만났습니다. JavaScript는 정말 모든 것이 가능했습니다. DOM에 접근하고 조작해서 못할 것이 없었습니다. 그리고 거기에는 그 니즈를 200% 만족시켜주는 jQuery가 있었습니다.

불행히도 jQuery는 내가 JavaScript와 DOM에 대해서 잘 몰라도, 간단하고 우아하게 래핑된 API로 멋드러지고 간결하게 코드를 작성함으로 내가 원하는 것을 이루게 해주었습니다.

이런 방법 역시 답답한 부분이 많았다🔗

동적으로 HTML을 만들때 HTML 조각을 만들고 그것을 떼었다 붙였다 하는 식은 직관적이고 jQuery 덕분에 사용법도 쉬워서 원하는대로 주무를 수 있었습니다.

그런데 이 HTML을 만드는 것이 역시 Cool 하지 않습니다. 일단 코드를 문자열안에 써야합니다. 문자열에 코드를 작성하는 것은 당시의 사용하던 IDE의 도움을 받기가 힘들었습니다. 또 이게 맞나 싶은 의구심이 들었습니다. 여기에다 코드를 관리하는 것도 문제였습니다. 원본 HTML이 변경되면, 이 문자열로된 코드도 변경해주어야 합니다. 개발자라면 누구나 공감하겠지만, 사람이 모든 변화를 기억하고 대응하는 것은 정말 좋지 않은 구조입니다. 필연적으로 버그가 발생합니다. 사람이 아닌 시스템에 의해 변화에 대응되거나 대응하지 않으면 작동이 불가능하게 만들어야 합니다. JSP같은 환경에서 이런 작업을 하다보면 JavaScript코드와 Java코드가 짬뽕이 되어 내가 무엇을 하고 있는지 헷갈리고 코드는 역대급으로 엉망이 되어갔습니다.

이때가 2014년 정도였습니다.

여기까지의 정리🔗

  • 서버 언어만으로는 웹에서 인터랙티브 표현이 불가능하다는 것을 알게 됐습니다.
  • JavaScript가 정말 매력적으로 느껴졌습니다. 계속 쓰고 싶었습니다. 모든 프로그래밍은 JavaScript로 하고 싶어졌습니다. (Node.js가 가능하게 했습니다!)
  • JSP코드에다 <script>안에 무지성 코딩을 하고 싶지 않았습니다</script> 뭔가 체계화된 시스템을 찾기 시작했습니다.
  • 이 시기에 웹 세계는 v8 엔진을 등에 업은 Node.js가 폭발적인 호응을 얻으며 기존의 파이를 잠식해갔고, JS에 대한 엄청난 논의들과 발전이 이루어지던 시기였던 것으로 기억합니다.

드디어 JS 프레임워크를 만나게 됨🔗

프레임워크라고 타이핑을 하고 나니 정말 웅장하게 느껴지네요. 실제로 마주한 프레임워크들은 웅장했습니다.

  • backbone.js
  • ember.js
  • Knockout.js
  • Meteor.js
  • angularJS

이 때부터 이름끝에 JS를 달고나온 프레임워크들이 시작된 것 같습니다. 저는 이 중에 구글의 angularJS를 접하고 그야말로 만세를 불렀습니다. 만세가 아니라 유레카 수준이었습니다. 아래는 그 시절의 감동이 있는 ToDo App입니다. 이때부터 들었던 생각은 이것이었습니다. 아 됐다. 이제 나는 요구하는 모든 것을 만들수 있겠다.

기존의 갈증을 모두 해소시킴🔗

그토록 원하던 DOM 조작의 방식이 유려하고 간결하고 아름다운 표현으로 대체되고 제법 체계적으로 관리할 수 있게 되었습니다.

  • 코드를 문자열안에 쓰지 않습니다. 원본 HTML과 동적생성을 위한 HTML을 분리하지 않게 되었습니다. 이로서 웹페이지가 마치 하나의 자바스크립트 프로그램으로 작동합니다. SPA로의 발전인 것입니다.
  • 관리할 수 있게 되었습니다. 파일별로 역할을 분리할 수 있게 되었고 서버 템플릿언어 없이도 할 수 있는 것이 많았고, 대체가능했습니다.

여기서부터 이제 저는 가능하면 모든 것을 웹으로 만들려고 했습니다. 학부 선배가 2009년 어느날, 실버라이트로 만든 페이지를 보여주면서, 언젠가는 문서작성이나 엑셀 등 모든 것을 브라우저에서 하는 날이 올 것이고 설치형 프로그램은 구시대의 산물이 될것이다 라고 한 적이 있습니다. 그 때의 저는 그저 콘솔에 printf를 찍고 있었기 때문에, 웹 브라우저에 뭔가 UI 요소를 표현한다는 것 자체가 신기하고 놀라웠습니다.

그러나 웹프로그래밍을 하면서 그 이야기가 실감났고, 2022년 현재는 정말 그런시대를 살고 있습니다.

클래식과 모던 각각의 장점이 있다🔗

누구나 미성숙한 시기가 있죠. 그때의 그런 열정과 패기는 나쁘다고만 생각하지 않습니다. 당장 모든 곳에 AngularJS를 전파하고, 기존 것을 갈아 엎고 싶은 욕심이 가득한 패기의 시기였습니다. 신기술이라면 가장 먼저 검색하고 써보는 것이 취미가 되어버렸습니다.

특이하게 캐나다에서 처음 직장생활을 하게 되었습니다. 운영규모에 비해 인력은 아주 약한 회사였습니다. 나중에 알게되었지만 월급을 줄 능력이 없는 곳이었고 몇 달치 월급을 받지 못했습니다. 당시에는 찬밥인지 더운밥인지 구별하는 법도 알지 못했고, 한 달도 채 버티지 못하는 돈을 들고 캐나다를 갔기 때문에, 저를 뽑아주는 곳이 있다는 것이 감사할 뿐이었습니다.

이 곳에서는 북미의 닷넷 환경을 경험하게 되었습니다. 생소한 윈도우 서버 / IIS를 사용하고 있었고, .NET MVC 프레임워크와 MS-SQL 등을 사용하는 환경이었습니다. 이것이 아주 일반적이었습니다.

이 당시 제가 관리하고 요구사항을 처리해야 했던 사이트는 PV가 100만 이상 나오는 온라인 커뮤니티 포털이었습니다. 사수도 없을 뿐더러 사수라는 개념도 몰랐습니다. 모든 것이 미숙했고, 제가 프로그래밍을 할 줄 알고, 코드를 보고 해석할 줄 알기에 하면 되는것이었죠.

실제 서비스되는 엔터프라이즈의 코드를 보니 기존에 작성하던 JSP같은 템플릿 언어들도 잘 사용할 수 있다는 것도 곳곳에서 확인했습니다. .NET / C# 기반의 코드였는데 우선 C#에 놀랐습니다. Java에 익숙한더라 클래스도 아닌데 함수를 대문자로 시작하는 것이 보기에 불편했지만 그것이 공식 가이드였습니다. 그것에 놀란 것은 아니고 다양하고 유연한 표현들과 문법이 놀라웠습니다. 특히 select, where, join과 같은 DB에서나 볼법한 쿼리를 C#으로 작성하며 데이터를 주무르는 모습은 직관적이고 아름답다고 느꼈습니다.

여기에다 원하는 기능을 AnguarJS가 최신기술이고 생산성이 좋다고해서 냅다 칠하는 것이 뭔가 잘못하는 것이라는 생각이 들었습니다. 자연스럽게 서버사이드 렌더링(SSR)과 클라이언트사이드 렌더링(CSR)의 역할과 사용범위를 구분짓고 필요한 부분에 사용하는 것을 생각했습니다.

좋은 기술이 있겠지만, 기존 기술과 억지로 융합하는 순간 쓰레기로 전락하고 맙니다. 다행히도 이것을 느낄 수 있었습니다. 그런데 안다고 해서 다 참지는 못하고, 군데군데 섞어 본 곳도 있습니다.

모던 프론트엔드의 시작🔗

당시에 웹사이트내에 로컬 업소록 서비스가 있었습니다. 업종별로 상호와 전화번호 위치등이 데이터베이스로 구축된 것이었습니다. 이 페이지의 중요성에 대해서 대표님은 아주 많이 말씀하셨습니다. 저는 이것을 지도서비스에 직방, 다방과 같은 UI를 가진 지도 기반 웹으로 개편하면 좋겠다는 생각이 있었습니다.

이 당시에 우후죽순 생겨났던 SPA 프레임워크 중 대표작들을 나열해 보겠습니다.

  • Angular2
  • react.js
  • vue.js

당시 저는 vue.js를 선택했습니다. 각 프레임워크에 대한 당시를 회고해보자면, Angular 라는 이름으로 새로 나온 angularJs 는 메이저 업그레이드 라고 하더라도 너무나도 큰 변화에 이게 angularJs 가 맞아? 하는 느낌이었습니다. 기술 숙련에는 러닝커브가 있기 마련이지만 진입부터 가파르기가 크다고 느껴져서 패스했습니다. 당시 react.js 역시 초창기였던 것으로 기억합니다. 도입고려 대상이었지만 jsx 문법이 생소했습니다. 지금은 너무나 익숙하지만요.

Vue.js 가 원래의 HTML 문법에 가장 충실하고 정직하다고 생각했습니다. HTML영역은 <template>이라는 html영역에 작성하고, 로직은 <script>에서 , 스타일은 <style>에서 작성하고 이것이 컴포넌트가 된다는 기본 개념이 직관적이고 마음에 들었습니다.

당시 스타일로 ToDo App을 작성해본다면 이렇겠죠.

// Angular 2
import { Component } from '@angular/core';

@Component({
selector: 'my-app',
template: `
<h1>Todo</h1>
<form (submit)="addTodo()">
<input type="text" [(ngModel)]="newTodo" placeholder="아 맞다...!" size="30">
<button type="submit">추가</button>
</form>
<ul class="todo-list">
<li *ngFor="let todo of todos; let i = index">
{{todo.text}}
<button (click)="removeTodo(i)">삭제</button>
</li>
</ul>
`,
})
export class AppComponent {
todos = [{text: '할일1'}, {text: '할일2'}, {text: '할일3'}];
newTodo = '';

addTodo() {
this.todos.push({text: this.newTodo});
this.newTodo = '';
}

removeTodo(index: number) {
this.todos.splice(index, 1);
}
}
// Angular 2
import { Component } from '@angular/core';

@Component({
selector: 'my-app',
template: `
<h1>Todo</h1>
<form (submit)="addTodo()">
<input type="text" [(ngModel)]="newTodo" placeholder="아 맞다...!" size="30">
<button type="submit">추가</button>
</form>
<ul class="todo-list">
<li *ngFor="let todo of todos; let i = index">
{{todo.text}}
<button (click)="removeTodo(i)">삭제</button>
</li>
</ul>
`,
})
export class AppComponent {
todos = [{text: '할일1'}, {text: '할일2'}, {text: '할일3'}];
newTodo = '';

addTodo() {
this.todos.push({text: this.newTodo});
this.newTodo = '';
}

removeTodo(index: number) {
this.todos.splice(index, 1);
}
}
Angular 2 를 사용한 ToDo 수도코드
//React.js

class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
todos: [{text: '할일1'}, {text: '할일2'}, {text: '할일3'}],
newTodo: ''
};
}

addTodo = () => {
this.setState({
todos: [...this.state.todos, {text: this.state.newTodo}],
newTodo: ''
});
}

removeTodo = (index) => {
this.setState({
todos: this.state.todos.filter((_, i) => i !== index)
});
}

render() {
return (
<div>
<h1>Todo</h1>
<form onSubmit={this.addTodo}>
<input
type="text"
value={this.state.newTodo}
onChange={e => this.setState({newTodo: e.target.value})}
placeholder="아 맞다...!"
/>
<button type="submit">추가</button>
</form>
<ul>
{this.state.todos.map((todo, i) => (
<li key={i}>
{todo.text}
<button onClick={() => this.removeTodo(i)}>삭제</button>
</li>
))}
</ul>
</div>
);
}
}

ReactDOM.render(<TodoApp />, document.getElementById('root'));
//React.js

class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
todos: [{text: '할일1'}, {text: '할일2'}, {text: '할일3'}],
newTodo: ''
};
}

addTodo = () => {
this.setState({
todos: [...this.state.todos, {text: this.state.newTodo}],
newTodo: ''
});
}

removeTodo = (index) => {
this.setState({
todos: this.state.todos.filter((_, i) => i !== index)
});
}

render() {
return (
<div>
<h1>Todo</h1>
<form onSubmit={this.addTodo}>
<input
type="text"
value={this.state.newTodo}
onChange={e => this.setState({newTodo: e.target.value})}
placeholder="아 맞다...!"
/>
<button type="submit">추가</button>
</form>
<ul>
{this.state.todos.map((todo, i) => (
<li key={i}>
{todo.text}
<button onClick={() => this.removeTodo(i)}>삭제</button>
</li>
))}
</ul>
</div>
);
}
}

ReactDOM.render(<TodoApp />, document.getElementById('root'));
react.js 를 사용한 ToDo App 수도코드
// Vue.js 2.0
<div id="app">
<h1>Todo</h1>
<form v-on:submit.prevent="addTodo">
<input type="text" v-model="newTodo" placeholder="아 맞다...!">
<button type="submit">추가</button>
</form>
<ul>
<li v-for="(todo, index) in todos" :key="index">
{{todo.text}}
<button v-on:click="removeTodo(index)">삭제</button>
</li>
</ul>
</div>

<script>
new Vue({
el: '#app',
data: {
todos: [{text: '할일1'}, {text: '할일2'}, {text: '할일3'}],
newTodo: ''
},
methods: {
addTodo() {
this.todos.push({text: this.newTodo});
this.newTodo = '';
},
removeTodo(index) {
this.todos.splice(index, 1);
}
}
});
</script>
// Vue.js 2.0
<div id="app">
<h1>Todo</h1>
<form v-on:submit.prevent="addTodo">
<input type="text" v-model="newTodo" placeholder="아 맞다...!">
<button type="submit">추가</button>
</form>
<ul>
<li v-for="(todo, index) in todos" :key="index">
{{todo.text}}
<button v-on:click="removeTodo(index)">삭제</button>
</li>
</ul>
</div>

<script>
new Vue({
el: '#app',
data: {
todos: [{text: '할일1'}, {text: '할일2'}, {text: '할일3'}],
newTodo: ''
},
methods: {
addTodo() {
this.todos.push({text: this.newTodo});
this.newTodo = '';
},
removeTodo(index) {
this.todos.splice(index, 1);
}
}
});
</script>
Vue.js 2.0 을 사용한 ToDo App 수도코드

그리고 현재🔗

위 언급한 프레임워크는 지금도 이 세계를 평정하고 있는 프레임워크입니다. 수 많은 발전을 거듭하고 현재까지 사랑받고 엔터프라이즈에서 활발히 사용되고 있습니다. 심지어 전자정부프레임워크는 react를 택했습니다.

지난 몇 년 JS를 중심으로 가장활발했던 웹 프론트엔드 성장시기를 함께 겪으면서 하루에도 수없이 쏟아지고 발전하는 세대를 경험하고 있습니다.

이 글만 하더라도 grunt, gulp와 같은 태스크러너부터 webpack, rollup같은 눈부신 번들 시스템의 진화, 체계화되고 성숙해진 모듈시스템, es6 이후 끊임없는 JS의 발전과 그로 인한 브라우저 의존성, 폴리필과 트랜스파일러, TypeScript의 발전 등 숨 쉴 틈도없이 빽빽히 들어선 내용은 개인적인 수준에서 언급만 해도 그 분량이 버거울 정도입니다.

마무리🔗

커피한잔하며 이 글을 작성하려고 생각해 보았을 때 가장 뚜렷한 대비로 몸에 각인되어 있는 것은 단연 생산성입니다. 해를 거듭하며 생산성이 폭발적으로 늘어난 것 같습니다. 현재는 JS기반 패키지 매니저는 npm, yarn, pnpm 으로 골라잡을 수 있고, CRA같은 잘 만들어진 CLI도구로 보일러레이트 프로젝트를 뚝딱 만들어 4000 포트에 서비스를 하나 띄우는데 1분도 걸리지 않습니다.

심지어 이런 모던 JS 프레임워크를 사용하면서도 Remix나 Next.js 를 씌우면 SEO도 해결할 수 있죠. 심지어는 이제 React에서 자체적으로 SSR을 지원하기 시작합니다. JS를 사용하면서 SSR까지 해결하는 시대로 발전해왔네요.

이 쯤에서 글을 마무리하겠습니다. 과거를 돌아보며 웹 특히 프론트엔드의 개인적인 발전과정을 돌아보니, 그 안에는 역동적인 많은 사람들의 고민과 결정, 논의, 더 나은 방향을 위한 노력들이 숨어 있는 것 같아 감동적이네요. 이런 발전은 천재적인 한 사람에 의해서 큰 도약을 하기도 하지만, 결국 그 사이 수많은 개발자들과 끊임없는 시행착오가 만들어낸 결과이고 앞으로도 그럴것이라 생각합니다.

저도 이런 과정에 동참하며 함께 기여하는 개발자가 될 수 있기를 바랍니다. 이 글을 읽는 여러분도 같은 마음으로 새로운 도전을 이어나가시기를 응원합니다. 감사합니다.


추천글🔗

글을 모두 작성하고나서 비슷한 키워드로 검색을 해보았습니다. 그러다 이 글의 비슷한 제목과 흐름의 글을 발견했습니다.여기에 기술적인 발전 역사가 잘 서술되어 있고 읽기도 좋은 글을 발견하여 아래에 링크합니다.

https://velog.io/@minsangk/짧게-써보는-웹-프론트엔드의-역사