brunch

You can make anything
by writing

C.S.Lewis

by 이지원 Oct 01. 2022

Dom 객체 다루기

DOM 객체 다루기_끝말잇기 게임

진행 상황

순서도 그리기 2021.11.10

웹페이지 화면 구현하기 2021.11.10

대화창(prompt, alert, confirm) 2021.11.10

HTML 태그 선택하기(querySelector) 2021.11.10

이벤트 리스너와 콜백 함수 2021.11.10

첫 번째 사람인지 판단하기 2021.11.11

올바른 단어인지 판단하기 2021.11.12

틀렸을 때 오류 표시하기 2021.11.12

순서도 최적화(and, or) 2021.11.12

마무리 2021.11.12


1. 순서도 그리기

프로그래밍에서는 절차가 매우 중요하다. 코드 작성 전에 내가 만들 프로그램이 어떤 절차로 돌아갈지 미리 생각하면 좋다. 나는 아직 프로그래밍 사고력이 길러지지 않은 상태라 순서도 그리기를 통해 사고력을 기르는 법도 좋은 방법이라 생각된다.


1-1. 무엇을 만들 것인가?

끝말잇기 게임을 만들 것이다. 끝말잇기 게임이란 무엇일까? A와 B라는 2명의 참가자가 있고 A가 '끝말잇기'라고 말했다. B는 '기차'라고 말했다. 다시 A는 '차도'라고 말했다. 이와 같은 방식으로 서로 번갈아가며 각자 얘기한 단어의 마지막 글자를, 다음번 단어의 시작 글자로 얘기한다. 이러한 절차가 반복되는 형태가 끝말잇기 게임이다. 순서로 표시하면 아래와 같다.


2명의 참가자가 있다.(A, B)

A가 '끝말잇기'라고 말했다.

B는 '기'로 시작하는 '기차'를 말했다.

A는 '차도'를 말했다.

B는 '도'로 시작하는...

무한 반복


그런데 위 절차를 프로그램으로 만들려고 하니 어려움이 따른다. 끝말잇기 게임 규칙은 맞지만 위와 같은 절차로는 프로그램을 만들 수 없다. 왜 그럴까? 우선 절차 1을 살펴보면 참가 인원이 항상 2명일까? 3명 일 수도, 4명 일 수도, 혼자서 끝말잇기를 할 수도 있다. 다양한 가능성을 닫아둔 채 구체적으로 2명이라고 명시하는 것은 좋지 않다.


또한 처음엔 2명이서 시작했는데 또 다른 친구가 와서는 게임 참가를 요구한다. 2명이서 진행할 때와 3명이서 진행할 때는 아래처럼 절차가 달라진다. 6단계였던 절차가 7단계로 늘어난 것이다. 만약 이처럼 참가자 수가 계속 늘어난다면 어떻게 될까? 참가자 수가 1명씩 늘어날 때마다 절차는 계속 증가한다.


3명의 참가자가 있다.(A, B, C)

A가 '끝말잇기'라고 말했다.

B는 '기'로 시작하는 '기차'를 말했다.

C는 '차도'를 말했다.

A는 '도자기를 말했다.'

B는 '기'로 시작하는...

무한 반복


문제는 이뿐만이 아니다. A가 항상 '끝말잇기'라고 말한다는 보장이 없다. '자바스크립트'라고 말할 수도, '프론트엔드'라고 말할 수도 있다. A는(===사용자) 자기가 원하는 어떤 단어든 말할 수 있다. 그다음 차례인 B는 A가 말하는 단어에 따라 대답이 달라져야 한다. 또한 A가 만약 '자바스크립트'라고 말했는데 B가 '트'로 시작하는 단어로 말하지 않고 엉뚱한 단어로 답 할 수도 있다. 이런 경우엔 틀렸다고 안내하거나 게임이 더 이상 진행되지 않아야 한다. 하지만 위와 같은 절차를 사용하면 틀린 대답을 한 경우를 고려하지 않게 된다.


1-2. 프로그램 절차의 원칙 4가지

