💻

001. 메인페이지 만들기

1. 화면 레이아웃 구성하기

1.1 우리가 만들 화면

notion imagenotion image
 

1.2 화면 나누기

notion imagenotion image
1.1에서 확인한 우리가 만들 화면을 위의 이미지와 같이 나눕니다. 콘텐츠들을 넣을 하나의 큰 컨테이너(빨간 상자)와 그 안을 다섯 부분(파란 상자)으로 나누었습니다.
 

2. HTML

2.1 기본 구조

메인페이지를 만들기 위해 index.html 파일을 생성합니다. 우리가 실습할 Visual Studio Code에서 ! (느낌표)를 입력 후 Tab 을 누르면 기본 구조가 자동으로 생성됩니다. (Emmet이 설치되어 있어야 합니다.)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> </body> </html>
 
여기서, <title></title> 에 '나의 개발 유형찾기'를 입력하여 제목을 설정합니다.
<title>나의 개발 유형찾기</title>
 

2.2 태그 입력하기

1.2에서 나누었던 화면을 태그를 사용하여 실제로 구성해 봅시다. 콘텐츠들을 넣을 section 과 콘텐츠들을 감쌀 div 하나, 그리고 실제 콘텐츠들을 넣을 div 5개로 구성됩니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>나의 개발 유형찾기</title> </head> <body> <section> <div> <div></div> <div></div> <div></div> <div></div> <div></div> </div> </section> </body> </html>
 
💡
section>div>div*5 를 입력 후 Tab을 누르면 자동으로 입력됩니다.
 

2.3 id, class 입력하기

CSS 적용을 위해 id와 class명을 각 태그에 입력합니다.
<section id="main_contents"> <div class="wrapper"> <div class="title"></div> <div class="intro"></div> <div class="buttons"></div> <div class="result_data"></div> <div class="weniv"></div> </div> </section>
 

2.4 콘텐츠 넣기

2.4.1 제목

<div class="title"></div> 에 제목을 넣기 위해서 h3 태그 2개를 입력하고 각 태그들의 class 명을 main_titlesub_title로 설정하고 콘텐츠를 채워넣어 줍니다.
<div class="title"> <h3 class="main_title">나의 MBIT</h3> <h3 class="sub_title">My Best IT personalities</h3> </div>
 

2.4.2 개발 유형 리스트

<div class="intro"></div>에는 animation을 사용하여 개발 유형 리스트를 아래와 같이 넣을 것입니다.
 
notion imagenotion image
 
<div class="intro"> <h1>나의 개발 유형은?!</h1> <div class="type"> <ul class="type_list"> <li>개발자</li> <li>데이터 분석과 인공지능</li> <li>정보보안</li> <li>게임 개발</li> <li>개발자</li> </ul> </div> </div>
 
"나의 개발 유형은?!"은 h1 태그를 사용하고, 개발 유형 리스트는 ul 태그를 사용하여 입력합니다. animation 적용은 css 파트에서 진행하도록 하겠습니다.
 

2.4.3 버튼

이번에는 테스트 시작을 위한 '시작하기' 버튼을 넣어주도록 합시다. <div class="button"></div><button> 태그를 사용하여 버튼을 생성합니다. 이때 링크 연결을 위해 각 버튼을 a 태그로 감싸줍니다.
<div class="button"> <a href="#"> <button class="start" type="button">시작하기</button> </a> </div>
 
여기서 a 태그는 링크를 통해 다른 웹페이지 또는 문서로의 이동을 위해 사용되며, hrefhypertext reference의 약자로 연결할 주소를 지정하는 속성입니다. 주소는 #으로 설정하고 이후에 수정해 주도록 합시다.
button 태그에서 class명은 start로, type 속성은 button으로 설정하였습니다.
 

2.4.4 데이터

