국비학원 51일차 : Spring Boot_11 Websoket, Scheduler

Digeut·2023년 5월 9일
0

국비학원

목록 보기
43/44

서버관련

파일 서버(File server):

파일 서버는 파일을 저장하고 관리하는 서버입니다. 다른 서버에서 파일을 업로드하거나 다운로드할 수 있도록 파일 공유 기능을 제공합니다.

API 서버(API server):

API 서버는 다른 프로그램이나 서비스에서 요청하는 데이터를 처리하고, 해당 요청에 대한 응답을 반환하는 서버입니다. REST API, SOAP API 등 다양한 종류의 API를 제공할 수 있습니다.

스케줄러 서버(Scheduler server):

스케줄러 서버는 주기적으로 실행해야 하는 작업을 자동으로 처리하기 위한 서버입니다. 주로 백업, 배치 처리 등의 작업을 자동화하기 위해 사용됩니다.

웹소켓 서버(Websocket server):

웹소켓 서버는 웹 브라우저와 서버 간 양방향 통신을 가능하게 하는 기술입니다. 웹소켓을 이용하여 실시간 채팅, 게임, 주식 거래 등의 서비스를 구현할 수 있습니다.

인증 서버(Auth server):

인증 서버는 사용자의 인증 정보를 관리하고, 다른 서비스에서 해당 사용자의 인증을 처리하기 위한 서버입니다. OAuth, OpenID Connect 등의 프로토콜을 이용하여 인증을 처리합니다. 사용자가 로그인하여 인증된 후, API 서버 등의 다른 서비스에서 해당 인증 정보를 활용할 수 있습니다.

Image UpLoad, DownLoad

application.propertise

spring.servlet.multipart.max-file-size =100MB
spring.servlet.multipart.max-request-size=150MB

file.path=D:/SpringbootBasic/file/
file.url=http://localhost:4040/file

jwt.secret-key=Secret1!


경로 설정할때 마지막 /부분으로 닫아줘야 지정한 경로까지 지정된다!

spring.servlet.multipart.max-file-size는 하나의 파일이 업로드될 때 허용되는 최대 파일 크기를 설정합니다. 예를 들어, 위의 설정에서는 최대 100MB까지의 파일을 업로드할 수 있습니다. 이 값을 초과하는 파일이 업로드되면, Spring은 MaxUploadSizeExceededException 예외를 발생시킵니다.

spring.servlet.multipart.max-request-size는 전체 요청에 대한 최대 크기를 설정합니다. 예를 들어, 위의 설정에서는 요청 전체 크기가 150MB를 초과하지 않도록 설정되어 있습니다. 이 값은 max-file-size보다 큰 값을 설정해야 합니다. 만약 요청 전체 크기가 이 값을 초과하면, Spring은 MaxUploadSizeExceededException 예외를 발생시킵니다.

FileController

@RestController
@RequestMapping(RequestPattern.⭐FILE_API)
@RequiredArgsConstructor
public class FileController { 
//api 서버가 아니므로 api 붙이지 않았다.

    private final FileService fileService;

    private final String 🍉UPLOAD_URL = "upload";
    private final String 🧃GET_URL = "url";

    // 파일 업로드 (이미지만 진행)
    @PostMapping(🍉UPLOAD_URL)
    public String upload(
        @RequestParam("file") MultipartFile file
    ) {
        return fileService.upload(file);
    }

    // 파일 불러오기 
    @GetMapping(value = 🧃GET_URL, produces = 
    	{MediaType.IMAGE_JPEG_VALUE,MediaType.IMAGE_PNG_VALUE})
    public Resource getFile(
        @PathVariable("fileName") String fileName
    ) {

        return fileService.getFile(fileName);
    }
    
}

FileService

public interface FileService {
    public String upload(MultipartFile file);
    public Resource getFile(String fileName);
}

FileServiceImplement

@Service
public class FileServiceImplement implements FileService{
    @Value("${file.path}") 
    private String FILE_PATH;
    @Value("${file.url}") 
    private String FILE_URL;

