SQL 첫걸음

데이터베이스와 SQL 데이터베이스 데이터베이스: 데이터란 컴퓨터 안에 기록되어 있는 숫자를 의미하며, 이러한 데이터의 집합을 데이터베이스라고한다. 데이터베이스는 일반적으로 데이터센터의 서버에서 운용하지만 개인용 컴퓨터나 휴대용 기기에 내장되어 있기도 하다. 데이터베이스를 효율적으로 관리하는 소프트웨어를 데이터베이스 관리 시스템, 약자로 DBMS라 부른다. DBMS의 사용 목적은 다음과 같다. 생산성: 시스템을 구축할 때 검색, 추가, 삭제, 갱신과 같은 기본 기능부터 구현할 필요가 없어진다. 기능성: DBMS는 데이터베이스를 다루는 기능을 많이 제공한다. 복수 유저의 요청에 대응하거나, 대용량의 데이터를 저장하고 고속으로 검색하는 기능을 제공하기도 한다....

2024-09-15 · 13 min · 2648 words

Spring의 Thread pool

목표 Thread pool의 사용 목적을 이해한다. Spring boot에서 Tomcat의 Thread pool 설정 방법을 이해한다. Thread Pool DB, 웹 서버 등의 프로그램에서 요청이 도착할 떄마다 새 스레드를 생성하는 방법은 문제점이 있다. 요청을 처리할 때마다 스레드를 생성하고 삭제하는 것은 많은 시간과 시스템 리소스를 사용한다. 너무 많은 요청이 오면, 동시에 너무 많은 스레드가 생성되어 시스템 리소스가 부족해질 수 있다. 스레드 수를 제한할 필요가 있다. 이 문제를 해결하기 위해서 이전에 미리 생성된 스레드를 재사용하기 위한 Thread pool을 사용한다....

2024-09-15 · 2 min · 241 words

Spring으로 WebSocket 시작하기

Spring으로 WebSocket 시작하기(STOMP) Maven 의존성 추가 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>5.2.2.RELEASE</version> </dependency> 최신 버전은 여기서 또한 JSON 사용하여 메시지를 전달 하려면 Jackson 의존을 추가해야된다. Spring Boot의 경우에는 추가할 필요 없을 것으루 추정된다. <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.10.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.2</version> </dependency> Spring에서 WebSocket 활성화 AbstractWebSocketMessageBrokerConfigurer 클래스를 상속하고 @EnableWebSocketMessageBroker 어노테이션을 붙여준다. @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config....

2024-09-15 · 3 min · 476 words

Spring에서 Redis를 이용해 캐싱 구현하는 법

