SlideShare a Scribd company logo
SJBoard Project
신입 개발자 강주영
GitHub: https://github.com/seojoo21/SJBoard
Blog: https://seojoo21.tistory.com/
게시판 프로젝트
INDEX
01제작 동기
02
개발 환경
03제작 기간
설계 구조 04
05Front-End
06
Back-End
07후기 및 보완점
01 제작 동기
게시판은 신입 Back-End 개발자라면 반드시 갖추어야 하는 기본적인 스프링 프레임워크 사용법과 CRUD 기능
구현 능력을 학습하고 활용하는데 가장 적합하며 추가 응용 및 확장 가능성 또한 많은 요소입니다.
저는 아래의 이유로 게시판을 첫번째 개인 프로젝트의 주제로 선택하였습니다.
게시판은 모든 웹 애플리케이션에서 필수이자 기본 요소입니다.
기본적인 게시물 생성(Create), 등록(Register), 수정(Update), 삭제(Delete) 기능에 댓글 등록 및 파일
업로드 기능을 추가함으로써 기본 CRUD 구현 능력을 심화하고 발전시킬 수 있습니다.
또한 단순히 게시판 구현으로 끝내지 않고 조금 더 기능을 추가하여 회원 가입, 로그인, 로그아웃 기능 및
관리자 페이지까지 구현한다면 웹 애플리케이션에서 기본적으로 요구하는 기능을 좀 더 심도있게 학습하고
활용할 수 있습니다.
02 개발 환경 저는 아래의 개발 환경에서 SJBoard 프로젝트를 진행하였습니다.
Front-End
ü JavaScript
ü jQuery 3.3.1
ü BootStrap 3.3.7
Front-End 개발환경:
Back-End
ü Spring 5.0.7
ü JavaSE 1.8
ü Maven 2.9
ü Tomcat 8.5
ü Oracle Express Edition
11g
ü SQL Developer 21.4.2
ü HikariCP 5.0.1
ü MyBatis 3.5.9
ü Lombok 1.18.22
• Front-End 는 https://startbootstrap.com에서 무료로 배포하는 BootStrap
템플릿을 바탕으로 SJBoard의 필요에 맞게 수정하여 사용하였습니다.
• jQuery는 BootStrap 템플릿에 맞는 버전인 3.3.1을 사용하였습니다.
Back-End 개발환경:
• STS3에서 Spring 5.0.7 버전을 사용하였습니다.
• WAS는 Tomcat 8.5 버전을 사용하였습니다.
• Database는 Oracle DB의 Express Edition 11g 버전을 사용하였습니다.
• Database를 보다 쉽고 효율적으로 관리하기 위해 SQL Developer를 사용하였습니다.
• Database 연결을 위한 커넥션 풀은 HikariCP 5.0.1 버전을 사용하였습니다.
• Oracle DB의 SQL문을 그대로 활용하기 위해 SQL 매핑 프레임워크로는 MyBatis 3.5.9
버전을 사용하였습니다.
03 제작 기간 2022/03/02 ~ 2022/03/30 (총 5주 중 실제 프로젝트 작업기간: 19일)
1주차 (2022/03/02~2022/03/06)
- 03/02 개발 환경 설정 및 프로젝트 기획 및 설계. 게시판 DB 생성 및 게시판 영속 및 비즈니스 계층 CRUD 작업
- 03/03 BootStrap 무료 템플릿의 HTML/CSS를 프로젝트에 맞게 수정하여 JSP 페이지로 변환. 게시판 프레젠테이션 계층 CRUD 작업
- 03/04 게시판 페이징 처리 및 검색 처리 기능 구현. 댓글 기능을 위한 영속 계층 CRUD 작업
- 03/06 댓글 기능 서비스 계층 CRUD 작업
2주차 (2022/03/07~2022/03/13)
- 03/07~03/10 스프링 AOP, 트랜잭션, 파일 업로드 기능 기본 개념 및 예제 학습
- 03/11 프로젝트 내 파일 업로드 구현 설계. 첨부 파일 DB 생성. 첨부파일 영속, 비즈니스, 프레젠테이션 계층 작업
- 03/12~03/13 스프링 웹 시큐리티 기본 개념 및 예제 학습
3주차 (2022/03/14~2022/03/20)
- 03/14 스프링 웹 시큐리티 기본 개념 및 예제 학습
- 03/15 회원 정보 DB 생성. 로그인, 로그아웃 기능 영속, 비즈니스, 프레젠테이션 계층 작업
- 03/16 기존 게시판에 스프링 웹 시큐리티 기능 추가
- 03/17 회원 가입 기능 추가 작업
- 03/18 회원 정보 조회, 수정, 탈퇴 기능 작업
- 03/19 회원 가입 시 아이디 및 사용자 이름 중복 체크 기능 작업. 회원 가입 시 SMTP 서버를 이용한 이메일 인증 번호 전송 기능 작업
03 제작 기간 2022/03/02 ~ 2022/03/30 (총 5주 중 실제 프로젝트 작업기간: 19일)
4주차 (2022/03/21~2022/03/27)
- 03/21 회원 가입 시 이메일 인증 번호 입력 및 일치 여부 확인 기능 작업
- 03/22 회원 아이디 찾기, 비밀번호 찾기 기능 작업
- 03/23 기존 게시판 기능 보완 (사용자 아이디를 기준으로 게시물 수정 및 삭제 처리를 할 수 있도록 기존 기능 수정)
- 03/24 게시물 추천 기능 구현 설계
- 03/25 게시물 추천 기능 작업
- 03/26 기존 게시판 기능 보완 (SummerNote 에디터 적용)
5주차 (2022/03/28~2022/03/30)
- 03/28 관리자 페이지 설계. 관리자 페이지 내 회원 목록 조회 페이지 작업
- 03/29 관리자 페이지 내 주간 현황 조회 페이지 작업 (구글 차트 활용)
- 03/30 관리자 페이지 내 기간별 현황 조회 페이지 작업 (구글 차트 활용) 및 코드 정리
2022년 3월 한 달 동안 스프링 공부와 SJBoard 프로젝트를 병행하였습니다.
매일 새롭게 공부한 내용들과 프로젝트 중 발생한 에러들은 잊지 않고 나중에 필요하면 찾아볼 수 있도록 매일 블로그에 개발 일지로
정리하여 업로드하였습니다.
04 설계 구조 SJBoard 프로젝트의 설계 구조 중 데이터베이스 모델은 아래와 같습니다.
회원 정보 DB
회원 권한 DB
자동로그인 정보 DB
게시글 추천 여부 확인 DB
게시판 DB
게시판 첨부 파일 DB
댓글 DB
04 설계 구조 SJBoard 프로젝트의 설계 구조 중 패키지 구조는 아래와 같습니다.
04 설계 구조 SJBoard 프로젝트의 설계 구조 중 패키지 구조는 아래와 같습니다.
05 Front-End SJBoard 프로젝트의 Front-End는 이렇게 설계되었습니다.
처음 SJBoard 프로젝트 설계 당시 PPT로
기본적인 레이아웃을 기획하였습니다.
05 Front-End SJBoard 프로젝트의 Front-End는 이렇게 구현되었습니다.
PPT로 기획한 레이아웃을 바탕으로
BootStrap 무료 템플릿을 필요에 맞게
변형하여 Front-End 디자인을
완성하였습니다.
게시물 작성 페이지의 경우 SummerNote
에디터를 이용할 수 있도록 페이지에
적용하였습니다.
home.jsp
(홈)
/sjboard/list.jsp
(게시물 전체 목록)
/sjboard/get.jsp
(게시물 조회)
/sjboard/register.jsp
(게시물 등록)
/sjboard/modify.jsp
(게시물 수정 및 삭제)
05 Front-End SJBoard 프로젝트의 Front-End는 이렇게 구현되었습니다.
이후 홈 및 게시판 페이지 외에
회원가입, 로그인, 로그아웃, 관리자
페이지 등을 구현할 때도 BootStrap
무료 템플릿을 필요에 맞게 변형하여
Front-End 디자인을 완성하였습니다.
관리자 페이지의 경우 구글 차트 API
를 이용하여 기간별 현황 자료를 볼 수
있도록 페이지에 추가하였습니다.
/member/register.jsp
(회원 가입)
/member/login.jsp
(로그인)
/member/update.jsp
(회원 정보 수정)
/admin/main.jsp
(관리자 페이지 메인)
/admin/memberList.jsp
(관리자 페이지 전체 회원 조회)
06 Back-End Function Flow
스프링 웹 시큐리티를 이용하여 회원 가입 및 로그인 기능을 구현하였기 때문에 사용자의 권한에 따라 이용할 수 있는 메뉴와
접근할 수 있는 페이지를 차별화하였습니다.
특정 페이지의 경우 URL이 노출되어 권한이 없는 사용자가 접근하는 것을 방지하고자 해당 URL 접속 시 사용자의 권한을 사전에
체크할 수 있도록 security-context.xml에는 <security: intercept-url> 태그를, 담당 Controller 내 메서드에는 @PreAuthroize
어노테이션을 사용하였습니다.
1. 비회원 : 기본 메뉴 (홈, 게시판, 로그인, 회원가입)
2. 일반 회원(ROLE_MEMBER) : 기본 메뉴 + 회원정보
3. 관리자(ROLE_ADMIN) : 기본 메뉴 + 회원 정보 + 관리자 페이지
06 Back-End Function Flow
회원 가입 및 로그인 여부와 상관 없이 모든 비회원 및 일반 회원이 접근할 수 있는 홈 페이지와 게시판 페이지의 Function Flow
및 권한에 따른 이용 가능 서비스는 아래와 같습니다.
회원 비회원
홈 O O
게시판
게시물
(첨부파일
포함)
전체 목록 조회 O O
특정 게시물 조회 O O
작성 및 등록 O X
수정 only 작성자 X
삭제 only 작성자 X
댓글
작성 및 등록 O X
수정 only 작성자 X
삭제 only 작성자 X
1. 비회원 및 일반 회원
06 Back-End Function Flow
일반 회원만 접근할 수 있는 회원 정보 페이지의
Function Flow는 아래와 같습니다.
2. 일반 회원 및 관리자
관리자만 접근할 수 있는 관리자 페이지의 Function Flow는
아래와 같습니다.
06 Back-End
프로젝트 기본 설정
Function Index
회원 가입 로그인 게시판 CRUD
댓글 CRUD 파일 업로드 CRUD 회원 정보 관리자 페이지
• pom.xml
• root-context.xml
• web.xml
• servlet-context.xml
• security-context.xml
• ID 중복 확인
• 사용자 이름(별명) 중복 확인
• 이메일 인증 번호 전송 및 인증
번호 일치 여부 확인
• 아이디 찾기
• 비밀번호 찾기
• 이메일 인증 번호 전송 및
인증 번호 일치 여부 확인
• 자동 로그인
• 게시물 조회, 작성, 등록,
수정, 삭제
• 게시물 검색
• 게시물 추천, 취소
• 최신 게시물, 인기 게시물
• 댓글 조회, 작성, 등록,
수정, 삭제
• 파일 업로드 경로 내
‘연/월/일’ 폴더 생성
• 게시물 작성 시 이미지,
일반 파일 업로드
• 게시물 조회 시 이미지,
일반 파일 처리
• 전체 회원 목록 조회
• 회원 권한 수정 및 강제 탈퇴 처리
• 주간 신규 게시물 수 , 댓글 수, 회원
수 현황 확인
• 기간별 게시물 수, 댓글 수, 회원 수
현황 확인
01 02 03 04
05 06 07 08
• 회원 정보 조회
• 회원 정보 수정
• 회원 탈퇴
06 Back-End 01 프로젝트 기본 설정
pom.xml root-context.xml web.xml servlet-context.xml security-context.xml
기능 프로젝트 내 빌드 옵션 설정
정의
MVC Model의 Model과
관련된 객체를 정의
(Back-End 설정 파일)
WAS 설정 정의 MVC Model의 View와
관련된 객체를 정의
(Front-End 설정 파일)
스프링 시큐리티 설정 정의
변경 사항 아래의 라이브러리를 추가로
등록
json-simple 1.1.1
spring-context-support
javax.mail 1.6.2
spring-security-core 5.0.6
spring-security-web 5.0.6
spring-security-config 5.0.6
spring-security-taglibs 5.0.6
quartz 2.3.2
quartz-jobs 2.3.2
Thumbnailator 0.4.8
aspectjweaver
gson 2.9.0
jackson-databind 2.13.1
jackson-dataformat-xml
2.13.1
lombok 1.18.22
log4jdbc-log4j2-jdbc4.1
1.16
HikariCP 5.0.1
Mybatis 3.5.9
mybatis-spring 2.0.7
spring-test
아래의 빈을 추가로 등록
mailSender
hikariConfig
dataSource
sqlSessionFactory
transactionManager
첨부파일 업로드 시
파일들이 저장될 서버의
경로를 지정하기 위해
multipart-config 등록
UTF-8 인코딩을 위해
encodingFilter 등록
스프링 시큐리티 필터를
사용하기 위해
springSecurityFilterChain
등록
변경 사항 없음 스프링 시큐리티 설정을
보다 원활하게 하기 위해
별도의 security-
context.xml 생성 후
로그인, 로그아웃, 사용자
인증 및 권한 부여에 활용
06 Back-End 02 회원 가입
Task Controller URL Method Parameter
From
(별도의 입력화면 필요여부)
URL
이동 여부
회원 가입 페이지
Member
Controller
/member/register GET O O
회원 가입 처리 /member/register POST 모든 항목, HttpSession O O
회원 아이디 중복 확인 /member/idCheck POST userid X
Ajax 비동기
회원 사용자 이름 중복 확인 /member/userNameCheck POST username X
인증 번호 이메일 발송 /member/mailCheck POST email, HttpSession X
인증 번호 일치 여부 확인 /member/regCheckNum POST
regCheckNum,
HttpSession
X
회원 가입은 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다.
회원 가입 이메일 인증 번호 발송은 보안에 유리한 SecureRandom 클래스를 이용하여 6자리 난수를 생성하고 네이버 SMTP 서버를
이용해 발송 하도록 설정하였습니다.
인증 번호는 서버에 부담을 줄이면서도 보안을 유지하기 위해 세션에 저장하여 사용자가 입력한 값과 일치하는지 확인하도록
설정하였습니다.
회원 가입 시 사용자의 비밀번호 보안을 위해 BcryptPasswordEncoder로 인코딩 후 서버에 저장될 수 있도록 구현하였습니다.
06 Back-End 02 회원 가입 02-01 아이디 & 사용자 이름(별명) 중복 확인
/member/register.jsp
*아이디 및 사용자 이름 중복 확인 및 결과를
처리하는 JS 메서드
MemberController MemberServiceImpl
MemberMapper MemberMapper.xml
1. 사용자가 회원 가입 시 아이디와 사용자 이름(별명)을 입력하면 JS에서
입력값을 감지해 Ajax 비동기 방식으로 URL을 통해 중복 여부 확인을 담당하는
MemberController의 메서드에 사용자의 입력값을 전달합니다.
2. MemberController의 담당 메서드는 MemberServiceImpl에서 구현된
서비스 메서드를 통해 중복 확인 여부를 처리하고 이 과정에서
MemberServiceImpl 은 MemberMapper에 DB 접근을 위임합니다.
3. 그 다음 MemberMapper에서는 MemberMapper.xml을 이용하여 SQL
구문을 DB에 질의하고 그 결과값을 반환합니다. 반환된 결과값은
MemberController에 전달되고, 이 결과값은 다시 JS에 전달되어 중복 여부를
화면에 출력합니다.
06 Back-End 02 회원 가입 02-02 이메일 인증 번호 전송 및 인증 번호 일치 여부 확인
1. 사용자가 회원 가입 시 이메일 주소를 입력하고 인증 번호 전송 버튼을 클릭하면
회색으로 비활성화 되어있던 인증 번호 입력란이 흰색으로 변하며 활성화됩니다.
JS에서는 Ajax 비동기 방식으로 URL을 통해 MemberController에서 인증 메일 발송을
담당하는 메서드에 입력된 사용자의 이메일 주소를 전달합니다.
2. 그 다음 MemberController의 메일 발송 담당 메서드는 SecureRandom 인스턴스로
6자리 난수를 인증 번호로 생성하여 사용자에게 메일을 발송하고 이 인증 번호를 세션에
저장합니다.
3. 사용자는 메일로 전달받은 인증 번호를 인증 번호 입력란에 입력하고 JS에서는 이
입력값을 감지해 Ajax 비동기 방식으로 URL을 통해 일치 여부 확인을 담당하는
MemberController의 메서드에 사용자의 입력값을 전달합니다.
4. 그 다음 MemberController의 일치 여부 확인 담당 메서드는 앞서 메일 발송 담당
메서드에서 세션에 저장해놓은 인증 번호 값과 사용자가 입력한 인증 번호 값을 비교해
일치 여부 결과값을 반환하고 이 결과값은 JS에 전달되어 화면에 출력됩니다.
/member/register.jsp
*인증 번호 전송 버튼 클릭 시
동작을 처리하는 JS 메서드
/member/register.jsp
*인증 번호 일치 여부 결과를
처리하는 JS 메서드
MemberController
* 인증 번호 이메일 전송 메서드
MemberController
* 인증 번호 일치 여부 확인
메서드
06 Back-End 03 로그인
Task Controller URL Method Parameter
From
(별도의 입력화면 필요여부)
URL
이동 여부
로그인 Login
Controller
/login GET HttpSession O O
로그아웃 /logout GET O O
아이디 찾기 페이지
Member
Controller
/member/findId GET O O
아이디 찾기 /member/findId POST email X Ajax 비동기
비밀번호 찾기 페이지 /member/findPwd GET O O
비밀번호 찾기 /member/findPwd POST userid, email, HttpSession X
Ajax 비동기
인증 번호 이메일 발송 /member/mailCheck POST email, HttpSession X
인증 번호 일치 여부 확인 /member/regCheckNum POST
regCheckNum,
HttpSession
X
비밀번호 재설정 페이지 /member/updatePwd GET X O
비밀번호 재설정 /member/updatePwd POST
userid, userpw,
HttpSession
O O
로그인은 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다.
비밀 번호 찾기 시 사용자의 비밀 번호 보안을 위해 서버에서 임의의 비밀 번호를 생성하여 사용자 이메일로 전송하지 않고, 회원
가입시와 동일하게 비밀 번호 재설정을 위한 인증 번호를 사용자 이메일로 발송하여 인증 번호 일치 시 사용자가 스스로 비밀 번호를
재설정 하도록 하였습니다.
자동 로그인 기능을 추가하여 사용자의 로그인 상태가 유지되도록 하였으며 보안을 위해 자동 로그인 유효 기간은 7일로
설정하였습니다.
06 Back-End 03 로그인 03-01 아이디 찾기
1. 사용자가 회원 가입 시 등록했던 이메일
주소를 입력하고 아이디 찾기 버튼을 클릭하면
JS에서 Ajax 비동기 방식으로 URL을 통해
아이디 찾기를 담당하는
MemberController의 메서드에 이메일 주소
값을 전달합니다.
2. 그 다음 MemberController의 담당
메서드는 MemberServiceImpl에서 구현된
서비스 메서드를 통해 입력된 이메일 주소를
바탕으로 아이디 찾기를 처리하고 이 과정에서
MemberServiceImpl 은 MemberMapper에
DB 접근을 위임합니다.
3. 그 다음 MemberMapper에서는
MemberMapper.xml을 이용하여 SQL
구문을 DB에 질의하고 그 결과값을
반환합니다. 반환된 결과값은
MemberController에 전달되고, 이 결과값은
다시 JS에 전달되어 해당 이메일로 등록된
아이디의 존재 여부 결과 값을 화면에
출력합니다
/member/findId.jsp
*아이디 찾기 버튼 클릭 시
동작을 처리하는 JS 메서드
MemberController
MemberServiceImpl
MemberMapper
MemberMapper.xml
06 Back-End 03 로그인 03-02 비밀번호 찾기 및 인증 번호 일치 여부 확인
1. 사용자가 아이디와 회원 가입시 입력했던 이메일 주소를 입력하고 인증 번호 전송 버튼을
클릭하면 회색으로 비활성화 되어있던 인증 번호 입력란이 흰색으로 변하며 활성화됩니다.
JS에서는 Ajax 비동기 방식으로 URL을 통해 MemberController에서 인증 메일 발송을 담당하는
메서드에 입력된 사용자의 이메일 주소를 전달합니다.
2. 그 다음 MemberController의 메일 발송 담당 메서드는 SecureRandom 인스턴스로 6자리
난수를 인증 번호로 생성하여 사용자에게 메일을 발송하고 이 인증 번호를 세션에 저장합니다.
3. 사용자는 메일로 전달받은 인증 번호를 인증 번호 입력란에 입력하고 JS에서는 이 입력값을
감지해 Ajax 비동기 방식으로 URL을 통해 일치 여부 확인을 담당하는 MemberController의
메서드에 사용자의 입력값을 전달합니다.
4. 그 다음 MemberController의 일치 여부 확인 담당 메서드는 앞서 메일 발송 담당 메서드에서
세션에 저장해놓은 인증 번호 값과 사용자가 입력한 인증 번호 값을 비교해 일치 여부 결과값을
반환하고 이 결과값은 JS에 전달되어 화면에 출력됩니다.
5. 마지막으로 사용자가 비밀번호 찾기 버튼을 클릭하면 비밀번호 재설정 페이지로 넘어가
비밀번호를 다시 설정할 수 있습니다.
/member/findPwd.jsp
*인증 번호 전송 버튼 클릭 시
동작을 처리하는 JS 메서드
/member/register.jsp
*인증 번호 일치 여부
결과를 처리하는 JS 메서드
MemberController
* 인증 번호 이메일 전송 메서드
MemberController
* 인증 번호 일치 여부 확인
메서드
06 Back-End 03 로그인 03-03 자동 로그인
1. 사용자가 ‘로그인 상태 유지’ 체크 박스를 선택하고 로그인을 하면 ‘remember-me’라는 쿠키가 생성되며 자동 로그인을 관리하는
DB에 해당 사용자의 정보가 저장됩니다. 이후 해당 사용자의 재방문 시 세션에 해당 사용자의 정보가 있는지 확인하여 없을 경우 DB를
조회하여 사용자의 로그인 처리에 사용합니다.
2. 쿠키의 유효 시간은 7일이므로 7일 이후 해당 사용자의 자동 로그인 정보는 DB에서 삭제됩니다. 그리고 자동 로그인을 설정했던
사용자가 로그아웃을 하면 DB에 저장되었던 자동 로그인 정보는 삭제됩니다. 이후 다시 로그인 시 ‘로그인 상태 유지’를 체크 하고
로그인 해야만 다시 DB에 자동 로그인 정보가 저장됩니다.
06 Back-End 04 게시판 CRUD
Task Controller URL Method Parameter
From
(별도의 입력화면 필요여부)
URL
이동 여부
전체 목록
BoardController
/sjboard/list GET
게시물 조회 /sjboard/get GET bno=123 X O
게시물 작성 /sjboard/register GET 모든 항목 O O
게시물 등록 /sjboard/register POST 모든 항목 O O
게시물 수정 /sjboard/modify POST 모든 항목 O O
게시물 삭제 /sjboard/remove POST bno O O
게시물 추천
LikeContoroller
/updateLike POST bno, userid X
Ajax
비동기 처리
게시물 추천 취소 /deleteLike POST bno, userid X
게시판은 아래와 같이 계획하여 CRUD 기능을 구현하였습니다.
게시물 전체 목록 출력을 위한 SQL문 작성 시에는 로딩 속도 향상을 위해 order by 구문 대신 Index Hint를 사용하였습니다.
게시물 등록/수정/삭제 후에는 redirect 처리하여 전체 목록 페이지로 돌아가도록 하였습니다.
게시물 추천 및 취소 기능은 무한 추천을 방지하고자 Ajax 비동기 처리로 로그인한 회원에 한해 아이디 당 게시물 1건에 1회만 추천할
수 있도록 설정하였습니다.
게시물 추천 DB의 추천 수가 게시판 DB의 추천 수에 함께 반영이 될 수 있도록 게시판 서비스 계층의 실행 메서드에 트랜잭션 처리
하였습니다.
06 Back-End 04 게시판 CRUD 04-01 게시물 조회, 작성, 등록, 수정, 삭제
게시판 CRUD 기능에 SummerNote 에디터를 추가하여 사용자가 자유롭게 텍스트를 편집할 수 있도록 하였습니다.
게시물 수정/삭제는 사용자 아이디를 기준으로 작성자와 로그인한 사용자의 아이디가 동일한 경우에만 처리 가능하도록 설정하였습니다.
게시물 등록/수정/삭제 후 처리가 정상적으로 되었음을 사용자에게 알리기 위해 모달창을 사용하였습니다.
06 Back-End 04 게시판 CRUD 04-02 게시물 검색
게시판 CRUD 기능에 검색 기능을 추가하여 사용자가 조건에 맞는 게시물을 찾을 수 있도록 하였습니다.
검색 결과로 나온 게시물을 조회한 후 조회 페이지 하단에 있는 ’목록으로’ 버튼 클릭 시 게시판 조회 목록으로 돌아갈 때,
검색 결과와 페이지 위치가 그대로 유지될 수 있도록 하였습니다.
검색 조건이 적용된 게시물 조회 페이지의
URL
다시 게시판 목록 페이지로 돌아갔을 때 검색
조건이 유지되는 URL
MyBatis 동적 SQL문으로 작성한
검색 조건 SQL문
06 Back-End 04 게시판 CRUD 04-03 게시물 추천, 취소
1. 로그인한 회원이 게시물 조회 시 BoardController의 게시물 조회
페이지 담당 메서드는 해당 회원의 해당 게시물 추천 여부 이력을
확인합니다. 그리고 LikeServiceImpl과 LikeMapper,
LikeMapper.xml을 거쳐 DB로부터 확인한 결과값을 JS에 전달하여
화면에 추천 이력이 있으면 ‘추천1’ 버튼을, 추천 이력이 없으면 ‘추천’
버튼이 나타나도록 합니다.
2. ‘추천’ 버튼 클릭 시 JS에서는 Ajax 비동기 방식으로 URL을 통해
LikeController에서 게시물 추천 등록을 담당하는 메서드에 해당
게시물의 번호와 회원 아이디를 전달하고 이 값들은 모두 게시물 추천을
관리하는 DB에 저장이 됩니다. 그리고 화면의 ‘추천’ 버튼은 ‘추천1’
버튼으로 변경되고 비활성화 됩니다.
3. ‘추천1’ 버튼 클릭 시 JS에서는 Ajax 비동기 방식으로 URL을 통해
LikeController에서 게시물 추천 취소를 담당하는 메서드에 해당
게시물의 번호와 회원 아이디를 전달하고 이 값들을 가지고 DB는
저장해 놓았던 추천 이력을 삭제합니다. 그리고 화면의 ‘추천1’ 버튼은
‘추천’ 버튼으로 변경되고 비활성화 됩니다.
MemberController
* 로그인한 사용자의
게시물 추천 여부 확인
/sjboard/get.jsp
* 게시물 추천 이력에
따라 추천 버튼을 다르게
출력하는 JS 메서드
06 Back-End 04 게시판 CRUD 04-04 최신 게시물, 인기 게시물
사용자가 SJBoard 접속 시 가장 먼저 보게 되는 홈 페이지에 최신 게시물 및 인기 게시물이 나타나도록 하였습니다.
최신 게시물은 등록일 기준, 인기 게시물은 추천수 기준으로 기존 게시판의 페이징 처리시 사용한 DTO를 재활용하여 각각 10개씩 홈
페이지에 나타나도록 하였습니다.
06 Back-End 05 댓글 CRUD
댓글은 아래와 같이 계획하여 REST 방식으로 CRUD 기능을 구현하였습니다.
사용자의 입력 데이터는 JSON 타입으로 받고 서버 내부에서는 ReplyVO 타입으로 반환합니다.
사용자 댓글 조회 시 화면에 나타나는 출력 데이터는 JSON 타입과 XML 타입으로 전달됩니다.
댓글 DB에서 집계되는 댓글 수가 게시판 DB의 댓글 수에 함께 반영이 될 수 있도록 게시판 서비스 계층의 실행 메서드에서
트랜잭션 처리 하였습니다.
Task Controller URL Method
댓글 목록
ReplyController
/replies/pages/:bno/:page GET
댓글 조회 /replies/:rno GET
댓글 등록 /replies/new POST
댓글 수정 /replies/:rno PUT or PATCH
댓글 삭제 /replies/:rno DELETE
06 Back-End 05 댓글 CRUD
댓글 작성/등록은 로그인한 회원만 가능하도록 설정하였습니다.
05-01 댓글 조회, 작성, 등록, 수정, 삭제
댓글 수정/삭제는 신규 댓글 작성과 달리 댓글이 등록된 위치에서 바로 수정 및 삭제 처리가 가능하도록 모달창을 사용하였습니다.
댓글 수정/삭제는 사용자 아이디를 기준으로 작성자와 로그인한 사용자의 아이디가 동일한 경우에만 처리 가능하도록 설정하였습니다.
비회원/로그인 하지 않은 회원의 경우 댓글 창이 나타나지 않음
로그인한 사용자에 한해 댓글 창이 나타남
06 Back-End 06 파일 업로드 CRUD
파일 업로드는 아래와 같이 파일의 종류를 구분하여 페이지마다 CRUD 기능 구현 계획을 세웠습니다.
이미지 파일 일반 파일
sjboard/register.jsp
(게시물 작성 페이지)
- 파일 첨부란에 업로드 하고자 하는 이미지 파일의 섬네일 이미지가
나타나도록 한다.
- 파일 첨부란에서 파일 이름 옆 x 버튼 클릭 시 해당 파일이 파일 첨부란에서
사라지도록 한다.
- 파일 첨부란에 일반 문서 이미지가 나타나도록 한다.
(구글에서 무료 이미지를 찾아 attach.png로 활용)
- 파일 첨부란에서 파일 이름 옆 x 버튼 클릭 시 해당 파일이 파일 첨부란에서
사라지도록 한다.
sjboard/get.jsp
(게시물 조회 페이지)
- 파일 첨부란에 해당 게시물에 등록된 이미지 파일의 섬네일 이미지가
나타나도록 한다. (sjboard/register.jsp와 동일)
- 섬네일 이미지 클릭 시 원본 이미지가 화면에 나타나도록 한다.
- 파일 첨부란에 해당 게시물에 등록된 파일의 일반 문서 이미지가 나타나도록
한다. (sjboard/register.jsp와 동일)
- 원본 이미지 클릭 시 일반 파일을 다운로드할 수 있게 한다.
(클릭 시 JS로 ‘다운로드 하시겠습니까?’라는 confirm창을 화면에 띄운다)
sjboard/modify.jsp
(게시물 수정 페이지)
- 게시물 수정 시)
* 이미 등록된 첨부 파일을 삭제할 수 있다.
* 첨부 파일을 추가 등록할 수 있다.
- 게시물 삭제 시)
* 게시물과 함께 등록되어있던 첨부파일도 함께 삭제되어야 한다.
고려사항
1) 동일한 이름으로 파일이 업로드 되었을 때 기존 파일이 사라지는 문제
-> 게시판 첨부 파일을 모아 놓는 업로드 폴더 내에 '연/월/일' 폴더를 생성하여 업로드 날짜 별로 파일을 구분할 수 있도록 설계
-> java.util.UUID 클래스를 사용하여 파일 이름 앞에 UUID 값을 추가하고 '_'로 구분될 수 있도록 설계
2) 이미지 파일의 경우에는 원본 파일의 용량이 큰 경우 섬네일 이미지를 생성해야 하는 문제
-> Thumbnailator 라이브러리를 이용하여 섬네일 이미지 생성
-> 섬네일 이미지의 경우 원본 이미지와의 파일명 구분을 위해 's_UUID_파일명'으로 저장되도록 설계
3) 첨부파일 공격에 대비하기 위한 업로드 파일의 확장자 제한
-> 파일 당 최대 용량은 5MB로 지정
-> 확장자가 exe, sh, zip, alz 인 파일의 업로드 금지 설정
06 Back-End 06 파일 업로드 CRUD
파일 업로드는 아래와 같이 CRUD 기능을 구현하였습니다.
작업 Controller URL Method Parameter
From
(별도의 입력화면 필요여부)
URL 이동 여부
파일 업로드 처리
UploadController
/uploadAjaxAction POST uploadfile
Ajax 비동기 처리
이미지 파일인 경우
섬네일 표시
/display GET filename
일반 파일인 경우
첨부파일 다운로드
/download GET
userAgent,
(IE 호환을 위한 브라우저엔진 확인용)
filename
게시물 작성 시
첨부파일 삭제
/deletefile POST
filename,
type (이미지: 1, 일반 파일: 0)
게시물 조회 시 해당
게시물의 첨부 파일
목록을 가져옴
BoardController /getAttachList GET bno
첨부 파일은 게시물 생성, 수정, 삭제 시 함께 작동되어야 하므로 각각의 게시판 서비스 계층의 실행 메서드에서 트랜잭션 처리
하였습니다.
댓글 기능과 함께 웹 페이지 동작의 일관성을 유지하고자 Ajax 비동기 방식으로 구현하였습니다.
06 Back-End 06 파일 업로드 CRUD
사용자가 업로드한 파일이 서버에 저장될 시 동일한 이름의 파일이 업로드 되었을 때 기존 파일이 사라지는 문제를 해결하고자 서버 내
파일 업로드 경로에 ‘연/월/일’ 폴더를 생성하여 업로드 날짜별로 파일을 구분할 수 있도록 하였습니다.
java.util.UUID 클래스를 사용하여 사용자가 업로드하는 파일 이름에 UUID값을 추가하고 ‘_’로 구분할 수 있도록 설정하여 같은 날에
동일한 이름으로 업로드 된 파일 또한 서로 구분되어 각각 저장될 수 있도록 설정하였습니다.
06-01 파일 업로드 경로 내 ‘연/월/일’ 폴더 생성
06 Back-End 06 파일 업로드 CRUD 06-01 파일 업로드 경로 내 ‘연/월/일’ 폴더 생성
사용자가 업로드한 파일이 서버에 저장될 시 동일한 이름의 파일이 업로드 되었을 때 기존 파일이 사라지는 문제를 해결하고자 서버 내
파일 업로드 경로에 ‘연/월/일’ 폴더를 생성하여 업로드 날짜별로 파일을 구분할 수 있도록 하였습니다.
서버 내 파일 업로드 경로에 생성된 연/월/일 폴더
java.util.UUID 클래스를 사용하여 사용자가 업로드하는 파일 이름에 UUID값을 추가하고 ‘_’로 구분할 수 있도록 설정하여 같은 날에
동일한 이름으로 업로드 된 파일 또한 서로 구분되어 각각 저장될 수 있도록 설정하였습니다.
이미지 파일의 경우 파일 업로드 및 조회 시 어떤 이미지 파일인지 화면에서 미리 볼 수 있도록 섬네일 이미지를 자동으로 생성하도록
하였기 때문에, 섬네일 이미지의 경우에는 원본 이미지와의 파일명 구분을 하고자 's_UUID_파일명'으로 저장되도록 설정 하였습니다.
06 Back-End 06 파일 업로드 CRUD
게시물 작성 중 파일 업로드 시 이미지 파일의 경우에는
해당 이미지의 섬네일 이미지가, 일반 문서의 경우에는
일반 문서 이미지가 파일 첨부란에 나타나도록 하였습니다.
06-02 게시물 작성 시 이미지, 일반 파일 업로드
파일 업로드 시 이미지
파일의 섬네일을
보여주는
UploadController의
메서드
게시물 등록 시 첨부 파일을
저장하는
UploadController의 메서드
실제 게시물 등록과 함께 첨부 파일이 등록되므로 게시물
등록 시 첨부 파일 관리 DB에 첨부 파일 데이터가 저장될
수 있도록 BoardServiceImpl 내 게시물 등록 처리
메서드에 트랜잭션 처리를 하였습니다.
06 Back-End 06 파일 업로드 CRUD 06-03 게시물 조회 시 이미지, 일반 파일 처리
게시물 조회 페이지에서 첨부 파일 클릭 시 이미지는 원본 이미지가 화면에 출력되고, 일반 파일은 원본 파일을 다운로드 할 수 있게
구현하였습니다.
이미지 파일의 경우 클릭 시 원본 이미지 출력 일반 파일의 경우 클릭 시 원본 파일 다운로드
06 Back-End 07 회원정보
Task Controller URL Method Parameter
From
(별도의 입력화면 필요여부)
URL
이동 여부
회원 정보 조회
Member
Controller
/member/profile GET O
회원 정보 수정 페이지 /member/update GET Authentication O O
회원 정보 수정 /member/update POST HttpSession X O
회원 탈퇴 페이지 /member/delete GET Authentication O O
회원 탈퇴 /member/delete POST
Authentication,
HttpSession
X O
회원 정보는 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다.
비회원이 해당 URL에 직접 접근하더라도 페이지를 조회할 수 없도록 각각의 URL을 담당하는 Controller 내 메서드에
@PreAuthorize 어노테이션을 추가하였습니다.
회원 정보 수정 후에는 수정된 정보를 반영하기 위해 세션을 초기화 하고 다시 로그인할 수 있도록 로그인 페이지로 redirect
처리하였습니다.
회원 탈퇴 시 자동 로그아웃이 될 수 있게 SecurityContextHolder 클래스의 clearContext() 메서드를 사용하고 세션을
초기화하였으며 홈 페이지로 이동할 수 있도록 redirect 처리하였습니다.
06 Back-End 07 회원정보 07-01 회원 정보 조회, 수정, 탈퇴
회원 정보 수정/탈퇴 페이지 접근 시 현재 로그인한 사용자의 정보를 가져오기 위해 Authentication 객체와, Principal 객체를
사용하였습니다.
회원 정보 수정/ 탈퇴 후에는 세션을 초기화하고 모달창을
이용하여 처리 결과를 안내하도록 설정하였습니다.
06 Back-End 08 관리자 페이지
관리자 페이지는 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다.
비회원이나 일반 회원이 해당 URL에 직접 접근하더라도 페이지를 조회할 수 없도록 각각의 URL을 담당하는 Controller 내 메서드에
@PreAuthorize 어노테이션을 추가하였습니다.
관리자 페이지에서 관리자가 주간 현황 및 기간별 현황을 쉽게 볼 수 있도록 구글 차트로 데이터를 조회할 수 있도록 구현하였습니다.
Task Controller URL Method Parameter
From
(별도의 입력화면 필요여부)
URL
이동 여부
메인 페이지
Admin
Controller
/admin/main GET X O
전체 회원 정보 /admin/memberList GET O O
회원 권한 변경 /admin/updateAuth POST userid, auth X
Ajax 비동기
처리
회원 강제 탈퇴 /admin/deleteMember POST userid X
기간별 게시물 현황 /admin/bnoStats GET O O
기간별 게시물 수
Chart
Controller
/chart/bno GET fromDate, toDate X
Ajax 비동기
처리
기간별 댓글 수 /chart/rno GET fromDate, toDate X
기간별 회원 수 /chart/member GET fromDate, toDate X
06 Back-End 08 관리자 페이지
회원 목록 페이지에서 전체 회원 정보를 조회할 수 있도록 하였습니다.
사용자 편의를 위해 페이지 이동이나 새 창 없이 회원 목록 페이지 내에서 회원 권한 변경 및 회원 강제 탈퇴 처리를 할 수 있도록
구현하였습니다.
/admin/meberList.jsp 내 회원 권한 변경
및 회원 강제 탈퇴 처리 JS 메서드
08-01 전체 회원 목록 조회 & 회원 권한 변경 및 강제 탈퇴 처리
06 Back-End 08 관리자 페이지
메인 페이지에서 전체 현황 및 주간 신규 게시물 수, 댓글 수, 회원 수 현황을 확인할 수 있도록 구현 하였습니다.
08-02 주간 신규 게시물 수 , 댓글 수, 회원 수 현황 확인
사용자 편의를 위해 주간 신규 게시물 수, 댓글 수, 회원 수 현황 데이터는 보기 쉽게 시각화 할 필요성이 있어 구글 차트를
사용하였습니다.
주간 현황의 경우 조회 날짜를 기준으로 지난주와 이번주 데이터를 가지고 와서 사용자가 쉽게 변화 추이를 비교할 수 있도록 하였습니다.
/admin/main.jsp
구글 차트 JS 메서드
AdminMapper.xml
주간 현황 쿼리문
주간 현황의 경우 AdminMapper.xml에서 작성한
쿼리문을 통해 이미 주간 데이터를 조회하고 있기
때문에 따로 DB 데이터를 JSON으로 파싱하지 않고,
메인 페이지에 출력되는 데이터들을 JS 변수에
저장하여 구글 차트에 전달하는 식으로 설정하였습니다.
06 Back-End 08 관리자 페이지
기간별 게시물 현황, 기간별 댓글 현황, 기간별 회원 현황 메뉴에서는 사용자가 직접 날짜를 설정해 해당 기간 동안의 변화 추이를 볼 수
있도록 구현하였습니다.
08-03 기간별 게시물 수, 댓글 수, 회원 수 현황 확인
조회 기간 날짜 입력은 jQuery의 datepicker 위젯을 사용하여 사용자가 쉽게 달력을 확인하여 날짜를 선택할 수 있도록 하였습니다.
각 뷰 페이지 jsp
datepicker JS 메서드
06 Back-End 08 관리자 페이지 08-03 기간별 게시물 수, 댓글 수, 회원 수 현황 확인
기간별 현황 데이터는 사용자가 직접 조회 기간을 설정하는 것이므로 별도의 ChartMapper를 생성하고 ChartServiceImpl에서
Mapper에서 처리된 DB의 결과를 JSON 타입으로 파싱하도록 구현하였습니다.
JSON 구현 형태
{
"cols": [
{"type":"string",
"label":"등록일"}
{"type":"number",
"label":"개수"}
],
"rows": [
{"c":[{"v":"날짜"},
{"v":"개수"}]}
]
}
1. 사용자가 입력한 조회 기간이 Ajax 비동기
방식으로 URL을 통해 Controller에 전달 되면
Controller의 메서드는 해당 기간의 데이터를
JSON 타입으로 파싱하고자
ChartServiceImpl에서 구현된 담당 메서드를
호출합니다.
2. ChartServiceImpl, ChartMapper,
ChartMapper.xml을 거쳐 DB로부터 확인된
해당 기간의 데이터는 다시 ChartServiceImpl에
전달되고, ChartServiceImpl에서는 DB로부터
전달 받은 결과값을 JSON 타입으로 파싱하여
ChartController의 담당 메서드에 전달합니다.
3. ChartController를 통해 JSON 타입으로
파싱된 결과값은 JS로 전달되고 구글 차트로
출력됩니다.
07 후기 및 보완점
SJBoard 프로젝트는 저의 첫 스프링 프로젝트입니다. 작년 12월 말 그동안의 경력을 뒤로하고 새롭게 백엔드 개발자가 되기로 결심한 후 처음
개발 공부를 시작했을 때만 하더라도 Java의 개념과 용어들은 다소 낯설고 막연하게만 느껴졌습니다. 하지만 올해 2월 말부터 스프링 공부를
시작하면서 추상적으로만 느껴졌던 Java의 개념들이 실제 웹 개발에 어떻게 쓰이는지 깨닫게 되었고 실제 제가 작성한 코드가 웹 상에서
실행되는 것을 보며 개발 공부에 본격적으로 재미를 붙이게 되었습니다.
처음부터 모든 것의 이론과 예제를 끝까지 학습한 뒤 프로젝트를 시작하는 것보다 프로젝트를 진행 하면서 프로젝트에 필요한 개념과 기술들을
학습하는 것이 개발 공부를 하는데 가장 효율적인 방법이라는 생각이 들었습니다. 그래서 <코드로 배우는 스프링 웹 프로젝트 개정판> 책으로
스프링을 학습하며 책의 중반부터는 SJBoard 프로젝트를 기획하고 시작하게 되었습니다. 기본적으로 SJBoard의 게시판, 댓글, 파일 업로드,
로그인 기능은 책에 나온 예제를 바탕으로 구현하였습니다. 그러나 제가 책과 다르게 SJBoard 프로젝트에서 구현하고 싶은 기능들은 따로 책과
인터넷을 찾아보며 하나씩 만들어 나갔습니다. 댓글 작성 방식을 다르게 하고 게시판에 에디터를 활용한 것이 대표적인 예입니다.
그 외의 게시물 추천 기능, 회원 가입 기능, 관리자 페이지 기능들은 책의 도움 없이 혼자 구현해 낸 결과물입니다. 물론 구글 검색을 통해 각종
개발 블로그, StackOverFlow, Okky의 글을 참고하였으나 해당 자료들에 있는 코드가 제가 원하는 기능을 100% 동일하게 구현해낸 것은
아니었습니다. 그래서 DB는 어떻게 구성하는 것이 좋을지, 코드는 어떻게 작성하는 것이 효율적일지, 화면은 어떻게 구성해야 사용자가
이용하는데 편리할지에 대해 스스로 고민하고 노트에 로직도 그려보면서 느리지만 꾸준히 원하는 기능을 구현해냈습니다.
작성한 코드가 예상대로 동작하지 않아 새로운 로직을 생각해내야 할 때, 처음 보는 에러를 해결해야만 할 때, 어제까지만 해도 잘 동작하던
코드가 갑자기 오늘 테스트 시 동작하지 않을 때, 독학으로 개발 공부를 하는 상황이기 때문에 주변에 물어볼 곳이 없어 무조건 혼자 해결하느라
한 가지 문제를 가지고 몇 시간 혹은 하루를 통으로 허비하기도 했습니다. 하지만 스스로 원인을 찾아보고 문제를 파악하면서 스프링 동작 원리와
코드 구조, Java 및 JavaScript의 특징에 대해 좀 더 깊이 이해할 수 있었습니다. 그리고 아무리 오래 걸려도 결국에는 스스로 문제를 해결해내는
제 자신을 보며 작은 성취감을 맛보는 재미에 취해 더욱 개발 공부와 프로젝트 구현에 몰입할 수 있었습니다. 3개월 전 코딩의 ㅋ도 몰랐던 제가
스프링을 다루고 작은 프로젝트를 하나 끝냈다는 것이 꽤 자랑스럽고 즐겁습니다.
이번 SJBoard 프로젝트를 통해 학습한 개발 지식들을 바탕으로 어엿한 백엔드 신입 개발자가 될 수 있도록 계속 개발 지식과 역량을 쌓고자
합니다. 느리더라도 꾸준히 발전하는 개발자가 되도록 하겠습니다. 감사합니다.
01 후기
07 후기 및 보완점
SJBoard 프로젝트를 마무리 하면서 스스로 보완해야 하는 점이라고 생각한 부분은 아래와 같습니다.
1. 회원 정보 수정 기능에 RESTful API 적용
• 댓글 기능에 RESTful API를 적용한 것과 같이 회원 정보 수정 기능에도 RESTful API를 적용했으면 조금 더 보안에 유리하지 않았을까라는 생각이
듭니다. 회원 정보 수정 페이지의 경우 Authentication 객체와 Principal 객체를 이용하여 로그인한 사용자의 정보를 가져오는 방식으로 구현하였고,
@PreAuthorize 어노테이션으로 사용자 접근 권한에 제한을 두었기에 GET 방식의 URL이 노출되더라도 사용자가 임의로 타인의 회원 정보를 수정할 수
없습니다. 그러나 RESTful API를 적용한다면 회원 정보가 URL에 파라미터로 나타나지 않고 JSON 또는 XML로 전달되기 때문에 보안에 더 유리할
것이라는 생각이 들었습니다. 처음 해당 기능을 설계하고 구현했을 당시 RESTful API를 떠올리지 못했다는 것은 아직 RESTfulf API 사용에 미숙한 것을
의미하므로 RESTful API를 다시 학습해야겠다는 생각을 하였습니다.
2. 관리자 페이지 기능 보완 및 확대
• Back-End 개발 시 중요하게 생각해야 하는 점이 여러 가지 있지만 일반 사용자의 입장에서 가장 손쉽게 느낄 수 있는 중요한 점은 바로 관리자
페이지라고 생각합니다. DB나 개발 프로그램에 직접 접속하여 데이터를 사용하고 수정할 수 있는 개발자와 달리 일반 사용자는 화면에 구현된
기능들만으로 DB의 데이터를 활용해야하기 때문입니다. 일반 사용자와 달리 관리자의 경우에는 해당 웹 어플리케이션의 운영과 관리를 위해 DB를
필요에 맞게 수정, 가공할 수 있어야 하기 때문에 사용자 편의를 최우선으로 하여 관리자 페이지의 기능을 보완하고 확대할 필요를 느꼈습니다. SJBoard
프로젝트의 경우 기본 기능이 다양하지 않아 관리자 페이지를 구성하는데 한계가 있었으나, 다른 웹 사이트들처럼 회원 탈퇴 시 탈퇴 사유를 선택 또는
작성하도록 하고 기간별 탈퇴 회원 현황 및 탈퇴 사유를 관리자 페이지에서 조회할 수 있도록 한다면 관리자가 사이트 회원의 유출을 줄이기 위한 대안을
마련하는데 도움을 줄 수 있을 것이라는 생각을 하였습니다.
3. 코드 중복 및 AOP 미적용
• 이메일 인증 번호 전송 기능과 구글 차트를 사용하기 위해 DB 데이터를 JSON으로 파싱하는 기능을 별도의 서비스 클래스로 만들어 인스턴스로
사용하였다면 코드의 중복을 줄이고 프로젝트를 유지, 보수하는데 더 도움이 되었을 것이라는 생각을 하였습니다. 그리고 스프링의 특징 중 하나인
AOP에 대해 개념만 공부하고 실제로 프로젝트에는 적용하지 못해 아쉽습니다. 추후 AOP 활용을 위해 다시 AOP 개념과 사용법을 학습하고 프로그램
유지, 보수 관리에 필요한 로그들을 별도의 AOP로 관리하는 방식으로 프로젝트를 만들어야겠다는 생각을 하였습니다.
02 보완점