    @Override
    public String upload(MultipartFile file) {
        //검증
        if(file.isEmpty()) return null;

        //파일명 가져오기
        String originalFileName = file.getOriginalFilename();
        // 확장자 가져오기
        int extensionIndex = originalFileName.lastIndexOf("."); 
        								//.이 있는 위치의 인덱스 가져오기
        String extension = originalFileName.substring(extensionIndex); 
        									//. 이후의 확장자 가져오는것

        // 파일의 새로운 이름 지정 
        //여러 사람들이 이미지를 올리면 그때 마다 파일 이름이 여러개일것.
        String uuid = UUID.randomUUID().toString();
        //랜덤하게 파일 이름을 지정할 수 있게 한다
        String saveName = uuid + extension; //새로운 파일 이름이 생성됨.

        // 파일저장 경로 지정
        String savaPath = FILE_PATH + saveName;

        try {
            //파일 저장
            file.transferTo(new File(savaPath));
        } catch (Exception exception) {
            exception.printStackTrace();
            return null;
        }
        //클라이언트가 해당 파일에 접근하기 위한 url
        String fileUrl = FILE_URL + saveName;
        return fileUrl;
    }

    @Override
    public Resource getFile(String fileName) {
        
        Resource file = null; //참조변수 만들기

        try {
            // 파일을 url로 가져오기
            String url = "file:" + FILE_PATH + fileName;
            file = new UrlResource(url);
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        return file;
    }
}

RequestFattern

public interface RequestPattern {
    public static final String ⭐FILE_API = "file";
}

Fattern으로 따로 분리해서 만들어두면 코드를 더 깔끔하게 작성할 수 있다.

Scheduler

특정 시간에 작업을 주기적으로 실행하거나, 일정 주기로 반복 실행할 수 있는 기능을 제공하는 모듈입니다.

Spring의 Scheduler는 스레드풀과 작업 큐를 사용하여 다수의 작업을 병렬적으로 처리할 수 있습니다. 스케줄러를 사용하여 예약된 작업을 처리할 때, 다음과 같은 작업을 수행할 수 있습니다.

특정 시간에 작업 실행: 일정 시간에 한 번만 실행되는 작업을 예약할 수 있습니다. 예를 들어, 매일 정해진 시간에 데이터베이스를 백업하는 작업을 수행할 수 있습니다.

주기적으로 작업 실행: 주기적으로 반복 실행되는 작업을 예약할 수 있습니다. 예를 들어, 5분마다 데이터베이스에서 새로운 데이터를 읽어오는 작업을 수행할 수 있습니다.

Spring에서 스케줄러를 구현하는 방법은 다양하지만, 주로 @Scheduled 어노테이션을 사용하는 방법이 많이 사용됩니다. @Scheduled 어노테이션을 사용하면, 특정 메서드를 스케줄러로 등록하고, 주기적으로 실행될 시간을 지정할 수 있습니다. 또한 스케줄러를 구현할 때는 스케줄러의 실행 주기와 동시에 처리할 수 있는 최대 작업 수 등을 고려하여 적절한 스레드풀 크기와 작업 큐 크기를 설정해야 합니다.

Quartz Scheduler

Java 애플리케이션에서 작업을 예약하고 실행하는 데 사용되는 오픈 소스 라이브러리이다.

Quartz Scheduler의 구성 요소

Job: 작업을 수행하는 로직을 포함하는 클래스이다. 이 클래스는 Quartz의 Job 인터페이스를 구현해야 한다.execute 메소드는 스케줄에 따라 호출되며, 여기에 작업을 수행하는 코드를 작성한다.

JobDetail: 작업의 메타데이터를 포함하는 객체로, 작업의 식별자, 설명, JobDataMap 등이 포함된다. Quartz는 JobBuilder를 사용하여 JobDetail 객체를 생성할 수 있는 편리한 방법을 제공한다.

Trigger: 작업을 실행할 스케줄을 정의하는 객체이다. Quartz는 다양한 유형의 트리거를 제공하며, 간단한 반복 스케줄부터 복잡한 cron 표현식에 따른 스케줄까지 구성할 수 있다. Quartz는 TriggerBuilder를 사용하여 Trigger 객체를 생성할 수 있는 편리한 방법을 제공한다.

Scheduler: 작업 실행을 관리하는 핵심 구성이다. 스케줄러는 JobDetail 및 Trigger를 사용하여 작업을 예약하고 실행한다. 스케줄러는 작업 실행 전에 시작되어야 하며, 모든 작업이 완료되면 중지할 수 있다.

builder.gradle

의존성 주입

Sample Job

@Component
public class SampleJob implements Job{

@Component 어노테이션은 스프링 프레임워크에서 컴포넌트 스캔을 통해 빈으로 등록될 클래스를 표시하는 데 사용됩니다. SampleJob 클래스는 Quartz 스케줄러에서 사용되는 Job 인터페이스를 구현하는 클래스입니다. Job 인터페이스에는 execute 메서드가 선언되어 있으며, 이 메서드에서 실제 작업을 수행합니다.

