Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags
more
Archives
Today
Total
관리 메뉴

개발자입니다

[비트캠프] 78일차(16주차5일) - myapp-51~53(서비스 객체 도입, Front controller, Page Controller) 본문

네이버클라우드 AIaaS 개발자 양성과정 1기/DBMS, SQL, JDBC, Servlet

[비트캠프] 78일차(16주차5일) - myapp-51~53(서비스 객체 도입, Front controller, Page Controller)

끈기JK 2023. 2. 24. 18:42

 

51. 서비스 객체 도입 - 비즈니스 로직 분리

 

BoardInsertServlet 에서 BoardDao 로 insert() 한다. 그리고 BoardFileDao 로 insertList() 한다. 이를 Tx 로 묶는다.

 

BoardInsertServlet 역할은

- 입력값 가공

- 업무 흐름 제어 (+트랜잭션 제어)

- 출력 제어

 

-----Dao 역할은

- 데이터 처리

 

- 회사마다 업무 흐름이 다르다.

- 업무 흐름은 자주 변경된다.

기능 변경

↓ 계속 자주 변경 → 회사마다 변경해야 한다 → Controller 에서 비즈니스 로직을 분리! 여러 서블릿이 비즈니스 로직을 재사용 할 수 있다. 서블릿 기술과 상관없이 사용할 수 있다.                                                        

업무 흐름 제어

 

BoardInsertServlet 역할

- 입력값 가공

- 출력 제어

 

BoardService  ← 서비스 객체

- 업무 흐름 제어

- 트랜잭션 제어

insert() 를 BoardDao 로 한다.

insertList() 를 BoardFileDao 로 한다.

 

 

Dao 는 데이터 처리 관련 용어를 쓰는게 좋다.

Service 는 업무 처리 관련 용어를 쓰는게 좋다.

 

 

 

51. Servlet - Service - DAO

 

(Servlet, JSP, CLI) → Service → DAO → Table 로 흐름이 갈 수 있다.

하지만 Service ↔ Service 로 흐름이 진행되면 안된다.

 

 

 

51 Service 객체 교체하기 쉽게 변경 - 인터페이스 도입

 

BoardInsertServlet 에서 《interface》BoardService 를 사용한다.

구현체로 DefaultBoardService (첨부파일 다루는 서비스), SimpleBoardServiceImpl (첨부파일을 다루지 않는 서비스) 가 사용된다.

 

 

### 51-1. Controller에서 비즈니스 로직 분리하기: 서비스 컴포넌트 도입 
- Controller에서 비즈니스 로직을 분리하는 이유  
- 서비스 컴포넌트의 역할 이해
### 51-2. 서비스 객체에 인터페이스 적용하기: 서비스 객체를 교체하기 쉽게 만들기 
- 서비스 객체에 인터페이스를 적용하는 이유와 방법

 

BoardListServlet 과 DAO 사이에 Service 객체를 생성한다.

BoardService 객체는 리스너에 생성해서 ServletContext 보관소에 저장한다.

