Archive

React.js Next.js

|

React.js Next.js


  1. Next.js
    • Next.js는 리액트에서 SSR을 쉽게 구현할 수 있게 도와주는 프레임워크이다
    • SSR(Server Side Rendering)은 서버에서 클라이언트의 브라우저에 보여줄 HTML을 미리 준비해서 응답해주는 방식으로 클라이언트의 브라우저가 자바스크립트 번들을 다운로드받아 해석하기 전에 미리 화면을 보여준다
    • CSR(Client Side Rendering)은 클라이언트의 브라우저가 자바스크립트 번들을 해석해 화면을 렌더링 하는 방식이다
    • 리액트로 만든 일반적인 SPA의 렌더링은 render() 가 실행되고 ComponentDidMount() 등의 lifeCycle 메소드를 통해 데이터를 가져와 바뀐 부분을 다시 렌더링하는 방식이다. Next.js를 사용하면 getInitialProps() 메소드로 데이터를 먼저 가져와서 한번에 렌더링을 할 수 있다. 초기 로딩속도를 향상시킬 수 있다는 뜻이다
    • 초기 콘텐츠가 비동기 처리가 많게 되면 검색엔진의 크롤러는 이를 이해할 수 없기 때문에 상위 노출은 어렵다. SSR은 초기에 pre-rendered된 화면을 보여주기 때문에 검색 엔진의 크롤러가 이해를 할 수 있다.
    • Next.js 특징으로는 다음을 뽑을 수 있다
    • 간단한 라우팅
    • 검색 엔진 최적화
    • 코드 스플라이팅
    • HMR(Hot Module Replacement)을 지원하는 웹팩 기반 환경
    • babel, Webpack 커스터마이징
  2. 코드 스플리팅

    • 일반적인 SPA 는 초기 로딩시에 모든 컴포넌트를 일괄적으로 다운로드하기에 규모가 커지면 로딩 속도는 느려지기 마련이다
    • Next.js는 pages 폴더를 지정하고 index 페이지만 우선적으로 불러와 렌더링하고 다른 페이지로 넘어가면 그 페이지만 불러오는 식이다
    • 이 과정에서 여러 컴포넌트 조각들이 끼어있더라도 해당 페이지 관련 컴포넌트들만 import하므로 모든 컴포넌트를 전부 다운받는 SPA보다 초기 로딩속도가 빠르다
  3. 기본 사용법

    • npm install –save next react react-dom
    • package.json의scripts를 변경
    • “dev”: “next”
    • “build”: “next build”
    • “start”: “next start”
    • pages 폴더 만들기 (next에서 쓰이는 폴더이므로 반드시 이름 pages로)
    • 이 폴더의 폴더 하나하나가 url이 된다
    • ex) pages/user/user.js -> /user/user
    • component 조각들은 따로 components 폴더 만들고 import해서 사용
  4. 라우팅

    • Next에서 제공하는 Link 컴포넌트를 이용
    import Link from 'next/link';
       
    <Link href='/path'><a>이동</a></Link>
    
    • Next애서 제공하는 Router를 이용
    import Router from 'next/router';
       
    <button onClick={() => Router.push('/path')}></button>
    
  5. 스타일링

    • Next에서 기본적으로 제공하는 styled-jsx를 이용
    • <style jsx> 태그 안에 중괄호+백틱 사이에 css코드를 작성
    <div>
    	<style jsx>{`
        	div {
                border: 1px solid #eee;
            }
        `}</style>
    </div>
    
  6. 에러처리

    • 에러 페이지를 커스터마이징 할 수 있다
    • pages 폴더 안에 _error.js 파일을 작성(지정된 이름 사용)
    {/* ex) pages/404/_error.js */}
       
    import React from 'react';
    import Link from 'next/link';
       
    const errorPage = () => (
      <div>
        <h1>요청한 페이지가 존재하지 않습니다</h1>
        <Link href='/'>
          <a>돌아가기</a>
        </Link>
      </div>
    );
       
    export default errorPage;
    
  7. Lifecycle

    • getInitialProps(context) {} -> 클래스 방식
    • pageName.getInitialProps = context => {} -> 함수형 방식
    • CSR에서 렌더링이 된 후 componentDidMount 등으로 fetching을 하는 것과 달리 Next에서는 getInitialProps를 이용해 사전에 fetching 작업을 할 수 있다
    • Next ver 9.0 이상에서는 getInitialProps 대신 getStaticProps, getStaticPaths, getServerSideProps를 권장하고 있다
    • context 오브젝트는 pathname, query, asPath, req, res, err 등의 데이터를 담고 있다
    static async getInitialProps(context) {
        {/*data fetching*/}
    }
       
    pageName.getInitialProps = async context => {
        {/*data fetching*/}
    }
    



참고 자료


reactjs.org - 공식홈페이지

Udemy - React The Complete Guide

SSR 개념 이해와 Next.js로 실습까지 해보는 SSR 환경 구축하기

Next.js 제대로 알고 쓰자

nextjs.org - 공식 홈페이지

2021-02-25 TIL

|

2021-02-25 TIL


  • 오늘 한 것
    1. 학원 대면수업(15:30~22:00) JSP - 계층형 게시판 구현을 배웠다. 페이지 이동이나 이런 부분보다도 게시판 로직 자체를 이해하는데 시간이 많이 소비됐다. 내일 배울 페이징도 어렵겠지
    2. 리액트 Next.js - 서버사이드 렌더링을 쉽게 구현해주는 Next에 대해서 배웠다. Next를 사용하니 라우팅도 꽤나 간단히 되는것 같다. Next를 배우다가 CRA를 쓰지 않고 프로젝트를 빌드하는 연습을 해야겠다고 느꼈다. 실무에서 CRA를 쓴다는 보장도 없고 웹팩이나 바벨 같은 플로그인들을 설정하는 것은 아직 해본적도 없고 이 부분은 꽤나 중요하기에 한 번 짚고 넘어갈 필요가 있을 것이다.



  • 내일 할 것
    1. 리액트 공부
    2. 학원 대면수업(15:30~22:00) JSP - 게시판



  • 끝으로

알고리즘을 코드에 적용하는것보다 알고리즘 자체를 짜는것은 음.. 뭐랄까… 매우 어렵다..

공통되는 부분을 빼서 로직을 짜고 그것을 공식화(?)해서 하나의 알고리즘을 짜는 연습을 많이 해야겠다.

오늘의 한 줄 총평 : 기대되는 게시판2…


JSP - 계층형 게시판 로직

|

JSP - 계층형 게시판 로직


답글을 달 수 있는 계층형 게시판을 구현해보자.

답글은 댓글과는 다르게 남이 올린 글에 답변으로 새 글을 쓰는 것이다.

우선 DB 테이블을 만드는데 pk인 num은 1씩 증가하는 속성을 갖는다.

oracle의 sequence로 표현하자면 다음과 같다.

CREATE SEQUENCE board_seq --시퀀스명
	START WITH 1 -- 시작값 1
	INCREMENT BY 1 -- 증가값 1
	NOMAXVALUE -- 최대값 무한대
	NOCACHE
	NOCYCLE;

또 중요한 필드는 ref, step, depth 세 가지이다.

이 변수들은 계층형 게시판 로직의 핵심이다.

ref는 그룹이고 step은 같은 그룹 내의 순서, depth는 들여쓰기를 뜻한다.

변수를 두 개만 쓰는 방식은 게시글을 하나만 써도 전체 목록이 업데이트가 되기 때문에 DB에 부하가 걸려서 Q&A와 같이 글 수 자체가 적은 곳들 빼고는 선호되지 않는다.

게시판은 새 글을 쓰는 경우와 답글을 쓰는 경우 두 가지로 나뉜다.

먼저, 새 글을 쓰는 경우의 순서도는 다음과 같다.

  1. ref = num : 이 방식은 수정, 삭제등이 일어나면 잃어버리는 번호가 많아 기술적으로 선호되지 않는다. max(ref) + 1 : 이전 글들의 ref 중 최대값을 찾아 1을 증가시키는 방법이 선호된다. 초기값은 null
  2. step = 0, depth = 0 : 새 글은 그룹을 제외하고는 무조건 첫번째이므로 순서,들여쓰기의 초기값은 0이다.

다음은 답글을 다는 경우의 순서도이다.

  1. 원글의 ref, step, depth를 복사 : 답글을 달 원글의 ref, step, depth를 복사한다.
  2. 같은 그룹(ref)내에서 자신보다 큰 step의 값을 1 증가시킴 : 원글에 답글을 달고, 또 거기에 답글을 달고, 다시 원글에 답글을 다는 경우의 순서를 정리하기 위해 자신보다 큰 step에 1을 더해야한다.
  3. 자신의 step + 1, depth + 1 : 자신도 답글이므로 순서와 들여쓰기를 증가시킨다.

이제 코드로 이를 작성하는데 위의 로직은 DAO에서 DB에 insert 할 때 쓰인다.

먼저, 글을 작성하는 writeForm.jsp 부분이다.(자잘한 부분 생략)

<!-- writeForm.jsp -->

<%
	int num=0, ref=1, step=0, depth=0;
	try {
		if(request.getParameter("num") != null) {
			num = Integer.parseInt(request.getParameter("num"));
			ref = Integer.parseInt(request.getParameter("ref"));
			step = Integer.parseInt(request.getParameter("step"));
			depth = Integer.parseInt(request.getParameter("depth"));
		}
%>

이 writeForm은 새 글 쓰기, 답글 쓰기 두 가지 방식에서 모두 쓰이므로 새 글, 답글을 구분할 수 있어야한다. 만약 답글을 쓰기 위해 다른 곳에서 날린 HTTP request에 num 값이 있으면 원글의 num, ref, step, depth를 저장하고 아니면 ref=1을 제외한 다른 변수들은 0으로 초기화한다. 이 num값은 DAO에서 새 글인지 답글 쓰기인지 판별하는데 쓰인다. writeForm에서는 form과 input태그로 사용자가 작성한 게시글의 정보를 writeProc.jsp에 submit을 하게 된다.


<!-- writeProc.jsp -->

<jsp:useBean id="article" scope="page" class="boardone.BoardVO">
	<jsp:setProperty name="article" property="*" />
</jsp:useBean>
<%
	BoardDAO dao = BoardDAO.getInstance();
	dao.insertArticle(article);
	response.sendRedirect("list.jsp");
%>

writeProc에서는 writeForm에서 날린 게시글 관련 데이터를 VO에 담고 이를 통해 DAO의 insert 메소드를 호출해 DB에 게시글을 저장하는 기능을 한다. 작업을 마친 후 게시글 목록이 있는 list.jsp로 redirect 시킨다.


// BoardDAO.java

public void insertArticle(BoardVO article) {
		Connection conn = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
    	// 답글 1번 부분 로직
		int num = article.getNum();
		int ref = article.getRef();
		int step = article.getStep();
		int depth = article.getDepth();
		int number = 0; // 
		String sql = "";
		try {
			conn = ConnUtil.getConnection();
            // 새 글 1번 부분 로직
			pstm = conn.prepareStatement("select max(ref) from board");
			rs = pstm.executeQuery();
			if(rs.next()) {
				number = rs.getInt(1) + 1;
			} else {
				number = 1;
			}
			// 답글일 경우
			if(num != 0) {
                // 답글 2번 부분 로직
				sql = "update board set step=step+1 where ref=? and step > ?";
				pstm = conn.prepareStatement(sql);
				pstm.setInt(1,ref);
				pstm.setInt(2,step);
				pstm.executeUpdate();
                // 답글 3번 부분 로직
				step+=1;
				depth+=1;
			} else { // 새 글일 경우
                // 새 글 2번 부분 로직
				ref = number;
				step = 0;
				depth = 0;
				System.out.println("새글입니다.");
			}
			sql = "insert into board(num,subject,content,ref,step,depth) values(board_seq.nextval,?,?,?,?,?)";
			pstm = conn.prepareStatement(sql);
			pstm.setString(1, article.getSubject());
            pstm.setString(2, article.getContent());
			pstm.setInt(3, ref);
			pstm.setInt(4, step);
			pstm.setInt(5, depth);
			pstm.executeQuery();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(rs != null) try {rs.close();} catch(SQLException e) {}
			if(pstm != null) try {pstm.close();} catch(SQLException e) {}
			if(conn != null) try {conn.close();} catch(SQLException e) {}
		}
	}

앞서 설명한 계층형 게시판의 로직이 들어가는 DAO의 insert메소드이다.

writeProc에서 넘긴 VO의 게시글 데이터를 받아 num, ref, step, depth를 저장한다.(답글 1번 부분 로직)

DB에서 max(ref)를 조회하지만 최초 데이터는 없으므로 null이 반환되고 그 때는 다른 변수 number를 1로 초기화한다. 값이 있는 경우엔 제일 큰 ref에서 1을 증가시킨 값을 number에 저장한다. (새 글 1번 부분 로직)

num = 0은 새 글을 쓰는 경우이며 ref에 number 값을 대입해 그룹 번호 순서를 맞춘다. 최초의 새 글 ref = 1이 된다. 새 글이므로 모든 경우에서 step, depth는 0이 된다. (새 글 2번 부분 로직)

num != 0이면 답글을 다는 경우이며 원글의 ref를 찾아 해당 row에서 원글의 step보다 큰 step의 값을 1씩 증가시킨다. (답글 2번 부분 로직)

step과 depth를 1씩 증가시킨다. (답글 3번 부분 로직)

최종적으로 DB에 insert를 하고 자원을 반납한다.


list.jsp에서는 DB에서 게시글을 받아 렌더링을 해주면 되고 게시글을 선택하여 상세 내용을 보는 content.jsp 페이지를 만들고 그 곳에서 답글을 다는 버튼을 누르면 writeForm.jsp에 해당 원글의 num, ref, step, depth를 넘겨주게 된다.



참고 자료


KG 아이티뱅크 강의 자료

처음해보는 JSP&Servlet 웹 프로그래밍

2021-02-24 TIL

|

2021-02-24 TIL


  • 오늘 한 것
    1. 학원 대면수업(15:30~22:00) JSP - 어제 회원가입에 이어서 이번엔 로그인과 회원정보 수정, 회원탈퇴, 로그아웃 기능을 구현해보았다. 로그인 페이지에서 id,password가 담긴 form 태그를 submit하면 목표 페이지에 저장하고 DAO의 id, password 확인 메소드를 호출한다. 결과로 나온 값에 따라 로그인 성공과 실패를 판가름하고 성공시 아이디를 session에 set시킨다. 이 session에 id가 저장되어있는지 여부에 따라 다른 페이지에서 로그인 여부를 판단한다. 정보수정, 회원탈퇴도 session의 id로 DB에서 데이터를 불러오게 된다. 로그아웃은 session 자체를 없애버리면 된다.



  • 내일 할 것
    1. 리액트 공부
    2. 학원 대면수업(15:30~22:00) JSP



  • 끝으로

회원가입 끝. 이제는 게시판 만들기.

오늘의 한 줄 총평 : 회원가입 끝.


2021-02-23 TIL

|

2021-02-23 TIL


  • 오늘 한 것
    1. 학원 대면수업(15:30~22:00) JSP - 지금까지 배운 내용들을 활용해서 회원가입 페이지 만들기를 했다. 코딩양은 많지만 간단한 로직이라 잘 이해했는데 Form 태그에서 submit한 정보들이 어떻게 자바빈즈의 VO에 저장될 수 있는지가 이해되지 않았었다. 집에와서 책을 찾아봤는데 jsp의 setProperty 액션태그를 사용하면 명시되어있지는 않지만 request.getParameter()를 사용해서 VO에 set을 시키는 것과 동일한 것임을 알았다. 그래서 Form 태그에서 보낸 submit 정보들을 받아올 수 있었던 것이었다.



  • 내일 할 것
    1. 리액트 공부
    2. 학원 대면수업(15:30~22:00) JSP



  • 끝으로

안풀리면 어렵지만 풀리면 재밌고 몰랐던 내용을 아는 것이 즐겁다

오늘의 한 줄 총평 : 내일은 로그인 페이지 만들기