20211201 게시판의 리스트 페이지

DUUUPPAAN·2021년 12월 1일
0

20211122 WAS(TOMCAT), JSP

목록 보기
8/10

·리스트 페이지

-오늘은 리스트 페이지에 작성된 글에 대한 정보를 뿌려주는 코드를 작성했다.

-우선 리스트 페이지에 작성된 글을 보여주려면, 작성된 글이 저장되어 있는 DB의 정보를 가져와야 하고, DB에서 정보를 가져온다는 것은 곳 쿼리문을 작성해서 데이터를 가져와야 한다는 것을 의미한다.

-오전 수업을 거의 쿼리문에 할애했다고 봐도 무방할 정도로 긴 쿼리였다.

SELECT          
                BBS_SEQ,
                USER_ID,
                BBS_NAME,
                BBS_EMAIL,
                BBS_PWD,
                BBS_TITLE,
                BBS_CONTENT,
                BBS_READ_CNT,
                REG_DATE
  FROM (SELECT  ROWNUM AS RNUM,
                BBS_SEQ,
                USER_ID,
                BBS_NAME,
                BBS_EMAIL,
                BBS_PWD,
                BBS_TITLE,
                BBS_CONTENT,
                BBS_READ_CNT,
                REG_DATE
  FROM (SELECT
                A.BBS_SEQ AS BBS_SEQ,
                NVL(B.USER_ID, '') AS USER_ID,
                NVL(B.USER_NAME, '') AS BBS_NAME,
                NVL(B.USER_EMAIL, '') AS BBS_EMAIL,
                NVL(A.BBS_PWD, '') AS BBS_PWD,
                NVL(A.BBS_TITLE, '') AS BBS_TITLE,
                NVL(A.BBS_CONTENT, '') AS BBS_CONTENT,
                NVL(A.BBS_READ_CNT, 0) AS BBS_READ_CNT,
                NVL(TO_CHAR(A.REG_DATE, 'YYYY.MM.DD HH24:MI:SS'), '') AS REG_DATE
         FROM 
              TBL_BOARD A, TBL_USER B
        WHERE A.USER_ID = B.USER_ID
          AND B.USER_NAME LIKE '%용%'
          AND A.BBS_TITLE LIKE '%te%'
          AND DBMS_LOB.INSTR(A.BBS_CONTENT, 'te') > 0
        ORDER BY A.BBS_SEQ DESC))
WHERE RNUM >= 1 
  AND RNUM <= 5
;

-여기서 몇가지 짚고 넘어갈 부분에 대해서 나열하도록 하겠다.
-우선 인라인 뷰를 두번 사용해서 총 3개의 SELECT문이 한 쿼리 안에 존재한다. 처음 값을 가져오는 쿼리문은 NVL에 대한 처리까지 해주고, 유저 아이디와 이름, 이메일은 유저 테이블의 값을 사용할 것이기 때문에 유저 아이디를 통해서 보드 테이블과 유저 테이블을 조인을 해준다. 페이지에는 검색을 하는 부분이 있고, 작성자이름, 제목, 내용을 검색해서 결과를 가져올 수 있게 해줘야한다. 그래서 where 절에 각각 이름, 제목, 내용을 가져올 쿼리문을 작성해줬다. 물론, 위의 값들은 일단 시험해보기 위해서 현재 테이블과 매치되도록 넣은 값이다. 나중에 자바에서는 전부 ?를 줘서 값들을 넣어줄 것이다. 추가적으로 게시글은 보통 게시글 번호의 역순으로 페이지에 보여지기 때문에, 즉, 나중에 작성한 게시글이 먼저 보이는 구조이기 때문에 ORDER BY를 통해 BBS_SEQ값을 내림차순 정렬한다. 그리고 내용에 대한 BBS_CONTENT는 CLOB타입의 변수이고 CLOB 타입의 변수는 오라클에서 제공하는 메소드를 통해 내용에 특정 단어나 내용이 포함되어 있는지 검색하는 함수가 있어서 해당 함수를 사용했다. 그리고 나서는 그렇게 검색된 데이터에서 또 다시 ROWNUM이란 값을 추가한 값들을 SELECT한다.

