로그아웃 기능을 구현하던중 문제를 발견했다. 문제가 뭐냐면 나는 Dashboard안에 컴포넌트를 정의했다. 하지만 이 컴포넌트는 Dashboard 밖에서 쓰이는데, Dashboard안에 정의된 handleLogout이라는 컴포넌트의 스코프는 Dashboard컴포넌트 이므로 이 밖에서 쓰려고 하면 undefined에러를 발생 시킬것이다. 그렇다면 이때, 어떻게 해야 할까? 

 

먼저, 아래 코드부터 살펴보자.

 

import React, { useState } from 'react';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { Button } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import '@fortawesome/fontawesome-free/css/all.min.css'; 

const Sidebar = ({ isOpen, toggleSidebar }) => (
    <div style={{
        width: isOpen ? '250px' : '80px',
        transition: 'width 0.3s',
        backgroundColor: '#800000',
        height: '100vh',
        position: 'fixed',
        color: 'white',
        padding: '1rem',
        overflow: 'hidden',
        zIndex: 1000
    }}>
        <div onClick={toggleSidebar} style={{ cursor: 'pointer', marginBottom: '2rem', display: 'block', visibility: 'visible', position: 'relative' }}>
            <i className="fas fa-bars" style={{ fontSize: '1.5rem', color: 'white' }}></i>
        </div>
        {isOpen && (
            <>
                <div style={{ textAlign: 'center' }}>
                    <img src="profile_picture_url" alt="Profile" style={{ borderRadius: '50%', width: '100px', height: '100px' }} />
                    <h3>Jihoo Jeong</h3>
                    <p>Group 6</p>
                </div>
                <div style={{ marginTop: '2rem', textAlign: 'center' }}>
                    <Button variant="light" style={{ width: '100%', marginBottom: '1rem', backgroundColor: '#6a5acd', color: 'white' }}>Dashboard</Button>
                    <Button variant="light" style={{ width: '100%', marginBottom: '1rem', backgroundColor: '#6a5acd', color: 'white' }}>Teams</Button>
                    <Button variant="light" style={{ width: '100%', marginBottom: '1rem', backgroundColor: '#6a5acd', color: 'white' }}>Settings</Button>
                </div>
                <div style={{ marginTop: 'auto', textAlign: 'center' }}>
                    <Button variant="secondary" style={{ backgroundColor: '#6a5acd', width: '100%' }}>Create Teams</Button>
                    <Button onClick = {handleLogout} variant="danger" style={{ marginTop: '1rem', width: '100%' }}>Sign Out</Button>
                </div>
            </>
        )}
    </div>
);

const Card = ({ children, header }) => (
    <div className="card" style={{ borderRadius: '1rem', backgroundColor: '#ffe4e1', border: '1px solid #ccc', margin: '1rem 0' }}>
        <div className="card-header" style={{ backgroundColor: '#f08080', color: 'white', borderRadius: '1rem 1rem 0 0', padding: '1rem' }}>
            <h3 className="mb-0">{header}</h3>
        </div>
        <div className="card-body p-5 text-center">
            {children}
        </div>
    </div>
);

const Container = ({ children }) => (
    <div style={{ display: 'flex' }}>
        {children}
    </div>
);

const MainContent = ({ children, isSidebarOpen }) => (
    <div style={{
        marginLeft: isSidebarOpen ? '250px' : '80px',
        padding: '2rem',
        width: '100%',
        transition: 'margin-left 0.3s'
    }}>
        {children}
    </div>
);


const Dashboard = () => {
    const [isSidebarOpen, setSidebarOpen] = useState(false);
    const navigate = useNavigate();

    const toggleSidebar = () => {
        console.log("Sidebar toggled");
        setSidebarOpen(!isSidebarOpen);
    };

    const handleGiveFeedback = (event) => {
        event.preventDefault();
          navigate('/Givefeedback');
    };

    const handleLogout = () => {
        const casLogoutUrl = 'https://login.vt.edu/profile/cas/logout';
        window.location.href = casLogoutUrl;
    }

    return (
        <div>
            <ToastContainer />
            <Container>
                <Sidebar isOpen={isSidebarOpen} toggleSidebar={toggleSidebar} />
                <MainContent isSidebarOpen={isSidebarOpen}>
                    <h1>Dashboard</h1>
                    <Card header="Student Group 1">
                        <p>Jaison Dasika, Kristian Braun, Jihoo Jeong, Somin Yun</p>
                        <Button onClick={handleGiveFeedback} variant="primary">Give Feedback</Button>
                    </Card>
                    <Card header="Student Group 2" />
                    <Card header="Student Group 3" />
                    <Card header="Student Group 4" />
                </MainContent>
            </Container>
        </div>
    );
};

export default Dashboard;

- 보면 Dashboard안에 handleLogout이 정의되어있다. 이렇게 되면 Dashboard 컴포넌트 밖에서는 단순 호출을 할 수 없다. 이럴때, 내가 사용하고 싶은곳에 프로퍼티로 넘겨줄 수 있다. 

 

- 내 애플리케이션은 'Sign out' 버튼이 Sidebar 컴포넌트 안에 정의되어 있으므로(여기서 사용할것이므로), Sidebar 컴포넌트안에 프로퍼티로 넘겨준다. 넘겨주는 방식은 아래와 같다.

 

const Sidebar = ({ isOpen, toggleSidebar, handleLogout }) => (
    <div style={{
        width: isOpen ? '250px' : '80px',
        transition: 'width 0.3s',
        backgroundColor: '#800000',
        height: '100vh',
        position: 'fixed',
        color: 'white',
        padding: '1rem',
        overflow: 'hidden',
        zIndex: 1000
    }}>

 

{} 여기 안에 프로퍼티로 넘겨줄 함수, 인자들을 넘겨주면 이제 Sidebar안에서도 Dashboard안에 정의되어있는 컴포넌트들을 호출 할 수 있다.

 

그런데, 이렇게 코드를 수정하다가 의문이 들었다. "아니 그렇다면, 그냥 Dashboard가 아니라 Dashboard 밖에 global 함수로 선언하면 더 편할텐데?"

컴포넌트 내부에서 함수 정의

컴포넌트 내부에서 함수를 정의하면 해당 함수는 컴포넌트의 상태(state)와 props에 접근할 수 있다. 이는 함수가 컴포넌트의 동작에 직접적으로 연관된 경우 유용하다.

장점:
- 컴포넌트의 상태와 props에 접근 가능.
- 함수가 해당 컴포넌트의 라이프사이클과 연관될 수 있음.

단점:
- 함수가 컴포넌트 내부에 정의되어 있을 때마다 새로 생성됨. 이로 인해 메모리 사용량이 증가할 수 있음.
- 컴포넌트가 커질수록 복잡성이 증가할 수 있음.

※컴포넌트 외부에서 함수 정의
컴포넌트 외부에서 함수를 정의하면 해당 함수는 독립적으로 동작하며, 특정 컴포넌트에 종속되지 않는다. 이는 함수가 다른 컴포넌트에서도 재사용되거나, 특정 컴포넌트의 상태나 props에 의존하지 않는 경우 유용하다.

장점:
- 재사용성이 높아짐. 여러 컴포넌트에서 동일한 함수를 사용할 수 있음.
- 컴포넌트의 복잡성을 줄일 수 있음.

단점:
- 함수가 컴포넌트의 상태나 props에 접근할 수 없음. 이로 인해 필요한 데이터는 모두 함수 호출 시 전달해야 함.
- 컴포넌트와 함수 간의 결합도가 낮아짐. 이로 인해 특정 상황에서는 불편할 수 있음.

 요약
- 내부 정의: 상태와 props에 직접 접근할 수 있으며, 컴포넌트의 라이프사이클과 밀접하게 연관된 경우 유리하다.
- 외부 정의: 재사용성과 코드의 간결성을 높일 수 있으며, 컴포넌트에 종속되지 않는 함수에 적합하다.

자바스크립트로 웹 개발을 한번이라도 해본 사람이라면 절대 모르고 지나칠 수 없는것이 몇가지 있는데, 그중 하나가 바로 DOM(Document Object Model)이다. JS는 기본적으로 DOM을 사용하여 웹 브라우저의 요소들에 엑세스 하고, 이를 수정 할 수 있다.
 

기본 DOM 계층구조

DOM의 기본적인 계층 구조

 

  • Window : 계층 구조의 최상위층. document를 포함한 환경을 제어 할 수 있다. 브라우저가 페이지를 로드하면 자동으로 윈도우 객체가 만들어지고, 자바스크립트 코드에서 윈도우 개체 속성과 함수에 엑세스 할 수 있음.
  • History : 브라우저의 최근 방문 기록에 대한 세부 내용을 기록함. 히스토리 객체는 브라우저가 앞으로 또는 뒤로 가는 버튼 클릭을 시뮬레이션 할 수 있음.
  • Location : 페이지의 URL에 대한 정보가 들어있음
  • Navigator : 클라이언트 인터넷 브라우저 또는 사용자 에이전트의 개체 표현
  • Screen : 디스플레이 화면의 크기와 같은 사용자 화면에 대한 정보를 도출하는데 사용됨. 모바일 장치에서 실행되는 브라우저의 크기를 결정하는데 중요함
  • Document : 페이지 내의 모든 HTML 요소에 대한 엑세스를 제공함. 브라우저에 로드되는 각각의 HTML요소들은 document 객체가 됨.

 
우리가 자주 사용하는 alert()는 사실 winow.alert()에서 가져온것이지만 더 간단하게 표현하기 위해 접두사를 생략해서 사용한다.
 

그렇다면, DOM을 이용하여 html요소에 접근을 어떻게 할까?

가장 많이 사용되는 함수는 document.getElementById("___"); 이다.
 
아래는 자바스크립트 파일에서 HTML요소를 접근하는 예시이다.
 

<div id = "box">

var divTag = document.getElementById("box")

if(divTag) {
//상황에 맞는 로직 구현
}

 
getElementById를 사용해 괄호 안의 id에 할당된 HTML요소를 가져와 변수 divTag에 할당한 다음, 그 다음에는 그 HTML 요소에 우리가 원하는 로직을 추가 할 수 있다. => 정적인 웹에서 좀 더 반응형 웹으로 변하는 과정이다.
 
이제 그럼 inspect 기능을 활용해 자바 스크립트 코드를 써 보자. 웹 브라우저를 열고, 아무곳이나 커서를 올린다음 우클릭을 하면 inspect라는 탭이 있을것이다. 탭을 누르면 콘솔이 보일것이다. 이 콘솔 창에서 여러가지를 실험해볼것이다.
 
먼저, 모든 프로그래밍의 기본 출력 문장인 Hello world를 출력해보자. 자바에서는 System.out.println()을 통해 출력문을 한줄씩 출력했지만, 자바스크립트에서는 console.log을 통해 출력한다. 해보면,
 

이렇게 나온다. 아래의 undefined는 커맨드(console.log)는 아무 값도 리턴을 하지 않는다는 뜻이다.
 
이번에는 정말 간단한 함수를 하나 작성해보자

function printMyInput(user_input) {
    console.log("The parameter passed is " + user_input)
}

함수는 function 이라는 키워드를 통해 선언하고, 리턴 타입은 지정하지 않아도 되며, 괄호 안에는 파라미터를 받는다.
 
여기서 가장 중요한게 나온다. 화살표 함수!
 
자바스크립트 ES6부터 지원하는 화살표 함수다. 사실 난 화살표 함수를 안 좋아한다. 그냥 function키워드를 사용해 함수를 만드는게 더 가독성도 좋고, 직관적이다. 위의 printMyInput을 화살표 함수로 나타내 보겠다.

let printMyInputES6 = (user_input) => {
    console.log(user_input)
}

 
일단 함수를 let으로 선언해 변수화 하고, 더이상 function이라는 키워드 대신 =>를 쓴다. 나처럼 화살표 함수를 싫어해도 쓰는것이 좋을것이다,,, 왜냐면 이미 javascript 코드를 쓰는 사람들은 화살표 함수가 익숙해져있으므로 그냥 얼른 익숙해지는게 답이다 :(
 
마지막으로, 이벤트 핸들러를 짧게 짚고 넘어가보자. 우리가 웹사이트의 버튼들을 눌렀을때, 어떠한 동작을 하게 하고 싶다면, 자바스크립트의 eventHandler를 사용해야 한다. 예시를 보면 바로 이해가 될 것이다!
 

<button type="button" onclick="showAnswers()"> Show Solution
 <script>
  function showAnswers() {
   //code
   alert("A")
  }
 </script>
</button>

 
위의 코드는 'Show Solution'이라는 button을 만들고, onclick이라는 EventHandler를 통해 버튼이 클릭 되었을때 showAnswers()라는 함수를 실행하도록 한다. 간단하다! 이벤트 핸들러는 이런것이다. 정적인 웹에서 조금 더 동적인 웹으로 바뀌어 가는 중이다.

오늘은 자바스크립트에서 '함수'에 대해 짚고 넘어가겠다.

우선, 프로그래밍을 공부해본 사람이라면 함수에 대해 너무나 잘 알고 있을것이다. 그렇지만 한번만 더 짚고 넘어가보자!

 

함수(메서드)

function add(n, m) {
	return n + m;
}

var x = add(1,2); //3을 반환
x = add(1.23, 3.45) // 4.68을 반환
x = add("hello", "world") //"helloworld"를 반환

 

일단, 자바와 달리 자바스크립트의 함수는 function 키워드로 정의한다. 리턴 타입, 파라미터의 타입등은 명시해주지 않아도 되며, 각각의 타입들은 컴파일시 알아서 타입이 인지된다!(자바랑 관련이 없는데 왜 자바스크립트인지는 아직까지 모르겠다) 

 

위를 보면 세가지의 예시들이 있다. 신기하게도 리턴 타입이 명시되지 않은 함수(메서드)에서 각각은 다른 리턴 타입을 가진다.

 

오브젝트

function Car(make, model, year) {
	this.make = make;
    this.model = model;
    this.year = year;
    this.getName = function() {
    	return this.make + ' ' + this.model + ' ' + this.year;
    }
}

var c = new Car("Hyundai", "Sonata", 2021);
alert(c.getName()); // "Hyundai Sonata 2021"

자바스크립트에서의 오브젝트 생성은 자바와 비슷하다. new 연산자를 통해 새 오브젝트를 만들고, 함수의 인자를 원하는 값으로 넘겨주면 된다. this를 한번 더 설명하고 넘어가겠다. 나 조차도 이 this때문에 자료구조 수업에서 애를 먹었던 기억이 난다,,, 간단 명료하게 말해 여기서의 this는 "자기자신" 이다. 즉, 언제든 우리가 Car에 대한 인스턴스를 만들고, 파라미터들을 넘겨주면, 그 파라미터는 "자기자신" 즉, 그 오브젝트의 것이 된다. 위를 예로 들어 var c는 new 연산자를 통해 오브젝트가 생성되었고, 인자로 "hyndai", "sonata", 2021을 넘겨주었다. 그러면 맨 처음 함수 선언 당시 썼던 this는 "c"를 가리킨다. 아래와 같이 말이다.

c.make
c.model
c.year

 

또한, 위에서의 getName 이라는 함수는 Car이라는 함수 안에 선언된 또다른 함수이다(중첩함수). 함수 내부에서 또 다른 함수를 선언할때, 내부 함수는 외부 함수의 변수에 접근 할 수 있다. 이는 클로저(Closure)라 불리는 개념으로, 함수가 정의된 스코프를 기억하여 나중에 쓸 수 있도록 하는 개념이다.

프로토타입


"자바스크립트는 여타 프로그래밍 언어들과 다르게 '클래스' 라는 개념이 없는 프로그래밍 언어이다. 대신, 프로토타입은 객체 간에 상속을 담당하는데, 이를 '프로토타입 체인'이라고 한다. 자바에서 상속을 배운 사람이라면 프로토타입 체인이 비슷한 개념임을 이해할 수 있을 것이다. 예를 들어, VSCode에서 .js 확장자를 가진 자바스크립트 파일을 만들고, 위의 예시에서 보여준 Car를 입력하고 '.'을 누른다면 자동완성으로 'prototype'이라는 속성을 볼 수 있다. 이것은 자바스크립트가 모든 객체에 자동으로 `Object.prototype`이라는 내장 객체의 프로토타입을 상속해주기 때문이다. 말로는 설명이 너무 복잡하므로 예시를 보면서 이해해보자.

 

function Car(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
    this.getName = function() {
        return this.make + ' ' + this.model + ' ' + this.year;
    };
}

Car.prototype.country = "Korea"

var c = new Car("Hyundai", "Sonata", 2021);

console.log(c.getName() + c.country);

 

여기서 Car 함수는 위의 예시와 동일하다. 그렇지만 아래 다른점이 있다. Car.prototype.country = 'Korea'를 추가해주었다. "prototype"을 일종의 "유전자" 라고 이해하면 이해하기가 쉽다. 위의 함수에서 Car함수는 '부모' 이고, var c = new Car()에서의 c는 '자식' 이다. 그 말은 즉, Car.prototype.country = 'Korea'는 부모함수에 'country'라는 유전자를 추가해주고, 그 유전자의 속성은 'Korea'로 설정해줘. 라는 말이랑 같다. 이제 위의 코드에서 c.country를 하면 console.log문에 Korea가 출력되고, 최종 출력은 아래와 같다.

프로토타입을 추가한 후 출력문

그런데 여기서 이러한 의문이 들었다. 근데 나는 c라는 오브젝트에 Korea라는 속성을 할당한적이 없고, 부모함수 내에서도 Korea라는 속성을 할당한적이 없는데 어떻게 컴퓨터는 이 사실을 알고 Korea라는 속성을 할당했을까?

컴퓨터는 내부적으로 이러한 일련의 과정을 거쳐 속성을 찾아낸다.

[인스턴스에 country라는 속성이 있는지 확인하고 있으면 반환한다(위의 Car의 경우엔 c인스턴스엔 country라는 속성이 정의되어있지 않으므로 c 인스턴스의 부모(== Car 함수)로 올라가서 찾는다 -> 우리는 Car.prototype.country = "Korea"라고 지정해주었으므로 지정한 속성을 찾을때까지 부모를 타고 계속 올라간다) -이걸 프로토타입 체이닝 이라고 부른다!

 

그러면 도대체 왜 '프로토타입'을 사용할까? 그냥 부모함수에 this.country = "Korea" 라고 해주면 되는것 아닌가?

프로토타입을 사용하는 이유는 객체 간의 코드를 공유하고 메모리를 효율적으로 사용하기 위함이다. 특히, 여러 객체가 같은 메서드나 속성을 공유할 경우, 프로토타입을 사용하면 중복된 코드를 피하고 코드의 재사용성을 높일 수 있다.

프로토타입을 사용하지 않고 메서드를 직접 생성자 함수 내에 정의하면, 각 객체가 생성될 때마다 해당 메서드가 새로 생성되기 때문에 메모리 사용이 비효율적일 수 있다. 반면 프로토타입을 사용하면 모든 객체가 동일한 프로토타입을 공유하므로 해당 메서드는 한 번만 생성되고 모든 객체가 이를 공유한다.

아래는 두 가지 방식으로 메서드를 추가한 경우를 비교한 예제이다:

1. **프로토타입 사용:**
    

    function Car(make, model, year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    Car.prototype.getName = function() {
        return this.make + ' ' + this.model + ' ' + this.year;
    };


    

2. **객체 내에서 메서드 직접 정의:**
 

    function Car(make, model, year) {
        this.make = make;
        this.model = model;
        this.year = year;

        this.getName = function() {
            return this.make + ' ' + this.model + ' ' + this.year;
        };
    }


  

위의 두 방식을 사용하여 객체를 생성하면, 프로토타입을 사용한 경우에는 모든 객체가 같은 `getName` 메서드를 참조한다. 그러나 객체 내에서 메서드를 직접 정의한 경우에는 각 객체가 독립적으로 `getName` 메서드를 가지며, 이는 메모리의 낭비로 이어질 수 있다.

자바스크립트에서의 변수 선언은 어떻게 할까?

 

사실 처음에 자바 스크립트를 배우기 전 이름만 보고 "자바와 연관이 있지 않을까?" 자바에서 변수를 선언할때 변수형(정수, 실수, 문자열, 문자, 배열 등등)을 지정해주고 변수명을 지정해주고,,, 인줄 알았다!

 

그런데 자바스크립트는 자바와 아무런 연관이 없다. 진짜 어이가 없다. 그러면 이름은 왜 자바스크립트 인거지?

 

어쨌든! 이번에는 그러면 자바 스크립트에서는 변수를 어떻게 선언하는지 알아보자.

 

1. var

-자바스크립트에서 변수를 선언할때 변수명 앞에 var이라고 붙여주는것은 "variable"의 줄임말이고, 내가 말했듯 "변수" 라는 말은 가변적인 성질을 갖고 있다. 즉, 타입을 특정해주기 보단 var이라는 좀 더 포괄적인 타입을 선언해 조금 더 유동적으로 변수의 타입이 바뀔 수 있도록 지정해주는것이다. 

 

예를 들어보자.

 

var age;
age = 54;



var age = "Fifty four"

 

자바에 익숙한 사람이라면 이해하기 힘들것이다. "분명 자바에서는 변수 타입을 선언해줘야 했는데 여기서는 'var'이라고 단순히 가변적인 변수임을 알려주고 그냥 변수에 정수와 문자열을 지정해주었다." 그렇지만 자바스크립트에서의 var은 "문자열 또는 숫자" 둘중에 하나로만 컴파일이 되며, 지정해준 데이터에 따라 자동으로 컴파일 당시에 변수 타입이 지정된다. 

 

위의 예를들어 첫번째 age는 컴파일시 '정수'라는 데이터 타입이 자동으로 부여되고, 두번째 age는 컴파일 당시 '문자열' 이라는 데이터 타입이 자동으로 부여된다.

 

+ var을 통해 선언된 변수는 변수를 선언할때 초기화 해주지 않아도 된다. 첫번째 age변수처럼 변수를 선언만 해주고, 초기화는 나중에 해줘도 아무 문제가 없다!

2. const

위에서 말한 var은 '가변적인' 즉, 언제든 변할 수 있는 변수였다. 하지만 'const'로 선언된 변수 타입은 변할 수 없고, var과 다르게 선언과 동시애 초기화가 되어야 한다. 우리가 잘 알고 있는 자바에서의 'final'이다.

const PI = 3.14

또한, const로 선언된 변수는 재할당이 불가능하다. 

const PI = 3.14
PI = 100 //오류 발생. const는 값을 변경 할 수 없음

 

3. let

let은 블록 스코프를 갖는 변수를 의미한다. let은 var과 같이 재할당이 가능하며, 블록 스코프 내에서만 유효한 변수이다.

if (true) {
  let y = 20;
  console.log(y); // 20
}
console.log(y); // ReferenceError: y is not defined

 

위의 예시처럼 아래 console.log(y)는 에러를 발생시킨다. 왜냐하면 변수 y는 if문 안의 {} 안에서만 사용될 수 있도록 'let'으로 선언했기 때문이다.

 

+var타입은 "함수 스코프"를 갖고있어 같은 함수 내에서만 유효하다!

 


이렇게 세 가지 키워드를 사용하여 변수를 선언할 수 있습니다. 종종 `let`과 `const`를 더 선호하는 추세가 있으며, `var`는 호이스팅과 스코프 등에서 발생하는 문제로 인해 사용을 권장하지 않는 경우가 많다.

부트스트랩(Bootstrap)은 Twitter에서 만든 오픈 소스 프론트엔드 프레임워크로, 웹 개발을 쉽게 하기 위한 도구이다. 부트스트랩은 HTML, CSS, JavaScript를 기반으로 하며, 반응형 웹 디자인을 쉽게 구현할 수 있도록 도와준다.

부트스트랩은 사전에 정의된 스타일, 레이아웃, 컴포넌트 등을 포함하고 있어, 개발자들은 이를 사용하여 일관된 디자인과 레이아웃을 쉽게 구축할 수 있다. 또한, 부트스트랩은 모바일 기기에서도 잘 동작하는 반응형 웹을 만들 수 있도록 지원하며, 브라우저 호환성도 고려되어 있다.

이렇게 말해서는 이해하기 어려울것이므로 예제를 한번 보자.

다음은 조건이다.

웹 사이트에 링크를 하나 걸어두고, 그 링크를 접속하면 위험하다고 표시하도록 링크에 밑줄을 걸어두고,  그 링크에 마우스를 올리면 빨간색으로 나타나야 한다.

 

먼저, vanila CSS로 위의 상황을 구현한다고 해보자.

 

a {
	color : red;
    text-decoration : underline;
   }
a:hover {
  color : rgb(185, 28, 28);
  }

 

이렇게 하면 우리가 위에서 말했던 조건대로 화면에 잘 보여질것이다. 그런데, 뭔가 가독성도 떨어지고 코드의 길이가 길어져 보이므로(지금은 간단한 조건이지만 훨씬 더 복잡한 일을 하려면 코드는 더 복잡해지고 길어진다.)

 

그렇다면 bootstrap을 사용한다면 어떨까?

<a href="..." class="link-danger">Dangerous Link</a>

 

훨씬 더 간단하게 표현 할 수 있다. 저 안에는 Dangerous Link라는 텍스트가 밑줄이 그어지고, 마우스를 올리면 빨갛게 변하도록 기능이 다 내장되어있다.

 

이러한것처럼 bootstrap은 프론트엔드 웹 개발에 있어서는 없어서는 안될 존재이며, 코드 작성을 훨씬 쉽고 간결하게 해준다. 부트 스트랩은 사실 너무 기능이 많아 블로그 포스팅만으로는 알고 넘어가기에 너무 부족하므로, 궁금하다면 bootstrap홈페이지를 들어가보는것도 추천한다!

지난 시간에는 HTML의 기본 태그에 대해 배웠고, 이번에는 다른 태그들에 대해 알아보겠다.

**`<div>` 태그:**
`<div>` 태그는 페이지의 구획을 정의하고 콘텐츠를 그룹화하는 데 사용된다. 어떠한 형태의 콘텐츠도 배치할 수 있으며, 의미적으로 연관이 없어도 된다. 주로 많은 요소가 동일한 형식을 가져야 할 때 사용된다. 브라우저는 `<div>` 태그 앞뒤에 줄 바꿈을 삽입한다.

```html
<div>
  <h1>This is a heading in a div element</h1>
  <p>This is some text in a div element.</p>
</div>
```

**`<section>` 및 `<article>` 태그:**
`<section>` 태그는 콘텐츠를 의미적으로 그룹화 하는 데 사용되며, 주로 그룹화된 콘텐츠에 헤딩 태그가 사용된다. `<article>` 태그는 더 구체적으로, 독립적이고 의미 있는 콘텐츠를 그룹화하는 데 사용된다.

```html
<section>
    <h1>Section 1</h1>
    <p>This is text related to section 1.</p>
</section>
<article>
    <h1>Article 1</h1>
    <p>This paragraph is related only to article one and is meaningful on its own.</p>
</article>
```

**`<nav>` 태그:**
`<nav>` 태그는 내비게이션 요소들을 그룹화하는 데 사용된다. 웹페이지 상단에 있는 내비게이션 바와 같이 페이지 간 이동에 사용되는 요소들을 `<nav>` 안에 그룹화할 수 있다.

```html
<nav>
    <ul>
        <li><a href="#home">Home</a></li>
        <li><a href="#about">About</a></li>
        <li><a href="#services">Services</a></li>
        <li><a href="#contact">Contact</a></li>
    </ul>
</nav>
```

**`<audio>` 및 `<canvas>` 요소:**
`<audio>` 요소는 음악이나 팟캐스트 등 소리 콘텐츠를 임베드하는 데 사용된다. `<canvas>` 요소는 스크립트를 사용하여 그래픽을 그리는 데에 활용된다.

```html
<audio>
  <source src="soundtrack.mp3" type="audio/mpeg">
  <source src="soundtrack.ogg" type="audio/ogg">
  Your browser does not support the audio formats provided.
</audio>

<canvas>
    Your browser does not support the canvas tag.
</canvas>
<script>
    var canvas = document.getElementsByTagName("canvas")[0];
    var context = canvas.getContext("2d");
    context.fillRect(0, 0, 100, 100);
</script>
```

**`<embed>` 및 `<track>` 요소:**
`<embed>` 요소는 외부 리소스를 웹 페이지에 임베드하는 데 사용된다. `<track>` 요소는 `<audio>` 및 `<video>` 요소에 대한 텍스트 트랙(자막 등)을 정의하는 데 사용된다.

```html
<embed type="text/html" src="another_webpage.html">

<video>
  <source src="common_html_elements.mp4" type="video/mp4">
  <track src="english_subtitles.vtt" kind="subtitles" srclang="en" label="English">
  <track src="spanish_subtitles.vtt" kind="subtitles" srclang="es" label="Spanish">
</video>
```
**'<fieldset>' 및 '<legend>' 요소:**

<!DOCTYPE html>
<html>
    <body>
        <h1>The fieldset element</h1>
        <form>
            <fieldset name="personal_details"> 
                <legend>Personal Details</legend>
                <label for="fname">First name:</label>
                <input type="text" id="fname" name="fname"><br>
                <label for="lname">Last name:</label>
                <input type="text" id="lname" name="lname"><br>
                <label for="email">Email:</label>
                <input type="email" id="email" name="email"><br>
                <label for="phone">Phone Number:</label>
                <input type="tel" id="phone" name="phone"><br>
            </fieldset>
            <br>
            <fieldset name="professional_details"> 
                <legend>Professional Details</legend>
                <label for="occupation">Occupation:</label>
                <input type="text" id="occupation" name="occupation"><br>
                <label for="company">Company:</label>
                <input type="text" id="company" name="company"><br>
                <label for="start">Start Date:</label>
                <input type="date" id="start" name="start"><br>
                <label for="end">End Date:</label>
                <input type="date" id="end" name="end"><br>
            </fieldset>
            <br>
            <input type="submit" value="Submit">
        </form>
    </body>
</html>

 

1. **`<fieldset>` 태그:**
   - `<fieldset>` 태그는 여러 입력 요소를 그룹화할 때 사용된다. 일반적으로 이 태그는 폼 안에 있는 여러 입력 필드를 하나의 논리적 그룹으로 묶을 때 사용된다.
   - 이 그룹은 보통 선(border)으로 둘러싸여 있어 시각적으로 구분된다.
   - `<fieldset>`은 주로 비슷한 주제 또는 목적을 가진 입력 요소들을 그룹화하여 사용자에게 폼의 구조를 명확하게 전달하는 데에 활용된다.


2. **`<legend>` 태그:**
   - `<legend>` 태그는 `<fieldset>`의 제목을 정의한다. 즉, `<fieldset>`로 그룹화된 입력 필드들의 목적이나 주제를 설명하는 텍스트를 제공한다.
   - `<legend>`는 `<fieldset>`의 첫 번째 자식으로 와야 하며, `<fieldset>`의 시작 태그 바로 다음에 위치해야 한다.


 

아래는 위 코드를 웹페이지에서 봤을때의 모습이다

 

 

근데 UI들은 너무 못생겼다... 조금 더 이쁘게 할 수 있는 방법은 없을까? 이럴때 필요한게 CSS이다. 다음에는 CSS에 대해 따로 설명하겠다!

HTML에서는 크게 두가지 태그로 범위가 나뉜다. <head>와 <body>. 그렇다면 각각의 태그는 무엇들을 담고 있을까?

<!DOCTYPE html>
<html>
    <head>
        <!-- Metadata goes here -->
    </head>
    <body>
        <!-- Content goes here -->
    </body>
</html>
  • <head> : 해드 테그는 페이지에 있는 모든 메타 데이터들을 포함한다.
  • <body> : 최종 유저에게 보여지는 콘텐츠들을 포함한다.(즉, 화면에 보여지는 요소들을 담고있다.)

그렇다면, 여기서 말하는 페이지에 있는 "메타 데이터" 란 무엇일까?

 

메타데이터는 데이터에 관한 정보를 나타내는 데이터를 말한다. 즉, 데이터의 특성, 구조, 내용 등을 설명하는 데이터이다. 메타데이터는 주로 다른 데이터를 설명하거나 분류하는 데 사용된다. 예를 들면:

1. **도서관 카탈로그의 메타데이터:** 책의 제목, 저자, 출판사, 출판일 등의 정보로 구성되어 있다. 이 메타데이터는 실제 책 자체가 아니라 책에 대한 정보이다.
2. **음악 파일의 메타데이터:** 노래 제목, 가수, 앨범, 장르 등의 정보가 음악 파일에 저장되어 있다. 이 메타데이터는 음악 파일 자체가 아니라 음악에 대한 정보이다.
3. **사진 파일의 메타데이터:** 사진의 촬영 일시, 카메라 모델, 해상도 등의 정보가 포함된다. 이 메타데이터는 사진 파일이 아니라 사진에 대한 정보이다.
4. **웹 페이지의 메타데이터:** HTML 문서에서 사용되는 메타 태그는 웹 페이지의 제목, 설명, 작성자 등을 정의한다. 이 정보는 브라우저나 검색 엔진이 웹 페이지를 이해하고 적절히 표시하도록 도와준다.


간단한 예를 들어보자. 위의 설명에서 웹 페이지의 제목, 설명이라고 표현 하였는데, 웹 페이지의 제목(메타 데이터)를 코드로 한번 보자.

<head>
    <title>Jay's Developer Note</title>
</head>

 

위에서 언급한 <head>태그로 감싸진 부분 안에 <title>이라는 태그로 감싸고 그 사이에 타이틀을 넣는다. 그러면 저 타이틀은 내가 만들 웹사이트의 타이틀이 될것이다. 저 타이틀은 헤드태그로 감싸고 타이틀이란 태그 안에 감쌌기 때문에, 단순한 텍스트 타입 타이틀이 아니라 다른 웹사이트들과 구분될 수 있는 타이틀이다.

 

<body>태그 안의 여러가지 다른 태그 알아보기

 

  • Page headings
    • 페이지 헤딩이란 <h1>,<h2>...<h6>까지 있는 페이지 헤딩을 나타낼 수 있는 태그이다. 1부터 6까지 글자의 크기가 달라지기때문에 더 중요한 부분은 h1으로 감싸면 웹 페이지에서 더 돋보일 수 있다.
  • Adding Text
    • 그러면 헤딩과는 별개로 일반 문자들을 추가하고싶다면 어떻게 할까? 그때는 'paragraph'의 약자인 <p></p> 태그로 감싸준다.
  • External Link
    • 만약에 웹에 다른 페이지로 이동 할 수 있는 링크를 걸고싶다고 해보자. 이러한 경우에는 링크를 감싸는 태그가 따로 있다. 아래처럼 a태그로 시작한 다음 href= "안에 링크를 걸어두고> 그 다음에 링크가 표시 될 문자를 적어준다.
 <a href="https://www.ibm.com">IBM</a>

위의 텍스트는 웹 페이지에서 이렇게 보일 것이다. IBM. 이제 웹 페이지에서 저 IBM이라는 글자를 누르면 href안의 url로 이동한다.

 

그런데 여기서 한가지 기능이 더 있다. 아래 코드를 살펴보자.

 

 <a href="https://www.ibm.com" target="_blank">IBM</a>

첫번째 링크 코드와는 달리 target이라는 인자가 추가되었다. 위의 코드는 링크를 새로운 창에서 열어준다는 뜻이다. 즉, 첫번째 코드는 링크를 누르면 현재 페이지에서 바로 링크가 눌린다는 얘기이고, 두번째 코드는 새 창에다가 링크를 열어준다는 뜻이다.

 

  • 리스트

웹에서의 리스트란 무엇일까? 리스트는 말 그대로 여러가지 "목록" 들이다. 예를 들어, 쇼핑몰 페이지를 구축중이라고 해보자. "바지" 탭을 누르면 여러 종류의 바지들이 페이지에 나타날것이다. 그런데 바지들을 하나하나의 개별 요소들로 나타내기 보다는 리스트를 사용하는게 훨씬 더 직관적이고 깔끔할것이다. 아래 코드를 살펴보자.

<!-- Unordered List -->
<ul>
    <li>This is a bullet point </li>
    <li>The items in this list have no particular order </li>
    <li>Each item will appear as a bullet, rather than a number </li>
</ul>
<!-- Ordered List -->
<ol>
    <li>This is an ordered list </li>
    <li>The items in this list have a particular order </li>
    <li>Each item will be numbered, starting from 1 </li>
    <li>This is the fourth point in the list </li>
</ol>

 

`<ol>`과 `<li>`는 HTML에서 리스트를 생성하기 위한 태그이다.

1. `<ol>` (Ordered List):

   - `<ol>`은 "Ordered List"의 약어로, 순서가 있는 목록을 정의한다.
   - 기본적으로 숫자로 번호가 매겨지며, 각 아이템은 `<li>` 태그로 둘러싸여 있습니다.
   - 예를 들어, 순서가 있는 목록을 생성하고자 할 때 사용됩니다.

   <ol>
     <li>첫 번째 항목</li>
     <li>두 번째 항목</li>
     <li>세 번째 항목</li>
   </ol>
  
   결과:
   1. 첫 번째 항목
   2. 두 번째 항목
   3. 세 번째 항목

2. `<ul>` (Unordered List):

   - `<ul>`은 "Unordered List"의 약어로, 순서가 없는 목록을 정의한다.
   - 각 아이템은 역시 `<li>` 태그로 둘러싸여 있다.
   - 기본적으로 원형 또는 사각형의 마커가 사용되며, 목록의 순서에는 중요성이 없다.

   ```html
   <ul>
     <li>항목 1</li>
     <li>항목 2</li>
     <li>항목 3</li>
   </ul>
   ```

   결과:
   - 항목 1
   - 항목 2
   - 항목 3

따라서, `<ol>`은 순서가 있는 목록을 나타내고, `<ul>`은 순서가 없는 목록을 나타낸다. 어떤 목록인지에 따라 사용하면 된다.

 

테이블(표) 나타내기

 

우리가 흔히 볼 수 있는 웹 페이지에서의 테이블은 어떻게 나타낼까?

아래의 코드부터 살펴보자.

 

<table>
    <tr>
        <th>Heading 1</th>
        <th>Heading 2</th>
        <th>Heading 3</th>
    </tr>
    <tr>
        <td>H1 - Data Item 1</td>
        <td>H2 - Data Item 1</td>
        <td>H3 - Data Item 1</td>
    </tr>
    <tr>
        <td>H1 - Data Item 2</td>
        <td>H2 - Data Item 2</td>
        <td>H3 - Data Item 2</td>
    </tr>
    <tr>
        <td>H1 - Data Item 3</td>
        <td>H2 - Data Item 3</td>
        <td>H3 - Data Item 3</td>
    </tr>
</table>

 

상당히 직관적이다. 그냥 <table>태그로 감싸고, 그 안에 테이블 요소를 넣어주면 된다. 여기서의 <tr>은 table row이고, <td>는 table data, 그리고 <th>는 table heading 이다.

 

위의 코드로 만들어진 웹에서의 테이블 모습은 이렇게 생겼다.

 

 

웹에서의 테이블 모습

 

웹사이트에서 이미지 표시하기

우리가 흔히 보는 웹사이트에서의 이미지는 html로 어떻게 표현될까?

 

<!-- External Image -->
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/IBM_logo.svg/440px-IBM_logo.svg.png" alt="IBM Logo" width="300" height="300">
<!-- Local Images -->
<img src="images/IBMlogo.png" alt="IBM Logo" width="300" height="300">

이 코드는 HTML에서 이미지를 삽입하는 두 가지 방법을 보여준다. 주석(`<!-- -->`)은 코드에 설명을 추가하는 데 사용되며, 코드 실행 시에는 무시된다.

1. **External Image (외부 이미지):**
   
   <!-- External Image -->
   <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/IBM_logo.svg/440px-IBM_logo.svg.png" alt="IBM Logo" width="300" height="300">

   - `src`: 이미지 파일의 URL을 지정한다. 이 경우, 웹상에 있는 IBM 로고의 이미지 URL이다.
   - `alt`: 이미지에 대한 대체 텍스트를 지정한다. 이미지를 로드할 수 없을 때 대체 텍스트가 표시된다.
   - `width` 및 `height`: 이미지의 가로와 세로 크기를 픽셀 단위로 지정한다.

2. **Local Images (로컬 이미지):**
   <!-- Local Images -->
   <img src="images/IBMlogo.png" alt="IBM Logo" width="300" height="300">

   - `src`: 로컬에 저장된 이미지 파일의 상대 경로를 지정한다. 이 경우, "images" 폴더 내에 있는 "IBMlogo.png" 이미지를 사용한다.
   - `alt`: 이미지에 대한 대체 텍스트를 지정한다.
   - `width` 및 `height`: 이미지의 가로와 세로 크기를 픽셀 단위로 지정한다.

이렇게 이미지를 삽입하는 것은 웹 페이지에서 시각적인 콘텐츠를 표현하는 데 사용되며, 이미지는 `<img>` 태그를 사용하여 삽입된다.

우리는 항상 웹사이트를 사용한다. 컴퓨터를 켜서 크롬을 열고, 메일을 확인하고, 쇼핑을 하는 등 웹은 우리에게 없어서는 안될 존재이다. 그런데 인터넷을 쓰다 보면 한번쯤 이런 생각이 들것이다. "웹사이트는 어떻게 동작하는가?"

웹사이트의 동작 방식을 간단히 표현한 글

그림에서 보이듯이 생각보다 간단하다!

 

위의 그림에서 IBM의 도메인 주소가 주소창에 입력되어있다. 그러면 웹은 IBM서버에 요청을 보낸다.("지금 우리 서버에 어떤 유저가 홈페이지를 보내달래")

- 아 그래? 알았어! 내가 유저에게 응답을 해줄게!(그러면 서버에서 홈페이지를 유저에게 보내준다)

 

이렇게 단순화한다면, 요청, 응답으로 유저와 서버간의 상호작용이 이루어진다.

 

그렇다면, 웹 페이지는 어떠한 방식으로 만들어질까?

 

보통의 웹 개발자들이라면 위의 세가지 프로그래밍 언어를 선호한다.

  • HTML : 웹 페이지의 물리적 구조를 구축하기 위해 사용되는 언어. 여기서 말하는 물리적 구조란 대개 '텍스트', '링크', '이미지/ 영상',버튼 등을 일컫는다.
  • CSS : 웹 사이트 및 각 구성 요소에 대해 다양한 스타일 특성 세트를 정의, 적용 및 관리 할 수 있는 표준 방법을 제공한다. 즉 웹사이트의 모양과 느낌, 스타일, 색상, 글꼴, 디자인 및 레이아웃을 담당한다.
  • Javascript : 객체지향형 언어이며, 웹 사이트에 상호작용(동적인 상호작용)을 구현하기 위해 사용되는 프로그래밍 언어이다.

우리가 자주 사용하는 로그인 버튼으로 간단한 예를 들어보자. 물리적인 로그인 '버튼'은 HTML이 담당하고, 로그인 버튼의 모양이나 글꼴, 색상은 CSS가 담당하며 로그인 기능(유저가 입력한 아이디, 패스워드 일치 여부를 서버로 보내 일치하는지 확인하고 로그인을 성공적으로 하는 일)은 자바스크립트가 담당한다.

 

가장 널리 사용되는 웹 개발 자바스크립트 API들은 

  • Angular : 구글에서 관리하는 오픈소스 프레임워크. HTML 페이지를 빠르고 효율적이게 렌더링 할 수 있다.(라우팅 기능이 내장되어있다)
  • React : 페이스북에서 운영 관리하는 프레임워크로 배우기가 쉽지만 라우팅 기능이 내장되어 있지 않아 따로 구현해야한다.
  • Vue.js : 커뮤니티에서 관리, 운용하며 레이아웃에 초점을 둔 프레임워크이다.

가장 널리 사용되는 백엔드 언어는 : 

  • 자바스크립트 :  웹 브라우저에서 실행되도록 설계되어 웹 페이지에 대화형 기능과 동적 콘텐츠를 추가한다.
    • 자바스크립트에서 가장 잘 알려진 백엔드 프레임워크는 Node.js , Express 이다.
  • 파이썬 : 웹 페이지부터 데이터베이스 연결, 데이터 분석 수행에 이르기까지 광범위한 기능을 수행한다.
    • 잘 알려진 파이썬 프레임워크는 Django, Flask 이다.
    • 데이터를 다루기 위해 많이 사용되는것은 sql이다.

 

 

+ Recent posts