More Related Content

What's hot

『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
복연 이
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
Jeongmin Cha
 
김종욱 포트폴리오
김종욱 포트폴리오김종욱 포트폴리오
김종욱 포트폴리오
Jonguk Kim
 
MVx patterns in iOS (MVC, MVP, MVVM)
MVx patterns in iOS (MVC, MVP, MVVM)MVx patterns in iOS (MVC, MVP, MVVM)
MVx patterns in iOS (MVC, MVP, MVVM)
Yaroslav Voloshyn
 
3. 마이크로 서비스 아키텍쳐
3. 마이크로 서비스 아키텍쳐3. 마이크로 서비스 아키텍쳐
3. 마이크로 서비스 아키텍쳐
Terry Cho
 
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
정민 안
 
대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론
대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론
대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론
Terry Cho
 
정혜인 포트폴리오
정혜인 포트폴리오정혜인 포트폴리오
정혜인 포트폴리오henni31
 
MVVM - Model View ViewModel
MVVM - Model View ViewModelMVVM - Model View ViewModel
MVVM - Model View ViewModel
Dareen Alhiyari
 
Amazon Rekognition을 통한 이미지 인식 서비스 구축하기
Amazon Rekognition을 통한 이미지 인식 서비스 구축하기Amazon Rekognition을 통한 이미지 인식 서비스 구축하기
Amazon Rekognition을 통한 이미지 인식 서비스 구축하기
Amazon Web Services Korea
 
