8장 연습문제. 약 30여개 문제가 있음.

너무 단순하거나 간단히 풀수 있는 것을 제외하고 기록함.


8.10 N개의 정점을 가진 무방향 그래프 G에 대해 다음의 설명중 맞는 것만 모아놓은 것은?

1) G의 각 쌍의 정점 사이에는 1개의 경로만 존재하면 G는 트리이다

2) G가 하나의 연결성분으로 되어있고 N-1개의 간선을 가지면 G는 트리이다.

3) G가 N-1개의 간선을 가지면서 싸이클이 없으면 G는 트리이다.


용어를 정확히 이해하지 않고 풀면 많이 헷갈린다.

1) 트리란 1개 이상의 노드를 갖는 집합이다. 그렇기에 각 쌍의 정점 사이의 한개의 경로, 즉 최소 2개의 노드로 구성되어진 G는

트리이다.


2) 연결성분이란 최대로 연결된 부분의 그래프.

G가 하나의 연결성분을 가진다고 하였으므로 모든 정점들이 연결되어있다.

그런데 모든 정점을 연결하면서 간선이 N-1개란 뜻은 싸이클을 완성 할 수 없다는 뜻이다.

예를들어 5개의 정점을 하나의 연결성분으로 하면서 싸이클을 만들려면 5개의 간선이 필요로 하다.

(중간에 다른 방향을 통해서 3개의 싸이클을 만든다고 할 경우 하나의 연결성분이라는 조건을 충족 못함)

그렇기에 G는 트리라고 할 수 있다


3) 2에서의 설명을 다르게 바꾼 것. 



8.18 Kruskal 알고리즘과 Prim 알고리즘을 비교한 것 중 가장 적절하게 설명한 것을 고르시오.


이 문제에서 짚고 넘어가야 하는 부분은 그리디 알고리즘과 동적계획 알고리즘이다.


그리디 알고리즘 : 탐욕 알고리즘 이라한다. 처음엔 탐욕이라길래 뭔가 많이 가져가는거가 목표인가 라고 생각했으나

그게 아님.. 그래서 개인적으론 이기적이다 라고 이해하고 있다.

그리디 알고리즘은 쉽게 생각하면 근시안적으로 보는 것이다. 바로 3개 초콜릿, 1분뒤 10개 초콜릿 을 준다고 했을 경우

바로 3개의 초콜릿을 선택하는 것, 그것이 그리디 하다 할 수 있다(탐욕적이니까)


동적 계획법은 위와는 살짝 다르다.

얘는 조금 생각을 한다. 큰 맥락이 아닌 부분에 대한 이해를 바탕으로 최선을 고려하고 이를 통해 전체의 해답을 얻는다.


(작성중)

티스토리를 운영하면서 소스코드를 올려야겠다 라는 필요성이나 절박함? 은 없었는데

점점 그래야할 필요성을 많이 느끼게 되었다.

그냥 복사해서 올리면 기존에 내가 올려둔 느낌이 나게 되고..


여러가지 찾아본 방법은 git에 gist를 사용 하는 것.
https://gist.github.com/

1. 해당 사이트에 접속해서 소스코드를 복사 붙여 넣는다.

2. 저장 한 후에 주소를 복사한다

3. 티스토리에서 html로 체크 후 해당 url을 포스팅 한다.


상당히 간단하다.


그런데 Jupyter Notebook을 쓰면서 또 궁금해졌다.

다른 분들은 잘만 하는데 다른 방법을 모르겠어서..


그래서 일단 내가 찾은 방법은


1. 주피터 노트북을 html로 다운 받는다.

2. 해당 내용을 티스토에 html로 붙여 넣는다 이다!!

단순 무식하지만 일단은 된다... 일단은..

아 이쁘게 나오기 위해선 아래와 같은 코드를 주피터에 붙여야 한다.


from IPython.core.display import display, HTML

display(HTML("<style> .container{width:90% !important;}</style>"))


http://versusall.tistory.com/entry/1-Tistory-%EA%B8%80%EC%93%B0%EA%B8%B0-tip 

이분 블로그를 따라하였다.

Untitled2
In [82]:
from IPython.core.display import display, HTML
display(HTML("<style> .container{width:90% !important;}</style>"))

Pandas 리뷰

In [1]:
import pandas as pd
import numpy as np
from pandas import Series, DataFrame
# 기본 라이브러리 임포트, 제일 아래 Series나 DataFrame은 어차피 pd에 있기에
# pd.Series로 써도 되나 아래처럼 부르면 Series로 바로 부를 수가 있다.
In [84]:
movie = pd.read_csv('movie.csv')
# csv를 읽어들인다, 안에 다른 매개 인자가 많지만 아직 그 정도 레벨은 아님..
In [83]:
movie.head(5)
# head는 기본 5개를 보여줌. 안에 숫자쓰면 숫자만큼 보여줌.
Out[83]:
구분 요일 지역-시도 지역-시군구 지역-읍면동 성별 연령대 이용_비율(%)
0 영화관 2018 4 1 강원도 강릉시 금학동 10대 0.00018
1 영화관 2018 4 1 강원도 강릉시 금학동 30대 0.00143
2 영화관 2018 4 1 강원도 강릉시 금학동 20대 0.00161
3 영화관 2018 4 1 강원도 속초시 조양동 10대 0.00099
4 영화관 2018 4 1 강원도 속초시 조양동 20대 0.00457
In [7]:
df = movie.copy() # 원본은 놔두고 카피
In [12]:
df.index = movie['지역-시군구'] # 카피한 복사본에 index를 추가함. index는 원본의 지역-시군구
df.head()
Out[12]:
구분 요일 지역-시도 지역-시군구 지역-읍면동 성별 연령대 이용_비율(%)
지역-시군구
강릉시 영화관 2018 4 1 강원도 강릉시 금학동 10대 0.00018
강릉시 영화관 2018 4 1 강원도 강릉시 금학동 30대 0.00143
강릉시 영화관 2018 4 1 강원도 강릉시 금학동 20대 0.00161
속초시 영화관 2018 4 1 강원도 속초시 조양동 10대 0.00099
속초시 영화관 2018 4 1 강원도 속초시 조양동 20대 0.00457
In [16]:
# 시리즈로 다시 회귀.. 시리즈가 모이면 데이터 프레임
kk =pd.Series([100,200,300], index = ['a','b','c'])
ko =pd.Series([10,20,30], index = ['a','b','c'])
In [15]:
for k, v in kk.items():
    print (k, v)
a 100
b 200
c 300
In [20]:
dfd = df[:10]
dfd
Out[20]:
구분 요일 지역-시도 지역-시군구 지역-읍면동 성별 연령대 이용_비율(%)
지역-시군구
강릉시 영화관 2018 4 1 강원도 강릉시 금학동 10대 0.00018
강릉시 영화관 2018 4 1 강원도 강릉시 금학동 30대 0.00143
강릉시 영화관 2018 4 1 강원도 강릉시 금학동 20대 0.00161
속초시 영화관 2018 4 1 강원도 속초시 조양동 10대 0.00099
속초시 영화관 2018 4 1 강원도 속초시 조양동 20대 0.00457
속초시 영화관 2018 4 1 강원도 속초시 조양동 30대 0.00152
속초시 영화관 2018 4 1 강원도 속초시 조양동 10대 0.00215
속초시 영화관 2018 4 1 강원도 속초시 조양동 30대 0.00269
원주시 영화관 2018 4 1 강원도 원주시 단계동 40대 0.00287
원주시 영화관 2018 4 1 강원도 원주시 단계동 50대 0.00027
In [21]:
dfd[['구분']] # dfd['구분']과 다른 점은 대괄호 두개는 데이터 프레임 형식을 그대로 유지함.
Out[21]:
구분
지역-시군구
강릉시 영화관
강릉시 영화관
강릉시 영화관
속초시 영화관
속초시 영화관
속초시 영화관
속초시 영화관
속초시 영화관
원주시 영화관
원주시 영화관
In [22]:
dfd['구분']
Out[22]:
지역-시군구
강릉시    영화관
강릉시    영화관
강릉시    영화관
속초시    영화관
속초시    영화관
속초시    영화관
속초시    영화관
속초시    영화관
원주시    영화관
원주시    영화관
Name: 구분, dtype: object
In [30]:
df2 = pd.DataFrame(np.arange(12).reshape(4,3))
print(df2[0][1])
print(df2[1][3]) #[칼람][로우] 순이네
3
10
In [28]:
df2
Out[28]:
0 1 2
0 0 1 2
1 3 4 5
2 6 7 8
3 9 10 11
In [32]:
data = {
    "kor":[80,90,70,30],
    "eng":[90,70,60,40],
    "mat":[90,60,80,70]
};
columns = ['kor', 'eng', 'mat']
index = ['kim', 'lee', 'jin', 'dae']
df = pd.DataFrame(data, index = index, columns = columns)
In [33]:
df
Out[33]:
kor eng mat
kim 80 90 90
lee 90 70 60
jin 70 60 80
dae 30 40 70
In [35]:
df['mat'].T
Out[35]:
kim    90
lee    60
jin    80
dae    70
Name: mat, dtype: int64
In [36]:
df[['kor', 'eng']]
Out[36]:
kor eng
kim 80 90
lee 90 70
jin 70 60
dae 30 40
In [37]:
df['kor_avg'] = sum(df['kor']) / 4
In [86]:
sum(df['kor'])
Out[86]:
270
In [87]:
df['kor'].sum
Out[87]:
<bound method Series.sum of kim    80
lee    90
jin    70
dae    30
Name: kor, dtype: int64>