프로그램은 고정된 절차로 돌아가야 한다. 몇 명이 참가하든 절차의 수가 같은 프로그램을 만드는 것이 좋다. 또한 각 절차는 항상 내용이 같아야 한다. 어떤 사용자가 무엇을 입력하든 프로그램은 그것을 받아들일 준비가 되어 있어야 한다. 따라서 위 절차처럼 예시를 들어 절차를 설명하는 방식은 좋지 않다. 예시는 사용자에 따라 언제든지 바뀔 수 있기 때문이다. 하지만 처음부터 모든 가능성을 고려하긴 어렵다. 이런 경우엔 절차를 생각나는 대로 우선 만들어 놓고 차차 보완해 나가는 것이 현명하다.


프로그램 절차의 개수는 정해져 있어야 한다.

각 절차는 항상 같은 내용이어야 한다.

모든 가능성을 고려해야 한다.

예시는 절차를 검증하는 데 사용한다.


1-3. 절차 수정

아래와 같이 절차를 수정하면 '몇'이나 '어떤'이라는 용어를 사용하므로 다양한 경우에 대비할 수 있다. 다양한 경우를 대비할 수 있으니 처음 절차와 비교했을 때 원칙 1, 2번을 위배할 일이 없어진다. 다만 분기점이 있으므로 1, 2, 3, 4... 순서대로 표현하는 것보다는 순서도를 그려서 시각적으로 표현하는 것이 편리하다.


게임에 몇 명이 참가할지를 선택한다.

참가자 순서를 정한다.

첫 번째 사람이 어떤 단어를 말한다.

다음 사람이 어떤 단어를 말한다.

절차 4에서 말한 단어가 올바른지 판단한다.(분기점)

올바르면 그다음 사람이 어떤 단어를 말하고 게임을 계속 진행한다.(True-반복)

올바르지 않다면 틀렸다고 표시하고 게임을 끝낸다.(False-종료)


1-4. 사용한 순서도 도형 의미

'프로그래밍 사고력' 기르는 훈련을 할 때 순서도를 많이 사용하는데, 순서도는 프로그램이 수행하는 명령에 대한 순서와 절차가 시각적으로 표현되어 알아보기 쉽기 때문이다. 순서도를 작성하고 순서도를 코드로 옮기면 프로그램은 의도한 동작대로 수행된다. 순서도 그리는 방법은 워낙 다양해서 공식이 존재하지 않는다. 나는 시작과 끝, 일반 절차, 판단 절차, 특수한 상황(대기 또는 이벤트 발생), 다음 절차로 가는 흐름으로 순서도를 그려보았다.


1-5. 순서도 초안 완성

위와 같이 순서도 초안을 작성하면 앞서 얘기한 원칙 4가지를 위배하지 않으면서 모든 예시에 부합하게 된다. 보완이 필요한 부분은 코드를 작성하면서 생각해야 하므로 지금 단계에선 더 이상 깊게 생각하지 않는다. 우선 초안을 토대로 프로그램을 만들어 나가면서 보완이 필요한 부분들을 수정해보자.


2. 웹페이지 화면 구현하기

JavaScript Basic Project에서는 자바스크립트를 활용한 프로그래밍 사고력 증진에 초점을 둔다. 따라서 HTML과 CSS는 최소한으로 활용한다. 화면을 어떻게 만들 것인지에 대한 구상은 피그마로 간단히 만들어본다. 현재는 자바스크립트에 집중하는 것이 중요하므로 HTML과 CSS에서 너무 많은 시간을 사용하지 않는다. HTML과 CSS는 추후 상세하게 정리할 계획이다.


2-1. 어떤 화면을 만들 것인가?

피그마로 간단히 만들었다. 대략적으로 이러한 화면을 만들 생각이다. div 태그를 활용할 것이며 중요한 건 프로젝트 메인 주제인 DOM 객체를 다뤄보는 것이다. 자바스크립트를 활용하여 사용자의 행동에 따라 적절한 화면이 보이도록 할 것이다.


2-2. HTML 코드 및 실제 화면

피그마 스케치를 참고하여 작성한 HTML 코드이다. id 선택자인 order, word 및 input, button 태그 등을 자바스크립트로 다룰 생각이다.


3. 대화창(prompt, alert, confirm)