-우선 ROWNUM은 오라클에서 기본적으로 제공하는 것이며, 메모리에 데이터가 올라가면 그 순간 ROWNUM이 매겨진다. 그런데 왜 굳이 첫 인라인뷰에서 사용하지 않고 밖에서 사용했냐하면, ROWNUM이 매겨지는 순서 때문이다. ROWNUM은 앞서 언급했듯이 메모리에 데이터가 올라가는 순간 매겨진다. 그리고 ORDER BY는 데이터가 메모리에 올라가고 나서 특정 조건에 따라 정렬한다. 즉, ORDER BY를 하는 시점에 이미 ROWNUM은 매겨져 있고, ORDER BY를 하는 순간 ROWNUM의 순서는 뒤죽박죽이 된다.(물론 아닐 수도 있지만 그럴 가능성이 매우매우 높다.) 그래서 먼저 원하는 데이터를 메모리에 올리고 BBS_SEQ를 기준으로 내림차순 정렬을 한 후에 다시 해당 테이블을 SELECT해서 ROWNUM값을 차례로 매겨준다. 그렇게되면 ROWNUM의 1번에 해당하는 값에는 가장 큰 BBS_SEQ값이 매칭되게 된다. 여기서 ROWNUM에 ALIAS를 준 이유는 바로 이 인라인 뷰를 가지고 또 SELECT한 것을 다시 인라인 뷰로 사용해서 밖에서 또 SELECT를 해줄 것이기 때문이다. 만약 ROWNUM에 알리아스 RNUM을 주지 않는다면 밖에서 호출한 ROWNUM은 밖의 테이블의 ROWNUM이 되어버린다. 그럼 왜 굳이 안에서 안쓰고 또 한번의 인라인 뷰를 썼냐하면, 일단 데이터 전체를 불러와서 몇번부터 몇번 게시글을 보여줄지를 JAVA에서 결정하게 하기 위해서이다. 만약 세번째 SELECT가 없다면 매번 다른 페이지를 보여줄 때마다 쿼리문을 작성해야 한다. 그래서 한번 더 인라인 뷰로 사용해서 WHERE에 조건을 주는 것이다.

-BOARD.JAVA에도 페이징을 위한 새로운 변수를 다시 선언해주었다. 물론 이 변수는 아직 제대로 적용을 하지 않았기 때문에 어떻게 쓰일지는 현재로써는 불명확하지만 아마도 게시물의 처음과 마지막 값을 얻어오는 용도일 것이라 생각된다.

	private long startRow; //시작 rownum
	private long endRow; //끝 rownum

-당연히 생성자에도 초기화를 해주는 코드를 작성한다.

public Board() 
	{
    ...
    	startRow = 0;
		endRow = 0;
	}

-GETTER와 SETTER도 private로 선언했기 때문에 정의해줘야 다른 클래스에서도 해당 변수에 대한 접근이 가능하다.

이제 BoardDao에 가서 쿼리문에 대한 메소드를 만들어준다.

DAO의 메소드

-우선 해당 메소드를 작성하기에 앞서 생각해야 될 부분이 있다. 얻어올 값, 즉 리턴 값이 무엇이어야 할까? 만약 게시글 하나만 얻어온다면 Board타입의 객체일 것이다. 그러나 게시글이 하나가 아니라 하나 이상이기 때문에(물론 검색어에 따라서 하나만 오는 경우도 있겠지만 검색어가 없는 경우 DB의 모든 게시글을 전부 가져와야 하기 때문에) Board객체를 여러개 담을 또 다른 객체가 필요하다. 그래서 바로 List의 ArrayList를 활용한다. 사실, 교수님이 나중에 게시판을 만들면서 ArrayList에 대해 강의를 해주신다고 하셨는데, 오늘 정말정말 짧게 바짝해주셨다. 하지만, 나는 이전에 조금 여유로울 때 ArrayList에 대한 공부를 스스로 조금 해봤고 어느정도는 정리되어 있는 상태여서 수업이 굉장히 수월했다. 역시, 미리 공부하길 잘했다는 생각이 든다.
그래서 메소드의 리턴타입은 List<Board>가 된다. 그리고 메소드는 Board 객체를 받는데, 검색어를 줄 수도 있고 안줄 수도 있지만 그래도 줄 수 있으니 search라는 객체명을 사용해서 매개변수로 받아준다.

