사이먼's 코딩노트

[SpringBoot] REST API (2) 본문

Java/SpringBoot

[SpringBoot] REST API (2)

simonpark817 2024. 6. 16. 12:31

[REST API 적용]

  • 앞선 포스팅 'REST API (1)'에서는 개념 소개를 했다면, 이번에는 실제로 REST API를 적용하기 위해 코드에 적용해봅시다.
  • 구현된 코드는 저번 JWT 토큰 발급때 진행했던 리포지터리에서 작업을 이어갈 예정이기 때문에 전체 코드는 해당 리포지터리 주소를 통해 참고 부탁드립니다.
  • 리포지터리 URL 주소 : https://github.com/psm817/jwt_review
 

GitHub - psm817/jwt_review

Contribute to psm817/jwt_review development by creating an account on GitHub.

github.com

 

[기본 세팅]

  • 먼저 REST API 적용을 하기 위해 build.gradle에 아래와 같이 시큐리티, 유효성체크, DB와 관련된 라이브러리를 추가해준다.
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
runtimeOnly 'com.h2database:h2'

 

  • 기존에 application.yml에 작성한 임의의 secret key를 application-secret.yml이라는 파일을 새로 생성하여 옮겨준다.
  • 필자는 application-secret.yml을 보안상 secret key가 유출되지 않도록 깃허브로 push되는 것을 gitignore를 통해 막아놓기 때문에 리포지터리에서는 보이지 않는다.
custom:
  jwt:
    secretKey: alskdjvocijioq23450lckjvclxzk3430415lkzdlkjacv043121235lkjdazdflv3papopw

 

  • 다음은 application.yml를 아래와 같이 작성한다.
  • 아래 세팅은 프로그램 실행과 동시에 application-dev.yml이 활성화되고 application-secret.yml를 포함한다는 의미를 가지며, DB는 3306 포트에 rest_api_dev라는 데이터베이스와 연결된다는 의미를 가진다.
spring:
  profiles:
    active: dev
    include: secret
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://127.0.0.1:3306/rest_api_dev?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul
    username: root
    password:
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        use_sql_comments: true
logging:
  level:
    root: INFO
    com.ll.rest_api: DEBUG
    org.hibernate.orm.jdbc.bind: TRACE
    org.hibernate.orm.jdbc.extract: TRACE
custom:
  site:
    baseUrl: http://localhost

 

  • 마지막으로 테스트 환경에서 적용되는 설정을 위해 application-test.yml 파일을 생성하여 아래와 같이 작성한다.
spring:
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:test;
    username: sa
    password:

 

[Spring Security 설정]

  • 현재 세팅이 된 상태로 회원의 로그인 테스트를 하기엔 시큐리티가 적용되어 있기 때문에 진행을 할 수 없다.
  • 그래서 Spring Security에 관한 설정 SecurityConfig.java 클래스를 생성한 뒤 아래와 같이 코드를 작성한다.
  • 해당 코드를 작성하게 되면 시큐리티에 의해 생성된 폼 로그인 방식이 꺼지게 되면서 커스텀이 가능하게 된다.
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .cors().disable() // 타 도메인에서 API 호출 가능
                .csrf().disable() // CSRF 토큰 끄기
                .httpBasic().disable() // httpBaic 로그인 방식 끄기
                .formLogin().disable() // 폼 로그인 방식 끄기
                .sessionManagement(sessionManagement ->
                        sessionManagement.sessionCreationPolicy(STATELESS)
                ); // 세션끄기

        return http.build();
    }
}

 

[MemberController 생성]

  • /member/login POST 전달을 구현하기 위해서 MemberController.java 클래스를 생성하고 아래와 같이 코드를 작성한다.
  • 기존과 다르게 어노테이션을 @Controller가 아닌 @RestController를 작성해주면 return 값에 String 문자열을 @ResponseBody 없이 작성해도 문제가 없다.
@RestController
@RequestMapping("/member")
public class MemberController {
    @PostMapping("/login")
    public String login() {
        return "성공";
    }
}

 

  • 테스트 환경에서도 MemberController.java 클래스를 동일하게 만들어 MockMvc 라이브러리를 통해 웹 애플리케이션을 테스트 해본다.
  • 아래와 같이 코드를 작성하면 /member/login으로 데이터를 보내는데, 해당 데이터는 content에 작성된 username, password를 UTF-8형태의 JSON화 시켜서 보낸다.
  • 테스트를 실행하면 실제 위에서 MemberController.java에 구현한 /member/login로 해당 데이터가 전달되고, 전달에 잘 됐다면 테스트 창의 body에 "성공"이라는 문자가 표시된다.
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
@ActiveProfiles("test")
class MemberControllerTest {
    @Autowired
    private MockMvc mvc;

    @Test
    @DisplayName("POST /member/login 은 로그인 처리 URL 이다.")
    void t1() throws Exception {
        // When
        ResultActions resultActions = mvc
                .perform(
                        post("/member/login")
                                .content("""
                                        {
                                            "username": "user1",
                                            "password": "1234"
                                        }
                                        """.stripIndent())
                                .contentType(new MediaType(MediaType.APPLICATION_JSON, StandardCharsets.UTF_8))
                )
                .andDo(print());

        // Then
        resultActions
                .andExpect(status().is2xxSuccessful());
    }
}

 

[테스트용 Member 생성]

  • member에 관련된 기본 패키징은 리포지터리를 통해 참고 부탁드리며, 모든 구성이 완료되었다면 initData 패키지 내의 NotProd.java 클래스를 생성하여 테스트 회원 데이터를 2명 만들어준다.
  • 아래와 같이 코드를 작성하면 프로그램 시작과 동시에 DB에 회원 데이터 2명이 생성된다.
  • 해당 코드가 정상적으로 실행되려면 MemberService.java에 join() 메서드가 작성되어 있어야한다.
@Configuration
@Profile({"dev", "test"})
public class NotProd {
    @Bean
    CommandLineRunner initData(MemberService memberService, PasswordEncoder passwordEncoder) {
        String password = passwordEncoder.encode("1234");

        return args -> {
            Member member1 = memberService.join("user1", password, "user1@test.com");
            Member member2 = memberService.join("user2", password, "user2@test.com");
        };
    }
}

 

 

 

반응형

'Java > SpringBoot' 카테고리의 다른 글

[SpringBoot] REST API (4)  (0) 2024.06.19
[SpringBoot] REST API (3)  (0) 2024.06.16
[SpringBoot] REST API (1)  (0) 2024.06.16
[SpringBoot] JWT 토큰 발급  (0) 2024.06.15
[SpringBoot] Cookie / Session / JWT  (2) 2024.06.15