개발자 되는 중/TIL&WIL

내배캠 TIL 2022.11.16(알고리즘 3주차, DB 특강, SPA 특강)

SeonChoco 2022. 11. 16. 20:58

DB 특강

1. 데이터 베이스가 무엇인지

데이터 모음이다

데이터 베이스 관리 시스템 DataBase Management System DBMS

제어하는 프로그램

2. 관계형 데이터 베이스란?

열과 행으로 이루어져있다.

엑셀처럼 표처럼 생겼다.

장점: 직관적, 테이블 관계 파악이 쉽다

단점: 성능향상이 비싸다. 데이터베이스 설계를 잘못하게되면 ㅈ 된다. 

처음부터 설계를 잘해야된다. 

 

 scale up

 

 

scale out

SQL == 관계형 데이터 베이스 == RDBMS

프로그래머스에서 연습할 수 있다.

 

데이터이 다양하다. 

정확성도 좀 떨어져도 된다.

아마존에서 쓰는 데이터 베이스도  NoSQL

 

NoSQL 데이터 베이스 유형

 

키 벨류 유형

 

document 데이터 베이스

 

JS로 하는 SPA

Javascript 로 하는 Single Page Application

 

특강 듣는 이유는?

우리는 react라는 프레임워크 배울텐데 그게 SPA 방식을 이용한다.

내일 파이어베이스 강의에서 소개할 코드도 SPA 방식 이용한다.

 

MPA vs. SPA 개념 이해

MPA - multi page application 서버 사이드 렌더링

매번 새창을 서버에서 가져다준다

ex) 우리가 이전 미니 프로젝트에서 썼던 방식, 비수기 소개 페이지

HTML 통째로 서버와 클라이언트랑 주고 받는다. 

네트워크 창을 확인해보면 다른 창 넘어갈 때 서버에서 모든 내용을 다 그려서 새로 받아온다.

다른 창으로 갈 때 깜빡인다.

 

SPA - single page application 클라이언트 사이드 렌더링

처음에는  MPA 처럼 HTML을 받아온다.

하지만 그 후에서 클릭을 해서 넘어갈 때 통째로 받아오는것이 아니라

클라이언트에서 ajax라는 방식으로 부분적으로 요청을 보내면

서버는 JSON라는 가벼운 형태의 데이터로 받아와서

클라이언트 쪽에서 javascript로 재구성해서 사용한다. (그렇기 때문에 클라이언트 사이드 렌더링이라고 부른다)

네트워크 창을 확인해보면 지워지고 새로운 파일을 받아오는게 아니라 파일이 stack으로 하나하나 쌓인다. 

다른 창으로 갈 때  깜빡임이 없다. 페이지 이동이 부드럽다

 

#Ajax는 JavaScript의 라이브러리중 하나이며 Asynchronous Javascript And Xml(비동기식 자바스크립트와 xml)의 약자입니다. 브라우저가 가지고있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법 이며 Ajax를 한마디로 정의하자면 JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 XML 데이터를 주고받는 기술이라고 할 수 있겠습니다.

 

SPA 코드 -index.html

실제 코드를 살펴보면 index 파일에 뭐가 안 들어가있다.

main page라는 id를 가진 div 안에 main-nav에 들어있는 페이지를 넣어준다

이렇게 불러와주는 routing 하는 코드는 router.js에 들어가있다.

router 기능을 이용해서 페이지를 넣었다 뺐다 하는 것이다. 

<body>
    <div id="root">
        <nav id="main-nav" class="sidebar">
            <a href="/" onclick="route(event)">Home</a>
            <a href="#about" onclick="route(event)">About</a>
            <a href="#lorem" onclick="route(event)">Lorem</a>
        </nav>
        <div id="main-page"></div>
    </div>

    <script src="js/router.js"></script>
</body>

 

 

 

Hashed url path vs. Non-hashed url path

주소창에 # 있는지 vs # 없는지

https://www.naver.com/#asfasdfas

이렇게 쳤을 때 # 이후는 서버로 안 보내어진다. 

그래서 이 위의 주소를 넣어도 네이버가 그대로 나온다.

왜 똑같은 창이 나오냐면 #뒤의 내용은 로컬에서만 이용하는 것이기 때문이다. 