    //실제 작업이 실행될 메서드
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Scheduler.");
    }

execute 메서드는 Job 인터페이스의 추상 메서드입니다. 이 메서드는 스케줄러가 실행될 때마다 호출되며, 실제 작업을 수행하는 코드를 포함합니다. 이 예제에서는 "Scheduler."라는 메시지를 콘솔에 출력하는 단순한 작업을 수행하고 있습니다.

	//Job Detail 설정 (job의 메타데이터 지정)
    @Bean
    public JobDetail jobDetail(){
        return JobBuilder.newJob()
                .ofType(SampleJob.class)
                .storeDurably()
                .withIdentity("Sample Job")
                .withDescription("Sample Job 테스트 입니다")
                .build();
    }

jobDetail 메서드는 JobDetail 객체를 생성하여 반환합니다. JobDetail 객체는 스케줄러의 메타데이터를 포함하고 있습니다. 이 예제에서는 JobBuilder 클래스를 사용하여 JobDetail 객체를 생성하고, SampleJob 클래스를 지정하여 이 작업의 클래스를 설정합니다. withIdentity 메서드를 사용하여 이 작업의 식별자와 이름을 설정할 수 있습니다.

	 //Trigger 설정(반복할 스케줄 지정)
    @Bean
    public Trigger trigger(JobDetail jobDetail){
        CronScheduleBuilder schedule =
            CronScheduleBuilder.cronSchedule✔️("* * * * * ?");
        
        return TriggerBuilder.newTrigger()
                                .forJob(jobDetail)
                                .withIdentity("Sample Trigger")
                                .withDescription("Sample Trigger 입니다.")
                                .withSchedule(schedule)
                                .build();
    }
}

trigger 메서드는 Trigger 객체를 생성하여 반환합니다. Trigger 객체는 작업을 실행할 스케줄을 정의합니다. 이 예제에서는 CronScheduleBuilder 클래스를 사용하여 스케줄을 지정하고 있습니다. withIdentity 메서드를 사용하여 이 트리거의 이름과 식별자를 설정할 수 있습니다. forJob 메서드를 사용하여 트리거가 실행할 작업을 지정합니다.

cron 표현식
cronSchedule

(”초(0-59, *) 분(0-59, *) 시(0-23, *) 일(1-31, *) 월(1-12, *) 요일(0-7, ?)”);

*로 표현하면 매초, 매분, 매시, 매일, 매월 ?은 매 요일마다 반복

WebSocket

실시간 양방향 통신을 가능하게 하는 프로토콜이다. 웹에서 실시간 양방향 통신을 위해 기본적으로 사용되는 HTTP 프로토콜과는 다르다. 클라이언트와 서버 간의 지속적인 연결을 유지하여 실시간 데이터 교환을 가능하게 한다. 이를 통해 시간 지연이 적은 웹 애플리케이션과 서버 간 통신을 구현할 수 있다.

WebSocketConfig

@EnableWebSocket
@Configuration
public class WebsocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {  
    }
}

WebSocketProvider //다음시간에 진행

@Component
public class WebSocketProvider extends TextWebSocketHandler {
    //실제로는 handler에 진행해야하는것. 수업때만 provider에서 진행한다


    //모두 AbstractWebSocketHandler에서 기본적인 틀 가져옴

    // 1. 연결 (클라이언트와 서버 간의 연결) 
    @Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
	}

    // 2. 메세지 송수신
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
	}

    // 3. 연결 해제
    @Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
	}
}
profile
개발자가 될 거야!

0개의 댓글