대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴
대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴
대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴
Terry Cho
 
技術選定をしてみたというお話
技術選定をしてみたというお話技術選定をしてみたというお話
技術選定をしてみたというお話
ssuser000144
 
Tổng quan ASP.NET CORE - NIVIKI.COM
Tổng quan ASP.NET CORE - NIVIKI.COMTổng quan ASP.NET CORE - NIVIKI.COM
Tổng quan ASP.NET CORE - NIVIKI.COM
Khoa Nguyen
 
MySQL operator for_kubernetes
MySQL operator for_kubernetesMySQL operator for_kubernetes
MySQL operator for_kubernetes
rockplace
 
제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석
제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석
제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석
BOAZ Bigdata
 
웹프로그래밍 팀프로젝트 중간발표
웹프로그래밍 팀프로젝트 중간발표웹프로그래밍 팀프로젝트 중간발표
웹프로그래밍 팀프로젝트 중간발표
Seong Heum Park
 
대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐
대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐
대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐
Terry Cho
 
4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴
Terry Cho
 
Training: MVVM Pattern
Training: MVVM PatternTraining: MVVM Pattern
Training: MVVM Pattern
Betclic Everest Group Tech Team
 
제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스
제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스
제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스
BOAZ Bigdata
 

What's hot (20)

『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
『이펙티브 디버깅』 - 디버깅 지옥에서 탈출하는 66가지 전략과 기법
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
 