콘솔창에 window.location을 치면 현재 위치 정보가 나오는데 해쉬 자리도 확인 할 수 있다.

 

근데 왜 이거 쓰는데? - Hash Routing하는 이유가 뭔데?

새고고침했을 때 주소에 맞는 파일을 서버에 요청하게 되는데, (브라우저가 get 요청하도로 default로 설정되어있다)

SPA를 이용하기 때문에 서버에는 우리가 원하는 파일이 없는 상태 => 오류가 난다. 

# 쓰면은 이런 에러를 방지 할 수 있다.

 

hashed routing vs ordinary routing 비교해보면서 이유를 다시 확인

ordinary routing일 경우

처음 창을 켜서 이것 저것 눌러보면 실행된다.

네트워크에 304 상태가 뜨는데

304는 캐싱된 파일 - 서버에서 다운받는게 아님. 브라우저가 다운받아놓은 것

새로고침을 하면 서버에는 이런 url에 맞는 파일 없는데? 하면서 404 오류 내는 것을 볼 수 있다

(막상  react 시작하면 이런 오류 볼 일 없음)

 

코드 살펴보면 

app.py 없다 그래서 서버 있는 것 처럼 실행해보려면

vscode는  live server

pychaarm에서는 Live Edit 플러그인 설치

Go live를 누르면 된다.

 

주의사항

html파일을 선택해서 라이브를 띄우면 도메인 주소에 html 파일 이름이 붙으면서 전체적으로 다 불러오질 못 한다. 

css나 javascript 파일 선택한 후 go live 해야 인터넷 주소에 도메인만 불러오면서 잘 뜬다.

 

코드 살펴보자

여기서 구현된 기능은 딱 2개

1. 맨 처음 페이지가 렌딩했을 때 또는 새로고침 했을 때 , 어떻게 보여줄 건지, router.js를 이용해서 만들었다.

2. 네비게이션바에서 메뉴를 클릭했을 때 화면을 받아와서 이동하는 것.

 

어떻게 구현되었는가

먼저 네비게이터 부분부터 살펴보면 onclick 했을 때  route(event) 함수를 실행해라

js에 가서 route 함수를 보자.

event.target.hash

- route 함수가 들어간 a 태그에 해시가 들어가있다는 뜻

- href = #about 이부분이 해시 내용인 줄 알았는데(맞네, href에 넣어준게 해시 값이다)

튜터님이 콘솔에서 찍어본다. 

수많은 객체중에 해시가 있다는 것을 찍어보면서 알 수가 있다. 

 

 route 함수에 다시 가서 window.location.hash에 위의 a href 에 들어간 hash를 넣어준다. =>  주소에 해시를 넣어준다는 것 근데 이 바뀐해시로 바로 화면이 띄워지는게 아니고

 addeventlistener('hashchange') handlelocation 이렇게 써줘야 진짜로 해시가 바뀌고  그제서야 화면이 띄워진다

handlelocation은 화면을 띄워주는 함수

 

innerHTML을 이용해야 화면이 바뀐다.

 

eventlistener를 이용해서  DOMContentLoaded을 실행해서 처음 랜딩했을 때 파일들을 다 다운받아준다

그리고 handle.location이라는 함수를 실행한다. 이것은 주소에 # 붙는것을 #없어도 되도록? 바꿔주는 함수이다. 이게 필수인가?

 

이번 코드에서는 AJAX 와 JSON를 쓰지는 않았다 .하지만 여전히 중간 중간 페이지 넘길 때 서버가 아닌 클라이언트에서 처리하기 때문에 SPA라고 할 수 있다.

SSR vs CSR

SPA vs MPA 에 대한 블로그 글

https://velog.io/@hlna0308/SPA%EC%99%80-CSR%EC%9D%80-%EA%B0%99%EC%9D%84%EA%B9%8C

 

기타 상식

locahost === 127.0.0.1

자기 자신(브라우저)이 자신(본인 PC 서버)에 접근하는 경우를 Loopback 이라고 한다.

127.0.0.1 을 통상 Loopback IP address 라고 함.

 

SPA의 장단점

 

장점

1.자연스러운  UX

-깜빡임 없다

-앱 같은 느낌으로 자연스러운 페이지 이동 (웹앱) 

 

