graph를 배열의 형태로 완성한다. → 각 index에 해당 index번째 노드와 연결된 간선의 번호를 적는다. cf) 양방향인 경우, 양쪽에 적어야한다.
탐색 시작 노드를 스택에 삽입하고 방문처리한다.
스택의 최상단 노드에 방문하지 않은 인접 노드가 있으면 해당 노드를 스택에 넣고 방문 처리한다. → 방문하지 않은 인접 노드가 없으면 다시 스택에서 최상단 노드를 꺼낸다.
2번이 불가능 할때까지 반복한다.
# 방문 정보를 리스트 자료형으로 표현
# 노드는 9개지만, index 0번 노드는 사용하지 않는다.
visited =[False] * 10
# 각 노드가 연결된 정보를 리스트 자료형으로 표현 (2차원 리스트)
graph = [
[], # 빈 자리
[3, 4, 5], # 1번 노드와 연결된 노드들
[2, 3, 8], # 2번 노드와 연결된 노드들
[1, 7], # 3번 노드와 연결된 노드들
[1, 4, 5], # 4번 노드와 연결된 노드들
[3, 5], # 5번 노드와 연결된 노드들
[3, 4], # 6번 노드와 연결된 노드들
[7], # 7번 노드와 연결된 노드들
[2, 6, 8], # 8번 노드와 연결된 노드들
[1, 7] # 9번 노드와 연결된 노드들
]
def DFS(graph, visited, start):
# 현재 노드를 방문 처리
visited[start] = True
print(start, end = ' ')
for i in graph[start]:
if not visited[i]:
DFS(graph, visited, i) // 재귀함수!!
# 현재 노드와 연결된 다른 노드를 재귀적으로 방문
DFS(graph, visited, 1)
🔎BFS (Breadth First Search)
너비 우선 탐색으로, deque를 사용하여 구현
구현 방법
graph를 배열의 형태로 완성한다.cf) 양방향인 경우, 양쪽에 적어야한다. → 각 index에 해당 index번째 노드와 연결된 간선의 번호를 적는다.
탐색 시작 노드를 큐에 삽입하고 방문 처리한다.
큐에서 노드를 꺼내 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 삽입하고 방문 처리한다.
2번이 불가능 할때까지 반복한다.
from collections import deque
# BFS
def BFS(graph, visited, start):
queue = deque([start])
# 첫 노드 방문 처리
visited[start] = True
# 큐가 빌 때까지 반복
while queue:
# 큐에서 하나의 원소를 뽑아 출력
v = queue.popleft()
print(v, end = ' ')
# 해당 원소와 연결된, 아직 방문하지 않은 원소들을 큐에 삽입
for i in graph[v]:
if not visited[i]:
queue.append(i)
visited[i] = True
# 노드는 9개지만, index 0번 노드는 사용하지 않는다.
visited =[False] * 10
# 각 노드가 연결된 정보를 리스트 자료형으로 표현 (2차원 리스트)
graph = [
[], # 빈 자리
[], # 1번 노드와 연결된 노드들
[2, 3, 8], # 2번 노드와 연결된 노드들
[1, 7], # 3번 노드와 연결된 노드들
[1, 4, 5], # 4번 노드와 연결된 노드들
[3, 5], # 5번 노드와 연결된 노드들
[3, 4], # 6번 노드와 연결된 노드들
[7], # 7번 노드와 연결된 노드들
[2, 6, 8], # 8번 노드와 연결된 노드들
[1, 7] # 9번 노드와 연결된 노드들
]
BFS(graph, visited, 1)
✏️팁
둘다 O(NlogN)의 시간 복잡도를 지닌다.
True / False를 적극 활용하기
visited =[False] * (N+1)
⭐노드가 1부터 시작하는 경우, graph와 visited도 1부터 시작하기 → 헷갈림 방지
DFS의 재귀가 이미 visited를 모두 방문했음에도 실행하고 있을 때를 대비하여, 해 호출마다 check_end 함수를 넣을 수 있음.
이때, 4번의 속도가 매우 빨라서, User는 마치 이미 만들어진 페이지를 가져오는 것처럼 보인다.
하지만, 실제로는 뼈대 Html만 받아오는 것이다
→ 이는, SEO (Search Engine Optimization)에 부정적인 영향을 미친다.
(아래 사진) Skeleton HTML만 렌더링된 모습
NextJS는 React와 다른 “Pre-Rendering”을 통해 페이지를 렌더링한다.
공식문서에는 다음과 같이 설명되어 있다.
By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO.
Each generated HTML is associated with minimal JavaScript code necessary for that page. When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive (this process is called hydration in React).
Pre-Render하는 대략적인 과정은 다음과 같다.
User의 Page Request
Server는 뼈대 Html + Javascript 코드를 바탕으로 완성된 페이지를 제공한다. → 이때, 사용한 Javascript 코드를 같이 넘겨준다 (Hydration) 이는, 첫 렌더링을 제외하면 Client Side Rendering 또한 가능하게 하기 위함이다. (event handling)
⭐여기서부터 중요하다⭐
Next.Js는 Pre-Rendering을 하는 시점을 On Build Time vs On Each Request로 구분한다
Build Time에 Pre-Render하는 방법을 Static Site Generation
Each Request에 Pre-Render하는 방법을 Server Side Rendering이라 한다.
그럼 CSR, SSG, SSR이 각각 어떻게 실행되는지 알아보자
Static Side Generation (Recommended)
→ 페이지들은 빌드할 때 Pre-Render된다.
이후, Hydrate을 통해 Regular React App처럼 Interactive한 Aplication으로 사용가능하다.
공식문서
If a page uses Static Generation, the ✏️page HTML is generated at build time.That means in production, the page HTML is generated when you run ⭐`next build`. This HTML will then be reused on each request. It can be cached by a CDN. In Next.js, you can statically generate pages with or without data.
How to User SSG?: `getStaticProps` Function
// 형식 정확히 일치 필요!
export async function getStaticProps(context) { … }
→ Server에서만 실행되는 코드를 작성한다. (i.e. Client에서 사용하는 코드는 사용 불가능하다.)
→ Not Be included in code bundle that server gives to client
→ getStaticPaths에 명시된 모든 params를 Static Site Generate한다. (Build때 pre-render) → 명시되지 않은 Path에 접근하면 404 Error를 발생시킨다
→ 해당 동적 라우트가 내용이 얼마 없을때
→ Pre-Render해야 하는 Route가 많거나, 데이터가 많으면 오래 걸린다 (ex. 게시판 or 판매목록)
true
→ getStaticPaths에 명시된 params만 SSG한다 → 명시되지 않은 Params는 useEffect하는 것처럼 그때 getStaticPaths 코드를 실행한다. → 즉, params에 없는 코드라도 404에러를 발생시키지 않는다 → params에 없으면 “blocking” 처럼 행동한다
→ 데이터가 많은데, Pre-Render해야하는 중요한 것만 몇개 있고 나머지는 그러지 않아도 되는 경우
“blocking”
→ SSR처럼, 눌렀을때 Pre-Render되기를 기다렸다가 Load된다.
Error Handling을 하면서 사용하기
fallback : false
→ route에 포함되지 않는 경우 404Error 발생.
→ `404.js` 에서 Error Handling
fallback : true
→ route에 포함되지 않는 경우 404Error가 발생하지 않음. 단, getStaticProps에서 데이터를 찾는 과정에서 코드Error가 발생함