public List<Board> boardList(Board search)
	{
		//리턴 타입이 List라는 것은 리턴 타입이 여러개라는 것이고, 
		//한 건의 대한 것이 Board 객체, 즉 보드 객체를 여러개 리턴하겠다는 뜻.
		
		List<Board> list = new ArrayList<Board>();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sql = new StringBuilder();
		
		sql.append("SELECT  ");
		sql.append(" 		BBS_SEQ, ");
		sql.append(" 		USER_ID, ");
		sql.append(" 		BBS_NAME, ");
		sql.append("		BBS_EMAIL, ");
		sql.append(" 		BBS_PWD, ");
		sql.append(" 		BBS_TITLE, ");
		sql.append(" 		BBS_CONTENT, ");
		sql.append(" 		BBS_READ_CNT, ");
		sql.append(" 		REG_DATE ");
		sql.append("   FROM (SELECT  ROWNUM AS RNUM, ");
		sql.append("  				 BBS_SEQ,  ");
		sql.append(" 				 USER_ID, ");
		sql.append(" 				 BBS_NAME, ");
		sql.append(" 				 BBS_EMAIL, ");
		sql.append(" 				 BBS_PWD, ");
		sql.append(" 				 BBS_TITLE, ");
		sql.append(" 				 BBS_CONTENT, ");
		sql.append(" 				 BBS_READ_CNT, ");
		sql.append(" 				 REG_DATE ");
		sql.append(" 		 FROM (SELECT  ");
		sql.append(" 			 			A.BBS_SEQ AS BBS_SEQ,  ");
		sql.append(" 						NVL(B.USER_ID, '') AS USER_ID, ");
		sql.append(" 						NVL(B.USER_NAME, '') AS BBS_NAME, ");
		sql.append(" 						NVL(B.USER_EMAIL, '') AS BBS_EMAIL, ");
		sql.append(" 						NVL(A.BBS_PWD, '') AS BBS_PWD, ");
		sql.append(" 						NVL(A.BBS_TITLE, '') AS BBS_TITLE, ");
		sql.append(" 						NVL(A.BBS_CONTENT, '') AS BBS_CONTENT, ");
		sql.append(" 						NVL(A.BBS_READ_CNT, 0) AS BBS_READ_CNT, ");
		sql.append(" 						NVL(TO_CHAR(A.REG_DATE, 'YYYY.MM.DD HH24:MI:SS'), '') AS REG_DATE ");
		sql.append(" 				FROM 	TBL_BOARD A, TBL_USER B ");
		sql.append(" 				WHERE 	A.USER_ID = B.USER_ID ");
		
		//조건에 따라 append되게 하기 위해서 여기서 조건문을 줌.
		//%를 넣을 때 ''로 감싸고, ||연산자를 통해 붙여줌.
		if(search != null) 
		{
			if(!StringUtil.isEmpty(search.getBbsName())) 
			{
				sql.append(" 				AND 	B.USER_NAME LIKE '%' || ? || '%' ");			
			}
			
			if(!StringUtil.isEmpty(search.getBbsTitle())) 
			{
				sql.append(" 				AND 	A.BBS_TITLE LIKE '%' || ? || '%' ");			
			}
			
			if(!StringUtil.isEmpty(search.getBbsContent())) 
			{
				sql.append(" 				AND 	DBMS_LOB.INSTR(A.BBS_CONTENT, ?) > 0	");			
			}			
		}
		
		
		sql.append(" 			ORDER BY 	A.BBS_SEQ DESC)) ");
		//sql.append(" WHERE 	RNUM >= ? ");
		//sql.append(" AND 	RNUM <= ? ");

		
		try 
		{
			//검색조건 자체가 없는 경우도 있음. idx를 잘 사용해야 함
			int idx = 0;
			conn = DBManager.getConnection();
			pstmt = conn.prepareStatement(sql.toString());
			
			if(search != null) 
			{
				//검색조건이 있다는 애기.
				if(!StringUtil.isEmpty(search.getBbsName())) 
				{
					//검색 이름값이 있으면
					pstmt.setString(++idx, search.getBbsName());
				}
				
				if(!StringUtil.isEmpty(search.getBbsTitle())) 
				{
					//검색 제목이 있으면
					pstmt.setString(++idx, search.getBbsTitle());
				}
				
				if(!StringUtil.isEmpty(search.getBbsContent())) 
				{
					//검색 내용이 있으면
					pstmt.setString(++idx, search.getBbsContent());
				}
				//startRow와 endRow는 공통모듈에서 페이징해서 curPage를 매개변수로 넘김.
				//검색 조건이 null만 아니면 아래의 시작 숫자와 끝 숫자는 그냥 따라옴.
				//pstmt.setLong(++idx, search.getStartRow());
				//pstmt.setLong(++idx, search.getEndRow());
				//아직 공통모듈을 통해 위의 값을 받지 않았으니 주석처리하자. 안그럼 검색 결과가 없음
			}
			
			rs = pstmt.executeQuery();
			
			//다음 값의 데이터가 있을 때까지 실행되도록 while문 사용
			while(rs.next()) 
			{
				//.next()가 있으면 값이 있음
				Board board = new Board();
				
				//건건이 데이터를 다 얻어와서 넣어줌.
				//NVL처리를 해줌. db에서 null처리를 해줬지만, java에서도 해줌 
				//StringUtil클래스에 nvl처리에 대한 메소드가 정의되어 있음
				//long하고 int는 숫자로 0이 오기 때문에 상관이 없음.
				board.setBbsSeq(rs.getLong("BBS_SEQ"));
				board.setUserId(StringUtil.nvl(rs.getString("USER_ID")));
				board.setBbsName(StringUtil.nvl(rs.getString("BBS_NAME")));
				board.setBbsEmail(StringUtil.nvl(rs.getString("BBS_EMAIL")));
				board.setBbsPwd(StringUtil.nvl(rs.getString("BBS_PWD")));
				board.setBbsTitle(StringUtil.nvl(rs.getString("BBS_TITLE")));
				board.setBbsContent(StringUtil.nvl(rs.getString("BBS_CONTENT")));
				board.setBbsReadCnt(rs.getInt("BBS_READ_CNT"));
				board.setRegDate(StringUtil.nvl(rs.getString("REG_DATE")));

				
				//ArrayList 객체에 데이터를 하나씩 담아서 리턴함.
				list.add(board);
			}
			
		}
		catch(SQLException e) 
		{
			logger.error("[BoardDao] boardList SQLException", e);
		}
		finally 
		{
			DBManager.close(rs, pstmt, conn);
		}
		
		return list;
	}  