2. 웹 성능 향상

-필요한 리소스만 부분적으로 로딩

- 서버 펨플릿 연산 클라이언트로 분산

 

3.생산성 향상(개발 속도가 올라간다) 

-컴포넌트별 개발 용이

-협업하기 좋다

-유지보수가 좋다

 

단점

1.첫 랜딩 속도가 느리다(한번에 모든 내용 다운받게 되어있어서) 

-> 나중에 code splitting 배울것 (화면에 띄워지는 부분만 먼저 다운 받고 나머지는 나중에 다운받는 것, lazy loading)

2.검색엔진에 최적화(SEO) 어려움 - body 내용이 없는거나 마찬가지여서

(crawling 로봇이 index.html만 읽는데 중요 내용은 다 다른곳에 있어서)

3. 보안 이슈 - 핵심 비지니스 로직이 서버에서 클라이언트로 옮겨감

 

기초프로젝트에서  spa 써보라

reloading 도 가능하면...? 해보라 

 

 

스택

빨래통

Last In First Out (LIFO)  

나중에 들어간 것이 먼저 나온다

 

순서를 쌓아두고 있다

되돌리기 ctrl + z 쓸 때 스택 자료구조를 이용한다

 

스택 자료구조에서 제공하는 기능 (메소드) - 스택이라는 클래스 안에서 제공하는 함수들

push(data): 맨 위에 데이터 넣기

pop(): 맨 위의 데이터 뽑기

peek(): 맨 위의 데이터 보기

isEmpty(): 스택이 비었는지 안 비었는지 여부 반환해주기

 

데이터는 넣고 뽑는 걸 자주하는 자료구조이다

그것을 보다 편리하게 할 수 있는 링크드 리스트를 이용해보자

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class Stack:
    def __init__(self):
        self.head = None

    # push 기능 구현 - 맨앞에 데이터 넣기
    def push(self, value):
        new_head = Node(value)
        new_head.next = self.head
        self.head = new_head
        return

    # pop 기능 구현 - 맨 앞의 데이터 없애기
    def pop(self):
        if self.is_empty():
            return "Stack is Empty"
        delete_head = self.head
        self.head = self.head.next
        return delete_head #삭제하는 Node를 return 해줘라

    # pop 기능 구현 - 맨 앞의 데이터 보기
    def peek(self):
        if self.is_empty():
            return 'Stack is Empty'
        return self.head.data

    # isEmpty 기능 구현
    def is_empty(self):
        return self.head is None

스택의 탑문제 풀어보자

다음에 풀어보자

 

스택 실전 사용법 - 파이썬의 list를 이용해서 쓴다는데, 링크드 리스트 안 쓰고 그냥 리스트 쓴다는 건가?

stack을 그냥 리스트 안에 넣는건가?

push 대신에 내장함수 append를 이용한다 

 

한쪽 끝으로 자료를 넣고 반대쪽으로는 자료를 뺄 수 있는 선형구조. 선형? 구조

놀이기구 타기

First in First Out (FIFO)

먼저 들어간 사람 먼저 나온다.

 

큐가 제공하는 기능 = 큐 클래스의 메소드

enqueue(data) : 맨 위에 데이터 추가하기

dequeue: 맨 위의 데이터 제거하기

peek(): 맨 위의 데이터 보기

isEmpty(): 큐가 비었는지 안 비었는지 여부 반환해주기

 

이것도 링크드 리스트 이용하면 좋다. 

 

머리와 꼬리 노드가 둘 다 있어야한다.

self.head 와 self.tail

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class Queue:
    def __init__(self):
        self.head = None
        self.tail = None

    # 맨 뒤에 데이터 넣기
    def enqueue(self, value):
        new_node = Node(value)
        if self.is_empty():
            self.head = new_node
            self.tail = new_node
            return
        self.tail.next = new_node
        self.tail = new_node
    # 맨 앞의 데이터 삭제하기
    def dequeue(self):
        if self.is_empty():
            return 'Queue is Empty'
        delete_head = self.head
        self.head = self.head.next
        return delete_head.data # 삭제 된 데이터 반환해주기

    # 맨 앞의 데이터 보기
    def peek(self):
        if self.is_empty():
            return 'Queue is Empty'
        return self.head.data

    # 큐가 비었는지 안 비었는지 여부 반환하기
    def is_empty(self):
        return self.head is None


