고등학생 개발자가 만든 축제 응원 도구

“웹 개발 첫걸음: 모바일 LED 전광판 만들기”
–고등학생, 김본수님 사례

개발하는 고등학생입니다

안녕하세요. 저는 IT 특성화 고등학교에 재학 중인 김본수입니다. 처음으로 개발한 웹 사이트를 소개하게 되어 쑥스럽네요. 부족하지만 개발자들의 공유 문화도 경험해보고자 글을 쓰게 되었습니다.

첫 웹 개발로 만든 모바일 LED 전광판 서비스

제가 구름IDE로 만든 서비스는 모바일 LED 전광판입니다. 원하는 문구를 입력하면 네온사인 효과로 변환하여 보여줍니다. 옆으로 움직이거나 깜빡거리는 효과를 줄 수 있죠. 취향에 따라 선택할 수 있도록 색상 선택지도 제공하고 있습니다.

친구를 응원하기 위해 만들었어요

저에겐 6년째 밴드 활동을 한 친구가 있어요. 제가 서울로 전학 와 사귄 등하교 메이트죠. 이 친구가 학교 축제에서 고등학생으로 마지막 공연을 하게 되었어요. 저는 반 친구들과 함께 작은 이벤트를 준비했습니다. 바로 친구가 무대에 섰을 때 핸드폰 전광판으로 응원 메시지를 띄우는 이벤트였죠.

처음에는 반 친구들과 소소한 이벤트로 시작했는데요, 학생회에서 제가 만든 서비스를 홍보하면서 다 함께 사용하는 학교 공식 응원 도구가 되었어요. 제가 만든 서비스를 교내 다양한 사람(후배, 선생님 등)이 사용하는 게 뿌듯한 경험이었습니다.

순수 HTML, CSS, JS 조합으로 구현했어요

개발할 때 프레임워크를 별도로 사용하지 않고 순수 HTML CSS JS 조합으로 구현했습니다. 서비스 배포는 구름IDE에서 기본으로 제공해주는 URL을 통해서 이루어졌습니다. 기본 제공 URL이 workspace 디렉토리까지 포함하다 보니 조금 긴 느낌이 들어서 편리성을 위해서 nginx에서 루트 폴더를 변경했습니다.

간단하게 구성한 서비스 플로우

네온사인 서비스
  1. 모바일로 네온사인 서비스에 접속합니다.
  2. 네온사인으로 만들고 싶은 문구를 입력합니다. (문구는 최대 2개까지 입력할 수 있고 문구마다 원하는 색으로 선택이 가능합니다)
  3. ‘제작’ 버튼을 클릭해서 최종적으로 네온사인 문구를 만들 수 있습니다. (아이패드, 안드로이드 OS에선 오른쪽 상단 버튼을 눌러 전체화면으로 띄울 수 있습니다)
  4. 문구를 꾹 누르면 문구를 멈추거나 자동으로 움직이는 효과를 줄 수 있습니다.

서비스 플로우 구현을 위해 구성한 파일 구조는 다음과 같습니다

  • index.html: 사용법 팝업 이미지를 띄우는 로직을 포함하는 파일
  • form.html: 문구와 색상을 선택할 수 있는 로직을 포함하는 파일
  • main.html: 설정한 네온사인을 띄우는 로직을 포함하는 파일

사용자가 문구와 색상을 선택했을 때 네온사인을 띄워주는 로직 상세 설명

1. form.html 파일에서는 사용자가 문구와 색상을 정합니다. 정한 문구와 색상 정보를 쿼리스트링을 통해 main.html 파일로 보냅니다

<예시> https://hansei-festival2022.run.goorm.io/main.html?ment1=최강&color1=red&ment2=구름&color2=blue

2. main.html파일의 스크립트에서 아래와 같은 로직을 통해 네온사인을 띄웁니다.

예시 코드

// main.html의 스크립트 영역
function searchParam() {
   let queryString = location.search;
   const urlParams = new URLSearchParams(queryString);
   var value = new Array(
       urlParams.get('ment1'),
       urlParams.get('ment2'),
       urlParams.get('color1'),
       urlParams.get('color2')
   );
   return value;
}

const uservalue = searchParam();

function printMent1() {
   document.getElementById('comment1').innerText = uservalue[0];
}
function printMent2() {
   document.getElementById('comment2').innerText = uservalue[1];
}
function startFS() {
   document.documentElement.webkitRequestFullscreen();
   document.getElementById('fullscreen').setAttribute("onClick", "exitFS()");
   document.getElementById('fullscreen').style.backgroundImage = 'url(./src/collapse.svg)';
}

function exitFS() {
	 document.exitFullscreen();
	 document.getElementById('fullscreen').setAttribute("onClick", "startFS()");
	 document.getElementById('fullscreen').style.backgroundImage = 'url(./src/fullscreen.svg)';
}