@WebListener
public class ContextLoaderListener implements ServletContextListener {
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    try {
      InputStream mybatisConfigInputStream = Resources.getResourceAsStream(
          "bitcamp/myapp/config/mybatis-config.xml");
      SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      BitcampSqlSessionFactory sqlSessionFactory = new BitcampSqlSessionFactory(
          builder.build(mybatisConfigInputStream));

      TransactionManager txManager = new TransactionManager(sqlSessionFactory);

      BoardDao boardDao = new DaoGenerator(sqlSessionFactory).getObject(BoardDao.class);
      MemberDao memberDao = new DaoGenerator(sqlSessionFactory).getObject(MemberDao.class);
      StudentDao studentDao = new DaoGenerator(sqlSessionFactory).getObject(StudentDao.class);
      TeacherDao teacherDao = new DaoGenerator(sqlSessionFactory).getObject(TeacherDao.class);
      BoardFileDao boardFileDao = new DaoGenerator(sqlSessionFactory).getObject(BoardFileDao.class);

      BoardService boardService = new DefaultBoardService(txManager, boardDao, boardFileDao);
      StudentService studentService = new DefaultStudentService(txManager, memberDao, studentDao);
      TeacherService teacherService = new DefaultTeacherService(txManager, memberDao, teacherDao);

      // 서블릿 컨텍스트 보관소를 알아낸다.
      ServletContext ctx = sce.getServletContext();

      // 서블릿들이 공유할 객체를 이 보관소에 저장한다.
      ctx.setAttribute("boardService", boardService);
      ctx.setAttribute("studentService", studentService);
      ctx.setAttribute("teacherService", teacherService);
      
/* 후략 */

 

BoardService 인터페이스 정의한다.

package bitcamp.myapp.service;

import java.util.List;
import bitcamp.myapp.vo.Board;

public interface BoardService {
  void add(Board board);
  List<Board> list(String keyword);
  Board get(int no);
  void update(Board board);
  void delete(int no);
  void deleteFile(int fileNo);
}

 

BoardService 구현체를 생성한다.

트랜잭션 처리 및 Dao 접근을 담당한다.

public class DefaultBoardService implements BoardService {

  private TransactionManager txManager;
  private BoardDao boardDao;
  private BoardFileDao boardFileDao;

  public DefaultBoardService(TransactionManager txManager, BoardDao boardDao, BoardFileDao boardFileDao) {
    this.txManager = txManager;
    this.boardDao = boardDao;
    this.boardFileDao = boardFileDao;
  }

  @Override
  public void add(Board board) {
    try {
      txManager.startTransaction();
      boardDao.insert(board);
      if (board.getAttachedFiles().size() > 0) {
        for (BoardFile boardFile : board.getAttachedFiles()) {
          boardFile.setBoardNo(board.getNo());
        }
        boardFileDao.insertList(board.getAttachedFiles());
      }
      txManager.commit();

    } catch (Exception e) {
      txManager.rollback();
      throw new RuntimeException(e);
    }
  }

  @Override
  public List<Board> list(String keyword) {
    return boardDao.findAll(keyword);
  }

  @Override
  public Board get(int no) {
    Board b = boardDao.findByNo(no);
    if (b != null) {
      boardDao.increaseViewCount(no);
    }
    return b;
  }

  @Override
  public void update(Board board) {
    try {
      txManager.startTransaction();
      if (boardDao.update(board) == 0) {
        throw new RuntimeException("게시글이 존재하지 않습니다!");
      }
      if (board.getAttachedFiles().size() > 0) {
        boardFileDao.insertList(board.getAttachedFiles());
      }
      txManager.commit();

    }  catch (Exception e) {
      txManager.rollback();
      throw e;
    }
  }

  @Override
  public void delete(int no) {
    try {
      txManager.startTransaction();
      boardFileDao.deleteOfBoard(no);
      if (boardDao.delete(no) == 0) {
        throw new RuntimeException("게시글이 존재하지 않습니다!");
      }
      txManager.commit();

    }  catch (Exception e) {
      txManager.rollback();
      throw e;
    }
  }

  @Override
  public void deleteFile(int fileNo) {
    boardFileDao.delete(fileNo);
  }
}

 

BoardListServlet 는 Dao 는 모르고 단지 boardService.list() 를 호출 할 뿐이다.

나머지 form, insert, update, delete 또한 마찬가지이다.

@WebServlet("/board/list")
public class BoardListServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private BoardService boardService;

  @Override
  public void init() {
    boardService = (BoardService) getServletContext().getAttribute("boardService");
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setAttribute("boards",
        boardService.list(request.getParameter("keyword")));
    request.getRequestDispatcher("/board/list.jsp").forward(request, response);
  }
}
@WebServlet("/board/form")
public class BoardFormServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    request.getRequestDispatcher("/board/form.jsp").forward(request, response);
  }
}
@WebServlet("/board/insert")
public class BoardInsertServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private BoardService boardService;

  @Override
  public void init() {
    boardService = (BoardService) getServletContext().getAttribute("boardService");
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    try {
      DiskFileItemFactory factory = new DiskFileItemFactory();
      ServletFileUpload upload = new ServletFileUpload(factory);
      List<FileItem> items = upload.parseRequest(request);
      Map<String,String> paramMap = new HashMap<>();
      List<FileItem> files = new ArrayList<>();

      for (FileItem item : items) {
        if (item.isFormField()) {
          paramMap.put(item.getFieldName(), item.getString("UTF-8"));
        } else {
          files.add(item);
        }
      }

      Board board = new Board();
      board.setTitle(paramMap.get("title"));
      board.setContent(paramMap.get("content"));

      Member loginUser = (Member) request.getSession().getAttribute("loginUser");
      Member writer = new Member();
      writer.setNo(loginUser.getNo());
      board.setWriter(writer);

      List<BoardFile> boardFiles = new ArrayList<>();
      for (FileItem file : files) {
        if (file.getSize() == 0) {
          continue;
        }
        String filename = UUID.randomUUID().toString();
        file.write(new File(getServletContext().getRealPath("/board/upload/" + filename)));

        BoardFile boardFile = new BoardFile();
        boardFile.setOriginalFilename(file.getName());
        boardFile.setFilepath(filename);
        boardFile.setMimeType(file.getContentType());
        boardFiles.add(boardFile);
      }
      board.setAttachedFiles(boardFiles);

      boardService.add(board);

    } catch (Exception e) {
      e.printStackTrace();
      request.setAttribute("error", "data");
    }

    request.getRequestDispatcher("/board/insert.jsp").forward(request, response);
  }
}
@WebServlet("/board/view")
public class BoardViewServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private BoardService boardService;

  @Override
  public void init() {
    boardService = (BoardService) getServletContext().getAttribute("boardService");
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setAttribute("board",
        boardService.get(Integer.parseInt(request.getParameter("no"))));
    request.getRequestDispatcher("/board/view.jsp").forward(request, response);
  }
}
@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/board/update")
public class BoardUpdateServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private BoardService boardService;

  @Override
  public void init() {
    boardService = (BoardService) getServletContext().getAttribute("boardService");
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    try {
      Member loginUser = (Member) request.getSession().getAttribute("loginUser");

      Board board = new Board();
      board.setNo(Integer.parseInt(request.getParameter("no")));
      board.setTitle(request.getParameter("title"));
      board.setContent(request.getParameter("content"));

      Board old = boardService.get(board.getNo());

      if (old.getWriter().getNo() != loginUser.getNo()) {
        response.sendRedirect("../auth/fail");
        return;
      }

      Collection<Part> parts = request.getParts();
      List<BoardFile> boardFiles = new ArrayList<>();
      for (Part part : parts) {
        if (!part.getName().equals("files") || part.getSize() == 0) {
          continue;
        }

        String filename = UUID.randomUUID().toString();
        part.write(this.getServletContext().getRealPath("/board/upload/" + filename));

        BoardFile boardFile = new BoardFile();
        boardFile.setOriginalFilename(part.getSubmittedFileName());
        boardFile.setFilepath(filename);
        boardFile.setMimeType(part.getContentType());
        boardFile.setBoardNo(board.getNo());
        boardFiles.add(boardFile);
      }
      board.setAttachedFiles(boardFiles);

      boardService.update(board);

    }  catch (Exception e) {
      e.printStackTrace();
      request.setAttribute("error", "data");
    }

    request.getRequestDispatcher("/board/update.jsp").forward(request, response);
  }
}
@WebServlet("/board/filedelete")
public class BoardFileDeleteServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private BoardService boardService;

  @Override
  public void init() {
    boardService = (BoardService) getServletContext().getAttribute("boardService");
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    Member loginUser = (Member) request.getSession().getAttribute("loginUser");
    int boardNo = Integer.parseInt(request.getParameter("boardNo"));

    Board old = boardService.get(boardNo);
    if (old.getWriter().getNo() != loginUser.getNo()) {
      response.sendRedirect("../auth/fail");
      return;
    }

    boardService.deleteFile(Integer.parseInt(request.getParameter("fileNo")));
    response.sendRedirect("view?no=" + boardNo);
  }
}
@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/board/delete")
public class BoardDeleteServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private BoardService boardService;

  @Override
  public void init() {
    boardService = (BoardService) getServletContext().getAttribute("boardService");
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    try {
      Member loginUser = (Member) request.getSession().getAttribute("loginUser");
      int boardNo = Integer.parseInt(request.getParameter("no"));

      Board old = boardService.get(boardNo);
      if (old.getWriter().getNo() != loginUser.getNo()) {
        response.sendRedirect("../auth/fail");
        return;
      }
      boardService.delete(boardNo);

    }  catch (Exception e) {
      e.printStackTrace();
      request.setAttribute("error", "data");
    }

    request.getRequestDispatcher("/board/delete.jsp").forward(request, response);
  }
}

 