코드가 굉장히 길다. 초반에는 비슷한 듯 싶지만, 우선 쿼리문의 조건 부분에 if문으로 각각의 상황에 맞게 처리해줘야 한다. 만약 페이지에서 해당 메소드를 사용하려고 보낸 search에 작성자 이름이 있다면 WHERE USER_NAME LIKE '%' || ? || '%'의 부분이 실행이 되어야 하지만, 아닐 경우 해당 WHERE절은 실행이 되면 안된다. 그래서 각각 작성자 이름, 제목, 내용에 대한 예외처리를 해준다. 그리고 원래라면 RNUM에 getStartRow()와 getEndRow()를 통해서 값을 넣어주는 처리를 했어야 했는데 시간관계상 하지 못했기에 해당 부분을 잠시 주석처리해놨다. 이제, 쿼리문을 실행할 때, PreparedStatement의 객체인 pstmt에 값을 세팅해줄 때, 위의 쿼리문에서 조건을 준 것과 마찬가지로 조건을 줘서 값을 세팅해줘야 한다. 왜냐하면 작성자 이름의 값이 없는데, 작성자 이름이 들어가는 ?에 값을 세팅해줄 수 없다. 왜냐하면 해당 쿼리문은 if문에 의해서 없어진 것이나 다름 없으니까. 그렇게 ResultSet 객체에 쿼리를 실행해서 결과를 담으면, 전에는 if문으로 값을 얻어왔지만, 이제는 여러개의 Board 객체를 얻어왔기 때문에 반복문을 사용한다. 반복문의 조건은 rs.next()가 참일때까지, 즉, rs에 다음 값이 없을때까지 돌라는 것이다.
또한 각각의 Board에 각 값을 rs의 get메소드를 통해서 해당 알리아스 값을 가져와서 매칭되는 Board객체의 변수에 넣어준다. 또한 값을 다 넣어준 board를 list에 넣어준다. list.add(board);로 간단하게 넣어줄 수 있다. 그리고 board가 매 반복문마다 선언되니까 똑같은 변수가 선언되고 똑같은 변수가 리스트에 들어가는 것이 아니냐고 생각할 수 있지만, 애초에 list에 들어가는 것은 해당 변수가 아니라 변수가 가진 주소값이라고 생각하면 이해가 된다. 그리고 해당 list객체를 리턴해주면 쿼리문 작성이 끝이난다.

