1. 빈 설정 및 DI (Dependency Injection)
문제: 의존성 주입을 이용해 서비스 클래스를 작성하고, @Autowired를 사용해 주입된 객체를 이용하는 방법을 구현하세요.
해결 방안:
@Service
public class OrderService {
private final ProductRepository productRepository;
// 생성자 주입
@Autowired
public OrderService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public Product getProductById(Long id) {
return productRepository.findById(id);
}
}
• @Autowired를 사용해 생성자에서 ProductRepository를 주입합니다. 이는 스프링이 자동으로 빈을 주입하는 방식 중 하나입니다.
2. 트랜잭션 관리
문제: 데이터베이스의 무결성을 유지하기 위해 트랜잭션을 사용하는 방법을 보여주세요.
해결 방안:
@Service
public class BankService {
@Autowired
private AccountRepository accountRepository;
@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
Account fromAccount = accountRepository.findById(fromAccountId);
Account toAccount = accountRepository.findById(toAccountId);
fromAccount.debit(amount);
toAccount.credit(amount);
accountRepository.save(fromAccount);
accountRepository.save(toAccount);
}
}
• @Transactional 애노테이션을 사용하여 트랜잭션을 관리합니다. 메서드가 실행되는 동안 예외가 발생하면 트랜잭션이 롤백됩니다.
3. AOP(Aspect-Oriented Programming) 사용
문제: 메서드 실행 시간을 측정하기 위한 AOP를 작성하세요.
해결 방안:
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - startTime;
System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return proceed;
}
}
• @Aspect와 @Around를 사용하여 특정 서비스 메서드의 실행 시간을 측정하는 AOP를 작성할 수 있습니다.
4. 프로파일 기반 설정
문제: 개발 환경(dev)과 운영 환경(prod)에 따라 다른 설정을 적용하는 방법을 구현하세요.
해결 방안:
@Configuration
@Profile("dev")
public class DevDatabaseConfig {
@Bean
public DataSource dataSource() {
return new H2DataSource(); // H2 데이터베이스 사용
}
}
@Configuration
@Profile("prod")
public class ProdDatabaseConfig {
@Bean
public DataSource dataSource() {
return new MySQLDataSource(); // MySQL 데이터베이스 사용
}
}
• @Profile을 사용해 환경(dev, prod)에 따라 다른 빈을 로드하는 설정을 구현합니다.
5. REST API 개발
문제: RESTful 웹 서비스를 개발하고, GET 요청으로 특정 데이터를 조회하는 엔드포인트를 작성하세요.
해결 방안:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/{id}")
public ResponseEntity<Product> getProduct(@PathVariable Long id) {
Optional<Product> product = productService.getProductById(id);
return product.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
}
• @RestController, @GetMapping을 사용해 RESTful API를 구현합니다. 제품 ID에 따라 제품 정보를 조회합니다.
6. 테스트 작성
문제: 스프링의 의존성 주입을 사용하여 서비스를 테스트하는 방법을 보여주세요.
해결 방안:
@SpringBootTest
public class ProductServiceTest {
@Autowired
private ProductService productService;
@Test
public void testGetProduct() {
Product product = productService.getProductById(1L);
assertNotNull(product);
assertEquals("Product1", product.getName());
}
}
• @SpringBootTest를 사용해 스프링 컨텍스트에서 서비스를 테스트합니다.
7. 스프링 시큐리티를 사용한 인증
문제: 스프링 시큐리티를 사용해 로그인 인증 기능을 구현하세요.
해결 방안:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/**").permitAll()
.and()
.formLogin();
}
}
• @EnableWebSecurity와 HttpSecurity를 사용해 권한에 따라 다른 페이지 접근을 제한합니다.
8. 파일 업로드 처리
문제: MultipartFile을 사용하여 파일 업로드 기능을 구현하세요.
해결 방안:
@RestController
public class FileUploadController {
@PostMapping("/upload")
public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("No file selected");
}
try {
byte[] bytes = file.getBytes();
Path path = Paths.get("uploads/" + file.getOriginalFilename());
Files.write(path, bytes);
return ResponseEntity.ok("File uploaded successfully");
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
• MultipartFile을 사용해 파일 업로드 기능을 구현합니다.
9. 스케줄러 사용
문제: 주기적으로 특정 작업을 수행하는 스케줄러를 작성하세요.
해결 방안:
@Configuration
@EnableScheduling
public class SchedulingConfig {
@Scheduled(cron = "0 0 * * * *")
public void performTask() {
System.out.println("Task performed at " + new Date());
}
}
• @Scheduled 애노테이션을 사용해 매 시간마다 작업이 실행되도록 설정합니다.
10. RabbitMQ를 사용한 메시지 큐
문제: RabbitMQ를 사용해 메시지를 송신하고, 메시지 수신을 처리하는 방법을 구현하세요.
해결 방안:
@Configuration
public class RabbitConfig {
@Bean
public Queue queue() {
return new Queue("messageQueue", false);
}
}
@RestController
public class MessageController {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostMapping("/send")
public String sendMessage(@RequestParam String message) {
rabbitTemplate.convertAndSend("messageQueue", message);
return "Message sent";
}
}
@Component
public class MessageListener {
@RabbitListener(queues = "messageQueue")
public void receiveMessage(String message) {
System.out.println("Received message: " + message);
}
}
• RabbitTemplate와 @RabbitListener를 사용하여 메시지를 송신 및 수신하는 RabbitMQ 설정을 구현합니다.
'Problem and Solution Guide > Spring Framework' 카테고리의 다른 글
Spring Framework 문제와 풀이 (0) | 2024.09.06 |
---|---|
AOP부터 트랜잭션 관리까지: Spring AOP 문제 풀이로 배우기 (0) | 2024.09.06 |
SpringFramework 테스트: 문제 해결 및 접근 방법 (0) | 2024.08.21 |