게시판 - 프로젝트 생성 및 navbar

소스코드

이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.

git clone https://github.com/a-mean-blogger/board.git
cd board
git reset --hard 3f61f06
npm install
atom .

- Github에서 소스코드 보기: https://github.com/a-mean-blogger/board/tree/3f61f064ea4994e8006eb92f3608cd5a50ea4483


게시판 프로젝트를 생성하고 아래와 같이 navbar 및 기본 페이지들을 만들어 봅시다.
기본 페이지는 welcome, about 두개입니다. 실제 게시판 메뉴/페이지는 다음 강의에서 만듭니다.

프로젝트 생성

프로젝트 생성에 앞서, 해당 프로젝트에서 사용할 DB를 생성하고 환경변수에 등록해 줍시다.

프로젝트 폴더를 만드는데, 이번에는 npm init 명령어에 --yes 옵션을 넣어서 사용해 봅시다.

$ npm init --yes

npm init에서 모든 항목을 skip하고 기본값으로만 구성된 package.json을 만드는 옵션입니다.

atom 에디터를 실행합시다.

$ atom .

폴더구조

.gitingore, README.md는 github을 위해 생성한 파일입니다.

Package 설치

ejs, express, mongoose, body-parser method-override package들을 설치해 줍시다.

$ npm install --save ejs express mongoose body-parser method-override

코드 - js

이 게시물의 node.js 코드는 주소록-만들기에서 모두 설명된 코드들만 사용되었습니다. 만약 이해가 안되는 부분이 있다면 주소록 만들기 코드를 다시 한번 복습해 주세요.

// index.js

var express    = require("express");
var mongoose   = require("mongoose");
var bodyParser  = require("body-parser");
var methodOverride = require("method-override");
var app = express();

// DB setting
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.connect(process.env.MONGO_DB);
var db = mongoose.connection;
db.once("open", function(){
  console.log("DB connected");
});
db.on("error", function(err){
  console.log("DB ERROR : ", err);
});

// Other settings
app.set("view engine", "ejs");
app.use(express.static(__dirname+"/public"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));

// Routes
app.use("/", require("./routes/home"));

// Port setting
app.listen(3000, function(){
  console.log("server on! http://localhost:"+port);
});
// routes/home.js

var express = require("express");
var router = express.Router();

// Home
router.get("/", function(req, res){
  res.render("home/welcome");
});
router.get("/about", function(req, res){
  res.render("home/about");
});

module.exports = router;

코드 - ejs

ejs 코드 역시 주소록-만들기에서 대부분 설명되었고, collapse(버튼을 눌러서 내용을 보이고, 숨기는 기능, 여기서는 navbar에서 사용했습니다.)을 포함한 새로운 부분들만 설명합니다.

<!-- views/partials/head.ejs -->

<meta name="viewport" content="width=device-width,initial-scale=1">

<!-- jquery -->
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> <!-- 2 -->

<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <!-- 1 -->

<!-- my css -->
<link rel="stylesheet" href="/css/master.css">

<title>My Website</title>

1. 메뉴를 열고 닫는 기능을 bootstrap에서 가져오는데, 이를 사용하기 위해서는 bootstrap CSS와, 추가로 bootstrap JS를 사용해야 합니다.

2. bootstrap JS은 jQuery를 요구하기 때문에 jQuery 역시 사용해야 합니다.

<!-- views/partials/nav.ejs -->

<nav class="navbar navbar-default">
  <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <div class="navbar-brand">My Website</div>
    </div>
    <div class="collapse navbar-collapse" id="myNavbar">
      <ul class="nav navbar-nav">
        <li><a href="/">Home</a></li>
        <li><a href="/about">About</a></li>
      </ul>
    </div>
  </div>
</nav>

주소록 만들기와 비교해서 달라진 부분은 <div class="navbar-header">안에 button이 들어간 것과, <ul class="nav navbar-nav"><div class="collapse navbar-collapse" id="myNavbar">로 감싼 것 뿐입니다.

button에 data-target이 #myNavbar로 설정되어 있고, 이 버튼을 누를때마다 <div class="collapse navbar-collapse" id="myNavbar">가 보이거나 숨겨지게 됩니다.

<!-- views/home/welcome.ejs -->

<!DOCTYPE html>
<html>
  <head>
    <% include ../partials/head %>
  </head>
  <body>
    <% include ../partials/nav %>
    <div class="container home home-welcome">
      <div class="jumbotron">
        <h1>MEN - 게시판</h1>
        <P>이 사이트는 <a href="http://a-mean-blog.com/ko/blog/MEAN/MEN-게시판">http://a-mean-blog.com/ko/blog/MEAN/MEN-게시판</a>에서 작성되었습니다!</p>
      </div>
    </div>
  </body>
</html>

jumbotron이라는 class는 bootstrap에서 제공하는 단순한 CSS class입니다. 굉장히 큰 글씨를 보여주는 class입니다.

