๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring Boot์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ: ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ, MockMvc ํ™œ์šฉ๋ฒ•

mrmount 2024. 10. 21.


Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ํ•„์ˆ˜์ ์ธ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋Š” ์ฝ”๋“œ ํ’ˆ์งˆ์„ ๋ณด์žฅ ํ•˜๊ณ , ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์˜ ์ฐจ์ด , @SpringBootTest ์™€ MockBean ์‚ฌ์šฉ๋ฒ• , ๊ทธ๋ฆฌ๊ณ  MockMvc๋ฅผ ํ™œ์šฉํ•œ REST API ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

 


 

 

๋ชฉ์ฐจ

  1. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์˜ ์ฐจ์ด
  2. @SpringBootTest์™€ MockBean ํ™œ์šฉ๋ฒ•
  3. MockMvc๋กœ REST API ํ…Œ์ŠคํŠธํ•˜๊ธฐ
  4. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์ค‘์š”์„ฑ๊ณผ ํŠธ๋ Œ๋“œ
  5. ํ…Œ์ŠคํŠธ ์˜ˆ์ œ ์ฝ”๋“œ์™€ ์‹คํ–‰ ๊ฒฐ๊ณผ

 


 

1. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์˜ ์ฐจ์ด

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ํฌ๊ฒŒ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(Unit Test) ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ(Integration Test) ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค. ์ด ๋‘ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ์˜ ๋ชฉ์ ๊ณผ ๋ฒ”์œ„๋ฅผ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํšจ์œจ์ ์ธ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์œ ํ˜• ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(Unit Test) ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ(Integration Test)
๋ฒ”์œ„ ๊ฐœ๋ณ„ ๋ฉ”์„œ๋“œ๋‚˜ ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ ํ…Œ์ŠคํŠธ
์†๋„ ๋งค์šฐ ๋น ๋ฆ„ ์ƒ๋Œ€์ ์œผ๋กœ ๋Š๋ฆผ
์˜์กด์„ฑ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ์— ์˜์กดํ•˜์ง€ ์•Š์Œ (Mock ์‚ฌ์šฉ) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์™ธ๋ถ€ ์„œ๋น„์Šค์— ์˜์กด
์ฃผ์š” ๋„๊ตฌ JUnit, Mockito @SpringBootTest
์˜ˆ์‹œ ํŠน์ • ์„œ๋น„์Šค ๋ฉ”์„œ๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ ์ „์ฒด API ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต ํ…Œ์ŠคํŠธ



๊ฒฐ๋ก 

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๋Š” ๋น ๋ฅด๊ฒŒ ์ฝ”๋“œ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ , ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๋Š” ์‹ค์ œ ํ™˜๊ฒฝ์—์„œ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธ ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋Š” ์ƒํ˜ธ๋ณด์™„์ ์ด๋ฏ€๋กœ ํ•จ๊ป˜ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค .

 


 

2. @SpringBootTest์™€ MockBean ํ™œ์šฉ๋ฒ•

@SpringBootTest ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ๋ฅผ ๋กœ๋“œํ•˜์—ฌ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. MockBean ์€ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ๋ชจ์˜(Mock) ๊ฐ์ฒด๋กœ ๋Œ€์ฒดํ•ด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ: UserService ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ

 

User.java (์—”ํ„ฐํ‹ฐ)

package com.example.demo.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // Constructor, Getter, Setter ์ƒ๋žต
}

 

UserRepository.java (๋ ˆํฌ์ง€ํ† ๋ฆฌ)

package com.example.demo.repository;

import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

 

UserService.java (์„œ๋น„์Šค ํด๋ž˜์Šค)

package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public Optional<User> getUserById(Long id) {
        return userRepository.findById(id);
    }
}

 

UserServiceTest.java (ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ)