-하지만 총 게시물 수에 대한 값도 필요하기 때문에 쿼리를 하나 더 작성해야 한다.

--전체 건수 조회
       SELECT   COUNT(A.BBS_SEQ) AS TOTAL_COUNT
         FROM   TBL_BOARD A, TBL_USER B
        WHERE   A.USER_ID = B.USER_ID
          AND   B.USER_NAME LIKE '%용%'
          AND   A.BBS_TITLE LIKE '%te%'
          AND   DBMS_LOB.INSTR(A.BBS_CONTENT, 'te') > 0;

-굳이 BBS_SEQ에 COUNT를 걸어서 가져오는 이유는 를 하면 테이블 풀스캔이지만, PK를 사용하면 INDEX를 타기 때문에, 굉장히 빠르게 전체 건수를 얻어올 수 있기 때문이다.
-건수 전체를 불러올 때
보다 PK를 사용해야 하는 이유이다.

	public long boardTotalCount(Board search) 
	{
		long totalCount = 0;
	
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuilder sql = new StringBuilder();
		
		sql.append("SELECT   	COUNT(A.BBS_SEQ) AS TOTAL_COUNT ");
		sql.append(" FROM   	TBL_BOARD A, TBL_USER B ");
		sql.append(" WHERE   A.USER_ID = B.USER_ID ");
		
		if(search != null) 
		{
			//search가 null이 아닐 때, 즉 검색 조건이 있을 때!
			//이건 쿼리문 생성을 위한 조건문이고 아래는 다름.
			if(!StringUtil.isEmpty(search.getBbsName())) 
			{
				sql.append(" AND   B.USER_NAME LIKE '%' || ? || '%' ");				
			}
			if(!StringUtil.isEmpty(search.getBbsTitle())) 
			{
				sql.append(" AND   A.BBS_TITLE LIKE '%' || ? || '%' ");				
			}
			if(!StringUtil.isEmpty(search.getBbsContent())) 
			{
				sql.append(" AND   DBMS_LOB.INSTR(A.BBS_CONTENT, ?) > 0 ");							
			}
		}
		
	    try 
	    {
	    	int idx = 0;
	    	conn = DBManager.getConnection();
	    	pstmt = conn.prepareStatement(sql.toString());
	    	
	    	
	    	if(search != null) 
	    	{
	    		//위에는 쿼리문 생성을 위한 조건문이고
	    		//지금은 값을 넣어주기 위한 것임.
	    		if(!StringUtil.isEmpty(search.getBbsName())) 
	    		{
	    			pstmt.setString(++idx, search.getBbsName());
	    		}
	    		
	    		if(!StringUtil.isEmpty(search.getBbsTitle())) 
	    		{
	    			pstmt.setString(++idx, search.getBbsTitle());
	    		}
	    		
	    		if(!StringUtil.isEmpty(search.getBbsContent())) 
	    		{
	    			pstmt.setString(++idx, search.getBbsContent());
	    		}
	    	}
	    	
	    	rs = pstmt.executeQuery();
	    	
	    	if(rs.next()) 
	    	{
	    		//TOTAL_COUNT의 값을 가져와야 함. ALias를 준 값을 가져와야 함.
	    		totalCount = rs.getLong("TOTAL_COUNT");
	    	}
	    	
	    	logger.debug("totalCount : " + totalCount);
	    	
	    }
	    catch(SQLException e) 
	    {
	    	logger.error("[BoardDao] boardTotalCount SQLException", e);
	    }
	    finally 
	    {
	    	DBManager.close(rs, pstmt, conn);
	    }
	    
	    
		return totalCount;
	}