Row 끼리 더하기

  • 칼럼끼리 더하는 것은 쉬움(생각보단)
  • Row 순으로 더하는 방법을 고민하다가 아래처럼 사용.
  • sum()과 df[].sum은 전혀 다르다.
    • 전자의 경우는 칼럼을 인덱싱 한 후에 모두 더하는 거고, 후자는 로우별 인덱싱 한 후에 더한다
In [88]:
df['sum'] = df[df.columns[:3]].sum(axis = 1)
#df.columns를 하면 여러개가 순서대로 나오는대 그 중에서 0,1,2번까지만 사용해서 
df
Out[88]:
kor eng mat kor_avg sum
kim 80 90 90 67.5 260
lee 90 70 60 67.5 220
jin 70 60 80 67.5 210
dae 30 40 70 67.5 140
In [80]:
df.loc['kim', :]
Out[80]:
kor         80.0
eng         90.0
mat         90.0
kor_avg     67.5
sum        260.0
Name: kim, dtype: float64
In [ ]:
# 모든 학생의 수학점수를 시리즈로 나타낸다.
# 모든 학새으이 국어와 영어점수를 데이터 프레임으로 나타낸다
# 모든 학새으이 각 과목 평균 점수를 새로운 열로 추가한다
# dae의영어 점수를 80점으로 수정하고 평균 점수도 다시 계산한다
# kim의 점수를 데이터 프레임으로 나타낸다
# jin의 점수를 시리즈로 나타낸다.

http://taewan.kim/post/numpy_cheat_sheet/

(추천 사이트)

차후에 정리를 위해서라도 남기는.


import numpy as np


파이썬 라이브러리 중 계산을 위한 필요 라이브러리. scipy랑 잘 사용.

다만 배워놓고 생각보다 많이 쓰지 않았음.


1. 리스트 만들기

np.array

np.arange(num)

두개다 리스트를 만들어 준다. 간편하게 만들 수 있어서 좋다.


2. 배열 연결 : 행이나 열을 연결할때 사용. 판다스에서 concat과 비슷.

np.hstack : 가로로 연결

np.vstack : 세로로 연결

np.dstack : 음... 차원이 새롭게 생긴다. 허허...


3.np.where(data 조건, true, false)

넘파이 하면서 첨 본듯.

삼항연산자이다. 조건을 주고 true일시, false일시의 값들을 정하면 된다.

np.where(lst > 10, 99, 88)

lst의 요소들이 10보다 크면 99로, 아니면 88로 

np.where(lst > 10, 99, lst)

lst요소들이 10보다 크면 99, 아니면 lst(그냥 둬라)



#번외 List Comprehension

for문을 한줄로 사용.

첨엔 헷갈리는데 익숙해지면 편한듯

for x in range(num):

print (x)

-> [x for x in range(num)] , 물론 얘는 리스트 이다.(위는 단순 출력)


 [[x + k*10+50*(i-1) for k in range(5)]  for i in range(1,4)]

이중 for문 형식으로도 사용 가능.

시간날때 천천히 개념 복습.

기본부터 충실히.


1) 객체 지향 언어.


- 가상세계의 현실화

- 현실에서의 상호작용의 주체를 객체(Object)로 이해한다.


예) 자판기에서 물건을 사는 고객이 있다고 할때 이를 

자판기(돈, 제품)

-메서드 : 돈을 받기, 검사하기, 잔돈주기, 제품주기

고객(돈, 제품)

-메서드 : 돈 넣기, 돈 받기, 제품받기 

등으로 쪼개어 이해한다.


- 모듈식으로 구성되므로 코드를 이해하고 유지하고 보수하는데 매우 용이하다.

이를 위해 추상화, 캡슐화 등이 있음(차후 설명)


* 그런데 객체지향의 반대를 절차지향이라 생각하는 것은 조금 위험한 발상 일 수도??

객체 지향이나 절차지향이나 결국 알고리즘, 데이터 플로우 대로 진행 된다. 그렇기에 객체지향과 절차지향을 서로 다르게 이해하는 것이 맞지, 무조건적으로 반대다 라곤 할 수 없다.


즉 절차지향은 프로그래므이 순서와 흐름이 먼저 고려한 후 자료구조와 함수들을 설계하는 방식이고, 객체지향은 자료구조와 함수를 설계한 후 실행순서와 흐름을 짜는 방식으로 이해


# 파이썬 -> 자바-> C언어 순으로 접하다 보니 확실히 모듈식으로 코드를 구성하는 것이 편하고 당연시 여겨진다.


2) 오버로딩과 오버라이딩

2.1) 오버로딩

- 같은 이름의 메서드를 매개변수의 변화를 통해 정의 하는것

- 같은 메서드 이름을 갖고 있으나 매개변수의 개수 또는 타입이 달라야 한다.

- 오로지 매개변수에 의해서 구분이 되어진다.

- 같은 기능을 하지만 서로 다른 인자를 받는 함수를 사용할때 편하다. 


2.2) 오버라이딩

- 조상클래스로부터의 상속 내용을 내 입맛대로 변경하는 것.

- 단 이름, 매개변수, return 타입은 같다.

- tostring 바꿀때 많이 사용했다.


# 오버로딩과 인터페이스, 다시금 정리할 필요가 있다.


3 추상클래스

- 자체로 역할을 하는 클래스는 아니지만 상속을 통해 자손에게 능력을 주는 클래스? 이다.

- 즉 추상클래스를 코드로 구현 후 자손에게 상속한뒤 자손은 이를 '오버라이딩' 해야만 한다.

# 그런데 나는 아직 경험이 없어서 그런지 추상클래스의 필요성을 못느끼겠다. 클래스를 작성할때 조상까지 생각할 겨를도 없고

그럴 필요도 못느낀다. 일을 두배로 하는 느낌? 물론 설계단계에서 추상클래스부터 작성한다면 모르겠지만...


4. 인터페이스

- 얘 역시 다른 클래스에게 도움을 줄 목적으로 만들어진다.

- 추상클래스와의 다른 점은 모양, 생긴것.

- 추상클래스는 말 그대로 클래스이지만 추상적(역할 x)이다.

- 하지만 인터페이스는 오로지 상수 멤버와 추상메서드만을 갖는다.

- 또한 extends와 implements의 차이도 존재한다.

- 한개만 받느냐 여러개를 받느냐..

# 보통 mapper로 인터페이스를 만들어서 사용 했는데 스프링 프로젝트할때는 mapper를 xml로 작성하다보니 이 마저도 사용을 잘 안하게 됬다.

큰그림을 얼마나 보느냐에 따라서 위 두개 개념을 사용하고 안하고가 갈리는 듯 하다.


5. 다형성(polymorphis)

- 같은 모양이 다르개 사용 되는 것?

- 전화기의 키보드, 문자할때의 키보드, 게임할때의 키보드 등... 모양은 같은데 서로 다른 기능을 수행

- 여러가지 형태를 가질 수 있는 능력

- 한 타입의 참조변수로 여러타입의 객체를 참조할 수 있도록 함.

# OOP에서 매우 중요한 개념이긴 한데 오랫만에서 봐서 헷갈림.

다시 정리 필요..


원래는 다익스트라 먼저 나와야 하는데

그 부분이 아직 정리가 덜 됬다.


플로이드 마샬의 경우 기존에 우리가 해왔던 임의의 정점, 또는 한 정점으로 부터가 아닌

모든 정점에 대한 계산을 실시한다.

바꿔 말하자면 X에서 Y로의 경로에 N 노드를 거치는게 빠르냐 아니냐를 따지는 것이다.

그렇기에 

1. X->Y의 비용

2. X->N + N -> Y의 비용

이 두개의 비용을 비교하여 최소 비용으로 업데이트 한다.

(아래 내용은 동빈나님의 블로그를 필기한 것이다, https://blog.naver.com/ndb796/221234427842)



위를 코드로 구성하자면

D = 인접 리스트

for i in range(len(D):

for k in range(len(D)):

for j in range(len(D)):

D[i][k] = min(D[i][k], D[i][j] + D[j][k])


매우 간단한데 이해가 바로 오지는 않는다.

위에 예시에 D[2,3] 이 누구랑 비교 되는지 확인하면서 생각해야한다.



어줍잖은 자만심때문에

내 본을 잃어버렸다.

다시금 새로이 준비를 해야겠다...


노드는 당분간 안녕....


그래서 새롭게 포트폴리오를 만들고 있는데

진짜 너무 슬프다.


30년 살아왔는데 쓸 내용이 이렇게 없나 싶다...

지난 회사에서 일했을때 기억은 군고구마밖에 없고...

2번째, 프림 알고리즘

개념은 이해가 되는데 코드로 구현한거는 이해가 안됬다.

그래서 수기로 순서대로 정리를...


import sys;

N = 7;

s = 0;

g = [None] * N # size 를 설정하기 위해서


g[0] = [(1,9), (2,10)];

g[1] = [(0,9), (3,10), (4,5), (6,3)];

g[2] = [(0,10),(3,9),(4,7),(5,2)];

g[3] = [(1,10),(2,9),(5,4),(6,8)];

g[4] = [(1,5),(2,7),(6,1)];

g[5] = [(2,2),(3,4),(6,6)]

g[6] = [(1,3), (3,8), (4,1), (5,6)];

visited = [False] * N

D = [sys.maxsize] * N #?????


D[s] = 0

previous = [None] * N;

previous[s] = s


if __name__ == '__main__':

 for k in range(N):

  m = -1

  min_value = sys.maxsize;

  print("k is %d" %k);

  for j in range(N):

   print("j in %d" %j);

   print("outter D[j] is %d" %D[j]);

   if not visited[j] and D[j] < min_value:

    print("D[j] is %d" %D[j]);

    min_value = D[j]

    m = j

  visited[m] = True

  

  for w, wt in list(g[m]):

   print("w : %d, wt : %d" %(w, wt));

   if not visited[w]:

    if wt < D[w]:

     print("if  wt :%d, D[w] : %d" %(wt, D[w]))

     print("previo", previous[w]);

     D[w] = wt

     previous[w] = m

     print("afeter pri", previous[w]);

    

 print("min tree", end = '');

 mst_cost = 0;

 for i in range(1, N):

  print("(%d, %d)" %(i, previous[i]), end='');


이 코드의 핵심은 방문리스트와 이전리스트를 활용하는 것이다.

방문이 되는 것은 최소 가중치로 선정이 됬을때이다.

이전 리스트는 가중치가 무한에서 자기가 갖고 있는 값으로 업데이트 됬을때 된다

이 장에선 여러가지 알고리즘을 배운다

이러한 알고리즘의 핵심은 최단 경로 혹은 최소 가중치로 신장트리를 만드는 것.

네비게이션이나 경로 탐색 등 다양한 분야에서 실제로 사용된다고 한다.


1. kruskal 알고리즘.

최소 신장트리를 만드는 것


if __name__ == '__main__':

 weights = [(0,1,9), (0,2,10), (1,3,10), (1,4,5), (1,6,3), (2,3,9), (2,4,7), (2,5,2), (3,5,4,), (3,6,8),(4,6,1),(5,6,6)]

 weights.sort(key = lambda t:t[2])

 mst = []

 N = 7

 p = []

 check = 0;  

 

 for i in range(N):

  p.append(i);

  

 def find(u):

  print("find", u)

  if u != p[u]:

   print("inner find", u, p[u]);ㅎ

   p[u] =find(p[u]);

  print("find p[u] : %d" %p[u]); 

  return p[u]

  

 def union(u,v):

  root1 = find(u)

  root2 = find(v)

  print("root1 :%d, root:%d" %(root1, root2));

  p[root2] = root1;

  print("p[r2] : %d, r1:%d" %(p[root2],root1))

  

 tree_edges = 0;

 mst_cost = 0;

 while True:

  if tree_edges == N-1:

   break;

  print("check", weights)

  u,v,wt = weights.pop(0);

  print("not if check", u, v, wt)

  if find(u) != find(v):

   print("check", u, v, wt)

   print("ch", p);

   union(u,v)

   mst.append((u,v))

   mst_cost += wt;

   tree_edges += 1

   

  

 print("최소 신장트리 :", end = '');

 print(mst)

 print('최소 신장트리 가중치 :', mst_cost)


코드는 위와 같다.

이 알고리즘의 핵심은 union-find 이다.

가중치로 정렬을 했기 때문에 제일 위부터 아래로 연결을 해주면 되는데

문제는 이 정점들이 싸이클이 되는지 확인하는 것이다.

그렇기에 이 싸이클 여부를 확인하는 것은 해당 정점의 최상 루트가 무엇인지를 파악 해주면 된다.

예를 들어 1-2, 2-3, 3-4, 4-5 이렇게 연결 되어 있는 경우에 5번 노드가 2,3번에 연결이 안되는 이유는 2,3의 최상 루트가 1번이기 때문이다.

재귀적 방식을 통해서 제일 위의 루트를 찾는것, 그리고 그것이 다를때만 연결을 해주는 것이 핵심이다.(이를 위해 p라는 임의의 리스트를 형성)

var express = require('express'), http = require('http'),

    path = require('path');

var router = express.Router();

// 라우터 객체 생성!

var ErrorH =  require('express-error-handler');

// 오류페이지 보내기 위한 핸들러 선언

var cookieParser = require('cookie-parser');

var expressSession = require('express-session');

var app = express();

var errh = ErrorH({

    static :{

        '404' : './public/404.html'

    }

});

app.use(ErrorH.httpError(404));

app.use(errh);

app.use(cookieParser());

app.use(expressSession({

    secret : 'my key',

    resave:true,

    saveUnintialized:true

}));

router.route('/process/product').get(function(req,res){

        console.log('product 호출');

        if(req.session.user){

            res.redirect('/public/product.html');

        }else{

            res.redirect('/public/login2.html');

        }

    });

router.route('/process/showCookie').get(function(req, res){

        console.log('/process/showCookie 호출');

        res.send(req.cookie);

        });

router.route('/process/setUserCookie').get(function(req,res){

    console.log('setuser 호출');

    res.cookie('user', {

        id :'mike',

        name :'sosi',

        authorized:true

    });

    res.redirect('/process/showCookie');

});


router.route('/process/login/').post(function(req,res){

    console.log('process/login check');

    var paramName = req.params.name;

    // 얘는 토큰이라 부른다.

    var paramId = req.body.id||req.query.id;

    var parPass = req.body.pass || req.query.pass;

    console.log('process/login check222');

    if(req.session.user){

        console.log('already login');

        res.redirect('/public/product.html');

    }else{

        console.log('process/login check333');

        req.session.user={

        id : paramId,

        name :'sosi',

        authorized:true

        };

    

    res.writeHead('200', {'Content-Type':'text/html;charset = utf8'});

    res.write('<h1> express server answer');

    res.write('<div><p>Param Name : ' +paramName + '</p></div>');

    res.write('<div><p>Param id :'+paramId + '</p></div>' );

    res.write('<div><p>param pass :' + parPass + '</p></div>');

    res.write(

    "<br><br><a href ='/public/login2.html'>go back</a>");

    res.end();

    }

});

router.route('/process/logout').get(function(req,res){

    console.log('logout');

    if(req.session.user){

        console.log('go logout');

        req.session.destroy(function(err){

            if(err){throw err;}

            console.log('session des');

            res.redirect('/public/login2.html');

        });

    }else{

        console.log('not yet login');

        res.redirect('/public/login2/html');

    }

});


var bodyParser = require('body-parser'), static = require('serve-static');

// static 미들웨어 불러오기


var app = express();

app.set('port', process.env.PORT||3000);


app.use(bodyParser.urlencoded({extended:false}));

// body-parser 활용

// application//www-xxx-xxx 주소를 파싱

// 즉 폴더안에 있는 페이지의 주소를 연결해줌!!

app.use(bodyParser.json());

// bp를 이용한 application/json 파싱

// 내용을 파밍하는듯?

app.use(static(path.join(__dirname, 'public')));

// 폴더명을 연결해줌!!

// public만 해주나?


app.use('/', router); //router을 app 객체에 등록


http.createServer(app).listen(3000, function(){

    console.log('server start');

});



이 부분은 서버 실행 + 로그인 + 세션 유지 파트이다.

기본적으로 특정 페이지 접속시 세션유무를 파악하여

세션이 있으면 페이즈를 응답하고

없으면 로그인 할 수 있도록 유도한다


근데 문제는 session 에러가 계속 뜸

TypeError: Cannot read property 'user' of undefined

분명 세션 사용과 if else를 통해 세션이 없을경우 저장 까지 할 수 있게 해놨는데

실행이 안된다.


내일 더 봐야할듯..

'Node.Js 도전(임시 마감)' 카테고리의 다른 글

Do.it과 함께하는 Node.js 5장  (0) 2018.04.30

+ Recent posts