<!-- views/home/about.ejs -->

<!DOCTYPE html>
<html>
  <head>
    <% include ../partials/head %>
  </head>
  <body>
    <% include ../partials/nav %>
    <div class="container home home-about">
      <h1>About</h1>

      <P>이 사이트는 <a href="http://a-mean-blog.com/ko/blog/MEAN/MEN-게시판">http://a-mean-blog.com/ko/blog/MEAN/MEN-게시판</a>에서 작성되었습니다!</p>
    </div>
  </body>
</html>

코드 - css

/* public/css/master.css */

.home h1{
  color: darkseagreen;
}

실행결과

nodemon으로 웹사이트를 실행합니다.

$ nodemon

http://localhost:3000 에 접속하면 jumbotron으로 만들어진 welcome 화면이 보입니다.

about page입니다.

화면 사이즈를 스마트폰 사이즈만큼 줄여보겠습니다.

메뉴가 사라지고 세줄짜리 버튼이 생겼습니다. 참고로 이 세줄짜리 버튼의 공식 명칭은 햄버거 버튼(hamburger button)입니다.

햄버거 버튼을 눌러봅시다.

메뉴가 열립니다. bootstrap을 이용하면 모바일 사이트 만드는 것이 어렵지 않아요.

마치며..

본격적으로 게시판 개발에 들어가기 앞서 메뉴를 만들어 보았습니다.
주소록 만들기에서 크게 벗어나는 내용은 없는데, 다음 CRUD 강의도 마찬가지입니다.
회원가입, 로그인이 나오기 전까지는 복습한다는 생각으로 봐주세요.

댓글

l
ljc0328 2016.12.03
nodemon하면 events.js:160       throw er; // Unhandled 'error' event       ^
Error: spawn cmd ENOENT     at exports._errnoException (util.js:1026:11)     at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)     at onErrorNT (internal/child_process.js:359:16)     at _combinedTickCallback (internal/process/next_tick.js:74:11)     at process._tickCallback (internal/process/next_tick.js:98:9)  이런 에러가 뜨는데 어떻게 해야 하나요?
I
Ian H 2016.12.09
@ljc0328,
r
rkdqudtjs1 2017.03.06
안녕하세요 좋은강의 올려주셔서 감사합니다. Angular2에 대한 강의도 올려주실 예정인지 궁금해서요. 강의예정에 대한 글을 올려주셨나 찾아봤는데 못찾아서 질문드려요.
I
Ian H 2017.04.04
@rkdqudtjs1,
Angular2는 블로그가 새로 디자인 되면 올라올 예정입니다^^
산호섬 2017.08.24
좋은 강의 늘 감사드립니다. !!  그런데 <head> 태그 안에 <meta name="viewport" content="width=device-width, initial-scale=1"> 코드를 넣지 않으면 모바일로 봐도 페이지 레이아웃이 바뀌지 않는 것 같습니다~
I
Ian H 2017.09.08
@산호섬,
아. 모바일뷰는 Bootstrap에 의해서 사이트 창의 width에 의해 결정됩니다. 
아마 폰의 브라우저에 자동으로 줌(scale)이 적용되는 거 같은데.. 맞습니다. 위 코드를 넣으면 scale을 1로 만들어서 그러한 현상을 막을 수 있습니다. 
알려주셔서 감사합니다!
d
dombegi 2017.10.18
많은 공부가 되고있습니다! 사소한 질문인데, index.js에서 Route 설정에 require 의 주소 앞에 점 (.)은 어떤 의미인가요? redirect나 다른 항목에는 (.)없이 '/'로 시작하니까 혼란스럽네요ㅠ
I
Ian H 2017.10.18
@dombegi,
사소하지만 중요한 질문입니다. 상대주소에서 "./"은 현재 위치를 나타냅니다. .과 /를 하나로 생각하셔야 합니다. 참고로 ../은 현재 위치의 한단계 위의 위치를 나타냅니다.  html에서 .없이 /로 시작하는 것은 사이트위 최상위 위치를 나타냅니다.
김남현 2017.10.30
직접 타이핑할 경우, 위 절차대로만 하면!! body-parser 가 없다고 에러나네요 :) $ npm install --save ejs express mongoose 에서 body-parser 를 추가 해... 바로 method-override 에러.... 몇개 에러뜨는 대로 처리해주면 잘됩니다!! 잘봤습니다. 감사합니다.
I
Ian H 2017.10.30
@김남현,
package 설치 부분 내용 수정하였어요^^ 감사합니다!
김남현 2017.11.02
/index.js 에서 
// Routes app.use("/", require("./routes/home")); app.use('/posts', require('./routes/posts'));  // 이 부분 추가되어야, 나중에 front-end부분에서 에러가 안나네요. 해당 글에서 다른 분이 남기신 글 참고 했습니다 :)
미국 현*에 계신다고 하셨죠? 저는 6월에 한국들어와서 .. 좀 지내다가 내년 3월경 다시 미국들어갈 예정입니다. 작년과 올해는 미국에서 거의 일만했는데, 이번에는 CA내 내셔널파크 등을 돌아다닐까 합니다. 일정중에 커피라도 한잔 마시면 좋을 것 같습니다 :)
I
Ian H 2017.11.02
@김남현,
routes/posts 부분은 이 다음 포스트 http://www.a-mean-blog.com/ko/blog/Node-JS-첫걸음/게시판-만들기/게시판-Back-End-개발 에서 추가됩니다. 
아.. 여행 부럽네요. 전 미국 살면서 맨날 집에만 있네요ㅠ Irvine쪽 오시게 되면 이메일 한번 보내주세요 시간이 되서 보면 좋죠^^
김남현 2017.11.04
@Ian H,
여행이라기 보단.. 서비스 하나 런칭(그것 때문에 지금 열심히 공부중이죠 하하..)하고 그것을 홍보해가면서 하는 여행이 될 예정입니다. 결국.. 일이죠. 하하.. 어바인쪽이면 가볼게요 :)
김남현 2017.11.02
강의에서만 적용이 안되어 있습니다. 깃허브에서는 적용되어 있었습니다. 이것과는 별개로, tap버튼을 누른면 submit 버튼으로 이동하는 것이 아니라, 위의 blog로 이동해서 엔터를 침과 동시에.. ㅠㅠ 썼던 글 다 지워지고 블로그 메인으로 가네요. 세번째 반복하다가 이상해서 천천히 해보니 그렇더군요. 이글까지 썼다가 또 습관적으로 tap키를 누르고 엔터를 흑흑.. 
I
Ian H 2017.11.02
@김남현,
submit 버튼이 실제 버튼이 아니고 span이라.. 한번 해결법을 찾아보죠
I
Ian H 2017.11.02
@김남현,
수정하였습니다! 제보 감사드려요!
김남현 2017.11.04
@Ian H,
오. 적용되었습니다. 편합니다!.. 하고!! 탭을 눌렀는데!! 아래 새로운 댓글창으로 이동하네요.  이건 제 습관의 잘못일지도.하하
뿡뽕뽕 2018.02.02
정말 많은 도움이 됩니다 ㅎㅎ 감사드려요! 댓글 보고 알게되었는데 미국 현X 자동차 계시나요? 저도 가본적이 있어서 반갑네요! 
I
Ian H 2018.02.02
@뿡뽕뽕,
오 반갑습니다! 워낙 눈에 띄게 생긴 건물이고 프리웨이 바로 옆에 있어서 다들 아시더라구요 ㅋㅋ
정현우 2018.08.31
안녕하세요  현재 올리셨던 소스로 실행은 되는 아래와 같은 경고 문구가 떠서요  혹시 몽고디비 버젼 문제 인가요.?  WARNING: The `useMongoClient` option is no longer necessary in mongoose 5.x, ple                                                                                                                ase remove it.     at handleUseMongoClient (C:\workspace\board\node_modules\mongoose\lib\connec                                                                                                                tion.js:586:17)     at NativeConnection.Connection.openUri (C:\workspace\board\node_modules\mong                                                                                                                oose\lib\connection.js:462:7)     at Mongoose.connect (C:\workspace\board\node_modules\mongoose\lib\index.js:2                                                                                                                32:15)     at Object.<anonymous> (C:\workspace\board\index.js:10:10)     at Module._compile (module.js:652:30)     at Object.Module._extensions..js (module.js:663:10)     at Module.load (module.js:565:32)     at tryModuleLoad (module.js:505:12)     at Function.Module._load (module.js:497:3)     at Function.Module.runMain (module.js:693:10)     at startup (bootstrap_node.js:191:16)     at bootstrap_node.js:612:3 (node:2584) DeprecationWarning: current URL string parser is deprecated, and wil                                                                                                                l be removed in a future version. To use the new parser, pass option { useNewUrl                                                                                                                Parser: true } to MongoClient.connect.
I
Ian H 2018.08.31
@정현우,
안녕하세요. 첫번째 문장을 읽어 보시면, The `useMongoClient` option is no longer necessary in mongoose 5.x, please remove it. 경고가 mongoose로 부터 오는 것을 알 수 있습니다. 또한 경고에서 설명하는 대로 useMongoClient 부분을 지우시면 문제가 해결 됩니다
I
Ian H 2018.08.31
본문 코드 수정하였습니다. 소스코드도 새로 받아주세요^^
정현우 2018.09.03
수정 감사합니다 ^ ^ 저는 mongoose 부분이 수정 될줄 알았는데  port setting 부분이 수정 되었군요
I
Ian H 2018.09.04
@정현우,
mongoose 부분은 useMongoClient이 useNewUrlParser로 수정되었구요,  port setting 부분은 알려주신 에러메세지랑은 관련없이 개인적으로 수정한 내용입니다^^
댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP