본문 바로가기

Others/NODE.JS

웹애플리케이션 제작 (목차 및 글쓰기)

진짜 현대적인 웹애플리케이션을 만들어보자.


이전 게시글은 이번 포스팅을 위한 부품을 모았던 것이라고 생각해도 좋다.

이제 그것들을 결합해서 제대로 만들어보자!


웹애플리케이션이 가지고 있는 전형적인 기능

즉, 사용자로부터 어떠한 정보를 입력받아서 그것을 서버에 저장하고 사용자가 필요한 정보를 요청하면 그것을 제공하는 전형적인 웹애플리케이션을 만드는 포스팅이다.


학습을 시작하기에 앞서, 어떤것을 만들지 살펴보자.


1. 링크(목차)를 클릭하면 해당 내용을 보여준다.

2. form을 통해 정보를 서버로 전송되면(제출), 그 정보를 받아서 1번 링크에 추가(서버로 부터 정보 받기)하기.



현대적인 웹 애플리케이션들은

실제로 사용자가 등록한 정보들을 데이터베이스라고 하는 곳에 저장한다. 여기서는 데이터베이스가 아닌 파일에 저장할 것이다.

파일을 포괄적으로 이야기한다면, 데이터베이스에 일종이라고 말할 수 있다.


파일에 데이터를 저장하는 이유는 파일이 일종의 삽과 같은 것이기 때문입니다.

예를 들어 삽과 포크레인이 있습니다. 둘중에 뭐를 선택하겠어요?

대부분 포크레인. 하지만 포크레인이 모두 좋은 것은 아니다. 왜냐하면 그것을 사용하려면 포크레인 사용법을 배워야 한다. 

BUT 삽은 보자마자 바로 쓸 수 있고 어디에서든지 사용 가능하다.


파일기반 사용의 가장 중요한 장점

- 사용하기 굉장히 쉽다

- 파일을 제어하는 방법을 배우기 쉽다. (물론 잘 제어하는건 어렵다, 막 제어하기는 편함 ㅎ)


궁긍적으로 데이터베이스 시스템을 사용하는 단계까지 가겠지만 그 중간과정을 경험해보는 것도 좋다.

복잡도를 낮춤으로써 쉽게 접근할 수 있기 때문에.




실전! (준비;폴더만들기)

  • 템플릿엔진파일 디렉토리 : views_file
  • 파일형태의데이터베이스 디렉토리 : data
  • 메인파일, 메인애플리케이션 또는 엔트리 애플리케이션 : app_files.js
  • 이외 파일들(css, js 등) : public_file



1. 커넥션 맺기 


Line 1 : express 모듈 가져오기 및 제어(변수에담기)하기

Line 2 : 모듈을 가져왔으면 모듈을 이용해서 애플리케이션 객체를 만들어야 한다. 그 때는 Line1의 변수에 담긴 무언가가 있을거 아니에요?

그게 함수인데, 그 함수를 실행하면 애플리케이션 객체라는 것을 리턴합니다.

Line 3 : 애플리케이션 객체가 가지고 있는 메소드 중에서 listen을 통해 어떤 특정 포트를 listening 하도록 설정한다. 예를 들어 3000포트를 바로보고 싶으면 첫번째 인자로 3000, 두번째 인자로 메소드를 전달한다. 3000포트로 연결되면 두번째 인자인 메소드를 호출한다.







2. 라우팅 : 사용자 요청을 적당한 콘트롤러와 연결해주는 라우팅 설정.


적당한 URL을 따라 적당한 정보를 사용자에게 보여줄 것이다.

- 사용자가 어떤 글을 작성해서 post 방식으로 서버로 정보를 보내면 그것을  data라는 디렉토리에 파일로 저장할 것이다.

- 이을 위해서는 글을 작성할 수 있는 form이 필요하며, 그 form은 /topic/new에 접속했을 때 나타낼 것이다.


2-1. Line 3-5 : /topic/new 라우팅하기


  


 

 

2-2. 템플릿엔진(jade)를 이용하기 위한 설정


Line 3 : 이 디렉토리에 템플릿 파일을 넣기 위한 설정(.set)을 해주어야 한다. 템플릿엔진의 디렉토리인 views를(첫번째인자) 두번째인자(./views_file)의 경로에 설정하겠다.

Line 4 : 템플릿엔진(첫번째인자)로 jade(두번째인자)를 사용하겠다고 설정해 주는 것.

* express에서 뷰엔진(템플릿엔진), jade 모듈이 설치 되어 있지 않다면 설치를 먼저 해야 한다.




2-3. 사용자가 작성할 폼(form;new.jade)을 만들어보자.


views_file > new.jade (form 코드 설명)



cannot post error 해결하기 : 애플리케이션이 post 방식을 받을 준비가 되어있지 않기 때문에 발생.


Line 9 : POST 방식으로 받을 라우터 만들기


 

(실행결과 왼-작성화면, 오-작성 후 제출화면)




3. 본문저장 (입력)


req.body 사용하기 위해서 : npm install --save body-parser 모듈필요., 자세히 보러가기

Line 3-4 : 코드 셋팅 필요, POST 방식으로 들어오면 해당 코드가 애플리케이션 중간에서 요청을 가로채어 request 객체의 body라는 프로퍼티를 만들어서 post 데이터에 접근할 수 있게 해준다.

Line 13,14,19 : body프로퍼티로 잘 가져오는지 확인.



4. data 폴더 만들기

- 전송한 데이터를 파일로 담는 곳.

- 사용자가 전송한 제목을 파일의 이름으로 지정.

- 사용자가 전송한 본문을 그 파일의 내용으로 지정.


Line 5 :파일을 제어하기 위해서는 fs시스템이라고 하는 nodejs가 제공하는 모듈을 사용해야한다.


Line 15 : fs.writeFile(파일경로 + 저장하고자하는데이터, 콜백함수 )


콜백함수의 인자 (err)

존재하지 않는 파일(첫번째인자)에 시도를 했을 때, 오류가 나면서 콜백함수의 매개변수 값으로 오류가 전달될 것이다.


Line 16 : 에러가 있을 때의 경우: 500-서버오류 (콘솔[터미널]에서는 상세하게 볼 수 있음)

Line 17 : 에러가 없을 때 처리 해줌.



(Line 17이 작동한 화면)







5. 글목록만들기 : 저장된 데이터 읽어오기 (출력)



    

( /topics으로 접근했을 때 오류화면 )



Line 12 : GET에 대한 라우터가 없기 때문에 설정해주자. /topics으로 접근하면 글목록이 보여지게 만들 것이다.

Line 13 : 응답(req)의 render을 통해 템플릿(파일명:view;form)을 사용하자.


====




Line 8 : 글목록을 만드는 태그 (또는 ol)





Line 10-12 : 사용자가 nodejs라는 글을 보고 싶다면 사용자가 치고 들어와야할 주소는 /topic/nodejs라고하자. 그렇다면 href는 이 코드처럼 작성하면 된다. (/topic/new로 접근해서 글을 몇개 더 작성해보자) 하지만 이 방법은 아~~~주 비효율적인 방법이다.

데이터가 추가될 때마다 코드를 수정하는 것은 아주 nono..






그렇다면 어떻게 해야할까?

사용자가 /topic으로 들어왔을 때, data라고 하는 디렉토리의 파일들의 목록을 가져와, 파일들의 이름들로 /topic의 리스트로 가져와야 한다.




Line 13 : fs.readdir( 알고싶은디렉토리의경로, 정보를 가져왔을 때 호출될 콜백함수 )

여기서 콜백함수는 문서를 살펴보면, 두개의 인자(err,files)를 가지고 있다는 것을 확인할 수 있다. (files;파일명을 배열로 받는다)


* res.render('파일명','첫번째인자 파일에 주입하고자 하는 데이터를 객체 안에 담아서 넣는다')


Line 19 : topics(view.jade의 Line 11의 in topics부분이 됨)를 통해 files의 내용을 가져올 수 있다.


view.jade Line 11 : view.jade파일에 다시 for문을 사용하여 리스트를 가져오려고 한다. ( jade iteration-반복문- 작성법 )

href 경로를 '/topic/파일명'으로 지정, 여기서 topic은 파일명을 담은 변수.


jade의 괄호가 궁금하다면? (hint속성)





6. 목차의 리스트 클릭하면 본문 읽기(가져오기)


사용자가 링크를 타고 들어왔을 떄, 해당 글을 가져와보자

= /topic/A : A의 내용을 읽어서 가공한 뒤 웹페이지로 만들어 사용자에게 전송해야 한다.


6-1. 언제나 시작은 라우터! 라우터와 어떻게 연결할것인가 생각해보자.




Line 31 : 사용자가 접근할 때, 링크를 타고 들어오는 것은 GET 방식이다. 바뀔 수 있는 URL 정보는 :(콜론)으로 표시한다.

Line 32 : 바뀔 수 있는 정보(path 상에 id)에 접근(access)할 수 있는 방법 : req.params.id로 접근. 링크에 따라 매번 바뀌는 id값을 변수에 담자.

Line 33 : id값에 해당되는 파일을 읽어서 가져오자. fs.readFile('읽어올파일의경로'+id, 'utf8', callback)

* callback의 형식 : (err,data)

Line 35 : id값에 해당되는 파일명을 가진 파일의 본문을 보여준다.



6-2. 사용자가 클릭한 링크의 내용이 목차 아래에 위치시켜보자.




Line 41 : res.send()를 res.render()로 바꾸어 가져오고자 하는 정보(제목, 본문)를 객체로 담는다.

제목은 Line 32에 의해 id라는 변수에 저장되어 있고, 본문은 Line 33의 fs.readFile의 콜백함수의 두번째 인자인 'data'에 담겨 있다.

topics:files는 아래 오류 내용을 살펴보면 이해할 수 있다.


Line 33 : fs.readdir()를 통해 파일경로에 접근 한 뒤, 정보 가져오기에 성공했을 때,

Line 39 : fs.readFile()이 실행되면서 res.render로 view.jade를 화면에 랜더링하고 있다.





* 다음과 같은 에러가 보인다면, 이 코드가 있는지 확인해보자. 앞서 /topic으로 접근했을 때, 라우터를 만들어주었다. (5번확인) 그런데 여기서링크를 누른다음에는 URL을 확인해보면 /topic/파일명 으로 되어 있다. 즉, topic/:id라우터에도 5번에서 사용한fs.readdir()의 성공시 render한 topics가 필요하다. 이 topics가 없기 때문에 view.jade의 반복문 사용에서 오류가 난것.




(성공 화면)




7. 코드 개선


1. /topic으로 접근했을 때

소스보기를 보면 article태그만 존재하고 내용은 없는 것을 볼 수 있는데 이는 보기 좋지 않다.


2. 중복 (중복제거하기) * 좋은 코드를 만드는 중요한 테크닉 중에서 가장 중요하다고 할 수 있다.

- readdir()의 중복 (왜 중복됐는지는 6번을 통해 알수 있다.)

- res.render('view', ~ );

- 라우터 주소의 비슷함 (/topic으로 대부분 시작 됨.)


사실은 주소가 달라질 수 밖에 없기 때문에 서로 다른 라우터를 만든것이다.

express의 문법을 보면, 라우터에 여러가지 패스를 가질 수 있다.

대괄호는 배열을 의미하죠. 배열에다가 복수로 주고 싶은 path를 지정해주면 된다.

그리고 각 배열에 담긴 특정 경로에 대해서 코드를 작성하고 싶을 때, 조건문을 걸어주면 된다.


3. 좀더 활용성 높은 웹애플리케이션 만들기


- Line 8 : 제목 부분에 홈으로 갈 수 있는 링크 설정/ Line 16-17 : 글쓰기로 넘어갈 수 있는 링크 설정



- /topic/new의 글쓰기 폼을 동떨어지지 않게 자연스럽게 만들기 (리스트항목추가)

-> Line 10-16 : 그럼 new.jade에도 topics이라는 객체로 접근할 수 있도록 res.render 부분 수정이 필요함.




- 글 작성 후 제출을 했을 때, 현재 success가 뜨는 것은 별로. 작성한 글에 대한 페이지로 보내보자.

-> Line 43 : 수정, 사용자가 글을 잘 작성했는지 확인할 수 있도록 하자아아아 ; res.redirect('사용자를 보내고 싶은 경로 작성');