Spring에서 Redis 서버로 캐싱하는 방법은 2가지 방법이 있다. 기본적인 동작 확인만 목표로 하기 때문에 자세한 설정 방법은 생략한다. 어노테이션을 사용하는 방법 의존성 추가 implementation 'org.springframework.boot:spring-boot-starter-data-redis' Config에 @EnableCaching 추가 @SpringBootApplication @EnableCaching public class Application { ... } Entity에 Serializable 구현 Redis에서 데이터를 바이트 스트림으로 저장하기 위해서 필요하다. @Entity public class User implements Serializable{ @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; private String name; private String email; private Integer age; public User() { super(); } public User(Integer id, String name, String email, Integer age) { super(); this....

2024-09-15 · 2 min · 261 words

SpringApplicationEvent

목표 SpringApplicationEvent 가 무엇인지 알아본다. SpringApplicationEvent 의 사용법을 알아본다. SpringApplication.run() @SpringBootApplication public class AccountCoreApplication { public static void main(String[] args) { SpringApplication.run(AccountCoreApplication.class, args); } } Spring Boot를 사용하면 main 메서드에 다음과 같은 함수를 호출하는 것을 볼 수 있다. run 메서드를 호출하면 SpringApplication 생성자를 호출하는 것을 확인할 수 있다. SpringApplication 생성자를 호출하면 ApplicationListener를 로드하여 등록하게 된다. ApplicationListener 관심이 있는 이벤트에 대한 ApplicationListener를 ApplicationContext에 등록하면 ApplicationEvent가 그에 따라 필터링되고, 일치하는 이벤트에 대해서만 Listener가 호출이 된다....

2024-09-15 · 1 min · 149 words

Spring 이벤트 처리

도메인 간의 복잡한 의존성을 제거하기 위해서 Spring의 이벤트를 이용할 수 있다. 이벤트를 사용하기 위해서는 3가지를 사용해야된다. 참고로, Spring Framework 4.2부터 지원하는 어노테이션 방법을 다룬다. 이벤트 클래스 이벤트 퍼블리셔 이벤트 리스너 이벤트 클래스 이벤트에 데이터를 저장하기 위한 클래스로 자유롭게 클래스를 선언하면 된다. public class MenuRegisteredEvent { private final Menu menu; public MenuRegisteredEvent(final Menu menu) { this.menu = menu; } public Menu getMenu() { return menu; } public Long getMenuGroupId() { return menu....

2024-09-15 · 2 min · 236 words

Spring 실행 시 포트 번호 지정 방법

java -jar -Dserver.port=8083 spring-5.jar 또는 java -jar spring-5.jar --server.port=8083 참고 자료 https://recordsoflife.tistory.com/325

2024-09-15 · 1 min · 12 words

Spring with AWS S3

다른 크루들의 이야기를 들어보니 Spring과 S3 연결이 access key 가 없어도 된다고해서 시도해보고 있다. Spring 애플리케이션이 AWS의 EC2에 부여한 IAM 권한을 이용해서 S3와 연결이 가능하다고 한다. 의존성 추가 이것 저것 찾아다니면서 의존성 추가를 시도해봤는데 테스트가 전부 터지거나 의존성 추가에 실패했다. Spring 공식문서 방시대로 하니 다행이 잘 동작했다. implementation 'org.springframework.cloud:spring-cloud-aws-context:2.2.6.RELEASE' 접근 권한 AWS 자원들에 접근 권한을 얻기 위해서는 아래의 과정을 순서대로 거쳐서 만족하면 된다. 5번의 경우가 내가 사용하려고 하는 접근 권한 얻는 방법이다....

2024-09-15 · 1 min · 172 words

Spring Validation과 lombok 예외 처리

티 spring validation의 @NotNull과 lombok의 @NonNull의 차이를 알아본다. @NotNull Spring MVC Spring boot에서 컨트롤러에 @Valid와 함께쓰면 검증을 하게된다. 만약 조건을 만족하지 못하면 MethodArgumentNotValidException 이 발생한다. 하지만 예외 메시지가 직접 담기는 것이 아니라 아래 코드와 같이 메시지를 뽑아내야된다. private List<ExceptionDto> extractErrorMessages(final MethodArgumentNotValidException exception) { return exception.getBindingResult() .getAllErrors() .stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .map(ExceptionDto::new) .collect(Collectors.toList()); } JPA JPA에서도 @NotNull을 사용할 수 있다. @Entity 클래스의 필드에 @NotNull이 있으면 동작을한다. 만약 조건을 만족하지 않으면 ConstraintViolationException 이 발생한다. 하지만 예외 메시지가 직접 담기는 것이 아니라 아래 코드와 같이 메시지를 뽑아내야된다....

2024-09-15 · 1 min · 114 words

Spring rest docs의 API 문서가 자동으로 덮어쓰기

build.gradle에 아래 코드를 추가하면 된다. asciidoctor.doFirst { delete file('src/main/resources/static/docs') }

2024-09-15 · 1 min · 10 words

Spring Rest Docs 시작

의존성 추가 <dependency> <groupId>org.springframework.restdocs</groupId> <artifactId>spring-restdocs-mockmvc</artifactId> <version>2.0.4.RELEASE</version> </dependency> Spring REST Docs는 문서화할 REST 서비스의 테스트를 처리해야 문서가 생성된다. 테스트를 실행하면 request와 response를 통해 문서 스니펫이 생성된다. @ExtendWith({RestDocumentationExtension.class, SpringExtension.class}) @SpringBootTest public class ApiDocumentationJUnit5IntegrationTest { //... } @BeforeEach public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) { this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) .apply(documentationConfiguration(restDocumentation)).build(); } 컨트롤러(CRUDController)의 엔드 포인트에 대한 링크가 있는 페이지를 반환하는 컨트롤러 생성 @RestController @RequestMapping("/") public class IndexController { static class CustomRepresentationModel extends RepresentationModel<CustomRepresentationModel> { public CustomRepresentationModel(Link initialLink) { super(initialLink); } } @GetMapping public CustomRepresentationModel index() { return new CustomRepresentationModel(linkTo(CRUDController....

2024-09-15 · 2 min · 245 words

Spring redis로 pub sub 구현하기

Redis 의존 추가 implementation 'org.springframework.boot:spring-boot-starter-data-redis' spring-boot-starter-data-redis 의존을 통해 properties 파일로 설정이 가능하다. Bean 생성 @Bean public RedisTemplate<String, Object> redisTemplate(final RedisConnectionFactory connectionFactory) { final RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); return template; } pubish 하기위한 RedisTemplate다. @Bean RedisMessageListenerContainer redisContainer(final MessageListener messageListener) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(jedisConnectionFactory()); container.addMessageListener(messageListener, topic()); return container; } 메시지 수신에 대한 비동기 처리를 하기위해서는 RedisMessageListenerContainer 에 MessageListener를 추가하면 된다. @Override public void onMessage(final Message message, final byte[] pattern) { try { EntryResponse response = objectMapper....

2024-09-15 · 1 min · 126 words

Spring MVC로 RSS 피드 API 만들기

의존 추가 Spring에서 RSS 지원은 ROME이라는 프레임워크를 기반으로 한다. <dependency> <groupId>com.rometools</groupId> <artifactId>rome</artifactId> <version>1.10.0</version> </dependency> 피드 구현 AbstractRssFeedView 를 구현해야된다. 2가지 메서드를 오버라이드해야된다. buildFeedMetadata는 해당 피드에 대한 정보를 반환하고, buildFeedItems는 피드에 있는 아이템들을 반환한다. public class PostRssView extends AbstractRssFeedView { @Override protected void buildFeedMetadata(Map<String, Object> model, Channel feed, HttpServletRequest request) { feed.setTitle("Baeldung RSS Feed"); feed.setDescription("Learn how to program in Java"); feed.setLink("http://www.baeldung.com"); } @Override protected List<Item> buildFeedItems(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) { Item entryOne = new Item(); entryOne....

2024-09-15 · 1 min · 115 words

Spring MVC 동작 과정

스프링 @MVC 스프링은 DispatcherServlet과 7가지 전략을 기반으로 한 MVC 프레임워크를 제공한다. 애노테이션을 중심으로 한 새로운 MVC의 확장 기능은 @MVC라는 별칭으로도 불린다. 스프링 웹 기술과 스프링 MVC 엔터프라이즈 애플리케이션의 가장 앞단에서 클라이언트 시스템과 연동하는 책임을 맡고 있는 것이 웹 프레젠테이션 계층이다. Java의 웹 프레젠테이션 계층의 기술과 프레임워크는 매우 다양하여 선택의 폭이 넓다. 스프링은 기본적으로 웹 계층과 다른 계층을 깔끔하게 분리해서 스프링 애플리케이션이지만 웹 계층을 다른 기술로 대체하더라도 아무런 문제가 없게 만들 수 있다....

2024-09-15 · 5 min · 856 words

Spring JPA로 논리적 삭제 사용하기

이전에 사용했던 @Where 어노테이션과 @SQLDelete 어노테이션을 사용하면 된다. @Entity @Table(name = "table_product") @SQLDelete(sql = "UPDATE table_product SET deleted = true WHERE id=?") @Where(clause = "deleted=false") public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private double price; private boolean deleted = Boolean.FALSE; // setter getter method } @SQLDelete 도 실제로 DB에 쿼리를 보낼 때 적용하게 되므로, 영속성 컨텍스트에 남아 있는 엔티티는 findAll() 같은 메서드로 조회가 되니 유의해야 된다....

2024-09-15 · 1 min · 76 words

Spring Framework에서 멀티 모듈 사용해보기

이 글은 Spring Framework에서 멀티 모듈을 적용하면서 겪은 트러블 슈팅들을 정리한 글이다. 모듈 및 패키지 구조 크게 api, client, core라는 모듈로 나뉘어지고, api와 client는 core 모듈의 의존한 상태다. 이후 소개할 트러블 슈팅들은 api와 core 사이의 관계로 설명하겠다. api 모듈과 core 모듈은 아래의 디렉터리 구조를 가지고 있다. 아래는 main 메서드가 있는 클래스의 코드다. @SpringBootApplication public class HyNoticeApplication { public static void main(String[] args) { SpringApplication.run(HyNoticeApplication.class); } } 트러블 슈팅 Parameter 0 of constructor in hynotice....

2024-09-15 · 1 min · 208 words

Spring data JPA 사용시 @Transactional을 붙이지 않으면 영속성 컨텍스트가 어떻게 동작할까

동작방식을 이해하기 위해서 JpaRepository의 기본 구현체를 확인해볼 필요가 있었다. 기본 구현체인 SimpleJpaRepository 코드를 확인해보니, class 레벨에 @Transactional(readOnly = true)가 설정되어 있고, 쓰기 메서드에 각각 @Transactional이 명시되어 있었다. 따라서, 기본적으로 각 메서드 호출마다 영속성 컨텍스트가 별개로 만들어져서 엔티티가 관리된다. 참고 자료 https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/support/SimpleJpaRepository.html https://www.baeldung.com/jpa-hibernate-persistence-context

2024-09-15 · 1 min · 42 words

Spring Custom Conditions

배경 config 클래스 중에 Condition 인터페이스의 구현체가 있었는데, 어떤 용도인지 이해하지 못했다. Custom Conditions 정의 조건부로 빈을 등록할 때 @Conditional 애노테이션을 사용할 수 있다. 이 애노테이션에서 사용할 조건을 클래스로 만들 수 있다. class Java8Condition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return JavaVersion.getJavaVersion().equals(JavaVersion.EIGHT); } } 사용 예 @Service @Conditional(Java8Condition.class) public class Java8DependedService { // ... } 참고 자료 https://www.baeldung.com/spring-conditional-annotations

2024-09-15 · 1 min · 63 words

Spring boot는 정적 파일을 어떻게 처리하나

Spring boot의 경우 ResourceHttpRequestHandler 라는 정적 리소스를 처리하는 핸들러가 따로있다. 기본적으로 /static, /public, /resources, /META-INF/resources 디렉토리에 있는 정적 컨텐츠를 처리하고 있다. https://www.baeldung.com/spring-mvc-static-resources https://github.com/spring-projects/spring-framework/blob/main/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java

2024-09-15 · 1 min · 23 words

Spring Boot 개발 환경에서 TestContainers 사용하기

목표 TestContainers를 통해 개발 환경에서 Spring 애플리케이션 실행 시 mariaDB 컨테이너를 실행하도록 한다. TestContainers를 통해 이미 mariaDB 컨테이너가 실행 중이라면 재사용하도록 한다. 의존성 추가 일반적으로 TestContainers는 테스트 환경에 사용하지만, Spring 애플리케이션이 dev 프로파일로 실행될 때 사용하는 것이 목표여서 아래와 같이 의존성을 추가한다. mariaDB를 사용하기 위한 JDBC Driver도 함께 의존성 추가한다. dependencies { //... implementation("org.mariadb.jdbc:mariadb-java-client") implementation("org.springframework.boot:spring-boot-testcontainers") implementation("org.testcontainers:mariadb") //... } 컨테이너 자동 실행 Spring Boot 3.1부터 Container 클래스를 Bean 등록하면, 자동으로 컨테이너를 실행해준다....

2024-09-15 · 1 min · 131 words