김종욱 포트폴리오
김종욱 포트폴리오김종욱 포트폴리오
김종욱 포트폴리오
 
MVx patterns in iOS (MVC, MVP, MVVM)
MVx patterns in iOS (MVC, MVP, MVVM)MVx patterns in iOS (MVC, MVP, MVVM)
MVx patterns in iOS (MVC, MVP, MVVM)
 
3. 마이크로 서비스 아키텍쳐
3. 마이크로 서비스 아키텍쳐3. 마이크로 서비스 아키텍쳐
3. 마이크로 서비스 아키텍쳐
 
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
20221131_레츠스위프트_2022_iOS개발에서_알아두면_좋은것들.pdf
 
대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론
대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론
대용량 분산 아키텍쳐 설계 #1 아키텍쳐 설계 방법론
 
정혜인 포트폴리오
정혜인 포트폴리오정혜인 포트폴리오
정혜인 포트폴리오
 
MVVM - Model View ViewModel
MVVM - Model View ViewModelMVVM - Model View ViewModel
MVVM - Model View ViewModel
 
Amazon Rekognition을 통한 이미지 인식 서비스 구축하기
Amazon Rekognition을 통한 이미지 인식 서비스 구축하기Amazon Rekognition을 통한 이미지 인식 서비스 구축하기
Amazon Rekognition을 통한 이미지 인식 서비스 구축하기
 
대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴
대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴
대용량 분산 아키텍쳐 설계 #2 대용량 분산 시스템 아키텍쳐 디자인 패턴
 
技術選定をしてみたというお話
技術選定をしてみたというお話技術選定をしてみたというお話
技術選定をしてみたというお話
 
Tổng quan ASP.NET CORE - NIVIKI.COM
Tổng quan ASP.NET CORE - NIVIKI.COMTổng quan ASP.NET CORE - NIVIKI.COM
Tổng quan ASP.NET CORE - NIVIKI.COM
 
MySQL operator for_kubernetes
MySQL operator for_kubernetesMySQL operator for_kubernetes
MySQL operator for_kubernetes
 
제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석
제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석
제 9회 보아즈(BOAZ) 빅데이터 컨퍼런스 - AiRBnB : Aspect in Review 비교 & 분석
 
웹프로그래밍 팀프로젝트 중간발표
웹프로그래밍 팀프로젝트 중간발표웹프로그래밍 팀프로젝트 중간발표
웹프로그래밍 팀프로젝트 중간발표
 
대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐
대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐
대용량 분산 아키텍쳐 설계 #4. soa 아키텍쳐
 
4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴
 