package com.example.demo;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Autowired
    private UserRepository userRepository;

    @Test
    public void ์‚ฌ์šฉ์ž_์กฐํšŒ_ํ…Œ์ŠคํŠธ() {
        // Given: ์‚ฌ์šฉ์ž ์ƒ์„ฑ
        User user = new User();
        user.setName("ํ™๊ธธ๋™");
        userRepository.save(user);

        // When: ์‚ฌ์šฉ์ž ์กฐํšŒ
        User foundUser = userService.getUserById(user.getId()).orElse(null);

        // Then: ๊ฒ€์ฆ
        assertThat(foundUser).isNotNull();
        assertThat(foundUser.getName()).isEqualTo("ํ™๊ธธ๋™");
    }
}

 


 

3. MockMvc๋กœ REST API ํ…Œ์ŠคํŠธํ•˜๊ธฐ

MockMvc ๋Š” ์Šคํ”„๋ง MVC์˜ HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‹ค์ œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ REST API์˜ ๋™์ž‘์„ ๊ฒ€์ฆ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ: REST API ํ…Œ์ŠคํŠธ

 

UserController.java (REST API ์ปจํŠธ๋กค๋Ÿฌ)

package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/users/{id}")
    public Optional<User> getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

 

UserControllerTest.java (API ํ…Œ์ŠคํŠธ)

package com.example.demo;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.util.Optional;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
public class UserControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private UserController userController;

    @MockBean
    private UserService userService;

    @Test
    public void ์‚ฌ์šฉ์ž_API_ํ…Œ์ŠคํŠธ() throws Exception {
        // Given: Mock ์„ค์ •
        User user = new User();
        user.setId(1L);
        user.setName("ํ™๊ธธ๋™");
        when(userService.getUserById(1L)).thenReturn(Optional.of(user));

        mockMvc = MockMvcBuilders.standaloneSetup(userController).build();

        // When & Then: API ํ˜ธ์ถœ ๋ฐ ๊ฒ€์ฆ
        mockMvc.perform(get("/users/1")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.name").value("ํ™๊ธธ๋™"));
    }
}

 


 

4. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์ค‘์š”์„ฑ๊ณผ ์ตœ์‹  ํŠธ๋ Œ๋“œ

  • CI/CD ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ํ•„์ˆ˜์ ์ธ ์—ญํ•  : ๋ชจ๋“  ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ํ…Œ์ŠคํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ(TDD) : ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ „์— ํ…Œ์ŠคํŠธ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก ์ž…๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ ์ธก์ • : ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ฝ”๋“œ๊ฐ€ ํ…Œ์ŠคํŠธ๋˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•˜์—ฌ ํ’ˆ์งˆ์„ ๋†’์ž…๋‹ˆ๋‹ค.
  • Mocking ๋„๊ตฌ : ์™ธ๋ถ€ API์™€์˜ ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด Mockito ์™€ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 


 

๊ด€๋ จ ๋งํฌ


JUnit 5 ๊ณต์‹ ์‚ฌ์ดํŠธ๐Ÿ‘†

Spring Boot ๊ณต์‹ ๋ฌธ์„œ๐Ÿ‘†

Mockito ๊ณต์‹ ๋ฌธ์„œ๐Ÿ‘†

MockMvc ์‚ฌ์šฉ๋ฒ•๐Ÿ‘†

TDD ๊ฐœ๋… ์†Œ๊ฐœ๐Ÿ‘†

Spring Boot ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๊ฐ€์ด๋“œ๐Ÿ‘†




FAQ

 

1. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‚˜์š”?

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๊ฐœ๋ณ„ ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘ ์„ ๊ฒ€์ฆํ•  ๋•Œ, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ์ „์ฒด ๊ธฐ๋Šฅ ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ ์„ ํ™•์ธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

2. MockBean๊ณผ Mockito์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

  • @MockBean ์€ Spring ์ปจํ…์ŠคํŠธ์— ์ฃผ์ž…๋˜๋Š” ์˜์กด์„ฑ์„ ๋ชจ์˜ ํ•˜๊ณ , Mockito๋Š” ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ๊ฐ์ฒด๋ฅผ ๋ชจ์˜ ํ•ฉ๋‹ˆ๋‹ค.

3. ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๊ฐ€ ๋Š๋ฆฐ ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋กœ๋“œ ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์™ธ๋ถ€ ์„œ๋น„์Šค์™€์˜ ํ†ต์‹ ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์–ด ๋Š๋ฆฝ๋‹ˆ๋‹ค.