처음으로 해야 할 것을 살펴보자. 무엇을 먼저 해야할까? 우선 '몇 명이 참가할지 선택'해야 한다. 프로그램은 몇 명이 참가할지를 스스로 알아내지 못한다. 따라서 직접 알려줘야 한다. 그럼 어떻게 알려줄 수 있을까? 사람이라면 손쉽게 말로 '5명 참가할 거야', '2명 참가할 거야' 하거나, 아이컨택과 텔레파시 등으로 몇 명이 참가할지 알 수 있지만 컴퓨터는 그렇지 않다. 방법은 크게 2가지이다. 입력창(input 태그)을 사용하는 방법과 prompt 함수를 사용하는 방법이다.


3-1. prompt 함수 사용

prompt 함수를 사용해서 직접 프로그램에 값을 전달해보자. 자바스크립트 코드는 HTML과 마찬가지로 위에서 아래로 실행되므로 첫 번째 절차인 prompt 함수는 script 태그 내부의 최상단에 위치하면 된다. prompt 형식과 작성된 코드는 아래와 같다.

세 명이 참가한다면 3을 입력하고 확인을 누르면 된다. 하지만 확인을 눌러도 아무일도 발생하지 않는다. 전달받은 3으로 아무것도 하지 않았기 때문이다. 또한 전달한 값을 어딘가에 저장하지 않았기 때문에 프로그램은 해당 값을 잃어버리기 쉬운 상태가 된다. 그렇기 때문에 변수라는 것을 사용해야 한다. 취소를 누르면 프로그램에 null 값이 전달되고 마찬가지로 아무 일도 일어나지 않는다.


prompt 함수로 입력받은 값은 놀랍게도 문자열이다. 예를들어 3을 입력하면 '3'이라는 문자열이 되고, true를 입력하면 'true'라는 문자열이 된다. 따라서 숫자로 활용하기 위해 Type Casting 과정이 필요하다. 변환 후 typeof 함수로 확인해보면 Console에 Type이 String에서 number로 찍힌 걸 볼 수 있다.

3-2. 변수 사용

number라는 변수에 값을 저장하는 코드이다. 참가자는 매번 다를 수 있으므로 let 대신 상수를 뜻하는 const를 사용한다. 값이 변수에 제대로 저장됐는지 확인해보기 위해 console.log 함수도 사용해보자.


3-3. alert은 무엇인가?

alert 함수는 주로 어떠한 메시지를 사용자에게 알릴 때 사용한다. console.log 대신에 변수의 값을 확인하는 용도로도 사용할 수 있다. 다만, console.log 함수로 값을 확인하는 것이 좋다. alert 함수를 사용하면 여러 값을 동시에 확인하기 어려울 뿐 아니라, alert('number', number) 같은 것들을 할 수 없다. alert 대화 상자는 실제 사용자에게도 보이기 때문이다.

3-4. confirm은 무엇인가?

confirm 함수는 사용자에게 의사를 물어볼 때 사용한다. 확인을 누르면 true가 콘솔 창에 기록되고 취소를 누르면 false가 콘솔 창에 기록된다. 이렇게 나온 true, false 값을 프로그래밍에 활용하면 된다.

4. querySelector

첫 번째 사람이 어떤 단어를 말하게 하려면 어떻게 해야할까? 입력창 input 태그로 입력을 받으면 된다. 다만, 입력창은 HTML 태그라서 자바스크립트에서 해당 입력창을 가져와야 한다. 일반적으로 자바스크립트에서 HTML 태그를 가져오는 것을 선택한다고 표현한다. 선택을 위해서는 특별한 함수와 방법을 사용하는데, 특별한 함수는 document.querySelector이고 사용 방법과 예시는 아래와 같다.

5. 이벤트 리스너와 콜백 함수

사용자는 화면과 다양한 상호 작용을 한다. 이는 HTML 태그와 상호작용을 하는 것이다. 이번 프로젝트에서 만들어 볼 끝말잇기만 하더라도 사용자는 input 태그에 글자를 입력하고 button 태그를 누른다. 이때 이벤트라는 것이 발생한다. 예를 들어, input 태그에 글자를 입력하면 input이라는 이벤트가 발생하고, 버튼을 클릭하면 click 이벤트가 발생하는 식이다. 이처럼 다양한 이벤트가 발생하지만 자바스크립트는 이벤트를 자동으로 감지할 수 없다. 그래서 이벤트 리스너(EventListener)를 직접 추가하여 자바스크립트가 HTML에서 발생하는 이벤트를 감지할 수 있게 만들 생각이다. 태그 선택 함수인 document.querySelector를 사용해서 HTML 태그들에 이벤트 리스너를 달아보자.


