📝 TIL

[TIL] JSP 웹페이지 만들기(MyBatis, Member)

오늘 ONEUL 2022. 6. 17. 10:24

✍ Today I Learned

  • 지금까지 JSP의 기능에 대해 공부했다면, 이번엔 제대로 웹페이지를 만들어보자.
  • 기본 게시판 기능, 로그인/로그아웃 기능, 파일 업로드 기능, 댓글 기능 등이 포함될 예정이다.
  • MyBatis 프레임워크를 사용할 것이다.

 

[환경 설정]

  • New → Dynamic Web Project로 새로운 프로젝트를 생성한다. (Generate web.xml deplyment descriptor 체크 필수)
  • 기본으로 생성되던 주석을 삭제한다.
    Window → Prefernces → Java → Code Style → Code Templates에서 Code에 있는 주석 부분을 전부 지워준다.

 

[web.xml 설정]

  • WEB-INF 폴더에 web.xml 파일을 만들고 다음과 같이 작성한다.
  • 이번엔 web.xml에서 Controller와 servlet의 맵핑을 설정하지 않고, WebServlet annotation을 이용할 것이다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>04_final_jsp_crud</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>log4j2Config</param-name>
    <param-value>/WEB-INF/log4j2.xml</param-value>
  </context-param>
  <context-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </context-param>
</web-app>

 

[context.xml 설정]

  • Servers → Tomcat → contex.xml 파일에 추가했던 Resource 부분을 주석 처리한다. (Mybatis를 사용할 예정)

 

[라이브러리 설정]

  • 새롭게 설치할 라이브러리는 5개이다.
  • 저번에 다운받은 라이브러리까지 총 9개의 라이브러리를 장착시켜준다.

lib 폴더에 장착

 

[데이터베이스 구조]

  • 데이터 베이스에 생성할 테이블은 다음과 같다
    • memeber - 회원
    • board - 게시판
    • comment - 댓글

 

[프로젝트 구조]

  • 저번과 비슷하게 src/mian/java 폴더에 6개의 패키지를 생성한다.
  • mapper패키지에는 SQL문을 작성한 xml 파일들이 담기게 된다.(MyBatis)

 

[MyBatisConfig.xml 설정]

  • MyBatis 공식문서를 참고하여 orm 패키지에 config를 작성한다.
  • 후에 작성할 mapper 파일의 위치를 미리 정의해둔다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="domain.MemberVO" alias="mvo"/>
</typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/jspdb"/>
        <property name="username" value="jspuser"/>
        <property name="password" value="mysql"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="mapper/memberMapper.xml"/>
  </mappers>
</configuration>

 

[DataBaseBuilder.java 설정]

  • SqlSessionFactory 타입의 factory를 리턴하는 getFactory 메서드를 생성한다.
  • static 블록에서 SqlSessionFactoryBuiler를 이용해 factory 값을 설정한다.
package orm;

import java.io.IOException;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DataBaseBuilder {
    private static Logger log = LoggerFactory.getLogger(DataBaseBuilder.class);
    private static SqlSessionFactory factory;

    static {
        try {
            factory = new SqlSessionFactoryBuilder()
                    .build(Resources.getResourceAsReader("orm/MybatisConfig.xml"));
        } catch (IOException e) {
            log.info(">>> Mybatis configuration Error");
            e.printStackTrace();
        }
    }
    public static SqlSessionFactory getFactory() {
        return factory;
    }
}

 

[DB schema.sql]

  • src > main > webapp > resources 폴더에 schema.sql 파일을 생성한다.
  • member, board, comment 테이블과 각 컬럼을 생성한다.
  • 개발 전에 pk - fk 관계를 설정하면 개발할 때 수정, 삭제 테스트에 제한이 있으므로 개발 후 수정 및 삭제 기능에 이상이 없는지 테스트하고 관계 설정을 추가하여 최종 테스트 후에 완료하는 것이 효율적이다.

 

[부트스트랩 템플릿 이용]

  • 효율성을 위해 프론트엔드쪽은 부트스트랩 템플릿을 이용해보자. 부트스트랩 5를 이용하는 무료 템플릿 중 로그인폼, 회원가입 폼, 리스트 폼(게시판용)이 있는 템플릿을 선택했다. (부트스트랩 무료 템플릿)

 

[JSP 페이지 영역 분리]

  • 부트스트랩 템플릿의 부분 부분을 사용하여 header, footer로 나누고, 편리한 사용을 위해 템플릿으로 설정한다.
  • 페이지 내 a 태그의 이동경로는 모두 "/"로 변경한다.
  • jsp 템플릿으로 index.jsp를 생성한다.

 

[톰캣 서버 설정]

  • 톰캣 서버에 이전 프로젝트는 Remove 하고 현재 프로젝트를 Add 한다.
  • 톰캣 서버 더블 클릭 → Modules로 이동하여 Path를 "/"로 설정한다. (/는 루트를 의미한다.)

 