Training: MVVM Pattern
Training: MVVM PatternTraining: MVVM Pattern
Training: MVVM Pattern
 
제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스
제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스
제 15회 보아즈(BOAZ) 빅데이터 컨퍼런스 - [MarketIN팀] : 디지털 마케팅 헬스체킹 서비스
 

Similar to SJBoard Project Portfolio

웹사이트기획 및 관리
웹사이트기획 및 관리웹사이트기획 및 관리
웹사이트기획 및 관리
봉조 김
 
Tks프로젝트v2
Tks프로젝트v2Tks프로젝트v2
Tks프로젝트v2
jrlim80
 
스프링시큐리티와 소셜연습 이해를 위한 글
스프링시큐리티와 소셜연습 이해를 위한 글스프링시큐리티와 소셜연습 이해를 위한 글
스프링시큐리티와 소셜연습 이해를 위한 글
라한사 아
 
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
Dae Kim
 
반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게
Sungju Jin
 
Web micro blog
Web micro blogWeb micro blog
Web micro blog
Hyeonseok Han
 
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
주식회사 내일비
 
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
Sang-ho Choi
 
REST Ovewview
REST OvewviewREST Ovewview
REST Ovewview
Terry Cho
 
5조_최종발표.pptx
5조_최종발표.pptx5조_최종발표.pptx
5조_최종발표.pptx
DonOh4
 
Enterprise
EnterpriseEnterprise
Enterprise
Seongmin Kim
 
정해균 포트폴리오
정해균 포트폴리오정해균 포트폴리오
정해균 포트폴리오
Haegyun Jung
 
Spring@mvc웹호스팅
Spring@mvc웹호스팅Spring@mvc웹호스팅
Spring@mvc웹호스팅
J.H Ahn
 
Parallel diary
Parallel diaryParallel diary
Parallel diary
Hong Jin Baek
 