5-1. 이벤트 리스너 사용

이벤트가 발생 할때 실행할 함수를 하나 만들고 해당 함수를 태그에 연결해준다. 이때 addEventListener 함수를 사용한다. 여기서는 태그를 document.querySelector('button')으로 선택했다. 해당 태그에 addEventListener를 붙여서 이벤트를 연결할 수 있다.


클릭 이벤트의 이름은 click이다. 버튼을 클릭하면 onClickButton 함수가 실행된다. 이때 주의해야 할 점은 onClickButton 대신 onClickButton()을 넣으면 안 된다. 왜냐하면 ()를 붙일 경우 클릭과 상관없이 해당 함수가 실행되기 때문이다. 함수 자체를 넣어야 하고, ()를 붙여 함수를 실행해서는 안된다는 점을 유의하자.


5-2. 콜백 함수(callback function) 사용

콜백 함수는 특정 작업이 실행되고 난 뒤에 추가로 실행되는 함수를 의미한다. 위 코드에서 onClickButton과 같은 함수가 바로 콜백 함수이다. 버튼을 클릭한 후에 onClickButton이 추가적으로 실행되므로 콜백 함수에 해당된다. 위 코드는 아래처럼 변수를 사용하지 않고 한 번에 작성할 수도 있지만, 가독성과 변수 재사용을 고려한다면 변수 사용을 권장한다.


5-3. input 태그에 입력한 값을 알아내려면?

event.target.value로 input 태그에 입력한 값을 알아낼 수 있다. 여기서 event는 매개변수이므로 다른 이름으로 지어도 괜찮다. event 또는 e로 해도 무방하고 전혀 관련 없는 hello로 지어도 되지만, hello로 지으면 다른 사람이 헷갈릴 수 있으니 유의하자.


6. 첫 번째 사람인지 판단하기

단어를 입력한 사람이 첫 단어를 입력한 참가자인지 판단이 필요하다. 이전 순서도를 다시 살펴보자.


6-1. 순서도 수정

input과 click 이벤트 모두 사용자가 이벤트를 발생시키지 않으면 다음 절차로 넘어가지 않는다. 이럴 경우 순서도를 한 번 끊어주는 것이 좋다. 제시어가 비어있을 경우, 입력한 단어가 올바른지, 제시어를 저장할 변수, 입력한 단어를 저장할 변수 등을 고려하여 순서도를 수정하면 아래와 같다.

6-2. 순서도 참고하여 코드 작성

제시어를 저장할 word 변수를 선언했다. 변수 선언 시 아무런 값을 넣지 않았으니 word는 undefined이다. undefined는 if문에 들어갈 경우 false로 취급되므로 if문을 조건을 true로 만들기 위해 !word 조건을 사용했다. if문안에 textContent가 나오는데 이는 태그 내부의 값을 얻거나 수정할 때 사용한다. 맨 처음 #word는 빈 값이므로 $word.textContent를 하면 "을 얻을 수 있다. textContent는 무조건 문자열로 나오므로 빈 값인 null 또는 undefined가 아니라 "가 나온다. 반대로 $word.textContent에 다른 값을 넣으면 태그 내부의 문자열을 해당 값으로 설정한다.

단어를 입력하면 제시어에 해당 단어가 표시된다. 이제 두 번째 사람이 단어를 입력했을 때 올바른 단어인지 판단하는 코드를 작성해보자.


7. 올바른 단어인지 판단하기

첫 번째 사람이 입력한 제시어를 시작으로 끝말잇기 게임이 진행되어야 한다. 이번엔 두 번째 사람이 단어를 입력할때부터 실행되는 코드를 작성한다. 끝말잇기에서 단어가 올바른지 판단하려면 제시어의 끝 글자와 현재 단어의 첫 글자를 비교하면 된다.


7-1. 어떻게 판단할것인가?

제시어의 마지막 문자와 현재 입력한 단어의 첫 번째 문자와 비교해서 같도록 비교해주면 된다. 글자 수에서 1을 빼면 마지막 자릿수가 나오므로 문자열의 길이를 구한다면 마지막 글자를 구할 수 있다.

