From a4ed9115aa242175028f02e099f0ac92769304a1 Mon Sep 17 00:00:00 2001 From: jueunk617 Date: Mon, 22 Sep 2025 14:33:29 +0900 Subject: [PATCH 1/5] =?UTF-8?q?Feat:=20WebSocket=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80=20+=20WebSocketConfig=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + .../websocket/config/WebSocketConfig.java | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/main/java/com/back/domain/websocket/config/WebSocketConfig.java diff --git a/build.gradle.kts b/build.gradle.kts index 7192cc2d..aeefb0b6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,6 +27,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("org.springframework.boot:spring-boot-starter-security") testImplementation("org.springframework.security:spring-security-test") compileOnly("org.projectlombok:lombok") diff --git a/src/main/java/com/back/domain/websocket/config/WebSocketConfig.java b/src/main/java/com/back/domain/websocket/config/WebSocketConfig.java new file mode 100644 index 00000000..af0cf877 --- /dev/null +++ b/src/main/java/com/back/domain/websocket/config/WebSocketConfig.java @@ -0,0 +1,36 @@ +package com.back.domain.websocket.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + /** + * 메시지 브로커 설정 + * - /topic: 1:N 브로드캐스트 (방 채팅) + * - /queue: 1:1 메시지 (개인 DM) + * - /app: 클라이언트에서 서버로 메시지 전송 시 prefix + */ + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + config.enableSimpleBroker("/topic", "/queue"); + config.setApplicationDestinationPrefixes("/app"); + config.setUserDestinationPrefix("/user"); + } + + /** + * STOMP 엔드포인트 등록 + * 클라이언트가 WebSocket 연결을 위해 사용할 엔드포인트 + */ + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/ws") + .setAllowedOriginPatterns("*") // 모든 도메인 허용 (개발용) + .withSockJS(); // SockJS 사용 + } +} From 61aec8fcc988def1a632b05a5dcdcf80ea112e10 Mon Sep 17 00:00:00 2001 From: jueunk617 Date: Mon, 22 Sep 2025 15:05:52 +0900 Subject: [PATCH 2/5] =?UTF-8?q?Feat:=20=EC=9B=B9=EC=86=8C=EC=BC=93=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=20=ED=99=95=EC=9D=B8=EC=9A=A9=20WebSocketTes?= =?UTF-8?q?tController=20=EC=B6=94=EA=B0=80=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/WebSocketTestController.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/main/java/com/back/domain/websocket/controller/WebSocketTestController.java diff --git a/src/main/java/com/back/domain/websocket/controller/WebSocketTestController.java b/src/main/java/com/back/domain/websocket/controller/WebSocketTestController.java new file mode 100644 index 00000000..4e1d8539 --- /dev/null +++ b/src/main/java/com/back/domain/websocket/controller/WebSocketTestController.java @@ -0,0 +1,65 @@ +package com.back.domain.websocket.controller; + +import com.back.global.common.dto.RsData; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@RestController +@RequestMapping("/api/websocket") +public class WebSocketTestController { // WebSocket 기능 테스트용 REST 컨트롤러 + + // WebSocket 서버 상태 확인 + @GetMapping("/health") + public ResponseEntity>> healthCheck() { + log.info("WebSocket 헬스체크 요청"); + + Map data = new HashMap<>(); + data.put("service", "WebSocket"); + data.put("status", "running"); + data.put("timestamp", LocalDateTime.now()); + data.put("endpoints", Map.of( + "websocket", "/ws", + "chat", "/app/rooms/{roomId}/chat", + "join", "/app/rooms/{roomId}/join", + "leave", "/app/rooms/{roomId}/leave" + )); + + return ResponseEntity + .status(HttpStatus.OK) + .body(RsData.success("WebSocket 서비스가 정상 동작중입니다.", data)); + } + + // WebSocket 연결 정보 제공 + @GetMapping("/info") + public ResponseEntity>> getConnectionInfo() { + log.info("WebSocket 연결 정보 요청"); + + Map connectionInfo = new HashMap<>(); + connectionInfo.put("websocketUrl", "/ws"); + connectionInfo.put("sockjsSupport", true); + connectionInfo.put("stompVersion", "1.2"); + connectionInfo.put("subscribeTopics", Map.of( + "roomChat", "/topic/rooms/{roomId}/chat", + "privateMessage", "/user/queue/messages", + "notifications", "/user/queue/notifications" + )); + connectionInfo.put("sendDestinations", Map.of( + "roomChat", "/app/rooms/{roomId}/chat", + "joinRoom", "/app/rooms/{roomId}/join", + "leaveRoom", "/app/rooms/{roomId}/leave" + )); + + return ResponseEntity + .status(HttpStatus.OK) + .body(RsData.success("WebSocket 연결 정보", connectionInfo)); + } +} \ No newline at end of file From f0aafacb7df2f9887e89c952cb4d0c26a185f99a Mon Sep 17 00:00:00 2001 From: jueunk617 Date: Mon, 22 Sep 2025 16:32:41 +0900 Subject: [PATCH 3/5] =?UTF-8?q?Fix:=20BaseEntity=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/back/global/entity/BaseEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/back/global/entity/BaseEntity.java b/src/main/java/com/back/global/entity/BaseEntity.java index 935cef49..772d8e1b 100644 --- a/src/main/java/com/back/global/entity/BaseEntity.java +++ b/src/main/java/com/back/global/entity/BaseEntity.java @@ -16,7 +16,7 @@ public abstract class BaseEntity { private Long id; @CreatedDate - private LocalDateTime createAt; + private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; From 717e722b5bd9a732cd0af731aa5d9d2615e10393 Mon Sep 17 00:00:00 2001 From: namgigun Date: Mon, 22 Sep 2025 15:44:07 +0900 Subject: [PATCH 4/5] =?UTF-8?q?Infra:=20=ED=85=8C=EB=9D=BC=ED=8F=BC=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - main.tf 파일 생성 - .gitignore에 terraform에 대한 민감한 정보를 등록 --- .gitignore | 8 +++++++- infra/terraform/main.tf | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 infra/terraform/main.tf diff --git a/.gitignore b/.gitignore index 5ca2add7..1d0b1312 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,10 @@ out/ ### Custom ### db_dev.mv.db db_dev.trace.db -.env \ No newline at end of file +.env + +### Terraform ### +/infra/terraform/.terraform +/infra/terraform/.terraform.lock.hcl +/infra/terraform/terraform.tfstate +/infra/terraform/terraform.tfstate.backup \ No newline at end of file diff --git a/infra/terraform/main.tf b/infra/terraform/main.tf new file mode 100644 index 00000000..6e1e7eef --- /dev/null +++ b/infra/terraform/main.tf @@ -0,0 +1,22 @@ +terraform { + // aws 라이브러리 불러옴 + required_providers { + aws = { + source = "hashicorp/aws" + } + } +} + +# 디폴드 리전 설정 +provider "aws" { + region = "ap-northeast-2" +} + +resource "aws_vpc" "example" { + cidr_block = "10.0.0.0/16" + + tags = { + Name = "example" + } +} + From 4f67a682c7b270a9c4dccbf808c96bc19b46afe7 Mon Sep 17 00:00:00 2001 From: namgigun Date: Mon, 22 Sep 2025 17:48:11 +0900 Subject: [PATCH 5/5] =?UTF-8?q?Infra:=20AWS=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 간단한 구조 1. VPC (1) 2. Subnet (2) -> Private, Public 3. EC2 (1) --- infra/terraform/main.tf | 103 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/infra/terraform/main.tf b/infra/terraform/main.tf index 6e1e7eef..647ac23e 100644 --- a/infra/terraform/main.tf +++ b/infra/terraform/main.tf @@ -12,11 +12,110 @@ provider "aws" { region = "ap-northeast-2" } -resource "aws_vpc" "example" { +# VPC_1 +resource "aws_vpc" "vpc_1" { cidr_block = "10.0.0.0/16" + enable_dns_support = true + enable_dns_hostnames = true tags = { - Name = "example" + Name = "team5-vpc-1" } } +# 퍼블릭 서브넷 (Subnet_1) +resource "aws_subnet" "subnet_1" { + vpc_id = aws_vpc.vpc_1.id + cidr_block = "10.0.1.0/24" + availability_zone = "ap-northeast-2a" + map_public_ip_on_launch = true # 퍼블릭 IP 자동 할당 + + tags = { + Name = "team5-subnet-1-public" + } +} + +# 프라이빗 서브넷 (Subnet_2) +resource "aws_subnet" "subnet_2" { + vpc_id = aws_vpc.vpc_1.id + cidr_block = "10.0.2.0/24" + availability_zone = "ap-northeast-2b" + + tags = { + Name = "team5-subnet-2-private" + } +} + +# 인터넷 게이트 웨이 +resource "aws_internet_gateway" "igw_1" { + vpc_id = aws_vpc.vpc_1.id + + tags = { + Name = "team5-igw-1" + } +} + +# 라우팅 테이블 +resource "aws_route_table" "rt_1" { + vpc_id = aws_vpc.vpc_1.id + + # 모든 트래픽에 대해 인터넷 게이트웨이로 보냄 + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw_1.id + } + + tags = { + Name = "team5-rt-1" + } +} + +resource "aws_route_table_association" "association_1" { + # 연결할 서브넷 + subnet_id = aws_subnet.subnet_1.id + + # 연결할 라우트 테이블 지정 + route_table_id = aws_route_table.rt_1.id +} + +resource "aws_route_table_association" "association_2" { + # 연결할 서브넷 + subnet_id = aws_subnet.subnet_2.id + + # 연결할 라우트 테이블 지정 + route_table_id = aws_route_table.rt_1.id +} + +resource "aws_security_group" "sg_1" { + name = "team5-sg-1" + description = "Allow SSH and HTTP" + vpc_id = aws_vpc.vpc_1.id + + ingress { + from_port = 0 + to_port = 0 + protocol = "all" # 모든 프로토콜 + cidr_blocks = ["0.0.0.0/0"] # 모든 IP 허용 + } + + egress { + from_port = 0 + to_port = 0 + protocol = "all" # 모든 프로토콜 + cidr_blocks = ["0.0.0.0/0"] # 모든 IP 허용 + } +} + +resource "aws_instance" "ec2_1" { + ami = "ami-077ad873396d76f6a" + instance_type = "t2.micro" + + subnet_id = aws_subnet.subnet_1.id + vpc_security_group_ids = [aws_security_group.sg_1.id] + + associate_public_ip_address = true + + tags = { + Name = "team5-ec2-1" + } +} \ No newline at end of file