ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 231206_Express 웹 서버 구축, Postman
    카테고리 없음 2023. 12. 6. 16:57

    프로젝트 평가기준은 아래와 같다. 

    Node.js 실습문제

    -환경 구축
    1. 사용 할 OpenAPI - 개별적으로 사용함
    2. node.js 구동 및 서버 실행(http. express 등을 이용함)
    3. 클라이언트 html 을 구성함
    4. DB 구성 및 웹서버를 연결함

    *실습 순서 및 점수
    1. node.js 서버 구동 및 웹과 DB 연결
    2. API 호출 후 Response 출력(10점)
    3. 공공데이터 API 를이용하여 얻은 데이터 적용(20점)
    4. response 에서 <litems> 의 모든 요소를 파싱하여 DB에 저장하고 출력(10점) 
    5. 공공데이터 API 를이용하여 얻은 데이터 적용(20점)
    5. DB E-R 다이어그램을 그리기(10점)

     

    오늘은 클라이언트-서버 간 출력과정을 짚었고, 내일은 서버와 데이터베이스간 연결하는 것을 진행할 예정. 실질적으로 데이터에 들어가서 서버를 거쳐 클라이언트에 적용하고-클라이언트에서 데이터를 받아 데이터베이스에 집어넣는 것으로 Node.js의 과정이 끝난다. 

    내일은 데이터베이스 테이블 생성부터 연결까지 할 예정, 스키마 모델 생성이 어려울 수 있다고 하셨으니 예습을 해둬서 나쁠 건 없을 것 같다. 아직 프로젝트에 대한건 감이 잘 안 잡힌다. 미니 프로젝트: 제품판매 웹앱 구현 과 공공데이터 API 를 이용한 웹 페이지 출력, 두가지가 평가 기준에 들어가는건가... 

     


    포스트맨 다운로드

    구현된 익스프레스 라우트를 테스트하기 위한 클라이언트 환경, 주로 클라이언트 환경이 없는 백앤드 개발자가 개발하고 있는 서버 프로그램이 정상구동 하는지 테스트를 할 수 있는 프로그램. 

    익스프레스 라우트 테스트를 하기 위해 node.js 폴더 생성 후 폴더를 불러왔다. 터미널을 열고 npm init 을 치면 node,js 에서 새로운 패키지를 만들기를 시작한다. 패키지와 패키지 락 등등이 생성된걸 모두 확인한 뒤 app.js 파일을 생성 -  postman 에서 서버가 돌아가는지 시험해서 확인해보기 위해 아래와 같이 작성했다. 

    const express = require('express')
    const app = express()
    const port = 3000

    app.get('/', (req, res) => { res.send('Hello World!')} )
    app.post('/', (req, res) => {res.send('guro_1206')} )

    app.get('/customer', (req, res) => {res.send('get')} )
    app.post('/customer', (req, res) => {res.send('post')} )

    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

     

    포스트맨에서 확인한 코드 결과는 더보기 참고

    더보기
    app.get('/', (req, res) => { res.send('Hello World!')} )
    app.post('/', (req, res) => {res.send('guro_1206')} ) 결과
    app.get('/customer', (req, res) => {res.send('get')} ) 결과
    app.post('/customer', (req, res) => {res.send('post')} ) 결과

     

    get이든 post든 해당되는 프로토콜 요청이 들어오면 그에 대해서 응답을 하는, 서버가 존재한다면 클라이언트와 주고 받는것만 확인하는 코드. 뭔가 들어오면 어떤 결과를 내 주는 것, 이게 서버의 동작이고 스프링부트에서도 웹 서버 동작이 동일하다.

     서버가 DB와 주고받기 위해서는, 서버와 DB를 매치 시켜주는게 별도로 필요하다. (지금은 클라이언트-서버간 출력을 볼 것이다.)

    app.get('/', (req, res) => { res.send('Hello World!')} )
    app.post('/', (req, res) => {res.send('guro_1206')} )

    app.get('/customer', (req, res) => {res.send('get')} )
    app.post('/customer', (req, res) => {res.send('post')} )

    위 코드는 서버가 어떻게 동작할지에 대해서 get 과 post로 받는 코드다. 위 코드는 없어도 웹 페이지 자체는 활성화 된다. (단지 출력 결과가 안 보일 뿐이다.) 

    const express = require('express')
    const app = express()
    const port = 3000
     
    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

    하지만 이건 웹 서버를 활성화 하는 것이기 때문에, 위의 코드가 없으면 get 과 post가 있어도 웹서버가 활성화 되지 않는다. 참고하자. 

     

    7.2.3 라우트(Route)경로

    const express = require('express')
    const app = express()
    const port = 3000
     
    //get방식으로 'host:port/acd' 혹은'host:port/abcd'를 호출했을 때
    //'b?'는 문자'b' 가 0개 혹은 1개 있다는 것을 의미
    app.get('/ab?cd', function(req, res){ res.send('ab?cd'); });

    //클라이언트에서 요청한 라우트 경로가 abcd, abbcd, abbbcd 등과 일치
    //'b++'는 문자'b' 가 1개 이상 있다는 것을 의미
    app.get('/ab+cd', function(req, res){ res.send('ab+cd'); });

    //클라이언트에서 요청한 라우트 경로가 abcd, abxcd, abanycd, ab123cd등과 일치
    //'ab*cd'는 문자 'ab'와 문자 'cd'사이에 문자가 없거나 혹은 어떤 문자도 올 수 있다는 것을 의미
    app.get('/ab*cd',function(req, res){ res.send('/ab*cd'); });

    //클라이언트에서 요청한 라우트 경로가 abc 혹은 abcde 와 일치
    //'(cd)?'는 문자 'cd'가 0번 혹은 1번 있을 수 있음을 의미
    app.get('/ab(cd)?e',function(req,res){ res.send('/ab(cd)?e'); });

    //클라이언트에서 요청한 라우트 경로에 'a'가 포함되어있는 경우
    app.get(/a/, function(req, res){ res.send('/a/'); });

    //클라이언트에서 요청한 라우트 경로가 문자 'insert'로 시작하는 경우, 결과 확인안됨
    // app.get(/^insert/, function(req,res){
    //     res.send('/^insert/');
    // });
     
    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

     

    포스트맨에서 확인한 코드 결과는 더보기 참고

    더보기
    app . get ( '/ab?cd' ,&nbsp; function ( req ,&nbsp; res ){&nbsp; res . send ( 'ab?cd' );&nbsp; });
    app . get ( '/ab+cd' ,&nbsp; function ( req ,&nbsp; res ){&nbsp; res . send ( 'ab+cd' );&nbsp; });
    app . get ( '/ab*cd' , function ( req ,&nbsp; res ){&nbsp; res . send ( '/ab*cd' );&nbsp; });
    app . get ( '/ab(cd)?e' , function ( req , res ){&nbsp; res . send ( '/ab(cd)?e' );&nbsp; });
    app . get ( /a/ ,&nbsp; function ( req ,&nbsp; res ){&nbsp; res . send ( '/a/' );&nbsp; });

    마지막 코드( insert )는 결과가 확인이 되지 않아 보류했다.

     

    실습. request로 파라미터를 추가해 호출하기

    // request 구글 크롤링 하는 법 다시 해보기
    const request = require('request');
    //한글 안깨지는법
    const iconv = require('iconv-lite');
    request({
      method: 'GET',
      qs: {q: '신사역 맛집'},
      encoding: null,
    }, (error, response, body)=> {
    const decodedResult = iconv.decode(body, 'euc-kr')
    console.log(decodedResult);
    });

     

    교재처럼 출력이 되지는 않았는데, 이렇게 나오는게 맞다고 하셔서 이걸 더 고치지는 않았다. 왜 이렇게 나온건지는 잘 모르겠지만 넘어갔다.

     

    7.2.4 라우트(Route)핸들러

    const express = require('express')
    const app = express()
    const port = 3000
     
    const ex0 = function(req, res, next){
        console.log('첫 번쨰 콜백 함수');
        next();
    }
    const ex1 = function(req, res, next){
        console.log('두 번쨰 콜백 함수');
        next();
    }
    const ex2 = function(req, res){
        console.log('세 번쨰 콜백 함수');
    }
    app.get('/examples',[ex0,ex1,ex2]);
     
    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

    서버가 실행 된 후, 서버에 접속하니까 콜백 함수가 출력되었다.

     

     

    7.2.5 응답 메소드

    종류가 다양하다는걸 살펴본 뒤 넘어갔다. 사용 방법만 알고 있으면 될 것 같다.

     

    7.2.6 app.route()

    get, post, put, delete 등의 라우트 메소드를 app.route() 로 받아서 각 라우트 메소드로 처리하는 방법. 처리방법마다 받는 방법을 맞추면 코드가 길어지고 불필요하게 중복되는 부분이 생기게 된다. app.route()  로 각 라우트 메소드를 처리하면 불필요하게 중복되는 부분을 줄이고 효율적으로 코드를 관리할 수 있음. 

    const express = require('express')
    const app = express()
    const port = 3000
     
    app.route('/customer')
    .get(function(req,res){res.send('고객 정보 조회'); }) //HTTP 메소드 GET 요청에 대한 조회 처리
    .post(function(req,res){res.send('신규 고객 추가'); }) //HTTP 메소드 Post 요청에 대한 조회 처리
    .put(function(req,res){res.send('고객 정보 수정'); }) //HTTP 메소드 PUT 요청에 대한 조회 처리
    .delete(function(req,res){res.send('고객 정보 삭제'); }); //HTTP 메소드 Delete 요청에 대한 조회 처리
     
    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

     

     

    더보기
    get ( function ( req , res ){ res . send ( '고객 정보 조회' ); })
    post ( function ( req , res ){ res . send ( '신규 고객 추가' ); })
    put ( function ( req , res ){ res . send ( '고객 정보 수정' ); })
    delete ( function ( req , res ){ res . send ( '고객 정보 삭제' ); })

     

    7.2.7 express.Router (중요)

    express.Router클래스를 사용하면 라우트처리를 여러 개의 파일로 분리해서 기능에 맞게 구현할 수 있다. 나는 routes라는 이름의 폴더를 새로 생성하고, routes 폴더에 customer.js, product.js 파일을 만들어서 각각 라우트를 정의했다.

    정리하자면 아래와 같은 느낌으로 폴더를 만들고, 폴더 안에 라우트를 정의한 것이다. 

    routes 폴더 customer.js router.get('/',function(req,res){ res.send('customer 라우트 루트'); });
    router.post('/insert',function(req,res){ res.send('/customer/insert 라우트'); });
    router.put('/update',function(req,res){ res.send('/customer/update 라우트'); });
    router.delete('/delete',function(req,res){ res.send('/customer/delete 라우트'); });
    prduct.js router.get('/',function(req,res){ res.send('prduct 라우트 루트'); });
    router.post('/insert',function(req,res){ res.send('/prduct/insert 라우트'); });
    router.put('/update',function(req,res){ res.send('/prduct/update 라우트'); });
    router.delete('/delete',function(req,res){ res.send('/prduct/delete 라우트'); });

     

     

    const express = require('express');
    const router = express.Router();
    //고객정보 조회를 위한 라우트
    //app.js에서 기본경로에 /customer를 사용하기 때문에 /customer라우트 경로를 가짐
    router.get('/',function(req,res){
        res.send('customer 라우트 루트');
    });

    //고객정보 추가를 위한 라우트
    //app.js에서 기본경로에 /customer를 사용하기 때문에 /customer/insert라우트 경로를 가짐
    router.post('/insert',function(req,res){
        res.send('/customer/insert 라우트');
    });

    //고객정보 수정을 위한 라우트
    //app.js에서 기본경로에 /customer를 사용하기 때문에 /customer/update라우트 경로를 가짐
    router.put('/update',function(req,res){
        res.send('/customer/update 라우트');
    });

    //고객정보 삭제를 위한 라우트
    //app.js에서 기본경로에 /customer를 사용하기 때문에 /customer/delete라우트 경로를 가짐
    router.delete('/delete',function(req,res){
        res.send('/customer/delete 라우트');
    });

    module.exports = router;

     

    const express = require('express');
    const router = express.Router();
    //고객정보 조회를 위한 라우트
    //app.js에서 기본경로에 /prduct 사용하기 때문에 /prduct 라우트 경로를 가짐
    router.get('/',function(req,res){
        res.send('prduct 라우트 루트');
    });

    //고객정보 추가를 위한 라우트
    //app.js에서 기본경로에 /prduct 를 사용하기 때문에 /prduct/insert라우트 경로를 가짐
    router.post('/insert',function(req,res){
        res.send('/prduct/insert 라우트');
    });

    //고객정보 수정을 위한 라우트
    //app.js에서 기본경로에 /prduct 를 사용하기 때문에 /prduct/update라우트 경로를 가짐
    router.put('/update',function(req,res){
        res.send('/prduct/update 라우트');
    });

    //고객정보 삭제를 위한 라우트
    //app.js에서 기본경로에 /prduct 를 사용하기 때문에 /prduct/delete라우트 경로를 가짐
    router.delete('/delete',function(req,res){
        res.send('/prduct/delete 라우트');
    });

    module.exports = router;

     

    const express = require('express');
    const customerRoute = require('./routes/customer'); //customer라우트 추가
    const productRoute = require('./routes/product'); //product라우트 추가
    const app = express();

    app.use(express.json({
        limit: '50mb'
    }));

    app.listen(3000, () => {
        console.log('Server started. port 3000');
    });

    app.use('/customer', customerRoute);
    app.use('/product', productRoute);

     

    서버 테스트 결과는 접은 글 참고

    더보기
    app . use ( '/customer' ,&nbsp; customerRoute );
    router.post('/insert',function(req,res){ res.send('/customer/insert 라우트'); });

    ...그 외 나머지 루트도 동일한 방법으로 서버 확인 가능

    app . use ( '/product' ,&nbsp; productRoute );
    router.post('/insert',function(req,res){ res.send('/prduct/insert 라우트'); });

    ...그 외 나머지 루트도 동일한 방법으로 서버 확인 가능

     

    7.3 에러 처리하기

    웹 서버 구축 시, 에러 처리는 필수는 아니지만 넣어주는것이 좋다. 웹에서 어떻게 에러가 나는지 클라이언트에게 알려주면 그것을 보고 에러를 처리할 수 있기 때문에 효율적임.

    const express = require('express')
    const app = express()
    const port = 3000
    
    app.get('/error',function(req, res){
        throw new Error('에러 발생')
        //리우트에서 에러가 발생하면 익스프레스가 알아서 이를 잡아 처리함.
        // 클라이언트로 500 에러코드와 에러 정보를 전달합니다. 
    })
    
    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

    const express = require('express')
    const app = express()
    const port = 3000
    
    app.use(function(err, req, res, next){
        res.status(500).json({statusCode:res.statusCode, errMessage:err.message})
    })
    
    app.get('/error2',function(req, res, next){
        next(new Error('에러발생'));
    });
    
    app.listen(port,() => {console.log(`서버가 실행됩니다. http://localhost:${port}`) })

     

    실습. Express 모듈2 - response

    const express = require('express');
    
    const app = express();
    
    app.get('/',(request, response) => {
        const result = [];
        const multipleNumber = 9;
        for(let i = 1; i < 5; i++){
            result.push({
                number: `${multipleNumber}X${i}`,
                multipe: multipleNumber * i,
            });
        }
        response.send(result);
    });
    
    app.get('/error', (request, response) => {
        response.status(404).send('404 ERROR');
    });
    
    app.listen(4000, () => {
        console.log('Server is running port 4000!')
    });

    Server is running port 4000!

     

     

     

    7.4 정적파일 제공하기

    이미지, CSS, 자바스크립트 파일과 같은 정적 파일을 제공하려면 위에서 그랬듯, 폴더 안의경로나 파일을 지정해주면 URL 로 불러와서 웹브라우저를 통해 보여준다. 

     

    7.5 미들웨어 모듈

    파비곤 제공, HTTP 요청로그를 남기거나 응답 시간을 기록하는 등, 요청과 응답 중간에 목적에 맞게 특정 기능을 하는 함수, 종류를 살펴보고 넘어갔다. 

     

    7.5.1 body-parser

    body-parser 는 구문을해석해서 req.body 속성으로 사용하게 해 주는미들웨어로, 모듈을 쓰기 위해서는 터미널에서 npm install body-parser  인스톨로 명령어를 설치해야한다. (교재로 읽고 넘어감, 별도로 코드를 작성 하지 않았다. )


     

    슬슬 프로젝트 주제를 잡아야 할 필요가 있다. 지금부터 대략 구상을 해야 늦지 않게 프로젝트를 시작, 마무리 할 수 있을 듯. 

     

Designed by Tistory.