문자열. length를 사용해서 제시어인 word의 마지막 문자를 구했으니 현재 단어인 newWord의 첫 번째 문자와 비교해주는 코드를 작성하였다.


7-2. 다음 참가자에게 순서 넘기기

이제 다음 사람에게 순서를 넘겨야 한다. number 변수에 참가자가 몇 명인지 저장되어 있다. 그리고 #order 태그 안에는 몇 번째 참가자인지 순서가 나와있다. 참가자가 만약 3명이라면 1번 참가자부터 시작하여 다음 순서는 2번, 그다음 순서는 3번이 됐다가 다시 1번 참가자로 순서가 돌아가도록 코드를 작성해보자.

#order 태그를 선택해 $order 변수에 저장했다. 그리고 #order 태그 내부의 값을 꺼내 숫자로 변환하고 이를 order 변수에 저장했다. 만약 그 값에 1을 더한 값이 참가자보다 크면 화면에 순서를 다시 1로 표시하고 작다면 order에 1 더한 값을 순서로 표시했다. 이렇게 작성하면 참가자가 5명일 때 1,2,3,4,5 -> 1,2,3,4,5 식으로 반복되므로 게임 순서가 올바르게 진행될 수 있다.


8. 틀렸을 때 오류 표시하기

올바르지 않은 단어를 입력한 경우 처리하면 끝말잇기 게임이 완성된다. alert 함수를 사용하여 틀렸다는 것을 사용자에게 알려주자.


8.1 alert 함수로 오류 표시 코드 작성

마지막 글자와 입력한 글자의 첫 글자가 다를 경우 '올바르지 않은 단어입니다!' 팝업이 출력되는 모습이다. 그런데 테스트를 하다보니 부족한 점이 보인다. 단어를 입력하고 입력 버튼을 누르면 다음 참가자로 순서가 넘어가는데, 이때 이전 사람이 input 태그에 입력한 단어가 그대로 남아 있어서 지우고 다시 입력해야 하는 번거로움이 있다. 단어를 지우기 위해 input 태그도 눌러서 커서를 표시해야 하니 꽤나 번거롭다. 사용자 편의를 위해 순서도와 코드를 수정하여 해당 부분을 개선해보자.


8.2 사용자 편의성을 위한 순서도 및 코드 수정

input 태그 값을 수정하기 위해 $input.value를 사용했다. 참고로 태그 내부 값을 선택할 때는 textContent를 사용하는 게 적절하지만, 입력 태그만 value를 사용한다. input은 대표적인 입력 태그라서 value를 사용했다. 다른 입력 태그로는 select와 textarea가 있다. value와 focus 메서드를 사용하여 값을 수정하고 입력 태그 내부에 커서를 위치하게 하여 다음 사용자가 입력하기 편하도록 보완하였다.

9. 순서도 최적화(and, or)

마지막으로 순서도와 코드를 한번 더 점검해보자. 목적은 중복되는 부분을 찾아 최적화시키는 것이다.


9.1. 중복되는 순서도와 코드 찾기

1. 순서도와 코드에서 '입력창을 비우고 커서를 둔다' 절차가 중복된다.

2. 순서도에서는 중복되지 않지만 코드에서만 중복되는 부분도 있다. '입력한 단어가 제시어가 된다'와 '다음 사람에게 순서를 넘긴다'에 해당되는 코드이다.

9.2. 합칠 수 있는 절차인지 판단하기

이외에도 '제시어가 비어 있는가?'와 '단어가 올바른가?'라는 절차는 '제시어가 비어 있거나 단어가 올바른가?'라는 절차로 줄일 수 있다. 이처럼 판단하는 절차가 연이어 나오고 '예' 또는 '아니오'가 공통된 절차로 이어질 때에는 절차를 하나로 만들 수 있다.

순서도의 절차가 적을수록 효율적인 프로그램이 되므로 순서도의 길이를 짧게 만들 수 있을지 고민해보자.


9.3 순서도 및 코드 최적화 마무리

코드가 상당히 짧아졌다. OR 관계가 있는 판단 절차 두 개를 하나로 줄였고(!word || word[word.length -1] === newWord[0]), 다른 부분은 실행 순서를 조정했다. 이로써 첫 번째 기초 프로젝트인 끝말잇기 게임 구현이 끝났다.


10. 마무리

코드 작성하는 것은 부가적인 일이고 순서도 작성의 중요성을 알게 됐다. 순서도가 명확하게 정리되지 않으면 코드도 엉망이 될 수 있다는 것을 배웠다. 생각하는 대로 바로 코딩하지 못해서 아직은 많이 답답하지만, 아직 난 초보자이고 배우는 단계이기 때문에 앞으로도 느리지만 천천히 순서도를 그려가는 습관을 들이려 한다. 습관이 어느 정도 잡히면 자연스레 머릿속으로도 순서도를 그릴 수 있게 되고 결과적으로 코딩 속도가 빨라지는 날이 오길 기대해본다. 좋은 강의를 제공해주신 제로초님께 감사드리고, 나처럼 프로그래밍을 시작하는 사람들에게 제로초님 자바스크립트 입문 강의를 추천해주고 싶다. 끝으로 배운 내용을 정리해봄으로써 기초 프로젝트 회고를 마친다.


10.1. 순서도 그리기

초심자일수록 프로그래밍에서 중요한 것은 코드 작성 전에 올바른 순서도를 만드는 것이라 생각된다. 모든 가능성을 고려하여 한번에 순서도를 만들 수는 없고 코딩하면서 계속해서 수정 보완이 필요하다. 하지만 아래 4가지 원칙을 지키며 순서도를 설계한다면 수정 횟수와 전체 절차 수를 최소화할 수 있다.


프로그램 절차의 수는 정해져 있어야 한다.

각 절차는 항상 같은 내용이어야 한다.

모든 가능성을 고려해야 한다.

예시는 절차를 검증하는 데 사용한다.


또한 순서도를 만들 땐 사용자의 이벤트(버튼 클릭, 입력창 글자 입력 등)가 필요한 곳에선 순서도를 끊어야 한다는 점을 잊지 말자.


10.2. 대화 상자 띄우기

웹 브라우저에서 대화 상자를 띄울 수 있는 3가지 방법을 배웠다.

promt는 대화 상자에 사용자가 입력한 메시지가 문자열 형태로 전달되고 입력하지 않고 취소를 누르면 null 값이 전달된다.


alert는 단순한 알림 창으로, 호출하면 확인을 누르기 전까지 다음 스크립트 실행이 중단된다. 디버깅 용도로 사용할 땐 console.log를 사용하자.


confirm은 사용자에게 확인을 받을 때 사용한다. 사용자가 확인을 누르면 true가 전달되고 취소를 누르면 false가 전달된다. 이 점을 프로그래밍에 잘 활용하자.


10.3. HTML 태그 선택하기

document.querySelector로는 하나의 태그만 선택 가능하고, document.querySelectorAll로는 여러 개의 태그를 선택할 수 있다.

하나의 태그만 선택하고 싶을 땐 id 속성을 사용하고 여러 개의 태그를 동시에 선택하고 싶을 땐 class 속성을 사용하면 된다. 선택자로는 #아이디, .클래스이다.

어떤 태그 안에 있는 다른 태그를 선택하고 싶을 땐 선택자 사이를 한 칸 띄우면 된다.

10.4. 태그에 이벤트 달기

태그를 선택한 후에 addEventListener 메서드를 사용해 이벤트를 연결한다. 첫 번째 인수로 이벤트 이름을 넣고, 두 번째 인수로 리스너 함수를 넣는다. 리스너 함수는 이벤트가 발생할 때 실행되는 함수이다.

리스너 함수의 매개변수로 event 객체를 제공해서 이벤트와 관련된 정보를 얻을 수도 있다. 예를 들어, input 태그에 입력된 값을 가져오려면 event.target.value를 넣어주자. 여기서 event.target은 이벤트가 발생한 대상 태그를 가리킨다.

value 속성은 입력창에 입력된 값을 가져올 수 있고 값을 대입하면 대입한 값으로 변경된다.

입력 태그(input, select, textarea 등)가 아닌 일반 태그들의 내부 값을 가져올 땐 value 대신 textContent 속성을 사용하자.

입력창이나 버튼의 경우 focus 메서드를 호출하면 해당 태그가 하이라이트 된다.

매거진의 이전글 Ad-Hoc Testing과 Error Guessing
작품 선택
키워드 선택 0 / 3 0
댓글여부
afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari