🗂️ 개인프로젝트/IDOL

[개인프로젝트/IDOL] 7. 타겟 페이지 개발

케로⸝⸝◜࿀◝ ⸝⸝ 2024. 6. 21. 10:01

1. web 모듈 설정

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.6'
    id 'io.spring.dependency-management' version '1.1.5'
}

group = 'me.progfrog.idol'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

 

application.properties

  • 포트 설정 9000
server.port=9000

 

WebApplication

package me.progfrog.idol.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }
}

 

2. 타겟 페이지

설명 HTTP 메서드와 URL
타겟 페이지 GET /home

 

AllowedUserResponse

package me.progfrog.idol.web.dto;

public record AllowedUserResponse(
        Boolean isAllowed
) {
}

 

HomeController

  • 타겟 페이지로 접근을 시도했을 때, 입장 가능 상태의 사용자라면 접근을 허용하고 만약 허용되지 않은 사용자라면 대기용 웹 페이지로 리다이렉트 하는 흐름을 가지고 있다.
  • 앞서, 토큰을 사용하여 입장 가능 여부를 판단하도록 코드를 변경하였는데 같은 도메인이면 이와 같이 port가 달라도 쿠키를 활용할 수 있다.
package me.progfrog.idol.web.controller;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import me.progfrog.idol.web.dto.AllowedUserResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Arrays;

@Controller
public class HomeController {

    RestTemplate restTemplate = new RestTemplate();

    @GetMapping("/home")
    public String getHome(@RequestParam(name = "queue", defaultValue = "default") String queue,
                          @RequestParam(name = "user-id") Long userId,
                          HttpServletRequest request) {

        var cookies = request.getCookies();
        var cookieName = "user-queue-%s-token".formatted(queue);

        var token = "";
        if (cookies != null) {
            var cookie = Arrays.stream(cookies).filter(i -> i.getName().equalsIgnoreCase(cookieName)).findFirst();
            token = cookie.orElse(new Cookie(cookieName, "")).getValue();
        }

        var uri = UriComponentsBuilder
                .fromUriString("http://127.0.0.1:9010")
                .path("/api/v1/queue/allowed")
                .queryParam("queue", queue)
                .queryParam("user-id", userId)
                .queryParam("token", token)
                .encode()
                .build()
                .toUri();

        ResponseEntity<AllowedUserResponse> response = restTemplate.getForEntity(uri, AllowedUserResponse.class);
        if (response.getBody() == null || !response.getBody().isAllowed()) {
            // 입장 가능 상태가 아니라면, 대기용 웹 페이지로 리다이렉트
            return "redirect:http://127.0.0.1:9010/waiting-room?user-id=%d&redirect-url=%s".formatted(
                    userId, "http://127.0.0.1:9000/home?user-id=%d".formatted(userId));
        }

        // 입장 가능 상태라면 해당 페이지를 진입
        return "home";
    }
}

 

home.index

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IDOL</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            background: #000;
        }
        .container {
            position: relative;
            width: 100%;
            height: 100%;
        }
        .container img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            position: absolute;
            z-index: 1;
        }
        .overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 2;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            color: #fff;
            font-family: 'Arial', sans-serif;
            text-align: center;
        }
        .overlay h1 {
            font-size: 3em;
            margin: 0;
            animation: fadeIn 2s forwards;
        }
        .overlay p {
            font-size: 1.5em;
            animation: fadeIn 4s forwards;
            opacity: 0;
        }
        .video-container {
            margin-top: 20px;
            width: 80%;
            max-width: 800px;
            position: relative;
            z-index: 2;
        }
        iframe {
            width: 100%;
            height: 450px;
            border: none;
        }
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
    </style>
</head>
<body>
<div class="container">
    <img th:src="@{/images/idol.webp}" alt="Idol Image">
    <div class="overlay">
        <h1>★IDOL★</h1>
        <p>거짓말은 최고의 사랑인걸?</p>
        <div class="video-container">
            <iframe width="560" height="315" src="https://www.youtube.com/embed/GqP628id5Kg?si=FROm2245LYq6ULDH" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
        </div>
    </div>
</div>
</body>
</html>

 

3. 동작 확인

타겟 페이지 접근 시, 대기용 웹 페이지로 넘어갔다가 대기 후 타겟 페이지로 접근하는 흐름을 확인할 수 있다.

갓 요아소비

 

반응형