<div class="result_data></div> 에는 테스트에 참여한 참여자 수를 넣도록 합시다. '참여자 수'는 h3 태그, 각 유형별 참여자 수는 ul 태그를 사용하도록 하겠습니다. 각 콘텐츠들은 div 태그로 감싸주고 class명은 data_wrap으로 입력합니다.
<div class="result_data"> <div class="data_wrap"> <h3>참여자 수</h3> <ul> <li>백엔드 개발자 : 0명</li> <li>프론트엔드 개발자 : 0명</li> <li>데이터 분석과 인공지능 : 0명</li> <li>정보보안 : 0명</li> <li>게임 개발 : 0명</li> </ul> </div> </div>
 
💡
실제 데이터(참여자 수)를 넣어보는 실습은 백엔드 파트에서 진행됩니다.
 

2.4.5 weniv 로고

마지막으로 weniv 로고 이미지를 배치하겠습니다. 이미지 삽입을 위해 img 태그를 사용합니다. 이미지를 클릭하면 위니브 홈페이지(http://www.paullab.co.kr)로 이동되도록 a 태그를 사용합니다.
<div class="weniv"> <a href="http://www.paullab.co.kr"> <img src="img/weniv_logo_black.png" alt="weniv"> </a> </div>
 
이미지는 img 폴더에 있는 weniv_logo_black.png를 사용합니다. src 속성에 이미지 주소인 img/weniv_logo_black.png를 입력합니다.
alt 속성은 이미지의 주소가 잘못되었거나 해당 이미지가 존재하지 않을 경우 이미지를 대신하여 나타낼 대체 텍스트를 지정할 수 있는 속성입니다. 여기서는 'weniv'라고 입력하겠습니다.
 
💡
태그.클래스명 또는 태그#아이디명을 입력 후 Tab 을 누르면 클래스명 또는 아이디명이 입력된 태그가 자동으로 생성됩니다.
 

2.5 실행화면

notion imagenotion image
 

3. CSS 적용하기

3.1 CSS 파일 만들기

3.1.1 style.css

이제부터 메인페이지를 꾸며주기 위한 css 파일을 만들어 봅시다. css 폴더를 만든 후 style.css 파일을 만들어 주세요.
메인페이지에서의 모든 스타일 설정은 style.css에서 진행됩니다.
 

3.1.2 reset.css

css 폴더 내에 reset.css 파일을 생성한 후 아래 링크에서 코드를 복사하여 붙여넣기합니다.
 
행 높이, 여백 및 글꼴 크기 등과 같은 기본 스타일 설정은 브라우저마다 모두 다릅니다. 이에 따른 문제를 개선하고 기본 설정을 모두 통일시켜주기 위해 reset.css를 통해 스타일을 초기화합니다.
reset.css는 스타일 초기화에만 사용되며 추가 작업이 이루어지지 않습니다.
 

3.1.3 html 파일에 적용하기

앞서 생성한 두 개의 css 파일을 index.html에 적용합시다. <head></head> 안에 아래 코드를 넣어줍니다.
<link rel="stylesheet" type="text/css" href="css/reset.css"> <link rel="stylesheet" type="text/css" href="css/style.css">
 

3.2 스타일 적용하기

3.2.1 기본 설정

기본적으로 설정할 것은 글꼴, 배경, 그리고 기본 배치입니다.
우선 @font-face를 사용하여 폰트를 적용하여 봅시다. 우리가 사용할 폰트는 'Gmarket Sans B''넥슨 Lv.1 고딕 Reqular' 이렇게 두가지입니다.
아래와 같이 css 코드 제일 상단에 입력합니다.
@font-face { font-family: "GmarketSansBold"; src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2001@1.1/GmarketSansBold.woff") format('woff'); font-weight: normal; font-style: normal; } @font-face { font-family: "NEXON Lv1 Gothic OTF"; src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-04@2.1/NEXON Lv1 Gothic OTF.woff") format("woff"); font-weight: normal; font-style: normal; }
 