teacher, student 는 생략

 

 

 

52 Front Controller 도입

 

BoardInsertServlet, BoardListServlet, BoardViewServlet, ... 의 공통 기능을 추출하여 분리 → 《Front Controller》DispatcherServlet 을 생성한다.

DispatcherServlet 에 요청이 들어오면 각 Servlet 으로 위임한다. 그리고 forwarding 을 JSP 로 한다.

 

다른 컨트롤러 앞쪽에서 요청을 대신 받고, JSP 실행을 제어 = "Front(앞쪽) Controller"

특정 페이지의 요청 처리를 담당 = "Page Controller"

 

 

 

52 Front Controller 도입 - 가장 큰 이점?

 

《Front Controller》DispatcherServlet 에 요청한다. 모든 요청은 프론트 컨트롤러가 받는다.

여기서 Board----Servlet 으로 위임할 필요는 없다.

페이지 컨트롤러는 굳이 서블릿이 될 필요가 없다! → 페이지 컨트롤러의 관리는 별도의 객체로 분리할 수 있다.

 

 

/app/board/list 로 ① 요청 들어오면 DispatcherServlet (/app/*) 가 실행된다. 여기서 ② forward() include() (한 번 forward 되면 다른 서블릿으로 forward 할 수 없다) 를 BoardListServlet 으로 한다. 여기서 ③ 실행 하고 ④ 리턴 을 DispatcherServlet 으로 한다. ⑤ forward 를 list.jsp 로 하고 ⑥ 리턴 받아 ⑦ 응답 한다.

 

DispatcherServlet, BoardListServlet, list.jsp 모두 ServletRequest 를 공유한다.

 

 

### 52. Front Controller 디자인 패턴 도입하기 
- Front Controller 디자인 패턴의 효과 및 적용 방법

 

BoardListServlet, BoardInsertServlet, ... 각 서블릿이 요청을 받지 않고 DispatcherServlet 이 모든 요청을 받아 전달한다.

pathInfo 를 뽑아내서 .include(...) 로 다른 서블릿으로 보낸다.

@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/app/*")
public class DispatcherServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 요청 URL => http://localhost:8080/web/app/board/list
    // - Context Root: /web
    // - ServletPath: /app
    // - PathInfo: /board/list
    String pathInfo = request.getPathInfo();

    // 페이지 컨트롤러 실행
    if (pathInfo.equals("/")) {
      response.sendRedirect(request.getContextPath() + "/");
      return;
    }
    request.getRequestDispatcher(pathInfo).include(request, response);

    // 쿠키 처리
    @SuppressWarnings("unchecked")
    List<Cookie> cookies = (List<Cookie>) request.getAttribute("cookies");
    if (cookies != null) {
      for (Cookie cookie : cookies) {
        response.addCookie(cookie);
      }
    }

    String view = (String) request.getAttribute("view");

    // 뷰 컴포넌트 실행
    if (view != null) {
      if (view.startsWith("redirect:")) {
        response.sendRedirect(view.substring(9));
      } else {
        request.getRequestDispatcher(view).forward(request, response);
      }
    }
  }
}

 

 

 

 

53 Front Controller 와 Page Controller (POJO)

 

《Front Controller》DispatcherServlet 에서 《interface》PageController 구현체에게 execute 지시한다. 구현체로 BoardListController, BoardViewController, ... 가 있다.

 

Page Controller 가 직접 요청을 받지 않기 때문에 => Page Controller 를 POJO (Plain Old Java Object)로 전환

 

 

### 53. 페이지 컨트롤러를 POJO로 전환하기 
- 프론트 컨트롤러 구조에서 페이지 컨트롤러를 POJO로 전환하는 방법 
- POJO? Plain Old Java Object (그냥 일반 자바 문법으로 만든 클래스)

 

URL 주소에 해당하는 요청을 pathInfo 에 저장한 뒤 ServletContext 에서 해당하는 페이지 컨트롤러를 가져온다.

@MultipartConfig(maxFileSize = 1024 * 1024 * 50)
@WebServlet("/app/*")
public class DispatcherServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 요청 URL => http://localhost:8080/web/app/board/list
    // - Context Root: /web
    // - ServletPath: /app
    // - PathInfo: /board/list
    String pathInfo = request.getPathInfo();

    // 페이지 컨트롤러 실행
    if (pathInfo.equals("/")) {
      response.sendRedirect(request.getContextPath() + "/");
      return;
    }

    ServletContext ctx = getServletContext();

    // 클라이언트가 요청한 URL을 가지고 페이지 컨트롤러를 찾는다.
    PageController controller = (PageController) ctx.getAttribute(pathInfo);
    if (controller == null) {
      request.getRequestDispatcher("/NotFoundController.jsp").forward(request, response);
      return;
    }

    // 페이지 컨트롤러 실행
    String view = controller.execute(request, response);

    // 쿠키 처리
    @SuppressWarnings("unchecked")
    List<Cookie> cookies = (List<Cookie>) request.getAttribute("cookies");
    if (cookies != null) {
      for (Cookie cookie : cookies) {
        response.addCookie(cookie);
      }
    }

    // 뷰 컴포넌트 실행
    if (view != null) {
      if (view.startsWith("redirect:")) {
        response.sendRedirect(view.substring(9));
      } else {
        request.getRequestDispatcher(view).forward(request, response);
      }
    }
  }
}

 

페이지 컨트롤러 인터페이스 정의한다.

public interface PageController {
  String execute(HttpServletRequest request, HttpServletResponse response);
}

 

서블릿을 컨트롤러로 변경한다.

페이지 컨트롤러 구현체를 만든다.

내부적으로 작업 수행 후 jsp 주소 리턴한다.

public class LoginFormController implements PageController {

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    return "/auth/form.jsp";
  }
}

 

리스너에 페이지 컨트롤러 생성해서 보관한다.

@WebListener
public class ContextLoaderListener implements ServletContextListener {
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    try {
      InputStream mybatisConfigInputStream = Resources.getResourceAsStream(
          "bitcamp/myapp/config/mybatis-config.xml");
      SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      BitcampSqlSessionFactory sqlSessionFactory = new BitcampSqlSessionFactory(
          builder.build(mybatisConfigInputStream));

      TransactionManager txManager = new TransactionManager(sqlSessionFactory);

      BoardDao boardDao = new DaoGenerator(sqlSessionFactory).getObject(BoardDao.class);
      MemberDao memberDao = new DaoGenerator(sqlSessionFactory).getObject(MemberDao.class);
      StudentDao studentDao = new DaoGenerator(sqlSessionFactory).getObject(StudentDao.class);
      TeacherDao teacherDao = new DaoGenerator(sqlSessionFactory).getObject(TeacherDao.class);
      BoardFileDao boardFileDao = new DaoGenerator(sqlSessionFactory).getObject(BoardFileDao.class);

      BoardService boardService = new DefaultBoardService(txManager, boardDao, boardFileDao);
      StudentService studentService = new DefaultStudentService(txManager, memberDao, studentDao);
      TeacherService teacherService = new DefaultTeacherService(txManager, memberDao, teacherDao);

      LoginFormController loginFormController = new LoginFormController();
      LoginController loginController = new LoginController(studentService, teacherService);
      LogoutController logoutController = new LogoutController();
      AuthFailController authFailController = new AuthFailController();

      BoardListController boardListController = new BoardListController(boardService);
      BoardFormController boardFormController = new BoardFormController();
      BoardInsertController boardInsertController = new BoardInsertController(boardService);
      BoardViewController boardViewController = new BoardViewController(boardService);
      BoardUpdateController boardUpdateController = new BoardUpdateController(boardService);
      BoardDeleteController boardDeleteController = new BoardDeleteController(boardService);
      BoardFileDeleteController boardFileDeleteController = new BoardFileDeleteController(boardService);

      // 서블릿 컨텍스트 보관소를 알아낸다.
      ServletContext ctx = sce.getServletContext();

      // 프론트 컨트롤러가 사용할 페이지 컨트롤러를 보관한다.
      ctx.setAttribute("/auth/form", loginFormController);
      ctx.setAttribute("/auth/login", loginController);
      ctx.setAttribute("/auth/logout", logoutController);
      ctx.setAttribute("/auth/fail", authFailController);

      ctx.setAttribute("/board/list", boardListController);
      ctx.setAttribute("/board/form", boardFormController);
      ctx.setAttribute("/board/insert", boardInsertController);
      ctx.setAttribute("/board/view", boardViewController);
      ctx.setAttribute("/board/update", boardUpdateController);
      ctx.setAttribute("/board/delete", boardDeleteController);
      ctx.setAttribute("/board/filedelete", boardFileDeleteController);


    } catch (Exception e) {
      System.out.println("웹 애플리케이션 자원을 준비하는 중에 오류 발생!");
      e.printStackTrace();
    }
  }

  @Override
  public void contextDestroyed(ServletContextEvent sce) {
    // 웹 애플리케이션이 종료될 때 서블릿 컨테이너가 호출한다.
    System.out.println("ContextLoaderListener.contextDestroyed() 호출됨!");
  }
}

 

각 서블릿을 컨트롤러로 만든다.

public class LoginController implements PageController {

  private StudentService studentService;
  private TeacherService teacherService;

  public LoginController(StudentService studentService, TeacherService teacherService) {
    this.studentService = studentService;
    this.teacherService = teacherService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {

    String usertype = request.getParameter("usertype");
    String email = request.getParameter("email");
    String password = request.getParameter("password");

    if (request.getParameter("saveEmail") != null) {
      Cookie cookie = new Cookie("email", email);
      cookie.setMaxAge(60 * 60 * 24 * 30); // 30일 동안 유지
      response.addCookie(cookie);

    } else {
      Cookie cookie = new Cookie("email", "");
      cookie.setMaxAge(0);
      response.addCookie(cookie);
    }

    Member member = null;
    switch (usertype) {
      case "student":
        member = studentService.get(email, password);
        break;
      case "teacher":
        member = teacherService.get(email, password);
        break;
    }

    if (member != null) {
      HttpSession session = request.getSession();
      session.setAttribute("loginUser", member);
      return "redirect:../";
    } else {
      request.setAttribute("error", "loginfail");
      return "/auth/form.jsp";
    }
  }
}

 

public class LogoutController implements PageController {

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    request.getSession().invalidate();
    return "redirect:../";
  }
}

 

public class AuthFailController implements PageController {
  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    return "/auth/fail.jsp";
  }
}

 

public class BoardListController implements PageController {

  private BoardService boardService;

  public BoardListController(BoardService boardService) {
    this.boardService = boardService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute("boards",
        boardService.list(request.getParameter("keyword")));
    return "/board/list.jsp";
  }
}

 

public class BoardFormController implements PageController {
  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    return "/board/form.jsp";
  }
}

 

public class BoardViewController implements PageController {

  private BoardService boardService;

  public BoardViewController(BoardService boardService) {
    this.boardService = boardService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute("board",
        boardService.get(Integer.parseInt(request.getParameter("no"))));
    return"/board/view.jsp";
  }
}

 

public class BoardInsertController implements PageController {

  private BoardService boardService;

  public BoardInsertController(BoardService boardService) {
    this.boardService = boardService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    try {
      DiskFileItemFactory factory = new DiskFileItemFactory();
      ServletFileUpload upload = new ServletFileUpload(factory);
      List<FileItem> items = upload.parseRequest(request);
      Map<String,String> paramMap = new HashMap<>();
      List<FileItem> files = new ArrayList<>();

      for (FileItem item : items) {
        if (item.isFormField()) {
          paramMap.put(item.getFieldName(), item.getString("UTF-8"));
        } else {
          files.add(item);
        }
      }

      Board board = new Board();
      board.setTitle(paramMap.get("title"));
      board.setContent(paramMap.get("content"));

      Member loginUser = (Member) request.getSession().getAttribute("loginUser");
      Member writer = new Member();
      writer.setNo(loginUser.getNo());
      board.setWriter(writer);

      List<BoardFile> boardFiles = new ArrayList<>();
      for (FileItem file : files) {
        if (file.getSize() == 0) {
          continue;
        }
        String filename = UUID.randomUUID().toString();
        file.write(new File(request.getServletContext().getRealPath("/board/upload/" + filename)));

        BoardFile boardFile = new BoardFile();
        boardFile.setOriginalFilename(file.getName());
        boardFile.setFilepath(filename);
        boardFile.setMimeType(file.getContentType());
        boardFiles.add(boardFile);
      }
      board.setAttachedFiles(boardFiles);

      boardService.add(board);

    } catch (Exception e) {
      e.printStackTrace();
      request.setAttribute("error", "data");
    }
    return "/board/insert.jsp";
  }
}

 

public class BoardUpdateController implements PageController {

  private BoardService boardService;

  public BoardUpdateController(BoardService boardService) {
    this.boardService = boardService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    try {
      Member loginUser = (Member) request.getSession().getAttribute("loginUser");

      Board board = new Board();
      board.setNo(Integer.parseInt(request.getParameter("no")));
      board.setTitle(request.getParameter("title"));
      board.setContent(request.getParameter("content"));

      Board old = boardService.get(board.getNo());
      if (old.getWriter().getNo() != loginUser.getNo()) {
        return "redirect:../auth/fail";
      }

      Collection<Part> parts = request.getParts();
      List<BoardFile> boardFiles = new ArrayList<>();
      for (Part part : parts) {
        if (!part.getName().equals("files") || part.getSize() == 0) {
          continue;
        }

        String filename = UUID.randomUUID().toString();
        part.write(request.getServletContext().getRealPath("/board/upload/" + filename));

        BoardFile boardFile = new BoardFile();
        boardFile.setOriginalFilename(part.getSubmittedFileName());
        boardFile.setFilepath(filename);
        boardFile.setMimeType(part.getContentType());
        boardFile.setBoardNo(board.getNo());
        boardFiles.add(boardFile);
      }
      board.setAttachedFiles(boardFiles);

      boardService.update(board);

    }  catch (Exception e) {
      e.printStackTrace();
      request.setAttribute("error", "data");
    }

    return "/board/update.jsp";
  }
}

 

public class BoardFileDeleteController implements PageController {

  private BoardService boardService;

  public BoardFileDeleteController(BoardService boardService) {
    this.boardService = boardService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {

    Member loginUser = (Member) request.getSession().getAttribute("loginUser");
    int boardNo = Integer.parseInt(request.getParameter("boardNo"));

    Board old = boardService.get(boardNo);
    if (old.getWriter().getNo() != loginUser.getNo()) {
      return "redirect:../auth/fail";
    } else {
      boardService.deleteFile(Integer.parseInt(request.getParameter("fileNo")));
      return "redirect:view?no=" + boardNo;
    }
  }
}

 

public class BoardDeleteController implements PageController {

  private BoardService boardService;

  public BoardDeleteController(BoardService boardService) {
    this.boardService = boardService;
  }

  @Override
  public String execute(HttpServletRequest request, HttpServletResponse response) {
    try {
      Member loginUser = (Member) request.getSession().getAttribute("loginUser");
      int boardNo = Integer.parseInt(request.getParameter("no"));

      Board old = boardService.get(boardNo);
      if (old.getWriter().getNo() != loginUser.getNo()) {
        return "redirect:../auth/fail";
      }
      boardService.delete(boardNo);

    }  catch (Exception e) {
      e.printStackTrace();
      request.setAttribute("error", "data");
    }
    return "/board/delete.jsp";
  }
}

 

 

 


 

 

조언

 

*특수한 기술을 이용한 웹을 만들지 말라. 모바일로 가고싶으면 웹 페이지를 만들고 리액트를 이용해서 모바일을 적용하는 시도를 하라.

*웹 개발자 포트폴리오를 만들려면 관리시스템을 만들라. DB 많이 쓰고 CRUD 많이 사용하는 것을 만들라.

*디자인 툴(가구배치 등) 이런거 만들지 말라.

*주제 선정시 말로 아이디어만 내지 말고 카카오 오븐 등으로 UI 프로토타입 제시하는 룰을 지켜라.

*AI 를 주로 하든 보조로 하든 포트폴리오에 녹여내는게 좋다.

예) 게시글 쓰면 영어로 번역한 것이 나오게. 음성 인식해서 텍스트로 변환해주는 것. 내가 쓴 게시글 요약해 주는 것. 로그인 시 캡챠 또는 안면 인식 사용.

*면접시 질문

백엔드: 스프링 프레임워크 다뤄봤는지? SQL 다뤄봤는지? INNER JOIN, OUTER JOIN 차이를 아는지?

프론트엔드: 제이쿼리 다뤄봤는지? 부트스트랩 다뤄봤는지? 리액트 다뤄봤는지?

 

 


 

과제

 

TeacherController, StudentController 마이그레이션 하기