Skip to content

clean17/first-blog3

Repository files navigation

블로그 프로젝트

blogmain

  • 관리자 페이지

image

image

image

image

일반 계정 : ssar / 1234
관리자 엔트리포인트 : /admin
관리자 계정 : admin / admin

개발 목표

  • DB를 설계하고 연관관계를 파악해서 기본적인 CRUD 쿼리를 작성해본다
  • 블로그의 로직을 이해하고 필요한 기능 및 추가되면 좋을 기능을 생각해서 추가해본다.
  • 단위 테스트를 하는것에 익숙해진다.

개발 환경

  • Visual Studio Code
  • Java 11

기술 스택

  • JDK 11
  • Spring Boot 2.7.8
  • MyBatis
  • 테스트 h2 DB
  • 프로덕션 MySql DB
  • JSP
  • JUnit

기능정리

1단계

  • 회원 가입, 로그인, 글 쓰기, 글 목록보기 (썸네일 제외), 글 상세보기, 글 삭제 , 글 수정, 썸네일

2단계

  • 댓글 쓰기, 댓글 목록보기, 댓글 삭제, 프로픽 사진 추가

3단계

  • 좋아요 버튼, 좋아요 갯수

4단계

  • 아이디 중복체크, 회원수정하기

5단계

  • 관리자 추가, 검색, 이메일

의존성 주입

implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.jsoup:jsoup:1.15.3'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.9'
implementation 'javax.servlet:jstl'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.3.0'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter-test', version: '2.2.2'

테이블 모델링

블로그 DB 설계


적용된 기능

  • 아이디 중복체크기능
  • 비밀번호 중복확인 기능
  • 글 쓰기 수정 삭제 기능
  • 자신이 썼던 글에 들어갈 경우만 수정 삭제 버튼 보임
  • 글을 작성하면 메인화면에 작성한 글목록에 보이고 첫번째 사진이 썸네일로 사용
  • ajax 비동기 통신으로 댓글 작성 삭제 기능
  • 글과 댓글에 좋아요 기능 및 좋아요수 확인기능
  • 프로필사진 수정 기능
  • 관리자 계정 및 관리자 페이지 추가 후 작성된 글, 댓글 검색기능 및 삭제기능
  • 이메일 api를 이용해서 관리자가 메일을 보내는 기능
  • Sha256을 이용한 비밀번호 암호화
  • Junit을 이용한 단위 테스트
  • 인터셉터를 추가해 인증처리

이슈

  • 좋아요 기능을 구현하려고 할때 테이블에서 삭제하지 않고 상태값만 변하게 만들고 싶었는데 여러 환경마다 방법이 달라서 시행착오 끝에 지금 환경에서는 useGenerateKey를 사용해서 id를 리턴하면 손쉽게 좋아요상태를 update할 수 있었다.

기술 블로그


Object Mapper 의존성 주입 방법


일반적으로 스프링부트가 실행되면 스프링 컨텍스트에 Object Mapper가 자동으로 빈으로 등록됩니다.
하지만 테스트할 때는 테스트 범위에 따라 컨텍스트에 생성되는 빈들의 범위가 달라져 필요한 빈이 없을수도 있습니다.
예를 들면 통합테스트를 하는 @SpringBootTest 는 테스트에 필요한 모든 빈들을 컨텍스트에 등록해 테스트를 진행하므로
@Autowired를 통해서 의존성을 가져올 수 있습니다.
image

하지만 단위 테스트인 @MybatisTest일 경우 컨텍스트에 Mybatis와 관련된 빈들만 등록되어 Object Mapper 빈이 없기 때문에
@Autowired 통해서 빈을 주입한다면 테스트 시 UnsatisfiedDependencyException 익셉션이 발생합니다.
image
image
image

따라서 @MybatisTest 같은 단위 테스트 시에는 다른 방법으로 의존성을 주입해야 합니다.

  • 첫번째 방법으로는 @MockBean + Mockito라이브러리의 조합으로 메소드의 동작을 정의해서 테스트를 하는 방법이 있습니다.
  • 두번째 방법으로는 @TestConfiguration를 이용해서 테스트 환경에서만 등록될 빈을 직접 등록하는 방법입니다.
    image
  • 세번째 방법으로는 수동으로 인스턴스를 직접 생성해서 사용하는 방법입니다.
    image

기타 메모

  • 단위테스트에서 세션이 필요한 경우는 MockHttpSession 을 직접 생성합니다.
    @Autowired를 해봤자 컨텍스트에 없기 때문에 가져오지 못합니다.
    image

  • 테스트 시 리턴된 모델 null 처리 방법
	ResultActions rs = mvc.perform(get("/board/detail/1"));
	ModelAndView mv = rs.andReturn().getModelAndView();
	Map<String, Object> map = (mv != null) ? mv.getModel() : new HashMap<>();
	List<ReplyListRespDto> rdo = (List<ReplyListRespDto>) map.get("replyList");
	assertThat(rdo.get(0).getUsername()).isEqualTo("ssar");
  • 추가적인 리턴 결과 확인
	MockHttpServletResponse response = rs.andReturn().getResponse();
	int status = response.getStatus(); // 상태 코드
	String contentType = response.getContentType(); // 컨텐츠 타입
	String content = response.getContentAsString(); // 본문 데이터
  • 유효값 검증 @NotBlank
    @ExceptionHandler(BindException.class) 
    public ResponseEntity<?> customException(BindException e){
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();		
        String errorMessage = fieldErrors.get(0).getDefaultMessage();
        return new ResponseEntity<>(Script.back(errorMessage), HttpStatus.BAD_REQUEST);
    }
  • @Controller + ResponseEntity 는 json을 응답한다. // ResponseEntityResponseBody를 포함

About

블로그 프로젝트 [ 개인 ]

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published