💡
폰트는 상업용 무료 한글 폰트 사이트인 '눈누'(https://noonnu.cc)에서 가져왔으며, 다양한 폰트를 확인할 수 있습니다.
 
이제 body에 기본 폰트, 글자 색상, 그리고 배경색을 지정해 봅시다. 앞서 설명했듯이 우리가 사용할 폰트는 두가지이지만, 우선 '넥슨 Lv.1 고딕 Reqular'를 기본 폰트로 설정하겠습니다.
body { background-color: #FAF1BE; color: #000; font-family: "NEXON Lv1 Gothic OTF"; }
 
모든 콘텐츠를 감싼 <section id="main_contents></seciton>를 전체 화면으로 설정해 주기 위해 widthheight를 모두 100%로 지정합니다.
#main_contents{ width: 100%; height: 100%; }
 
하지만 아래 사진과 같이 #main_contents 는 전체 화면이 아닌 콘텐츠만큼의 영역만 차지합니다.
notion imagenotion image
 
이러한 문제를 해결하기 위해서는 htmlbody 각각의 width와 height에도 100%씩 설정해 주어야 합니다. 아래와 같이 입력하면 #main_contents의 영역이 전체 화면만큼 차지하는 것을 확인할 수 있습니다.
html { width: 100%; height: 100%; } body { width: 100%; height: 100%; background-color: #FAF1BE; color: #000; font-family: "NEXON Lv1 Gothic OTF"; }
 
💡
개발자 도구(F12 또는 Ctrl+Shift+i)를 사용하면 태그 및 콘텐츠의 영역과 스타일을 쉽게 확인할 수 있습니다.
 
1.1의 우리가 만들 화면은 중앙 정렬이 되어 있고 화면의 상단에는 여백이 있습니다.
여기서는 플렉스 박스(flex box)를 사용하여 레이아웃을 설정합니다. 해당 요소를 블록 타입으로 정의하기 위해 display 속성을 flex로 지정하고, 플렉스 박스의 속성 중 수평 방향 정렬을 설정할 수 있는 justify-content 속성을 center로 설정하여 콘텐츠들을 중앙으로 배치합니다.
상단의 여백은 margin-top을 100px 만큼 설정하여 만들어 줍니다.
#main_contents{ display: flex; justify-content: center; width: 100%; height: 100%; margin-top: 100px; }
 
콘텐츠를 다시 한 번 감싸주는 div<div class="wrapper"></div> 의 width, height, 그리고 배치도 설정해 줍시다.
width와 height, 그리고 display는 #main_contents 와 동일하게 설정합니다. 하지만 .wrapper 에서는 플렉스 박스의 속성 중 하나인 flex-direction 속성을 column으로 설정하여 요소들의 배치 방향을 수직으로 변경시킵니다.
또한, max-width를 사용하여 500px 만큼의 최대 너비를 설정합니다. max-width는 내부 콘텐츠들의 너비가 최대 너비보다 커지는 것을 방지하기 위하여 사용합니다.
#main_contents .wrapper { display: flex; flex-direction: column; width: 100%; height: 100%; max-width: 500px; }
 

3.2.2 제목

이제 제목의 스타일을 설정합시다. text-align 을 center로 설정하여 중앙 정렬을 하고, padding-bottom 을 사용하여 하단에 50px만큼 여백을 줍니다.
.title { text-align: center; padding-bottom: 50px; }
 
메인 제목과 서브 제목은 서로 글자 크기와 색상 등의 스타일이 다르기 때문에 각각의 class명을 사용하여 설정합니다.
.main_title 의 폰트는 'Gmarket Sans B'로 지정하고 font-size 는 50px로 설정합니다. 또한 하단의 .sub_title 과의 간격을 주기 위해 padding-bottom 을 사용하여 15px만큼 여백을 설정합니다.
.main_title { font-family: "GmarketSansBold"; font-size: 50px; padding-bottom: 15px; }
 
.sub_title 에서는 글자 크기와 굵기, 그리고 색상을 설정합니다.
.sub_title { font-size: 20px; font-weight: bold; color: #7F47DD; }
 

3.2.3 개발 유형 리스트

지금부터는 CSS 애니메이션을 사용해서 개발 유형들이 하나씩 돌아가면서 나타나도록 하겠습니다.
우선 애니메이션 적용에 앞서 .intro 에 스타일을 적용하여 요소들을 배치하고 아래 버튼과 간격을 주도록 하겠습니다.
text-align 속성을 center로 설정하여 중앙 정렬시키고, padding-bottom 을 사용하여 40px만큼 여백을 줍니다.
.intro { text-align: center; padding-bottom: 40px; }
 
"나의 개발 유형은?!"에 스타일을 설정해 주도록 합시다. .intro 의 자손인 h1 을 선택하기 위해 .intro h1 선택자를 사용하여 스타일을 적용합니다.
.intro h1 { font-size: 30px; padding-bottom: 15px; }
 
개발 유형 리스트의 font-size 를 25px로 설정합니다. .typeline-heightheight 를 동일한 값으로 설정합니다.
.type { font-size: 25px; line-height: 3em; height: 3em; }
 
실행화면을 보면 아래와 같이 리스트가 넘친 것을 확인할 수 있습니다. 이를 해결하기 위해 overflow: hidden 을 추가하여 넘친 콘텐츠를 잘라내어 보이지 않게 합니다.
notion imagenotion image
 
.type { font-size: 25px; line-height: 3em; height: 3em; overflow: hidden; }
 
이제 애니메이션을 적용하기 위해 animation 속성과 애니메이션 중간 상태를 기술하기 위한 @keyframes 규칙을 사용하도록 하겠습니다.
우리는 아래와 같이 5개의 중간 상태를 기술하여 5개의 li 요소의 위치를 이동시키며 하나씩 나타나게 할 것입니다. transform 속성의 translateY() 를 사용하여 Y축(수직 방향)으로 이동 효과를 부여합니다.
@keyframes rotate { 0% { transform: translateY(0); } 25% { transform: translateY(-20%); } 50% { transform: translateY(-40%); } 75% { transform: translateY(-60%); } 100% { transform: translateY(-80%); } }
 
키프레임을 통해 애니메이션의 중간 상태를 기술하였으면 이제 적용하도록 합시다. 스타일은 .type_list 에 적용합니다.
animation 속성에 중간 상태를 기술한 animation-name 과 한 사이클을 완료하는 데 걸리는 시간을 지정하는 animation-duration , 그리고 애니메이션이 무한히 반복되도록 animation-iteration-count 를 설정합니다. 이때, 따로 설정하지 않은 속성들은 기본값으로 설정됩니다.
.type_list { animation: rotate 7s infinite; }
 
위의 코드처럼 animation 속성에 한 번에 입력할 수도 있으나, 아래와 같이 풀어서 입력할 수도 있습니다.
animation-name: rotate; animation-duration: 7s; animation-iteration-count: infinite;
 

3.2.4 버튼

이제 버튼을 꾸며줄 차례입니다. 우선 앞에서 해왔던 것과 동일한 방법으로 배치부터 해보도록 합시다. text-align 을 center로 설정하여 중앙 정렬하고, padding-bottom 으로 안쪽 아래 50px만큼의 여백을 줍니다.
.button { text-align: center; padding-bottom: 50px; }
 
버튼의 widthheight 를 각각 300px, 50px로 하여 크기를 변경합니다. 또한, padding 을 5px로 설정하여 버튼 안쪽 여백을 상, 하, 좌, 우, 모두 균일하게 5px씩 줍니다.
border-style 을 none으로 지정하여 버튼의 테두리를 없애고, 버튼의 각 모서리를 부드럽게 만들어 주기 위해 border-radius 를 10px로 설정합니다.
.button button{ width: 300px; height: 50px; padding: 5px; border-style: none; border-radius: 10px; }
 
이어서 버튼의 폰트, 크기, 굵기 등의 스타일을 설정합니다.
.button button{ (...) font-family: "NEXON Lv1 Gothic OTF"; font-size: 20px; font-weight: bold; }
 
버튼의 배경색과 글자색도 함께 설정합니다. 요소 위에 마우스 커서가 올라갔을 때 모양을 지정하는 cursor 속성을 pointer로 지정합니다. 또한 margin-bottom 을 20px로 설정하여 아래 요소와의 여백을 줍니다.
.button button{ (...) background-color: #fff; color: #7F47DD; cursor: pointer; margin-bottom: 20px; }
 
💡
padding은 요소의 안쪽 여백을 설정하고, margin은 요소의 바깥 여백을 설정합니다.
 
버튼에 마우스 커서가 올라갔을 때 효과를 주고 싶습니다. 이때 사용하는 것이 가상 클래스 :hover 입니다
.button button:hover.bottun 의 자손인 button 에 마우스 오버했을 때 button이 선택되며, 이때 선택된 요소(button)에 스타일을 설정할 수 있습니다.
여기서는 text-decoration 속성을 underline으로 설정하여 마우스 오버되면 밑줄이 생기도록 합니다.
.button button:hover{ text-decoration: underline; }
 

3.2.5 데이터

'참가자 수'를 표시할 .result_data 를 중앙 정렬시키기 위해 display 를 flex로 설정하고, 수평 방향으로 정렬하는 justify-content 를 center로 설정합니다.
.result_data { display: flex; justify-content: center; }
 
데이터 영역은 버튼과 같은 width를 설정할 것입니다. 하지만 버튼은 300px로 설정해 주었지만 .data_wrap 에서 width는 270px로 설정합니다. 그 이유는 padding 값을 15px씩 주었으므로 300px로 설정하면 실제 차지하는 width는 330px이 되어버리기 때문입니다. 따라서 270px로 설정해야 실제 차지하게 되는 width는 300px이 됩니다.
그 다음은 위, 아래에 각각 수평선을 그리기 위해 요소의 테두리를 설정하는 border 를 사용합니다. border-topborder-bottom 에는 각각 "3px solid #000"의 동일한 값을 입력합니다. 이는 하나의 직선(solid)으로 두께가 3px인 검은색 테두리를 그린다는 뜻입니다.
.result_data .data_wrap { width: 270px; padding: 15px; border-top: 3px solid #000; border-bottom: 3px solid #000; }
 
이어서 line-height 을 1.5로 설정하여 행간을 띄우고, 아래 로고와의 여백을 50px만큼 줍니다.
.result_data .data_wrap { (...) line-height: 1.5; margin-bottom: 50px; }
 
'참여자 수'를 중앙 정렬하고 폰트 사이즈를 20px로 설정합니다. 그리고 글자 굵기는 bold로 설정합니다.
안쪽 여백을 상, 하에만 각각 20px과 30px로 설정하기 위해 padding: 20px 0 30px 로 입력합니다.
.result_data h3 { text-align: center; font-size: 20px; font-weight: bold; padding: 20px 0 30px; }
 
유형별 참여자 수는 '참여자 수'보다 좀 작게 표현하기 위해 폰트 사이즈를 15px로 합니다. 또한 안쪽 아래 여백을 위의 여백과 동일하게 20px로 설정합니다.
.result_data li { font-size: 15px; padding-bottom: 20px; }
 

3.2.6 로고

이제 메인페이지의 마지막 작업인 로고입니다. 이전과 마찬가지로 우선 배치부터 해보도록 합시다. justify-content 를 center로 설정하여 중앙 정렬을 시켜주고 아래 여백은 50px만큼 줍니다.
.weniv { display: flex; justify-content: center; padding-bottom: 50px; }
 
로고의 크기를 조절하기 위해 img 태그를 감싸고 있는 a 태그의 width를 100px로 설정하고, imgwidthheight는 각각 100%, auto로 설정합니다.
.weniv a { width: 100px; } .weniv img{ width: 100%; height: auto; }
 

3.3 실행화면

notion imagenotion image
 

4. 전체 코드

4.1 index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="css/reset.css"> <link rel="stylesheet" type="text/css" href="css/style.css"> <title>나의 개발 유형찾기</title> </head> <body> <section id="main_contents"> <div class="wrapper"> <div class="title"> <h3 class="main_title">나의 MBIT</h3> <h3 class="sub_title">My Best IT personalities</h3> </div> <div class="intro"> <h1>나의 개발 유형은?!</h1> <div class="type"> <ul class="type_list"> <li>개발자</li> <li>데이터 분석과 인공지능</li> <li>정보보안</li> <li>게임 개발</li> <li>개발자</li> </ul> </div> </div> <div class="button"> <a href="#"> <button class="start" type="button">시작하기</button> </a> </div> <div class="result_data"> <div class="data_wrap"> <h3>참여자 수</h3> <ul> <li>백엔드 개발자 : 0명</li> <li>프론트엔드 개발자 : 0명</li> <li>데이터 분석과 인공지능 : 0명</li> <li>정보보안 : 0명</li> <li>게임 개발 : 0명</li> </ul> </div> </div> <div class="weniv"> <a href="http://www.paullab.co.kr"> <img src="img/weniv_logo_black.png" alt="weniv"> </a> </div> </div> </section> </body> </html>
 

4.2 style.css

@font-face { font-family: "GmarketSansBold"; src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2001@1.1/GmarketSansBold.woff") format('woff'); font-weight: normal; font-style: normal; } @font-face { font-family: "NEXON Lv1 Gothic OTF"; src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-04@2.1/NEXON Lv1 Gothic OTF.woff") format("woff"); font-weight: normal; font-style: normal; } @keyframes rotate { 0% { transform: translateY(0); } 25% { transform: translateY(-20%); } 50% { transform: translateY(-40%); } 75% { transform: translateY(-60%); } 100% { transform: translateY(-80%); } } html { width: 100%; height: 100%; } body { width: 100%; height: 100%; background-color: #FAF1BE; color: #000; font-family: "NEXON Lv1 Gothic OTF"; } #main_contents { display: flex; justify-content: center; width: 100%; height: 100%; margin-top: 100px; } #main_contents .wrapper { display: flex; flex-direction: column; width: 100%; height: 100%; max-width: 500px; } .title { text-align: center; padding-bottom: 50px; } .main_title { font-family: "GmarketSansBold"; font-size: 50px; padding-bottom: 15px; } .sub_title { font-size: 20px; font-weight: bold; color: #7F47DD; } .intro { text-align: center; padding-bottom: 40px; } .intro h1 { font-size: 30px; padding-bottom: 15px; } .type { font-size: 25px; line-height: 3em; height: 3em; overflow: hidden; } .type_list { animation: rotate 7s infinite; } .button { text-align: center; padding-bottom: 50px; } .button button { width: 300px; height: 50px; padding: 5px; border-style: none; border-radius: 10px; font-family: "NEXON Lv1 Gothic OTF"; font-size: 20px; font-weight: bold; cursor: pointer; background-color: #fff; color: #7F47DD; margin-bottom: 20px; } .button button:hover { text-decoration: underline; } .result_data { display: flex; justify-content: center; } .result_data .data_wrap { width: 270px; padding: 15px; border-top: 3px solid #000; border-bottom: 3px solid #000; line-height: 1.5; margin-bottom: 50px; } .result_data h3 { text-align: center; font-size: 20px; font-weight: bold; padding: 20px 0 30px; } .result_data li { font-size: 15px; padding-bottom: 20px; } .weniv { display: flex; justify-content: center; padding-bottom: 50px; } .weniv a { width: 100px; } .weniv img { width: 100%; height: auto; }