queue = Queue() # 클래스의 새로운 객체 생성하기
queue.enqueue(3)
print(queue.peek())
queue.enqueue(4)
print(queue.peek())
queue.enqueue(5)
print(queue.peek())
queue.dequeue()
print(queue.peek())
print(queue.is_empty())

해쉬

어쩌구 저쩌구 위의 설명 모르겠다

기억해야 할 것 해쉬는 데이터의 검색과 저장이 아주 빠르게 진행된다.

콘솔 창에서 실험해보자 hash라는 함수는 이미 파이썬에서 구현이 되어있다.

 

 

파이썬 콘솔 창에서 hash 기능을 먼저 이용해보자

hash에 값을 넣어주면 고유한 숫자 같은게 나온다. 

 

나머지 구하기 %를 해서 나오는 숫자가 인덱스라는데 왜 그렇지?

배열 길이로 나누어서 나머지를 구하면 무조건 인덱스 안에 들어가는 숫자가 나오기 때문에

class Dict:
    def __init__(self):
        self.items = [None] * 8

    def put(self, key, value):
        index = hash(key) % len(self.items)
        self.items[index] = value

    def get(self, key):
        index = hash(key) % len(self.items)
        return self.items[index]


my_dict = Dict()
my_dict.put('text',3) 
print(my_dict.get('text')) # 프린트 된다

나머지가 겹치는 경우는 없나?

hash에서 겹치지 않도록 하나?

강의 듣다보니 강사님이 언급하셨다. 

링크드 리스트를 쓰면 겹치는 인덱스 문제도 해결할 수 있다고 하신다. 

새로운 노드로 추가해버리면 된다.

링크드 리스트의 노드에 키랑 밸류 둘 다 저장한다.

 

링크드 리스트로 해쉬 기능 이용해보기

 

어려워서 포기 

연습문제, 퀴즈 또한 포기

 

한글 문자열로 넣었는데 저렇게 유니코드로 나온다. 강사님은 안 그렇던데

 

 

 

git 명령어

  • git log --oneline: 커밋 목록 한줄로 간단하게 보기
  • git log --patch: 커밋 목록에서 어떤 변경사항이 있는지 보기
  • git log -- graph: 브랜치 상황 그래프로 보기

같이 쓸 수도 있다.

ex)

git log --oneline --graph 

git log -- oneline -- patch

 

  • git stash: 변경사항 임시저장
  • git stash list: 변경사항 임시저장 리스트 확인
  • git branch: branch 확인하기
  • git branch 브랜치 이름: branch 생성
  • git checkout 브랜치 이름: 해당 브랜치로 체크아웃
  • git log --branches: 어디 브랜치에 체크아웃 했는지 상관 없이 모든 브랜치의 커밋 확인하기
    • (foo 브랜치로 체크아웃 하고 거기서 커밋을 만든다. 그 다음 master 브랜치도 돌아와서 보면 foo 브랜치의 커밋을 볼 수 없다. 그럴 경우에 git log -- braches를 쓰면 된다.)
  • git merge 병합할 브랜치 이름: 브랜치 병합하기
    • (merge 할 때  먼저 병합하려는 브랜치에서 다른 브랜치로 체크아웃 해준다.) 
  • git branch -d 삭제할 브랜친 이름 : 브랜치 삭제하기
    • (삭제할 때 먼저 삭제할 브랜치에서 다른 브랜치로 체크아웃 해준다.) 
    • (병합되버린 브랜치가 더 이상 쓸모 없다면  그럴 때는 삭제해주는게 좋다.) 
  • git checkout -b 브랜치 이름: 브랜치를 만드는 동시에 체크아웃도 하기

충돌이 났을 경우

충돌난 곳에 들어가서 head와 다른 브랜치 두개가 나란히 있을 때 하나만 선택해서 저장해주고

다시 add 하고 commit 해준다 그러면 미리 커밋 메세지가 작성되어 있는 vi 창이 열린다

:wq :작성한 내용 저장하고 편집기 나가기

 

해시: 각 커밋에 주어지는 고유한 이름 같은 것