4. MockMvc๋กœ ๋น„๋™๊ธฐ ์š”์ฒญ์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

  • ๋„ค, MockMvc ๋Š” ๋น„๋™๊ธฐ ์š”์ฒญ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. .asyncDispatch() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5. ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋Š” ์ฝ”๋“œ์˜ ๋ช‡ ํผ์„ผํŠธ๊ฐ€ ํ…Œ์ŠคํŠธ๋˜๊ณ  ์žˆ๋Š”์ง€๋ฅผ ์ธก์ • ํ•˜๋Š” ์ง€ํ‘œ์ž…๋‹ˆ๋‹ค. ๋†’์€ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋Š” ์ฝ”๋“œ ํ’ˆ์งˆ์„ ๋ณด์žฅํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

 


 

๋งˆ๋ฌด๋ฆฌ

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” Spring Boot์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐฉ๋ฒ• ์„ ํ•™์Šตํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์˜ ์ฐจ์ด์  ์„ ์ดํ•ดํ•˜๊ณ , MockBean ๊ณผ MockMvc ๋ฅผ ํ™œ์šฉํ•ด REST API๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ํ•จ๊ป˜ ๋‹ค๋ค˜์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ํ”„๋กœ์ ํŠธ์˜ ํ’ˆ์งˆ๊ณผ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅ ํ•˜๋ฉฐ, ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌ ํ•˜๋Š” ์ค‘์š”ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด๋ฉด, ์ฝ”๋“œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง€๊ณ  ํŒ€์›Œํฌ๊ฐ€ ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค. ํŠนํžˆ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ž๋™ํ™”๋œ ํ…Œ์ŠคํŠธ๋Š” ๋ฐฐํฌ ์ „์— ๋ฌธ์ œ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐœ๊ฒฌ ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์ด ๊ฐ€์ด๋“œ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋” ๋งŽ์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์—ฐ์Šต ํ•ด๋ณด์„ธ์š”. ์ž‘์€ ์‹ค์Šต๋“ค์ด ๋ชจ์—ฌ ๋” ๋‚˜์€ ๊ฐœ๋ฐœ์ž ๋กœ ์„ฑ์žฅํ•˜๋Š” ๋ฐ‘๊ฑฐ๋ฆ„์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿš€

 


 

์—ฐ์Šต ๊ณผ์ œ

  1. ์‚ฌ์šฉ์ž ์ƒ์„ฑ API ํ…Œ์ŠคํŠธ ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์„ธ์š”. (POST ์š”์ฒญ ์‚ฌ์šฉ)
  2. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์ƒํ™ฉ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์„ธ์š”. ์˜ˆ: ์—†๋Š” ์‚ฌ์šฉ์ž ์กฐํšŒ ์‹œ 404 ์‘๋‹ต
  3. ๋น„๋™๊ธฐ ์š”์ฒญ ํ…Œ์ŠคํŠธ ๋ฅผ MockMvc๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ํ•ด๋ณด์„ธ์š”.
  4. ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ์ธก์ •ํ•ด๋ณด๊ณ , ์ปค๋ฒ„๋ฆฌ์ง€ ๋น„์œจ์„ ๋†’์—ฌ๋ณด์„ธ์š”.
  5. CI ๋„๊ตฌ(Jenkins, GitHub Actions) ์™€ ์—ฐ๋™ํ•ด ํ…Œ์ŠคํŠธ ์ž๋™ํ™” ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•ด๋ณด์„ธ์š”.

 


์—ฌ๋Ÿฌ๋ถ„์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ์‹ค๋ ฅ ์ด ํ”„๋กœ์ ํŠธ์˜ ์„ฑ๊ณต์„ ๊ฒฐ์ •์ง“๋Š” ์ค‘์š”ํ•œ ์š”์†Œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊พธ์ค€ํ•œ ์—ฐ์Šต์œผ๋กœ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ๋†’์ด๊ณ , ๋” ๋‚˜์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•ด๋ณด์„ธ์š”! ๐Ÿš€

๋Œ“๊ธ€