-전체 데이터 건수도 조건에 따라 달라질 수 있기 때문에 조건절에 if문을 걸어준다. 값을 넣어줄 때도 해당 조건과 똑같이 값을 넣어줄 수 있도록 매칭해준다. 이렇게까지 하면 dao에서 만들어줄 쿼리문은 끝이 났다. 이제 기존에 하드코딩해서 디스플레이했던 list의 html과 해당 html을 jsp문법을 통해 변경하는 코드를 작성한다.

우선 request 객체에서 searchType과 searchValue curPage를 얻어온다. 이 세 값은 현재 페이지에 있는 값인데 왜 얻어오냐 싶을 수 있지만, 1페이지에서 2페이지를 누르거나, 검색을 하면 list.jsp가 또 list.jsp를 호출하는 형태이기 때문에 이런식으로 request객체에서 넘겨준 값을 변수로 받아와야 한다. 단, 항상 request객체에 값이 있게 전달되는 것이 아니기 때문에 아무런 값이 없을 때의 예외처리도 해줘야 한다.

//페이지 2번을 누르거나, 검색을 하면, 또 본인이 본인을 호출해야 함. 그래서 밑의 searchType, searchValue, curPage가 필요함.
	//조회항목(1:작성자, 2:제목, 3:내용)
	String searchType = HttpUtil.get(request, "searchType", "");
	//조회값
	String searchValue = HttpUtil.get(request, "searchValue", "");
	//현재페이지
	long curPage = HttpUtil.get(request, "curPage", (long)1);
	
	Board search = new Board();
    
    if(!StringUtil.isEmpty(searchType) && StringUtil.isEmpty(searchValue))
	{
		//searchType, searchValue가 값이 있어야 처리 함
		//검색할 값을 넣었다는 뜻.
		if(StringUtil.equals(searchType, "1"))
		{
			//서치 타입이 1번 작성자이면
			//입력값인 searchValue를 작성자에 넣어줌.
			search.setBbsName(searchValue);
		}
		else if(StringUtil.equals(searchType, "2"))
		{
			//서치 타입이 제목이면
			search.setBbsTitle(searchValue);
		}		
		else if(StringUtil.equals(searchType, "3"))
		{
			//서치 타입이 내용이면
			search.setBbsContent(searchValue);
		}
		
	}
	else
	{
		//값이 비어있다면
		searchType = "";
		searchValue = "";
	}

-쿼리문을 실행하려면 BoardDao객체를 선언해줘야 한다. 또한 totalCount 변수를 통해서 실행한 결과값이 몇개인지를 얻어온다.

long totalCount = 0;
BoardDao boardDao = new BoardDao();
totalCount  = boardDao.boardTotalCount(search);

-search 객체를 매개변수로 넘긴 boardTotalCount의 결과를 totalCount에 넣어주고, 해당 값이 0이상이면, 즉, 결과가 한건이라도 조회가 된다면, boardList메소드를 실행한다

	List<Board> list = null;
	if(totalCount > 0 )
	{
		//검색 결과가 하나 이상 있음.
		//여기가 페이징 처리 추가할 곳

		list = boardDao.boardList(search);
		
	}

-결과로 리턴받는 값이 list객체이기 때문에 List객체인 list를 선언해주고 list에다가 boardList메소드의 결과를 넣어준다. 이제 이 list를 반복문을 통해 해당 반복문만큼 게시글에 대한 html을 보여주도록 해준다.

<tbody>
      <% 
    	//리스트 페이지에 보여주는 부분 작성
    	if(list != null && list.size() > 0)
    	{
    		//리스트의 값이 null이 아니고, list 객체의 크기가 0이상, 즉 board 객체가 1개 이상, 즉 결과가 하나 이상 있을 때 보여줌.
    		int i;
    		for(i = 0; i<list.size(); i++)
    		{
    			Board board = null;
    			board = list.get(i);
    			
      %>
      <tr>
         <td class="text-center"><%= board.getBbsSeq() %></td>
         <!-- 여기 onclick에 함수에 primary key인 bbsSeq를 가지고 상세페이지로 이동해야 함 -->
         <td><a href="javascript:void(0)" onclick="fn_view(<%= board.getBbsSeq() %>)"><%= board.getBbsTitle() %></a></td>
         <td class="text-center"><%= board.getBbsName() %></td>
         <td class="text-center"><%= board.getRegDate() %></td>
         <td class="text-center"><%= board.getBbsReadCnt() %></td>
      </tr>
      <%    	
    		}
    	}
      %>

Board board객체를 만들어서 해당 board 객체에 list의 i번째 값을 전부 넣어준다. 그리고 html의 해당되는 부분에 <%= %>로 각각 해당하는 값들을 넣어주면 원하는 결과만큼 페이지가 보여지게 된다.

·오늘 수업

-오늘은 굉장히 수업이 어려웠다. 비슷한거 같다가도 되게 멀어지는 난이도에 좌절하기도 하지만 또 굉장히 재밌기도 하다. 오늘은 심지어 내가 어제 코드에 대한 교수님의 실수를 잡아내기도 하고, 마지막에 결과가 뜨지 않는 이유를 찾아서 코드를 수정할 수 있도록 말씀도 드리고 했다. 내가 그렇게 할 수 있다는 것은 어느정도 코드를 이해했다고 봐도 된다 생각해서 뭔가 뿌듯했다. 실제로 교수님도 이정도면 어느정도 이해를 하고 코드를 본다고 봐도 무방한 것 같다고 하셨다. 물론 그렇다고 자만하지는 않는다. 왜냐하면 이정도 수준은 진짜 아무것도 아니기 때문이다. 집에 와서도 한참동안이나 쿼리문과 java와 jsp코드를 봤다. 내가 이걸 할 수 있을까 하는 의문도 엄청나게 들고 굉장히 의기소침해지기까지 했지만...그래도 이해는 어느정도 할 수 있게 되었다. 원래 내일은 정말 힘들어서 비대면 수업을 하는 날이기도 하고 집에서 수업을 들으려 했는데...아무래도 내일도 학원에서 대면수업을 해야할 것 같다...집중력의 차이가 심각하기 때문에... 내일도 파이팅!

profile
비전공자란 이름으로 새로운 길을 가려 하는 신입

0개의 댓글