[MemberVO.java]

  • 가장 먼저 member 관련 기능을 구현해보자.
  • join, modify, login 상황별 생성자를 만들고 getter, setter를 생성한다.
  • detail은 따로 생성하지 않는다.

 

[REST API]

  • REST란? Representational State Transfer의 약자로 자원의 이름을 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미한다.
    • HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고,
    • HTTP Method(POST, GET, PUT, DELETE)를 통해
    • 해당 자원(URI)에 대한 CRUD Operation을 적용하는 것!
  • REST API란? REST의 원리를 따라 HTTP 프로토콜을 활용한 소프트웨어 개발 아키텍처의 한 형식을 의미한다. 최근 플랫폼의 형태가 다양해지면서 멀티 디바이스의 통신에 대응해야 했기 때문에 REST API가 등장하게 되었다.
  • REST API 설계를 위한 규칙은 다음과 같다.
    • URI는 동사보다 명사를, 대문자보다 소문자를 사용한다.
    • URI 마지막 문자로 슬래시(/)를 포함하지 않는다.
    • 언더바 대신 하이픈을 사용한다.
    • 파일 확장자는 URI에 포함하지 않는다.
    • 행위를 포함하지 않는다.
  • RESTful API란? REST API의 설계 규칙을 올바르게 지킨 시스템을 의미한다.
  • JSP에서 RESTful을 완벽하게 구현하기에는 어려움이 있다.

 

[MemberCtrl.java]

  • Controller는 class가 아닌 servlet으로 생성한다. URL mappings는 /mem/*로 설정하고, doPost(), doGet(), service() 메서드를 선택한다.
  • service()에 모든 로직을 작성한다. 먼저 request와 response객체를 UTF-8로 인코딩하고, path 경로를 추출하여 switch문을 작성한다.
  • action은 따로 만들지고 않고 controller에 로직을 처리한다.
  • 각 switch case에서 역할을 수행하고, RequestDisptcher 클래스를 이용해 destPage로 데이터를 전달한다.
  • 모든 경로는 절대 경로로 설정한다.

 

[MemberDAO]

  • 설정해둔 빌더를 이용해 SqlSession을 생성한다.
  • SqlSession에서 제공하는 메서드를 통해 DB를 조작할 수 있다. 메서드의 첫 번째 파라미터는 실행시킬 쿼리의 주소 값을 작성해야 한다.
package repository;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import domain.MemberVO;
import orm.DataBaseBuilder;

public class MemberDAOImpl implements MemberDAO {
    private static Logger log = LoggerFactory.getLogger(MemberDAOImpl.class);
    private SqlSession sql;
    private final String NS = "MemberMapper."; // NS = NAMESAPCE 내가 정한 공간 이름

    public MemberDAOImpl() { // 싱글톤 패턴
        new DataBaseBuilder();
        sql = DataBaseBuilder.getFactory().openSession();
    }

    @Override
    public int insert(MemberVO mvo) {
        int isUp = sql.insert(NS+"reg", mvo); // 첫번째 파라미터는 내가 실행시킬 쿼리의 주소값
        if(isUp > 0) {
            sql.commit(); // DB에 변경사항이 있다면 커밋 명령어를 작동시켜야 함
        }
        return isUp;
    }
}

 

[memberMapper.xml]

  • 클래스나 인터페이스를 제외한 나머지의 파일 이름은 가급적 소문자로 시작하는 것이 좋다.
  • MyBatis 공식문서를 참고하여 mapper 패키지에 memberMapper.xml을 생성하고 member에 관한 쿼리를 작성한다.
  • DAOImpl에서 작성했던 namespace="MemberMapper"를 그대로 작성하고, 각 쿼리에 id를 지정한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="MemberMapper">
  <insert id="reg" parameterType="mvo">
    insert into member (email, pwd, nick_name)
    values (#{email}, #{pwd}, #{nick_name})
  </insert>
</mapper>

 

[CRUD, 로그인/로그아웃 기능 구현]

  • 여태까지 했던 방식으로 member에 관한 CRUD를 구현하고, 저번 시간에 배운 Session을 이용하여 로그인/로그아웃 기능을 구현하였다.
  • 권한에 따라 다르게 보이는 화면도 모두 처리해주었다.
    • 로그인 후, 로그인 버튼 로그아웃으로 변경
    • 로그인 후, 화면에 회원 email, nick_name, grade 출력
    • 로그인 후, 본인의 nick_name을 클릭하면 회원 수정 페이지로 이동
    • 회원가입 성공 → 로그인 페이지로 이동하면서 성공 메시지
    • 회원 수정 성공 → 회원 리스트 페이지로 이동하면서 성공 메시지
    • 회원 탈퇴 성공 → 회원 리스트 페이지로 이동하면서 성공 메시지
    • 로그아웃 성공 → 인덱스 페이지로 이동하면서 성공 메시지
    • 로그인 실패 → 인덱스 페이지로 이동하면서 실패 메시지

 

  • 한참을 찾아 헤매던 에러는 역시 오타였다😂 특히나 쿼리문에서의 오타는 치명적이기 때문에 주의 또 주의하자!