본문 바로가기

프로젝트/멋사 개인 프로젝트 (mutsa-SNS)

[14] mutsa-SNS 7일차 - 코드 리펙토링

팀 프로젝트의 조원분들의 피어리뷰를 토대로 코드 리펙토링을 해 보았다.

  • @ApiIgnore annotation 추가 (Swagger 관련)
  • Swagger Authorize button 추가
  • UserDto.build()의 중복 사용 개선
  • PostServiceTest code 개선

 

1. @Apilgnore

@RestController
@RequestMapping("/api/v1/posts")
@RequiredArgsConstructor
public class PostController {

    private final PostService postService;
    
    @PostMapping
    public Response<PostResponse> createPost(@RequestBody PostCreateRequest req, @ApiIgnore Authentication authentication) {
    
    ...
    
    }
    
    ...
}

controller method에 @ApiIgnore annotation을 추가하면, swagger에서 endpoint를 숨길 수 있다 한다.

다만, 받아오는 인자에 @ApiIgnore를 추가하면 @ApiImplictParam으로 선언하지 않은 parameter들을 숨길 수 있다고 한다.

PostController와 UserController의 Authentication의 parameter들이 매우 많아 보기 불편했는데, 위의 annotation을 앞에 추가해주니 보기 깔끔해 졌다.

 

<Reference>

https://velog.io/@gillog/Swagger-UI-Annotation-%EC%84%A4%EB%AA%85

 

[Swagger UI] Annotation 설명

Annotations Swagger 설정을 먼저 하고싶다면 여기글을 먼저 읽고 오면 된다. Swagger에서 API 설명을 위한 Annotation 들을 아래에 정리한다. @ApiOperation = Method 설명 @ApiOperation으로 해당 Control

velog.io

https://recordsoflife.tistory.com/349

 

Spring Boot의 Swagger 문서에서 끝점 숨기기

Java 에코 시스템에서 몇 년간의 경험이 있고 그 경험을 커뮤니티와 공유하고 (물론 작업에 대한 대가를받는 데) 관심이 있다면 "Write for Us"페이지를 참조하십시오 . 건배, Eugen 1. 개요 Swagger 문서

recordsoflife.tistory.com

 

2. Swagger Authorize button

토큰을 받은 후 swagger에서 토큰을 설정하는 법을 몰라 talend로 web test를 진행했었다.

팀원분의 조언으로 swagger authorize button에 대해 알게 되어 설정을 해 보았다.

 

SwaggerConfig

@Configuration
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.OAS_30)
                .securityContexts(Arrays.asList(securityContext()))
                .securitySchemes(Arrays.asList(apiKey()))
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    //Swagger authorization 추가
    private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth()).build();
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
    }

    private ApiKey apiKey() {
        return new ApiKey("Authorization", "Authorization", "header");
    }

}

swagger 공식 문서대로, authroization 설정을 추가하였다.

이 때, jwtTokenFilter에서 HttpHeaders.AUTHORIZATION 로 검증을 진행했기 때문에, ApiKey에서 "authorization"으로 설정하였다.

설정 방법은 아래의 reference들을 참조하였다.

 

<Reference>

https://www.baeldung.com/spring-boot-swagger-jwt

https://lemontia.tistory.com/1027

 

[swagger3] 설정 및 authroize button 활성화하기(Bearer 사용)

버전 2보다 좋은 점은 url에 다음과 같이 되어있을때 http://localhost:9001/swagger-ui/index.html#/1.Login/loginUsingPOST 브라우저로 접속하면 해당 api가 바로 펼쳐지면서 이동한다. (아마 그게 전부... 대신 이 기

lemontia.tistory.com

https://blog.jiniworld.me/113#a03-1

 

[Spring Boot Tutorial] 17. Bearer JWT를 이용한 api 인증 (Swagger v3)

※ [Spring Boot Tutorial] 16. Swagger v3에 HTTP 기본인증(Basic Authentication) 설정하기 과정을 먼저 선행한 후 진행해주세요. Bearer 기본 Bearer + JWT? JWT? JWT 라이브러리 추가 JwtBuilder 구조 Bearer + JWT api에 적용

blog.jiniworld.me

 

3. UserDto.of method 추가

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
public class UserDto {

    private int id;
    private String userName;
    private String password;
    private UserRole role;

    public UserDto of(User user) {
        return UserDto.builder()
                .id(user.getId())
                .userName(user.getUserName())
                .role(user.getRole())
                .build();
    }

}

 

기존 UserService.join과 UserService.changeUserRole method에서 return할 때,

db에 저장된 User Entity의 정보를 불러와 builder.build를 이용하여 UserDto를 설정하는 방식이 중복되었다.

팀원분의 조언을 받아 UserDto에서 of method를 만들어 사용해 중복되는 코드를 줄여보았다.

 

4. PostServiceTest code 개선

public class PostServiceTest {

    PostService postService;

    PostRepository postRepository = mock(PostRepository.class);
    UserRepository userRepository = Mockito.mock(UserRepository.class);

    User user;
    Post post;

    @BeforeEach
    void setUp() {
        postService = new PostService(postRepository, userRepository);

        user = User.builder()
                .id(1)
                .userName("userName")
                .password("password")
                .role(UserRole.USER)
                .build();

        post = Post.builder()
                .id(1)
                .user(user)
                .title("title")
                .body("body")
                .build();
                
	}

	...
    
}

postServiceTest에 불필요한 annotation인 @WithMockUser 붙어있었다.

ServiceTest에는 Security의 권한 인증이 필요 없기 때문에 제거해 주었다.

또한 ServiceTest에서 반복적으로 설정해 주었던 Post와 User들을 @BeforeEach에서 설정해 주어 중복되는 코드를 줄여 보았다.

 

또한, 작성자 != 변경글의 유저 를 검증과정에서 잘못된 로직을 발견하여 수정하였다.

@Test
@DisplayName("수정 실패 - 작성자!=유저")
void post_modify_fail2() {

    //작성자
    User postCreator = User.builder()
            .id(2)
            .userName("userName2")
            .password("password2")
            .role(UserRole.USER)
            .build();

    when(postRepository.findById(post.getId())).thenReturn(Optional.of(post));
    when(userRepository.findByUserName(postCreator.getUserName())).thenReturn(Optional.of(postCreator));


    AppException exception = assertThrows(AppException.class,
            ()-> {
                postService.modifyPost(post.getId(), post.getTitle(), post.getBody(), postCreator.getUserName());
            });

    Assertions.assertEquals("INVALID_PERMISSION", exception.getErrorCode().name());
}

 

피어리뷰를 진행하며, 다른 팀원들의 코드를 보면서 공부가 많이 되었던 것 같다.

새로운 기능들에 대한 정보도 알게 되었고, 어떻게 하면 보다 깔끔한 코드를 짤 수 있는지에 대한 힌트도 많이 얻었던 것 같다.

또한 받은 리뷰들을 보며 내가 생각치 못했던 부분들을 발견해주셔서 그것들을 고치면서 또한 공부가 많이 되었다.

 

<프로젝트 Git Lab URL>

https://gitlab.com/pigeon2gugu/finalproject_kimhaneul

 

하늘 / FinalProject_KimHaneul · GitLab

GitLab.com

gitlab.com

 

<전체 Reference>

https://velog.io/@gillog/Swagger-UI-Annotation-%EC%84%A4%EB%AA%85
https://recordsoflife.tistory.com/349
https://www.baeldung.com/spring-boot-swagger-jwt
https://lemontia.tistory.com/1027
https://blog.jiniworld.me/113#a03-1