Remote SSH로 원격 코딩하기

우리가 로컬에서 개발한 프로젝트를 서버 컴퓨터에서 실행하고 싶으면 어떻게 해야할까?

방법은 서버 컴퓨터에서 해당 프로젝트를 실행해주면 된다.

말로는 정말 쉬워보이지만 막상 하려고 하면 뭐부터 해야할지 모르겠다.

그래서 단계를 나눠서 도전해보자.

과정

remotessh

  1. 우선 VSCode에서 “Remote - SSH”라는 익스텐션을 다운받는다. 해당 extension을 사용하여 서버 컴퓨터에서 원격으로 프로젝트를 실행할 것이다.

sshSettings1

  1. 톱니바퀴를 눌러서 config 파일을 연다.

  2. config 파일 설정은 다음과 같다.

sshSetting2

  • Host는 원격 서버의 이름을 나타낸다.
  • User는 계정 이름으로 보통 “ubuntu”
  • ssh 파일 경로는 SSH키가 담긴 .pem 파일의 경로
  1. 이제 VSCode를 사용하여 서버를 원격으로 조종할 수 있다.

sshSetting3

우측에 새창으로 열기를 클릭하면 서버환경에서 VSCode가 열리게 될 것이다.

이 후 VSCode에서 터미널을 켜서 git clone을 하여 github 레포지토리를 클론한 다음

프로젝트를 실행하면 원격으로 서버 컴퓨터에서 프로젝트를 실행할 수 있게된다.

댓글 공유

기본적인 HTML구조와 CSS로 다음과 같은 form을 만들 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<!DOCTYPE html>
<html>
<style>
input[type="text"],
select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}