[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...
[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...
[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...
Tae-Seong Park
 
제품소개서 (Pastel editor)
제품소개서 (Pastel editor)제품소개서 (Pastel editor)
제품소개서 (Pastel editor)
Kevin Hyun
 
제품소개서( Pastel Editor)
제품소개서( Pastel Editor)제품소개서( Pastel Editor)
제품소개서( Pastel Editor)
Kevin Hyun
 
AWS DevDay 실습 가이드 - 서버리스
AWS DevDay 실습 가이드 - 서버리스AWS DevDay 실습 가이드 - 서버리스
AWS DevDay 실습 가이드 - 서버리스
Amazon Web Services Korea
 
Web Project
Web ProjectWeb Project
Web Project
baejaehyeon
 
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
Tae-Seong Park
 

Similar to SJBoard Project Portfolio (20)

웹사이트기획 및 관리
웹사이트기획 및 관리웹사이트기획 및 관리
웹사이트기획 및 관리
 
Tks프로젝트v2
Tks프로젝트v2Tks프로젝트v2
Tks프로젝트v2
 
스프링시큐리티와 소셜연습 이해를 위한 글
스프링시큐리티와 소셜연습 이해를 위한 글스프링시큐리티와 소셜연습 이해를 위한 글
스프링시큐리티와 소셜연습 이해를 위한 글
 
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
모바일 게임과 앱을 위한 오픈소스 게임서버 엔진 프로젝트 CloudBread 프로젝트
 
반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게반복적인 코드 작업 자동화, Codebone으로 손쉽게
반복적인 코드 작업 자동화, Codebone으로 손쉽게
 
Web micro blog
Web micro blogWeb micro blog
Web micro blog
 
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
 
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
[커빙 아키텍쳐] 커빙은 어떻게 소셜 컨텐츠를 모아올까요?
 
REST Ovewview
REST OvewviewREST Ovewview
REST Ovewview
 
5조_최종발표.pptx
5조_최종발표.pptx5조_최종발표.pptx
5조_최종발표.pptx
 
Enterprise
EnterpriseEnterprise
Enterprise
 
정해균 포트폴리오
정해균 포트폴리오정해균 포트폴리오
정해균 포트폴리오
 
Spring@mvc웹호스팅
Spring@mvc웹호스팅Spring@mvc웹호스팅
Spring@mvc웹호스팅
 
Parallel diary
Parallel diaryParallel diary
Parallel diary
 
[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...
[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...
[AWSKRUG] 혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 서버리스 웹 플...
 
제품소개서 (Pastel editor)
제품소개서 (Pastel editor)제품소개서 (Pastel editor)
제품소개서 (Pastel editor)
 
제품소개서( Pastel Editor)
제품소개서( Pastel Editor)제품소개서( Pastel Editor)
제품소개서( Pastel Editor)
 
AWS DevDay 실습 가이드 - 서버리스
AWS DevDay 실습 가이드 - 서버리스AWS DevDay 실습 가이드 - 서버리스
AWS DevDay 실습 가이드 - 서버리스
 
Web Project
Web ProjectWeb Project
Web Project
 
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
혼자서 커뮤니티 귀동냥하며 만든 Next.js & Amplify & serverless framework 웹 플랫폼 서비스 구현(삽질) 후...
 

SJBoard Project Portfolio

  • 1. SJBoard Project 신입 개발자 강주영 GitHub: https://github.com/seojoo21/SJBoard Blog: https://seojoo21.tistory.com/ 게시판 프로젝트
  • 2. INDEX 01제작 동기 02 개발 환경 03제작 기간 설계 구조 04 05Front-End 06 Back-End 07후기 및 보완점
  • 3. 01 제작 동기 게시판은 신입 Back-End 개발자라면 반드시 갖추어야 하는 기본적인 스프링 프레임워크 사용법과 CRUD 기능 구현 능력을 학습하고 활용하는데 가장 적합하며 추가 응용 및 확장 가능성 또한 많은 요소입니다. 저는 아래의 이유로 게시판을 첫번째 개인 프로젝트의 주제로 선택하였습니다. 게시판은 모든 웹 애플리케이션에서 필수이자 기본 요소입니다. 기본적인 게시물 생성(Create), 등록(Register), 수정(Update), 삭제(Delete) 기능에 댓글 등록 및 파일 업로드 기능을 추가함으로써 기본 CRUD 구현 능력을 심화하고 발전시킬 수 있습니다. 또한 단순히 게시판 구현으로 끝내지 않고 조금 더 기능을 추가하여 회원 가입, 로그인, 로그아웃 기능 및 관리자 페이지까지 구현한다면 웹 애플리케이션에서 기본적으로 요구하는 기능을 좀 더 심도있게 학습하고 활용할 수 있습니다.
  • 4. 02 개발 환경 저는 아래의 개발 환경에서 SJBoard 프로젝트를 진행하였습니다. Front-End ü JavaScript ü jQuery 3.3.1 ü BootStrap 3.3.7 Front-End 개발환경: Back-End ü Spring 5.0.7 ü JavaSE 1.8 ü Maven 2.9 ü Tomcat 8.5 ü Oracle Express Edition 11g ü SQL Developer 21.4.2 ü HikariCP 5.0.1 ü MyBatis 3.5.9 ü Lombok 1.18.22 • Front-End 는 https://startbootstrap.com에서 무료로 배포하는 BootStrap 템플릿을 바탕으로 SJBoard의 필요에 맞게 수정하여 사용하였습니다. • jQuery는 BootStrap 템플릿에 맞는 버전인 3.3.1을 사용하였습니다. Back-End 개발환경: • STS3에서 Spring 5.0.7 버전을 사용하였습니다. • WAS는 Tomcat 8.5 버전을 사용하였습니다. • Database는 Oracle DB의 Express Edition 11g 버전을 사용하였습니다. • Database를 보다 쉽고 효율적으로 관리하기 위해 SQL Developer를 사용하였습니다. • Database 연결을 위한 커넥션 풀은 HikariCP 5.0.1 버전을 사용하였습니다. • Oracle DB의 SQL문을 그대로 활용하기 위해 SQL 매핑 프레임워크로는 MyBatis 3.5.9 버전을 사용하였습니다.
  • 5. 03 제작 기간 2022/03/02 ~ 2022/03/30 (총 5주 중 실제 프로젝트 작업기간: 19일) 1주차 (2022/03/02~2022/03/06) - 03/02 개발 환경 설정 및 프로젝트 기획 및 설계. 게시판 DB 생성 및 게시판 영속 및 비즈니스 계층 CRUD 작업 - 03/03 BootStrap 무료 템플릿의 HTML/CSS를 프로젝트에 맞게 수정하여 JSP 페이지로 변환. 게시판 프레젠테이션 계층 CRUD 작업 - 03/04 게시판 페이징 처리 및 검색 처리 기능 구현. 댓글 기능을 위한 영속 계층 CRUD 작업 - 03/06 댓글 기능 서비스 계층 CRUD 작업 2주차 (2022/03/07~2022/03/13) - 03/07~03/10 스프링 AOP, 트랜잭션, 파일 업로드 기능 기본 개념 및 예제 학습 - 03/11 프로젝트 내 파일 업로드 구현 설계. 첨부 파일 DB 생성. 첨부파일 영속, 비즈니스, 프레젠테이션 계층 작업 - 03/12~03/13 스프링 웹 시큐리티 기본 개념 및 예제 학습 3주차 (2022/03/14~2022/03/20) - 03/14 스프링 웹 시큐리티 기본 개념 및 예제 학습 - 03/15 회원 정보 DB 생성. 로그인, 로그아웃 기능 영속, 비즈니스, 프레젠테이션 계층 작업 - 03/16 기존 게시판에 스프링 웹 시큐리티 기능 추가 - 03/17 회원 가입 기능 추가 작업 - 03/18 회원 정보 조회, 수정, 탈퇴 기능 작업 - 03/19 회원 가입 시 아이디 및 사용자 이름 중복 체크 기능 작업. 회원 가입 시 SMTP 서버를 이용한 이메일 인증 번호 전송 기능 작업
  • 6. 03 제작 기간 2022/03/02 ~ 2022/03/30 (총 5주 중 실제 프로젝트 작업기간: 19일) 4주차 (2022/03/21~2022/03/27) - 03/21 회원 가입 시 이메일 인증 번호 입력 및 일치 여부 확인 기능 작업 - 03/22 회원 아이디 찾기, 비밀번호 찾기 기능 작업 - 03/23 기존 게시판 기능 보완 (사용자 아이디를 기준으로 게시물 수정 및 삭제 처리를 할 수 있도록 기존 기능 수정) - 03/24 게시물 추천 기능 구현 설계 - 03/25 게시물 추천 기능 작업 - 03/26 기존 게시판 기능 보완 (SummerNote 에디터 적용) 5주차 (2022/03/28~2022/03/30) - 03/28 관리자 페이지 설계. 관리자 페이지 내 회원 목록 조회 페이지 작업 - 03/29 관리자 페이지 내 주간 현황 조회 페이지 작업 (구글 차트 활용) - 03/30 관리자 페이지 내 기간별 현황 조회 페이지 작업 (구글 차트 활용) 및 코드 정리 2022년 3월 한 달 동안 스프링 공부와 SJBoard 프로젝트를 병행하였습니다. 매일 새롭게 공부한 내용들과 프로젝트 중 발생한 에러들은 잊지 않고 나중에 필요하면 찾아볼 수 있도록 매일 블로그에 개발 일지로 정리하여 업로드하였습니다.
  • 7. 04 설계 구조 SJBoard 프로젝트의 설계 구조 중 데이터베이스 모델은 아래와 같습니다. 회원 정보 DB 회원 권한 DB 자동로그인 정보 DB 게시글 추천 여부 확인 DB 게시판 DB 게시판 첨부 파일 DB 댓글 DB
  • 8. 04 설계 구조 SJBoard 프로젝트의 설계 구조 중 패키지 구조는 아래와 같습니다.
  • 9. 04 설계 구조 SJBoard 프로젝트의 설계 구조 중 패키지 구조는 아래와 같습니다.
  • 10. 05 Front-End SJBoard 프로젝트의 Front-End는 이렇게 설계되었습니다. 처음 SJBoard 프로젝트 설계 당시 PPT로 기본적인 레이아웃을 기획하였습니다.
  • 11. 05 Front-End SJBoard 프로젝트의 Front-End는 이렇게 구현되었습니다. PPT로 기획한 레이아웃을 바탕으로 BootStrap 무료 템플릿을 필요에 맞게 변형하여 Front-End 디자인을 완성하였습니다. 게시물 작성 페이지의 경우 SummerNote 에디터를 이용할 수 있도록 페이지에 적용하였습니다. home.jsp (홈) /sjboard/list.jsp (게시물 전체 목록) /sjboard/get.jsp (게시물 조회) /sjboard/register.jsp (게시물 등록) /sjboard/modify.jsp (게시물 수정 및 삭제)
  • 12. 05 Front-End SJBoard 프로젝트의 Front-End는 이렇게 구현되었습니다. 이후 홈 및 게시판 페이지 외에 회원가입, 로그인, 로그아웃, 관리자 페이지 등을 구현할 때도 BootStrap 무료 템플릿을 필요에 맞게 변형하여 Front-End 디자인을 완성하였습니다. 관리자 페이지의 경우 구글 차트 API 를 이용하여 기간별 현황 자료를 볼 수 있도록 페이지에 추가하였습니다. /member/register.jsp (회원 가입) /member/login.jsp (로그인) /member/update.jsp (회원 정보 수정) /admin/main.jsp (관리자 페이지 메인) /admin/memberList.jsp (관리자 페이지 전체 회원 조회)
  • 13. 06 Back-End Function Flow 스프링 웹 시큐리티를 이용하여 회원 가입 및 로그인 기능을 구현하였기 때문에 사용자의 권한에 따라 이용할 수 있는 메뉴와 접근할 수 있는 페이지를 차별화하였습니다. 특정 페이지의 경우 URL이 노출되어 권한이 없는 사용자가 접근하는 것을 방지하고자 해당 URL 접속 시 사용자의 권한을 사전에 체크할 수 있도록 security-context.xml에는 <security: intercept-url> 태그를, 담당 Controller 내 메서드에는 @PreAuthroize 어노테이션을 사용하였습니다. 1. 비회원 : 기본 메뉴 (홈, 게시판, 로그인, 회원가입) 2. 일반 회원(ROLE_MEMBER) : 기본 메뉴 + 회원정보 3. 관리자(ROLE_ADMIN) : 기본 메뉴 + 회원 정보 + 관리자 페이지
  • 14. 06 Back-End Function Flow 회원 가입 및 로그인 여부와 상관 없이 모든 비회원 및 일반 회원이 접근할 수 있는 홈 페이지와 게시판 페이지의 Function Flow 및 권한에 따른 이용 가능 서비스는 아래와 같습니다. 회원 비회원 홈 O O 게시판 게시물 (첨부파일 포함) 전체 목록 조회 O O 특정 게시물 조회 O O 작성 및 등록 O X 수정 only 작성자 X 삭제 only 작성자 X 댓글 작성 및 등록 O X 수정 only 작성자 X 삭제 only 작성자 X 1. 비회원 및 일반 회원
  • 15. 06 Back-End Function Flow 일반 회원만 접근할 수 있는 회원 정보 페이지의 Function Flow는 아래와 같습니다. 2. 일반 회원 및 관리자 관리자만 접근할 수 있는 관리자 페이지의 Function Flow는 아래와 같습니다.
  • 16. 06 Back-End 프로젝트 기본 설정 Function Index 회원 가입 로그인 게시판 CRUD 댓글 CRUD 파일 업로드 CRUD 회원 정보 관리자 페이지 • pom.xml • root-context.xml • web.xml • servlet-context.xml • security-context.xml • ID 중복 확인 • 사용자 이름(별명) 중복 확인 • 이메일 인증 번호 전송 및 인증 번호 일치 여부 확인 • 아이디 찾기 • 비밀번호 찾기 • 이메일 인증 번호 전송 및 인증 번호 일치 여부 확인 • 자동 로그인 • 게시물 조회, 작성, 등록, 수정, 삭제 • 게시물 검색 • 게시물 추천, 취소 • 최신 게시물, 인기 게시물 • 댓글 조회, 작성, 등록, 수정, 삭제 • 파일 업로드 경로 내 ‘연/월/일’ 폴더 생성 • 게시물 작성 시 이미지, 일반 파일 업로드 • 게시물 조회 시 이미지, 일반 파일 처리 • 전체 회원 목록 조회 • 회원 권한 수정 및 강제 탈퇴 처리 • 주간 신규 게시물 수 , 댓글 수, 회원 수 현황 확인 • 기간별 게시물 수, 댓글 수, 회원 수 현황 확인 01 02 03 04 05 06 07 08 • 회원 정보 조회 • 회원 정보 수정 • 회원 탈퇴
  • 17. 06 Back-End 01 프로젝트 기본 설정 pom.xml root-context.xml web.xml servlet-context.xml security-context.xml 기능 프로젝트 내 빌드 옵션 설정 정의 MVC Model의 Model과 관련된 객체를 정의 (Back-End 설정 파일) WAS 설정 정의 MVC Model의 View와 관련된 객체를 정의 (Front-End 설정 파일) 스프링 시큐리티 설정 정의 변경 사항 아래의 라이브러리를 추가로 등록 json-simple 1.1.1 spring-context-support javax.mail 1.6.2 spring-security-core 5.0.6 spring-security-web 5.0.6 spring-security-config 5.0.6 spring-security-taglibs 5.0.6 quartz 2.3.2 quartz-jobs 2.3.2 Thumbnailator 0.4.8 aspectjweaver gson 2.9.0 jackson-databind 2.13.1 jackson-dataformat-xml 2.13.1 lombok 1.18.22 log4jdbc-log4j2-jdbc4.1 1.16 HikariCP 5.0.1 Mybatis 3.5.9 mybatis-spring 2.0.7 spring-test 아래의 빈을 추가로 등록 mailSender hikariConfig dataSource sqlSessionFactory transactionManager 첨부파일 업로드 시 파일들이 저장될 서버의 경로를 지정하기 위해 multipart-config 등록 UTF-8 인코딩을 위해 encodingFilter 등록 스프링 시큐리티 필터를 사용하기 위해 springSecurityFilterChain 등록 변경 사항 없음 스프링 시큐리티 설정을 보다 원활하게 하기 위해 별도의 security- context.xml 생성 후 로그인, 로그아웃, 사용자 인증 및 권한 부여에 활용
  • 18. 06 Back-End 02 회원 가입 Task Controller URL Method Parameter From (별도의 입력화면 필요여부) URL 이동 여부 회원 가입 페이지 Member Controller /member/register GET O O 회원 가입 처리 /member/register POST 모든 항목, HttpSession O O 회원 아이디 중복 확인 /member/idCheck POST userid X Ajax 비동기 회원 사용자 이름 중복 확인 /member/userNameCheck POST username X 인증 번호 이메일 발송 /member/mailCheck POST email, HttpSession X 인증 번호 일치 여부 확인 /member/regCheckNum POST regCheckNum, HttpSession X 회원 가입은 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다. 회원 가입 이메일 인증 번호 발송은 보안에 유리한 SecureRandom 클래스를 이용하여 6자리 난수를 생성하고 네이버 SMTP 서버를 이용해 발송 하도록 설정하였습니다. 인증 번호는 서버에 부담을 줄이면서도 보안을 유지하기 위해 세션에 저장하여 사용자가 입력한 값과 일치하는지 확인하도록 설정하였습니다. 회원 가입 시 사용자의 비밀번호 보안을 위해 BcryptPasswordEncoder로 인코딩 후 서버에 저장될 수 있도록 구현하였습니다.
  • 19. 06 Back-End 02 회원 가입 02-01 아이디 & 사용자 이름(별명) 중복 확인 /member/register.jsp *아이디 및 사용자 이름 중복 확인 및 결과를 처리하는 JS 메서드 MemberController MemberServiceImpl MemberMapper MemberMapper.xml 1. 사용자가 회원 가입 시 아이디와 사용자 이름(별명)을 입력하면 JS에서 입력값을 감지해 Ajax 비동기 방식으로 URL을 통해 중복 여부 확인을 담당하는 MemberController의 메서드에 사용자의 입력값을 전달합니다. 2. MemberController의 담당 메서드는 MemberServiceImpl에서 구현된 서비스 메서드를 통해 중복 확인 여부를 처리하고 이 과정에서 MemberServiceImpl 은 MemberMapper에 DB 접근을 위임합니다. 3. 그 다음 MemberMapper에서는 MemberMapper.xml을 이용하여 SQL 구문을 DB에 질의하고 그 결과값을 반환합니다. 반환된 결과값은 MemberController에 전달되고, 이 결과값은 다시 JS에 전달되어 중복 여부를 화면에 출력합니다.
  • 20. 06 Back-End 02 회원 가입 02-02 이메일 인증 번호 전송 및 인증 번호 일치 여부 확인 1. 사용자가 회원 가입 시 이메일 주소를 입력하고 인증 번호 전송 버튼을 클릭하면 회색으로 비활성화 되어있던 인증 번호 입력란이 흰색으로 변하며 활성화됩니다. JS에서는 Ajax 비동기 방식으로 URL을 통해 MemberController에서 인증 메일 발송을 담당하는 메서드에 입력된 사용자의 이메일 주소를 전달합니다. 2. 그 다음 MemberController의 메일 발송 담당 메서드는 SecureRandom 인스턴스로 6자리 난수를 인증 번호로 생성하여 사용자에게 메일을 발송하고 이 인증 번호를 세션에 저장합니다. 3. 사용자는 메일로 전달받은 인증 번호를 인증 번호 입력란에 입력하고 JS에서는 이 입력값을 감지해 Ajax 비동기 방식으로 URL을 통해 일치 여부 확인을 담당하는 MemberController의 메서드에 사용자의 입력값을 전달합니다. 4. 그 다음 MemberController의 일치 여부 확인 담당 메서드는 앞서 메일 발송 담당 메서드에서 세션에 저장해놓은 인증 번호 값과 사용자가 입력한 인증 번호 값을 비교해 일치 여부 결과값을 반환하고 이 결과값은 JS에 전달되어 화면에 출력됩니다. /member/register.jsp *인증 번호 전송 버튼 클릭 시 동작을 처리하는 JS 메서드 /member/register.jsp *인증 번호 일치 여부 결과를 처리하는 JS 메서드 MemberController * 인증 번호 이메일 전송 메서드 MemberController * 인증 번호 일치 여부 확인 메서드
  • 21. 06 Back-End 03 로그인 Task Controller URL Method Parameter From (별도의 입력화면 필요여부) URL 이동 여부 로그인 Login Controller /login GET HttpSession O O 로그아웃 /logout GET O O 아이디 찾기 페이지 Member Controller /member/findId GET O O 아이디 찾기 /member/findId POST email X Ajax 비동기 비밀번호 찾기 페이지 /member/findPwd GET O O 비밀번호 찾기 /member/findPwd POST userid, email, HttpSession X Ajax 비동기 인증 번호 이메일 발송 /member/mailCheck POST email, HttpSession X 인증 번호 일치 여부 확인 /member/regCheckNum POST regCheckNum, HttpSession X 비밀번호 재설정 페이지 /member/updatePwd GET X O 비밀번호 재설정 /member/updatePwd POST userid, userpw, HttpSession O O 로그인은 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다. 비밀 번호 찾기 시 사용자의 비밀 번호 보안을 위해 서버에서 임의의 비밀 번호를 생성하여 사용자 이메일로 전송하지 않고, 회원 가입시와 동일하게 비밀 번호 재설정을 위한 인증 번호를 사용자 이메일로 발송하여 인증 번호 일치 시 사용자가 스스로 비밀 번호를 재설정 하도록 하였습니다. 자동 로그인 기능을 추가하여 사용자의 로그인 상태가 유지되도록 하였으며 보안을 위해 자동 로그인 유효 기간은 7일로 설정하였습니다.
  • 22. 06 Back-End 03 로그인 03-01 아이디 찾기 1. 사용자가 회원 가입 시 등록했던 이메일 주소를 입력하고 아이디 찾기 버튼을 클릭하면 JS에서 Ajax 비동기 방식으로 URL을 통해 아이디 찾기를 담당하는 MemberController의 메서드에 이메일 주소 값을 전달합니다. 2. 그 다음 MemberController의 담당 메서드는 MemberServiceImpl에서 구현된 서비스 메서드를 통해 입력된 이메일 주소를 바탕으로 아이디 찾기를 처리하고 이 과정에서 MemberServiceImpl 은 MemberMapper에 DB 접근을 위임합니다. 3. 그 다음 MemberMapper에서는 MemberMapper.xml을 이용하여 SQL 구문을 DB에 질의하고 그 결과값을 반환합니다. 반환된 결과값은 MemberController에 전달되고, 이 결과값은 다시 JS에 전달되어 해당 이메일로 등록된 아이디의 존재 여부 결과 값을 화면에 출력합니다 /member/findId.jsp *아이디 찾기 버튼 클릭 시 동작을 처리하는 JS 메서드 MemberController MemberServiceImpl MemberMapper MemberMapper.xml
  • 23. 06 Back-End 03 로그인 03-02 비밀번호 찾기 및 인증 번호 일치 여부 확인 1. 사용자가 아이디와 회원 가입시 입력했던 이메일 주소를 입력하고 인증 번호 전송 버튼을 클릭하면 회색으로 비활성화 되어있던 인증 번호 입력란이 흰색으로 변하며 활성화됩니다. JS에서는 Ajax 비동기 방식으로 URL을 통해 MemberController에서 인증 메일 발송을 담당하는 메서드에 입력된 사용자의 이메일 주소를 전달합니다. 2. 그 다음 MemberController의 메일 발송 담당 메서드는 SecureRandom 인스턴스로 6자리 난수를 인증 번호로 생성하여 사용자에게 메일을 발송하고 이 인증 번호를 세션에 저장합니다. 3. 사용자는 메일로 전달받은 인증 번호를 인증 번호 입력란에 입력하고 JS에서는 이 입력값을 감지해 Ajax 비동기 방식으로 URL을 통해 일치 여부 확인을 담당하는 MemberController의 메서드에 사용자의 입력값을 전달합니다. 4. 그 다음 MemberController의 일치 여부 확인 담당 메서드는 앞서 메일 발송 담당 메서드에서 세션에 저장해놓은 인증 번호 값과 사용자가 입력한 인증 번호 값을 비교해 일치 여부 결과값을 반환하고 이 결과값은 JS에 전달되어 화면에 출력됩니다. 5. 마지막으로 사용자가 비밀번호 찾기 버튼을 클릭하면 비밀번호 재설정 페이지로 넘어가 비밀번호를 다시 설정할 수 있습니다. /member/findPwd.jsp *인증 번호 전송 버튼 클릭 시 동작을 처리하는 JS 메서드 /member/register.jsp *인증 번호 일치 여부 결과를 처리하는 JS 메서드 MemberController * 인증 번호 이메일 전송 메서드 MemberController * 인증 번호 일치 여부 확인 메서드
  • 24. 06 Back-End 03 로그인 03-03 자동 로그인 1. 사용자가 ‘로그인 상태 유지’ 체크 박스를 선택하고 로그인을 하면 ‘remember-me’라는 쿠키가 생성되며 자동 로그인을 관리하는 DB에 해당 사용자의 정보가 저장됩니다. 이후 해당 사용자의 재방문 시 세션에 해당 사용자의 정보가 있는지 확인하여 없을 경우 DB를 조회하여 사용자의 로그인 처리에 사용합니다. 2. 쿠키의 유효 시간은 7일이므로 7일 이후 해당 사용자의 자동 로그인 정보는 DB에서 삭제됩니다. 그리고 자동 로그인을 설정했던 사용자가 로그아웃을 하면 DB에 저장되었던 자동 로그인 정보는 삭제됩니다. 이후 다시 로그인 시 ‘로그인 상태 유지’를 체크 하고 로그인 해야만 다시 DB에 자동 로그인 정보가 저장됩니다.
  • 25. 06 Back-End 04 게시판 CRUD Task Controller URL Method Parameter From (별도의 입력화면 필요여부) URL 이동 여부 전체 목록 BoardController /sjboard/list GET 게시물 조회 /sjboard/get GET bno=123 X O 게시물 작성 /sjboard/register GET 모든 항목 O O 게시물 등록 /sjboard/register POST 모든 항목 O O 게시물 수정 /sjboard/modify POST 모든 항목 O O 게시물 삭제 /sjboard/remove POST bno O O 게시물 추천 LikeContoroller /updateLike POST bno, userid X Ajax 비동기 처리 게시물 추천 취소 /deleteLike POST bno, userid X 게시판은 아래와 같이 계획하여 CRUD 기능을 구현하였습니다. 게시물 전체 목록 출력을 위한 SQL문 작성 시에는 로딩 속도 향상을 위해 order by 구문 대신 Index Hint를 사용하였습니다. 게시물 등록/수정/삭제 후에는 redirect 처리하여 전체 목록 페이지로 돌아가도록 하였습니다. 게시물 추천 및 취소 기능은 무한 추천을 방지하고자 Ajax 비동기 처리로 로그인한 회원에 한해 아이디 당 게시물 1건에 1회만 추천할 수 있도록 설정하였습니다. 게시물 추천 DB의 추천 수가 게시판 DB의 추천 수에 함께 반영이 될 수 있도록 게시판 서비스 계층의 실행 메서드에 트랜잭션 처리 하였습니다.
  • 26. 06 Back-End 04 게시판 CRUD 04-01 게시물 조회, 작성, 등록, 수정, 삭제 게시판 CRUD 기능에 SummerNote 에디터를 추가하여 사용자가 자유롭게 텍스트를 편집할 수 있도록 하였습니다. 게시물 수정/삭제는 사용자 아이디를 기준으로 작성자와 로그인한 사용자의 아이디가 동일한 경우에만 처리 가능하도록 설정하였습니다. 게시물 등록/수정/삭제 후 처리가 정상적으로 되었음을 사용자에게 알리기 위해 모달창을 사용하였습니다.
  • 27. 06 Back-End 04 게시판 CRUD 04-02 게시물 검색 게시판 CRUD 기능에 검색 기능을 추가하여 사용자가 조건에 맞는 게시물을 찾을 수 있도록 하였습니다. 검색 결과로 나온 게시물을 조회한 후 조회 페이지 하단에 있는 ’목록으로’ 버튼 클릭 시 게시판 조회 목록으로 돌아갈 때, 검색 결과와 페이지 위치가 그대로 유지될 수 있도록 하였습니다. 검색 조건이 적용된 게시물 조회 페이지의 URL 다시 게시판 목록 페이지로 돌아갔을 때 검색 조건이 유지되는 URL MyBatis 동적 SQL문으로 작성한 검색 조건 SQL문
  • 28. 06 Back-End 04 게시판 CRUD 04-03 게시물 추천, 취소 1. 로그인한 회원이 게시물 조회 시 BoardController의 게시물 조회 페이지 담당 메서드는 해당 회원의 해당 게시물 추천 여부 이력을 확인합니다. 그리고 LikeServiceImpl과 LikeMapper, LikeMapper.xml을 거쳐 DB로부터 확인한 결과값을 JS에 전달하여 화면에 추천 이력이 있으면 ‘추천1’ 버튼을, 추천 이력이 없으면 ‘추천’ 버튼이 나타나도록 합니다. 2. ‘추천’ 버튼 클릭 시 JS에서는 Ajax 비동기 방식으로 URL을 통해 LikeController에서 게시물 추천 등록을 담당하는 메서드에 해당 게시물의 번호와 회원 아이디를 전달하고 이 값들은 모두 게시물 추천을 관리하는 DB에 저장이 됩니다. 그리고 화면의 ‘추천’ 버튼은 ‘추천1’ 버튼으로 변경되고 비활성화 됩니다. 3. ‘추천1’ 버튼 클릭 시 JS에서는 Ajax 비동기 방식으로 URL을 통해 LikeController에서 게시물 추천 취소를 담당하는 메서드에 해당 게시물의 번호와 회원 아이디를 전달하고 이 값들을 가지고 DB는 저장해 놓았던 추천 이력을 삭제합니다. 그리고 화면의 ‘추천1’ 버튼은 ‘추천’ 버튼으로 변경되고 비활성화 됩니다. MemberController * 로그인한 사용자의 게시물 추천 여부 확인 /sjboard/get.jsp * 게시물 추천 이력에 따라 추천 버튼을 다르게 출력하는 JS 메서드
  • 29. 06 Back-End 04 게시판 CRUD 04-04 최신 게시물, 인기 게시물 사용자가 SJBoard 접속 시 가장 먼저 보게 되는 홈 페이지에 최신 게시물 및 인기 게시물이 나타나도록 하였습니다. 최신 게시물은 등록일 기준, 인기 게시물은 추천수 기준으로 기존 게시판의 페이징 처리시 사용한 DTO를 재활용하여 각각 10개씩 홈 페이지에 나타나도록 하였습니다.
  • 30. 06 Back-End 05 댓글 CRUD 댓글은 아래와 같이 계획하여 REST 방식으로 CRUD 기능을 구현하였습니다. 사용자의 입력 데이터는 JSON 타입으로 받고 서버 내부에서는 ReplyVO 타입으로 반환합니다. 사용자 댓글 조회 시 화면에 나타나는 출력 데이터는 JSON 타입과 XML 타입으로 전달됩니다. 댓글 DB에서 집계되는 댓글 수가 게시판 DB의 댓글 수에 함께 반영이 될 수 있도록 게시판 서비스 계층의 실행 메서드에서 트랜잭션 처리 하였습니다. Task Controller URL Method 댓글 목록 ReplyController /replies/pages/:bno/:page GET 댓글 조회 /replies/:rno GET 댓글 등록 /replies/new POST 댓글 수정 /replies/:rno PUT or PATCH 댓글 삭제 /replies/:rno DELETE
  • 31. 06 Back-End 05 댓글 CRUD 댓글 작성/등록은 로그인한 회원만 가능하도록 설정하였습니다. 05-01 댓글 조회, 작성, 등록, 수정, 삭제 댓글 수정/삭제는 신규 댓글 작성과 달리 댓글이 등록된 위치에서 바로 수정 및 삭제 처리가 가능하도록 모달창을 사용하였습니다. 댓글 수정/삭제는 사용자 아이디를 기준으로 작성자와 로그인한 사용자의 아이디가 동일한 경우에만 처리 가능하도록 설정하였습니다. 비회원/로그인 하지 않은 회원의 경우 댓글 창이 나타나지 않음 로그인한 사용자에 한해 댓글 창이 나타남
  • 32. 06 Back-End 06 파일 업로드 CRUD 파일 업로드는 아래와 같이 파일의 종류를 구분하여 페이지마다 CRUD 기능 구현 계획을 세웠습니다. 이미지 파일 일반 파일 sjboard/register.jsp (게시물 작성 페이지) - 파일 첨부란에 업로드 하고자 하는 이미지 파일의 섬네일 이미지가 나타나도록 한다. - 파일 첨부란에서 파일 이름 옆 x 버튼 클릭 시 해당 파일이 파일 첨부란에서 사라지도록 한다. - 파일 첨부란에 일반 문서 이미지가 나타나도록 한다. (구글에서 무료 이미지를 찾아 attach.png로 활용) - 파일 첨부란에서 파일 이름 옆 x 버튼 클릭 시 해당 파일이 파일 첨부란에서 사라지도록 한다. sjboard/get.jsp (게시물 조회 페이지) - 파일 첨부란에 해당 게시물에 등록된 이미지 파일의 섬네일 이미지가 나타나도록 한다. (sjboard/register.jsp와 동일) - 섬네일 이미지 클릭 시 원본 이미지가 화면에 나타나도록 한다. - 파일 첨부란에 해당 게시물에 등록된 파일의 일반 문서 이미지가 나타나도록 한다. (sjboard/register.jsp와 동일) - 원본 이미지 클릭 시 일반 파일을 다운로드할 수 있게 한다. (클릭 시 JS로 ‘다운로드 하시겠습니까?’라는 confirm창을 화면에 띄운다) sjboard/modify.jsp (게시물 수정 페이지) - 게시물 수정 시) * 이미 등록된 첨부 파일을 삭제할 수 있다. * 첨부 파일을 추가 등록할 수 있다. - 게시물 삭제 시) * 게시물과 함께 등록되어있던 첨부파일도 함께 삭제되어야 한다. 고려사항 1) 동일한 이름으로 파일이 업로드 되었을 때 기존 파일이 사라지는 문제 -> 게시판 첨부 파일을 모아 놓는 업로드 폴더 내에 '연/월/일' 폴더를 생성하여 업로드 날짜 별로 파일을 구분할 수 있도록 설계 -> java.util.UUID 클래스를 사용하여 파일 이름 앞에 UUID 값을 추가하고 '_'로 구분될 수 있도록 설계 2) 이미지 파일의 경우에는 원본 파일의 용량이 큰 경우 섬네일 이미지를 생성해야 하는 문제 -> Thumbnailator 라이브러리를 이용하여 섬네일 이미지 생성 -> 섬네일 이미지의 경우 원본 이미지와의 파일명 구분을 위해 's_UUID_파일명'으로 저장되도록 설계 3) 첨부파일 공격에 대비하기 위한 업로드 파일의 확장자 제한 -> 파일 당 최대 용량은 5MB로 지정 -> 확장자가 exe, sh, zip, alz 인 파일의 업로드 금지 설정
  • 33. 06 Back-End 06 파일 업로드 CRUD 파일 업로드는 아래와 같이 CRUD 기능을 구현하였습니다. 작업 Controller URL Method Parameter From (별도의 입력화면 필요여부) URL 이동 여부 파일 업로드 처리 UploadController /uploadAjaxAction POST uploadfile Ajax 비동기 처리 이미지 파일인 경우 섬네일 표시 /display GET filename 일반 파일인 경우 첨부파일 다운로드 /download GET userAgent, (IE 호환을 위한 브라우저엔진 확인용) filename 게시물 작성 시 첨부파일 삭제 /deletefile POST filename, type (이미지: 1, 일반 파일: 0) 게시물 조회 시 해당 게시물의 첨부 파일 목록을 가져옴 BoardController /getAttachList GET bno 첨부 파일은 게시물 생성, 수정, 삭제 시 함께 작동되어야 하므로 각각의 게시판 서비스 계층의 실행 메서드에서 트랜잭션 처리 하였습니다. 댓글 기능과 함께 웹 페이지 동작의 일관성을 유지하고자 Ajax 비동기 방식으로 구현하였습니다.
  • 34. 06 Back-End 06 파일 업로드 CRUD 사용자가 업로드한 파일이 서버에 저장될 시 동일한 이름의 파일이 업로드 되었을 때 기존 파일이 사라지는 문제를 해결하고자 서버 내 파일 업로드 경로에 ‘연/월/일’ 폴더를 생성하여 업로드 날짜별로 파일을 구분할 수 있도록 하였습니다. java.util.UUID 클래스를 사용하여 사용자가 업로드하는 파일 이름에 UUID값을 추가하고 ‘_’로 구분할 수 있도록 설정하여 같은 날에 동일한 이름으로 업로드 된 파일 또한 서로 구분되어 각각 저장될 수 있도록 설정하였습니다. 06-01 파일 업로드 경로 내 ‘연/월/일’ 폴더 생성
  • 35. 06 Back-End 06 파일 업로드 CRUD 06-01 파일 업로드 경로 내 ‘연/월/일’ 폴더 생성 사용자가 업로드한 파일이 서버에 저장될 시 동일한 이름의 파일이 업로드 되었을 때 기존 파일이 사라지는 문제를 해결하고자 서버 내 파일 업로드 경로에 ‘연/월/일’ 폴더를 생성하여 업로드 날짜별로 파일을 구분할 수 있도록 하였습니다. 서버 내 파일 업로드 경로에 생성된 연/월/일 폴더 java.util.UUID 클래스를 사용하여 사용자가 업로드하는 파일 이름에 UUID값을 추가하고 ‘_’로 구분할 수 있도록 설정하여 같은 날에 동일한 이름으로 업로드 된 파일 또한 서로 구분되어 각각 저장될 수 있도록 설정하였습니다. 이미지 파일의 경우 파일 업로드 및 조회 시 어떤 이미지 파일인지 화면에서 미리 볼 수 있도록 섬네일 이미지를 자동으로 생성하도록 하였기 때문에, 섬네일 이미지의 경우에는 원본 이미지와의 파일명 구분을 하고자 's_UUID_파일명'으로 저장되도록 설정 하였습니다.
  • 36. 06 Back-End 06 파일 업로드 CRUD 게시물 작성 중 파일 업로드 시 이미지 파일의 경우에는 해당 이미지의 섬네일 이미지가, 일반 문서의 경우에는 일반 문서 이미지가 파일 첨부란에 나타나도록 하였습니다. 06-02 게시물 작성 시 이미지, 일반 파일 업로드 파일 업로드 시 이미지 파일의 섬네일을 보여주는 UploadController의 메서드 게시물 등록 시 첨부 파일을 저장하는 UploadController의 메서드 실제 게시물 등록과 함께 첨부 파일이 등록되므로 게시물 등록 시 첨부 파일 관리 DB에 첨부 파일 데이터가 저장될 수 있도록 BoardServiceImpl 내 게시물 등록 처리 메서드에 트랜잭션 처리를 하였습니다.
  • 37. 06 Back-End 06 파일 업로드 CRUD 06-03 게시물 조회 시 이미지, 일반 파일 처리 게시물 조회 페이지에서 첨부 파일 클릭 시 이미지는 원본 이미지가 화면에 출력되고, 일반 파일은 원본 파일을 다운로드 할 수 있게 구현하였습니다. 이미지 파일의 경우 클릭 시 원본 이미지 출력 일반 파일의 경우 클릭 시 원본 파일 다운로드
  • 38. 06 Back-End 07 회원정보 Task Controller URL Method Parameter From (별도의 입력화면 필요여부) URL 이동 여부 회원 정보 조회 Member Controller /member/profile GET O 회원 정보 수정 페이지 /member/update GET Authentication O O 회원 정보 수정 /member/update POST HttpSession X O 회원 탈퇴 페이지 /member/delete GET Authentication O O 회원 탈퇴 /member/delete POST Authentication, HttpSession X O 회원 정보는 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다. 비회원이 해당 URL에 직접 접근하더라도 페이지를 조회할 수 없도록 각각의 URL을 담당하는 Controller 내 메서드에 @PreAuthorize 어노테이션을 추가하였습니다. 회원 정보 수정 후에는 수정된 정보를 반영하기 위해 세션을 초기화 하고 다시 로그인할 수 있도록 로그인 페이지로 redirect 처리하였습니다. 회원 탈퇴 시 자동 로그아웃이 될 수 있게 SecurityContextHolder 클래스의 clearContext() 메서드를 사용하고 세션을 초기화하였으며 홈 페이지로 이동할 수 있도록 redirect 처리하였습니다.
  • 39. 06 Back-End 07 회원정보 07-01 회원 정보 조회, 수정, 탈퇴 회원 정보 수정/탈퇴 페이지 접근 시 현재 로그인한 사용자의 정보를 가져오기 위해 Authentication 객체와, Principal 객체를 사용하였습니다. 회원 정보 수정/ 탈퇴 후에는 세션을 초기화하고 모달창을 이용하여 처리 결과를 안내하도록 설정하였습니다.
  • 40. 06 Back-End 08 관리자 페이지 관리자 페이지는 아래와 같이 계획하여 스프링 웹 시큐리티의 기능을 이용해 구현하였습니다. 비회원이나 일반 회원이 해당 URL에 직접 접근하더라도 페이지를 조회할 수 없도록 각각의 URL을 담당하는 Controller 내 메서드에 @PreAuthorize 어노테이션을 추가하였습니다. 관리자 페이지에서 관리자가 주간 현황 및 기간별 현황을 쉽게 볼 수 있도록 구글 차트로 데이터를 조회할 수 있도록 구현하였습니다. Task Controller URL Method Parameter From (별도의 입력화면 필요여부) URL 이동 여부 메인 페이지 Admin Controller /admin/main GET X O 전체 회원 정보 /admin/memberList GET O O 회원 권한 변경 /admin/updateAuth POST userid, auth X Ajax 비동기 처리 회원 강제 탈퇴 /admin/deleteMember POST userid X 기간별 게시물 현황 /admin/bnoStats GET O O 기간별 게시물 수 Chart Controller /chart/bno GET fromDate, toDate X Ajax 비동기 처리 기간별 댓글 수 /chart/rno GET fromDate, toDate X 기간별 회원 수 /chart/member GET fromDate, toDate X
  • 41. 06 Back-End 08 관리자 페이지 회원 목록 페이지에서 전체 회원 정보를 조회할 수 있도록 하였습니다. 사용자 편의를 위해 페이지 이동이나 새 창 없이 회원 목록 페이지 내에서 회원 권한 변경 및 회원 강제 탈퇴 처리를 할 수 있도록 구현하였습니다. /admin/meberList.jsp 내 회원 권한 변경 및 회원 강제 탈퇴 처리 JS 메서드 08-01 전체 회원 목록 조회 & 회원 권한 변경 및 강제 탈퇴 처리
  • 42. 06 Back-End 08 관리자 페이지 메인 페이지에서 전체 현황 및 주간 신규 게시물 수, 댓글 수, 회원 수 현황을 확인할 수 있도록 구현 하였습니다. 08-02 주간 신규 게시물 수 , 댓글 수, 회원 수 현황 확인 사용자 편의를 위해 주간 신규 게시물 수, 댓글 수, 회원 수 현황 데이터는 보기 쉽게 시각화 할 필요성이 있어 구글 차트를 사용하였습니다. 주간 현황의 경우 조회 날짜를 기준으로 지난주와 이번주 데이터를 가지고 와서 사용자가 쉽게 변화 추이를 비교할 수 있도록 하였습니다. /admin/main.jsp 구글 차트 JS 메서드 AdminMapper.xml 주간 현황 쿼리문 주간 현황의 경우 AdminMapper.xml에서 작성한 쿼리문을 통해 이미 주간 데이터를 조회하고 있기 때문에 따로 DB 데이터를 JSON으로 파싱하지 않고, 메인 페이지에 출력되는 데이터들을 JS 변수에 저장하여 구글 차트에 전달하는 식으로 설정하였습니다.
  • 43. 06 Back-End 08 관리자 페이지 기간별 게시물 현황, 기간별 댓글 현황, 기간별 회원 현황 메뉴에서는 사용자가 직접 날짜를 설정해 해당 기간 동안의 변화 추이를 볼 수 있도록 구현하였습니다. 08-03 기간별 게시물 수, 댓글 수, 회원 수 현황 확인 조회 기간 날짜 입력은 jQuery의 datepicker 위젯을 사용하여 사용자가 쉽게 달력을 확인하여 날짜를 선택할 수 있도록 하였습니다. 각 뷰 페이지 jsp datepicker JS 메서드
  • 44. 06 Back-End 08 관리자 페이지 08-03 기간별 게시물 수, 댓글 수, 회원 수 현황 확인 기간별 현황 데이터는 사용자가 직접 조회 기간을 설정하는 것이므로 별도의 ChartMapper를 생성하고 ChartServiceImpl에서 Mapper에서 처리된 DB의 결과를 JSON 타입으로 파싱하도록 구현하였습니다. JSON 구현 형태 { "cols": [ {"type":"string", "label":"등록일"} {"type":"number", "label":"개수"} ], "rows": [ {"c":[{"v":"날짜"}, {"v":"개수"}]} ] } 1. 사용자가 입력한 조회 기간이 Ajax 비동기 방식으로 URL을 통해 Controller에 전달 되면 Controller의 메서드는 해당 기간의 데이터를 JSON 타입으로 파싱하고자 ChartServiceImpl에서 구현된 담당 메서드를 호출합니다. 2. ChartServiceImpl, ChartMapper, ChartMapper.xml을 거쳐 DB로부터 확인된 해당 기간의 데이터는 다시 ChartServiceImpl에 전달되고, ChartServiceImpl에서는 DB로부터 전달 받은 결과값을 JSON 타입으로 파싱하여 ChartController의 담당 메서드에 전달합니다. 3. ChartController를 통해 JSON 타입으로 파싱된 결과값은 JS로 전달되고 구글 차트로 출력됩니다.
  • 45. 07 후기 및 보완점 SJBoard 프로젝트는 저의 첫 스프링 프로젝트입니다. 작년 12월 말 그동안의 경력을 뒤로하고 새롭게 백엔드 개발자가 되기로 결심한 후 처음 개발 공부를 시작했을 때만 하더라도 Java의 개념과 용어들은 다소 낯설고 막연하게만 느껴졌습니다. 하지만 올해 2월 말부터 스프링 공부를 시작하면서 추상적으로만 느껴졌던 Java의 개념들이 실제 웹 개발에 어떻게 쓰이는지 깨닫게 되었고 실제 제가 작성한 코드가 웹 상에서 실행되는 것을 보며 개발 공부에 본격적으로 재미를 붙이게 되었습니다. 처음부터 모든 것의 이론과 예제를 끝까지 학습한 뒤 프로젝트를 시작하는 것보다 프로젝트를 진행 하면서 프로젝트에 필요한 개념과 기술들을 학습하는 것이 개발 공부를 하는데 가장 효율적인 방법이라는 생각이 들었습니다. 그래서 <코드로 배우는 스프링 웹 프로젝트 개정판> 책으로 스프링을 학습하며 책의 중반부터는 SJBoard 프로젝트를 기획하고 시작하게 되었습니다. 기본적으로 SJBoard의 게시판, 댓글, 파일 업로드, 로그인 기능은 책에 나온 예제를 바탕으로 구현하였습니다. 그러나 제가 책과 다르게 SJBoard 프로젝트에서 구현하고 싶은 기능들은 따로 책과 인터넷을 찾아보며 하나씩 만들어 나갔습니다. 댓글 작성 방식을 다르게 하고 게시판에 에디터를 활용한 것이 대표적인 예입니다. 그 외의 게시물 추천 기능, 회원 가입 기능, 관리자 페이지 기능들은 책의 도움 없이 혼자 구현해 낸 결과물입니다. 물론 구글 검색을 통해 각종 개발 블로그, StackOverFlow, Okky의 글을 참고하였으나 해당 자료들에 있는 코드가 제가 원하는 기능을 100% 동일하게 구현해낸 것은 아니었습니다. 그래서 DB는 어떻게 구성하는 것이 좋을지, 코드는 어떻게 작성하는 것이 효율적일지, 화면은 어떻게 구성해야 사용자가 이용하는데 편리할지에 대해 스스로 고민하고 노트에 로직도 그려보면서 느리지만 꾸준히 원하는 기능을 구현해냈습니다. 작성한 코드가 예상대로 동작하지 않아 새로운 로직을 생각해내야 할 때, 처음 보는 에러를 해결해야만 할 때, 어제까지만 해도 잘 동작하던 코드가 갑자기 오늘 테스트 시 동작하지 않을 때, 독학으로 개발 공부를 하는 상황이기 때문에 주변에 물어볼 곳이 없어 무조건 혼자 해결하느라 한 가지 문제를 가지고 몇 시간 혹은 하루를 통으로 허비하기도 했습니다. 하지만 스스로 원인을 찾아보고 문제를 파악하면서 스프링 동작 원리와 코드 구조, Java 및 JavaScript의 특징에 대해 좀 더 깊이 이해할 수 있었습니다. 그리고 아무리 오래 걸려도 결국에는 스스로 문제를 해결해내는 제 자신을 보며 작은 성취감을 맛보는 재미에 취해 더욱 개발 공부와 프로젝트 구현에 몰입할 수 있었습니다. 3개월 전 코딩의 ㅋ도 몰랐던 제가 스프링을 다루고 작은 프로젝트를 하나 끝냈다는 것이 꽤 자랑스럽고 즐겁습니다. 이번 SJBoard 프로젝트를 통해 학습한 개발 지식들을 바탕으로 어엿한 백엔드 신입 개발자가 될 수 있도록 계속 개발 지식과 역량을 쌓고자 합니다. 느리더라도 꾸준히 발전하는 개발자가 되도록 하겠습니다. 감사합니다. 01 후기
  • 46. 07 후기 및 보완점 SJBoard 프로젝트를 마무리 하면서 스스로 보완해야 하는 점이라고 생각한 부분은 아래와 같습니다. 1. 회원 정보 수정 기능에 RESTful API 적용 • 댓글 기능에 RESTful API를 적용한 것과 같이 회원 정보 수정 기능에도 RESTful API를 적용했으면 조금 더 보안에 유리하지 않았을까라는 생각이 듭니다. 회원 정보 수정 페이지의 경우 Authentication 객체와 Principal 객체를 이용하여 로그인한 사용자의 정보를 가져오는 방식으로 구현하였고, @PreAuthorize 어노테이션으로 사용자 접근 권한에 제한을 두었기에 GET 방식의 URL이 노출되더라도 사용자가 임의로 타인의 회원 정보를 수정할 수 없습니다. 그러나 RESTful API를 적용한다면 회원 정보가 URL에 파라미터로 나타나지 않고 JSON 또는 XML로 전달되기 때문에 보안에 더 유리할 것이라는 생각이 들었습니다. 처음 해당 기능을 설계하고 구현했을 당시 RESTful API를 떠올리지 못했다는 것은 아직 RESTfulf API 사용에 미숙한 것을 의미하므로 RESTful API를 다시 학습해야겠다는 생각을 하였습니다. 2. 관리자 페이지 기능 보완 및 확대 • Back-End 개발 시 중요하게 생각해야 하는 점이 여러 가지 있지만 일반 사용자의 입장에서 가장 손쉽게 느낄 수 있는 중요한 점은 바로 관리자 페이지라고 생각합니다. DB나 개발 프로그램에 직접 접속하여 데이터를 사용하고 수정할 수 있는 개발자와 달리 일반 사용자는 화면에 구현된 기능들만으로 DB의 데이터를 활용해야하기 때문입니다. 일반 사용자와 달리 관리자의 경우에는 해당 웹 어플리케이션의 운영과 관리를 위해 DB를 필요에 맞게 수정, 가공할 수 있어야 하기 때문에 사용자 편의를 최우선으로 하여 관리자 페이지의 기능을 보완하고 확대할 필요를 느꼈습니다. SJBoard 프로젝트의 경우 기본 기능이 다양하지 않아 관리자 페이지를 구성하는데 한계가 있었으나, 다른 웹 사이트들처럼 회원 탈퇴 시 탈퇴 사유를 선택 또는 작성하도록 하고 기간별 탈퇴 회원 현황 및 탈퇴 사유를 관리자 페이지에서 조회할 수 있도록 한다면 관리자가 사이트 회원의 유출을 줄이기 위한 대안을 마련하는데 도움을 줄 수 있을 것이라는 생각을 하였습니다. 3. 코드 중복 및 AOP 미적용 • 이메일 인증 번호 전송 기능과 구글 차트를 사용하기 위해 DB 데이터를 JSON으로 파싱하는 기능을 별도의 서비스 클래스로 만들어 인스턴스로 사용하였다면 코드의 중복을 줄이고 프로젝트를 유지, 보수하는데 더 도움이 되었을 것이라는 생각을 하였습니다. 그리고 스프링의 특징 중 하나인 AOP에 대해 개념만 공부하고 실제로 프로젝트에는 적용하지 못해 아쉽습니다. 추후 AOP 활용을 위해 다시 AOP 개념과 사용법을 학습하고 프로그램 유지, 보수 관리에 필요한 로그들을 별도의 AOP로 관리하는 방식으로 프로젝트를 만들어야겠다는 생각을 하였습니다. 02 보완점