function setColor1() {
   document.getElementById('comment1').className = uservalue[2];
}
function setColor2() {
   document.getElementById('comment2').className = uservalue[3];
}

function makeNeon() {
   printMent1();
   printMent2();
   setColor1();
   setColor2();
}
// main.html의 바디 구조
<body onload="makeNeon()">
        <div class="flow-container">
            <div class="flow-text">
                <div class="flow-wrap">
                    <div id="comment1"></div>
                    <div id="comment2"></div>
                </div>
            </div>
        </div>
</body>
// css 파일
.red {
    color: #fff;
    text-shadow: 0.5px 0vw 0.15px #ffd8d8, 0.1px 0vw 0.15px #ffd8d8, 0.2px 0vw 0.15px #ffd8d8,
        0.5px 0vw 0vw #f25757, 0.1px 0vw 0vw #f25757, 0.2px 0vw 0vw #f25757, 0.5px 0vw 0.5px #f25757,
        0.1px 0vw 0.5px #f25757, 0.2px 0vw 0.5px #f25757, 0.5px 0vw 10px #f25757,
        0.1px 0vw 10px #f25757, 0.2px 0vw 10px #f25757, 0.5px 0vw 10px #e50b0b, 0.1px 0vw 10px #e50b0b,
        0.2px 0vw 0.3px #e50b0b, 0.5px 0vw 30px #e50b0b, 0.1px 0vw .5px #e50b0b,
        0.2px 0vw 0.5px #e50b0b, 0.5px 0vw 0.5px #e50b0b, 0.1px 0vw 10px #e50b0b,
        0.2px 0vw 30px #e50b0b;
}

.green {
    color: #fff;
    text-shadow: 0 0 5px #00fff2, 0 0 10px #00fff2, 0 0 10px #00fff2, 0 0 0.1px #00fff2,
        0 0 0.1px #00fff2, 0 0 0.10px #00fff2, 0 0 10px #00fff2, 0 0 15px #00fff2;
}

.blue {
    color: #fff;
    text-shadow: 0 0 5px #1041ff, 0 0 15px #1041ff, 0 0 30px #1041ff, 0 0 30px #1041ff,
        0 0 0.2px #8bfdfe, 0.3px 0.3px 0.5px #147280;
}

a.searchParam 함수를 통해 쿼리 스트링의 문구(ment1, ment2)와 색상(color1, color2) 정보를 읽어 이를 uservalue 변수에 저장합니다.

b. printMent함수를 통해 각 노드에 접근하여 uservalue에 담긴 문구를 입력합니다.

c. setColor함수를 통해 각 노드에 접근하여 uservalue에 담긴 색상대로 클래스 이름을 지정합니다.

<예시>

<div id=”coment1”><div id=”coment1” class=”red”>

d. 이렇게 되면 CSS 파일에서 설정해둔 클래스에 맞는 색상의 네온 효과를 적용할 수 있습니다.

3. step 2의 모든 과정을 makeNeon 함수에 담았고, body 태그의 onload를 통해서 makeNeon함수를 호출해서 페이지가 로드될 때 네온사인 문구가 나타나도록 했습니다.

4. 글자가 이동하는 애니메이션은 HTML의 marquee 태그로도 사용할 수 있지만 좀 세밀한 효과를 구현하기 위해 CSS를 활용하였습니다.

a. 기본적으로 네온사인 문구는 멈춰있고, 클릭이 가능하도록 cursor: pointer 옵션을 지정해 주었습니다.

b. 문구를 꾹 누르게 되면 flow-text가 hover 상태로 바뀌는데 이때 문구가 8초 동안 화면상에서 반복적으로 움직이도록 작성했습니다.

c. 하드웨어 가속을 통한 부드러운 움직임을 위해 translate3d를 사용했습니다.

구름IDE 미리보기 기능이 유용했어요

저는 서비스는 주로 CSS로 개발했는데요, 왼쪽은 코드, 오른쪽은 웹페이지를 띄워 세팅한 뒤 ctrl+S를 눌러 결과물 확인과 코드 수정을 번갈아 가며 작업했습니다. 미리보기 기능으로 코드와 웹 페이지(코드 결과)를 한 공간에서 볼 수 있어서 수정 과정이 매우 편리했습니다.

개발을 시작한 지 얼마 되지 않았다면

저는 개발을 처음 시작할 때 개발 초기 설정이 어려웠는데요, 구름IDE는 컨테이너에서 자동으로 세팅해줘서 수월하게 개발을 시작할 수 있었던 기억이 있습니다. 또한 다양한 스택을 경험해볼 수 있기 때문에 많은 경험이 필요한 고등학생이나 개발을 시작한 지 얼마 안 된 분께 추천합니다.

Edit Ian Design Lily

Posted by
goorm

ANYONE CAN DEVELOP