input[type="submit"] {
width: 100%;
background-color: #4caf50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}

input[type="submit"]:hover {
background-color: #45a049;
}

div {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
</style>
<body>
<h3>Using CSS to style an HTML Form</h3>

<div>
<form action="/action_page.php">
<label for="fname">First Name</label>
<input
type="text"
id="fname"
name="firstname"
placeholder="Your name.."
/>

<label for="lname">Last Name</label>
<input
type="text"
id="lname"
name="lastname"
placeholder="Your last name.."
/>

<label for="country">Country</label>
<select id="country" name="country">
<option value="australia">Australia</option>
<option value="canada">Canada</option>
<option value="usa">USA</option>
</select>

<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>

commonForm

focused Inputs

1
2
3
input[type="text"]:focus {
background-color: lightblue;
}

icon/image 삽입하기

1
2
3
4
5
6
7
8
9
10
11
12
input[type="text"] {
width: 100%;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
font-size: 16px;
background-color: white;
background-image: url("searchicon.png");
background-position: 10px 10px;
background-repeat: no-repeat;
padding: 12px 20px 12px 40px;
}

icon

animated Search Input

1
2
3
4
5
6
7
input[type="text"] {
transition: width 0.4s ease-in-out;
}

input[type="text"]:focus {
width: 100%;
}

textarea 사이즈 재조정 방지하기

1
2
3
4
5
6
7
8
9
10
11
textarea {
width: 100%;
height: 150px;
padding: 12px 20px;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
background-color: #f8f8f8;
font-size: 16px;
resize: none;
}
  • resize 속성을 none으로 주어 사이즈 재조정을 막는다.

반응형 form 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
* {
box-sizing: border-box;
}

input[type="text"],
select,
textarea {
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
resize: vertical;
}

label {
padding: 12px 12px 12px 0;
display: inline-block;
}

input[type="submit"] {
background-color: #04aa6d;
color: white;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}

input[type="submit"]:hover {
background-color: #45a049;
}

.container {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}

.col-25 {
float: left;
width: 25%;
margin-top: 6px;
}

.col-75 {
float: left;
width: 75%;
margin-top: 6px;
}

/* Clear floats after the columns */
.row::after {
content: "";
display: table;
clear: both;
}

/* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
.col-25,
.col-75,
input[type="submit"] {
width: 100%;
margin-top: 0;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<h2>Responsive Form</h2>
<p>
Resize the browser window to see the effect. When the screen is less than
600px wide, make the two columns stack on top of each other instead of next to
each other.
</p>

<div class="container">
<form action="/action_page.php">
<div class="row">
<div class="col-25">
<label for="fname">First Name</label>
</div>
<div class="col-75">
<input
type="text"
id="fname"
name="firstname"
placeholder="Your name.."
/>
</div>
</div>
<div class="row">
<div class="col-25">
<label for="lname">Last Name</label>
</div>
<div class="col-75">
<input
type="text"
id="lname"
name="lastname"
placeholder="Your last name.."
/>
</div>
</div>
<div class="row">
<div class="col-25">
<label for="country">Country</label>
</div>
<div class="col-75">
<select id="country" name="country">
<option value="australia">Australia</option>
<option value="canada">Canada</option>
<option value="usa">USA</option>
</select>
</div>
</div>
<div class="row">
<div class="col-25">
<label for="subject">Subject</label>
</div>
<div class="col-75">
<textarea
id="subject"
name="subject"
placeholder="Write something.."
style="height:200px"
></textarea>
</div>
</div>
<br />
<div class="row">
<input type="submit" value="Submit" />
</div>
</form>
</div>

댓글 공유

반복문 시간 복잡도

다음 코드의 시간 복잡도를 구해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;
int n, cnt;
int main(){
cin >> n;
int a = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
a += i+j;
cnt++;
}
}
cout << a << '\n';
cout << " cnt : " << cnt << '\n'
return 0
}

처음에는 하나씩 콘솔을 찍어보면서 계산해보자.

  1. i = 0, j는 무시;
  2. i = 1, j = 0
  3. i = 2, j = 0,1
  4. i = 3, j = 0,1,2

정사각형의 한 변의 길이가 n일 때, 정사각형의 넓이는 n^2이다.

이와 마찬가지로 시간복잡도도 해당 도형의 넓이로 구할 수 있다.

위 식을 넓이로 나타내면 j는 i를 포함하지 않고 있기 때문에 n * (n - 1) % 2로 나타낼 수 있다.

재귀함수 시간 복잡도

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<bits/stdc++.h>
using namespace std;
int n, a[1004], cnt;

int go(int l, int r){
cnt++;
if(l == r) return a[l];
int mid = (l + r) / 2;
int sum = go(l, mid) + go(mid + 1, r);
return sum;
}

int main(){
cin >> n;
for(int i = 1; i <= n; i++){
a[i - 1] = i;
}
int sum = go(0, n - 1);
cout << sum << '\n';
cout << 'cnt: ' << cnt << '\n';
}

시간복잡도는 어떤 로직이 몇 번 반복되었는지를 식으로 만들고 빅오표기법으로 표현하는 것이다.

좀 더 자세히 말하면 재귀함수의 메인로직 * 몇번 호출되는지이다.

그래서 해당 go 함수가 몇번 호출되는지 직접 손코딩으로 그려보며 세어보았다.

n = 5일 때, 9가 나오고 n = 10일 때, 19, n = 20일 때, 39가 나오는 것을 보고 아 시간 복잡도가 2n - 1이구나라는 것을 알게되었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<bits/stdc++.h>
using namespace std; int N, cnt;

void solve(int N){
cnt++;
cout << cnt << '\n';
if(N == 0) return;
for(int i = 0; i < 3; i++){
solve(N - 1);
}
return;
}

int main(){
cin >> N;
solve(N);
return 0;
}

예를 들어 n = 3일 때, 처음 1회 실행되고 함수가 3번씩 호출되는데 만약 N이 0이아니면 또 3번씩 호출되므로 공비가 3인 등비수열로 생각할 수 있다.

따라서 등비수열의 합식이 성립한다.

time complexity

📌 Tip

함수 하나가 호출될 때 이 함수가 4번 호출된다면 => 4^n

함수 하나가 호출될 때, 이 함수가 2번 호출된다면 => 2^n

로그 지수 역함수의 시간 복잡도

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<bits/stdc++.h>
using namespace std; int N;

void solve(int N){
int a = 0, i = N;
while (i > 0) {
a += i;
i /= 2;
}
cout << a << '\n';
}

int main(){
cin >> N;
solve(N);
return 0;
}

위 식에서 while문은 log N + 1의 시간복잡도를 가지고 빅오표기법으로 나타내면 log N이다.

log N은 2를 몇번 곱해서 N의 값이 될 수 있는지를 나타낸 수이다.

댓글 공유

개발자는 사용자에게 안정적인 서비스를 제공하기 위해 여러가지 방법을 사용한다.

정적 타입 시스템도 그 중 하나다.

타입 시스템

타입 시스템은 개발자가 정의한 타입을 기반으로 해당 타입을 언어와 연관시키는 메커니즘이다.

  • 동등: 두 타입이 동일할 때 적용 (number:number)
  • 호환: 두가지 타입이 정확히 일치하지 않더라도 어느정도 호환이 되는지를 나타내는 규칙(any: number)
  • 추론: 타입이 정의되어 있지 않지만 주변 문맥에 따라 타입이 결정되는 규칙(a=3 일 때, a는 number)

모든 언어는 타입시스템이 존재하고 동적 타입과 정적 타입으로 나뉜다.

동적 타입과 정적 타입 차이

동적 타입

런타임에 모든 변수의 유형을 결정한다. 잘못된 경우 예외 발생시킨다.

ex) PHP, JS, Python

정적 타입

컴파일 타임에 모든 변수의 유형을 결정한다. 잘못된 경우 예외 발생시킨다.

ex) C, C++, Java

정적 타입 시스템의 필요성

  1. 타입을 명시하여 나중에 다른 개발자가 보더라도 어떤 매개변수를 넣고 이 함수가 어떤 값을 반환하는지 명시적으로 파악 가능

  2. 어떤 함수 또는 API에 대해 여러가지의 타입으로 이루어진 값이 발생될 수 있는데, 해당 값들에 대한 대처를 “미리” 할 수 있다.

  3. 매개변수 잘못입력하거나 등의 개발자 잔실수 줄여준다.

댓글 공유

[attribute]

특정 attribute를 선택하기 위해 사용하는 선택자이다.

1
2
3
a[target] {
background-color: yellow;
}
  • a 태그의 target attribute가 선언된 요소를 선택한다.
1
2
3
a[target="_blank"] {
background-color: yellow;
}
  • attribute 값에 해당하는 요소를 선택한다.

정확히 특정 단어 포함하는 attribute 선택

1
2
3
[title~="flower"] {
border: 5px solid yellow;
}
1
2
3
4
5
6
7
8
9
<h2>CSS [attribute~="value"] Selector</h2>
<p>
All images with the title attribute containing the word "flower" get a yellow
border.
</p>

<img src="klematis.jpg" title="klematis flower" width="150" height="113" />
<img src="img_flwr.gif" title="flower f" width="224" height="162" />
<img src="img_tree.gif" title="tree" width="200" height="358" />

  • title 속성에 “flower” 단어가 포함된 요소를 선택한다.

띄어쓰기로 구분된 요소는 개별요소로 취급하짐나, 하이푼(-)으로 구분된 요소는 여기서 제외된다.

특정 단어를 포함하는 attribute 선택

1
2
3
[class|="top"] {
background: yellow;
}
1
2
3
4
5
<h2>CSS [attribute|="value"] Selector</h2>

<h1 class="top-header">Welcome</h1>
<p class="top-text">Hello world!</p>
<p class="topcontent">Are you learning CSS?</p>

include value

  • top이라는 단어가 포함된 요소만 선택하는 것을 확인할 수 있다. (-으로 구분할 수 있다.)

특정 단어로 시작하는 attribute 속성 선택

1
2
3
[class^="top"] {
background: yellow;
}
1
2
3
4
5
<h2>CSS [attribute|="value"] Selector</h2>

<h1 class="top-header">Welcome</h1>
<p class="top-text">Hello world!</p>
<p class="topcontent">Are you learning CSS?</p>

startwith

특정 단어로 끝나는 attribute 속성 선택

1
2
3
[class$="test"] {
background: yellow;
}

특정 값을 포함하는 attribute 속성을 선택

1
2
3
[class*="te"] {
background: yellow;
}

댓글 공유

image sprites

이미지 스프라이트는 단일 이미지에 포함된 이미지 모음이다.

이미지가 많은 웹 페이지 로드하는데 많은 시간이 걸릴 수 있고 서버 요청도 여러번 발생할 수 있다.

이미지 스프라이트를 사용하면 서버 요청 수가 줄어들고 대역폭이 줄어든다.

예시

3개의 이미지를 사용하는 대신, 하나의 이미지를 사용한다.

그리고 나서 CSS로 보여주고 싶은 부분만 보여준다.

imageSprites

1
2
<img id="home" src="img_trans.gif" width="1" height="1" />
<img id="next" src="img_trans.gif" width="1" height="1" />
  • src 속성은 비워둘 수 없기 때문에 투명한 이미지를 넣어두었다.
  • 보여주고 싶은 이미지의 부분을 width, height로 정의했다.
  • background 속성으로 배경이미지를 불러오고 left, top 속성으로 배치한다.
1
2
3
4
5
6
7
8
9
10
11
#home {
width: 46px;
height: 44px;
background: url(img_navsprites.gif) 0 0;
}

#next {
width: 43px;
height: 44px;
background: url(img_navsprites.gif) -91px 0;
}

homeNext

댓글 공유

Dropdown

CSS만을 이용하여 dropdown을 구현해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<style>
.dropdown {
position: relative;
display: inline-block;
}

.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
padding: 12px 16px;
z-index: 1;
}

.dropdown:hover .dropdown-content {
display: block;
}
</style>

<div class="dropdown">
<span>Mouse over me</span>
<div class="dropdown-content">
<p>Hello World!</p>
</div>
</div>
  1. 우선 dropdown content를 열기 위한 span, button 요소를 사용한다.

  2. dropdown content는 div같은 컨테이너 요소를 사용한다.

  3. dropdown content를 CSS에 정확하게 배치하기 위해 1,2번을 div로 감싼다.

  4. wrapper div에는 position:relative 속성을 주어 기준이 되도록 하며 dropdown content에는 position:absolute 속성을 주어 dropdown button 바로 아래에 위치하도록 한다.

  5. dropdown content는 hidden 속성이 기본값이다. 그리고 hover시 아래에 보이도록 한다. 그리고 min-width 속성을 줘서 width를 갖게 한다.

이때, dropdown button 만큼 넓게 width를 갖게 하고 싶다면 width:100%로 설정해라. 작은 화면에서 스크롤을 활성화 시키려면 overflow:auto를 설정하라.

  1. border를 설정하는 것 대신 box-shadow 속성으로 카드처럼 보이게 할 수 있다.

  2. hover 속성은 dropdown menu를 보여줄 때 사용된다.

댓글 공유

앞서 IaaS와 PaaS의 장점만 결합시킨 것이 도커이다. IaaS의 이식성과 PaaS의 운영비 장점을 갖춘 도커에 대해 알아보자.

서사를 위해서 전통적인 배포는 어떠했을지 살펴보자.

deploy

전통적 배포

물리적 컴퓨터 한 대에 하나의 OS를 깔고 여러 프로그램을 설치하는 방식이었다. 이 때, 어떤 프로그램 설치하게되면 다른 앱에 영향을 미친다.

예를 들어, 예전에 보안 앱을 깔았더니 인터넷이나 어떤 애플리케이션이 제대로 동작하지 않았던 경험이 있다.

가상화 배포

전통적 배포에서 발전이 되어 가상머신을 기반으로 배포하는 가상화 배포가 등장하였다.

Hypervisor는 하나의 시스템상에서 가상 컴퓨터 여러 개를 구동할 수 있도록 중간계층 역할을 한다.

결과적으로 컴퓨터 한 대로 여러 앱을 독립적으로 실행하여 다른 앱에 영향을 끼치지 않는다.

단, OS도 독립적이기 때문에 비용이 많이든다.

가상머신: 컴퓨터 모든 부품을(HardWare) 소프트웨어적으로 구현한 것

컨테이너 배포

container

컨테이너는 코드와 모든 종속성(Node.js, 라이브러리 등)을 패키징하는 소프트웨어 표준 단위이다.

컨테이너는 VM(Virtual Machine)과 유사하지만, 운영체재(OS)만 공유하고 애플리케이션은 독립적 컴퓨터로 구분되어 있다.

때문에 애플리케이션끼리 영향을 미치지 않고 비용도 가상화 배포보다 저렴하고 빠르다.

다만 OS는 공유하기 때문에 애플리케이션의 문제가 OS에 영향을 미치면 구동 중인 전체 컨테이너에 문제가 될 수 있다.

Docker

그래서 도커는 앞서 설명한 컨테이너라는 단위로 애플리케이션을 실행하는 기능을 제공하는 플랫폼이다.

여러 컴퓨터 간에 공유된 규격으로 리소스를 공유할 수 있어 유지보수성이 좋다.

또한 IaaS의 이식성과 PaaS의 운영비 장점을 갖추었다.

기존의 종속성 라이브러리나 파일 등 기존 시스템에 대한 설치 절차를 Dockerfile 스크립트에 작성하고 배포 관련 사항을 도커스웜이나 쿠버네티스에 맞춰 작성해주기만 하면 된다. 그래서 보통 도커 + 쿠버네티스 또는 도커 + 도커 스웜으로 구축된다.

Docker 컨테이너 빌드 과정

docker

  1. 도커파일이 빌드
  2. 도커 이미지 생성 및 실행
  3. 도커 컨테이너 실행
  • 도커파일(Dockerfile): 컨테이너에 설치해야하는 패키지, 환경 변수설정 등을 기록한 하나의 파일
  • 도커이미지: 도커가 도커파일의 단계에 따라 컴퓨터의 상태를 “스냅샷”으로 저장한 것
  • 컨테이너: 도커가 이미지를 불러와 실행할 때 생성되며, 실행중인 컨테이너는 이미지에 지정된 프로그램과 데이터를 사용해 일반적인 실제 컴퓨터와 연결되어 사용가능

Docker는 IaaS인가? PaaS인가?

엄밀히 말하면 둘 다 아니고 “클라우드 가상화기술”이지만 굳이 따지면 PaaS의 일부라고 보면된다.

컨테이너의 가상화는 가상 머신의 가상화가 일어나는 곳에서 한 추상화 계층 높은 곳에서 일어난다.

댓글 공유

클라우드

클라우드란, 인터넷을 통해 접근할 수 있는 서버와 그 안에서 구동되는 소프트웨어, DB를 의미한다.

직접적으로 컴퓨터 장비를 구매하지 않고 온라인에 분산되어 존재하는 데이터 센터(클라우드)에게 작업을 맡겨 수행하는 것이다.

이를 오프프레미스(off-premise)방식이라고 한다.

반면 기업이나 개인이 자체 시설을 보유하고 직접 유지관리하는 데이터 센터(IDC)fmf 온프레미스(on-premise)방식이라고 한다.

장점

  • 서버컴퓨터, 네트워크, 방화벽, 전력 등에 대한 고려를 하지 않고 서비스 운영에만 집중할 수 있다.

SaaS(Software as a Service)

인터넷을 통해 소프트웨어(완제품)을 제공하는 방법이다. 구글 드라이브, N드라이브, 구글 DOCS 등.

예를 들어, 구글 DOCS처럼 다른 컴퓨터에서도 쉽게 작업을 하며 다른사람과 실시간 공유작업도 가능하다.

IaaS(Infrastructure as a Service)

인터넷을 통해 인프라를 제공(서버와 저장소)한다. 빈 방을 준다고 생각하면 된다.

특정 클라우드에 종속되지 않는 대신 운영비가 상승한다. 또한 이식성이 좋다.

ex) AWS의 EC2, NCP 등이 있다.

PaaS(Platform as a Service)

인터넷을 통해 플랫폼을 제공한다. 빌트인 방을 제공한다. 운영비 절감할 수 있고 모니터링, CI/CD 제공된다.

하지만, 하나의 서버에 여러가지 서비스를 설치할 수 없어서 IaaS보다는 유연하지 않고 플랫폼에 종속된다.

ex) heroku: 자유롭게 클릭 몇번으로 여러가지 서비스 설치 가능

PaaS vs IaaS

PaaS

  • 유연하지 않고 플랫폼에 종속된다.
  • 설치가 쉽다.
  • 이식성이 낮다.
    • 각 서비스가 각자의 서버에서 동작하고 각각의 서버를 따로 연결해줘야하기 때문에…
  • 운영비 효율 좋다.

IaaS

  • 유연하고 플랫폼에 종속되지 않는다.
  • 설치가 어렵다.
  • 이식성이 높다.
    • 반면 IaaS는 빈 방(서버)를 그대로 이식하면 되기에 이식성이 높다.
  • 운영비 효율 낮다.

댓글 공유

Navigation Bar

Navigation Bar는 link의 목록들이다.

1
2
3
4
5
6
<ul>
<li><a href="default.asp">Home</a></li>
<li><a href="news.asp">News</a></li>
<li><a href="contact.asp">Contact</a></li>
<li><a href="about.asp">About</a></li>
</ul>

기본적인 list 스타일을 제거하기 위한 CSS는 다음과 같다.

1
2
3
4
5
ul {
list-style-type: none;
margin: 0;
padding: 0;
}

수직 Navigation Bar

1. li 요소 내부의 a태그에 display:block 선언하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ul {
list-style-type: none;
margin: 0;
padding: 0;
width: 200px;
background-color: #f1f1f1;
}

li a {
display: block;
color: #000;
padding: 8px 16px;
text-decoration: none;
}

/* Change the link color on hover */
li a:hover {
background-color: #555;
color: white;
}

추가로 active 클래스를 추가하여 현재 선택된 link를 표시해줄 수 있다. JavaScript 사용해야한다.

1
2
3
4
5
6
7
8
9
10
li a.active {
background-color: #04aa6d;
color: white;
}

/* .active 클래스는 포함하지 않는 a태그 hover시 효과 */
li a:hover:not(.active) {
background-color: #555;
color: white;
}

2. 고정된 세로 Navigation Bar

sticky side 네비게이션 바를 만드는 방법이다.

1
2
3
4
5
6
7
8
9
10
ul {
list-style-type: none;
margin: 0;
padding: 0;
width: 25%;
background-color: #f1f1f1;
height: 100%; /* Full height */
position: fixed; /* Make it stick, even on scroll */
overflow: auto; /* Enable scrolling if the sidenav has too much content */
}

수평 Navigation Bar

1. li 요소를 display:inline 속성을 준다.

1
2
3
li {
display: inline;
}

2. floating li

float

1
2
3
4
5
6
7
8
9
li {
float: left;
}

a {
display: block;
padding: 8px;
background-color: #dddddd;
}

3. 상단 고정된 Navigation Bar

fixedTop

1
2
3
4
5
ul {
position: fixed;
top: 0;
width: 100%;
}

4. sticky Navigation Bar

sticky

1
2
3
4
5
ul {
position: -webkit-sticky; /* Safari */
position: sticky;
top: 0;
}

IE는 sticky를 지원하지 않는다. Safari는 -webkit- prefix가 필요하다. 또한 top, right, left, bottom 중 적어도 하나는 지정해줘야한다.

CSS만으로 Dropdown Navigation Bar 구현하기

dropdown

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#news">News</a></li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropbtn">Dropdown</a>
<div class="dropdown-content">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
<a href="#">Link 3</a>
</div>
</li>
</ul>

<h3>Dropdown Menu inside a Navigation Bar</h3>
<p>Hover over the "Dropdown" link to see the dropdown menu.</p>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #38444d;
}

li {
float: left;
}

li a,
.dropbtn {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}

li a:hover,
.dropdown:hover .dropbtn {
background-color: red;
}

li.dropdown {
display: inline-block;
}

.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}

.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}

.dropdown-content a:hover {
background-color: #f1f1f1;
}

.dropdown:hover .dropdown-content {
display: block;
}
  • dropdown-content는 기본 display 속성이 none이다.
  • dropdown 클래스가 있는 li에 hover 했을 때, dropdown-content에 display 속성은 block으로 바꿔주었다.

댓글 공유

loco9939

author.bio


author.job