μΉ΄μΉ΄μ€ν‘ λμμΈμ μ°Έκ³ ν μ€μκ° μ±ν μ ν리μΌμ΄μ λ§λ€μ΄ 보기 (1)
π» νλ‘μ νΈ λ―Έλ¦¬λ³΄κΈ°
μμΈλ‘ μ΄μ¬νκ³ νμ¬μ μ μ¬ν μ§ 4κ°μμ΄ μ§λμ OJTλ₯Ό νλ©΄μ μ 무λ₯Ό λ°°μ°κ³ μκ°μ 보λ΄λ€κ° μ¬μ κ° μκ²Όλ€. μ£Όλ§μ μ¬μ΄λ νλ‘μ νΈλ₯Ό λ§λ€μ΄λ³΄μκ³ λ§μλ¨Ήκ³ , μΉμμΌμ μ΄μ©ν μ±ν νλ‘κ·Έλ¨μ κ°λ°νλ€.
μ€νλ§ λΆνΈλ₯Ό μ·¨μ μ μ μ¬μ©νμ¬ μ¬λ¬ νλ‘μ νΈλ₯Ό μ§ννμλλ°, νμ¬μ μ μ¬ν μ΄νλ‘λ μ μ¬μ©νμ§ μμμ μμ΄λ²λ¦° λΆλΆμ΄ λ§μλ€.

μ€μκ° μ±ν μ ν리μΌμ΄μ
νλ‘μ νΈ λ£¨νΈ
β
βββ src
β βββ main
β β βββ java
β β β βββ com
β β β βββ example
β β β βββ chatapp
β β β βββ config
β β β β βββ WebSocketConfig.java
β β β β βββ WebConfig.java
β β β βββ controller
β β β β βββ ChatController.java
β β β βββ service
β β β βββ UserService.java
β β βββ resources
β β βββ application.properties
β β
β βββ webapp
β βββ WEB-INF
β βββ jsp
β βββ chat.jsp
β βββ username.jsp
λ¨Όμ μ¬μ©μκ° λλ€μμ μ λ ₯νλ λΆλΆμΈ username.jspλ₯Ό λ§λ€κ³ μ±ν λ°©μ μ μ₯νκ² λλ©΄ chat.jspκ° μ€νλλ€.
WebSocketμ μ·¨μ μ€λΉλ₯Ό νλ©΄μ ν νλ‘μ νΈμμ μ¬μ©ν΄λ³Έ κ²½νμ΄ μμμ§λ§, κ·Έλλ μΉμμΌμ λν μ΄ν΄κ° λΆμ‘±ν μνμμ μ¬μ©ν λλμ΄μλ€. μ΄λ²μλ μΉμμΌμ λν΄ κΉμ΄ 곡λΆνκ³ κ΅¬νν΄λ³΄μλ€.
κΈ°μ μ€ν
- λ°±μλ: Spring Boot, WebSocket
- νλ‘ νΈμλ: JSP, JavaScript, CSS
μ£Όμ κΈ°λ₯
- μ€μκ° μ±ν : μ¬μ©μλ λ©μμ§λ₯Ό μ€μκ°μΌλ‘ μ£Όκ³ λ°μ μ μλ€.
- μ¬μ©μ λͺ©λ‘: νμ¬ μ μ μ€μΈ μ¬μ©μ λͺ©λ‘μ νμνλ€.
- μ΄λͺ¨μ§ μ νκΈ°: μ¬μ©μκ° λ©μμ§ μ λ ₯ μ μ΄λͺ¨μ§λ₯Ό μ½κ² μ νν μ μλ κΈ°λ₯μ μ 곡νλ€. μ΄λͺ¨μ§λ μΉ΄ν κ³ λ¦¬λ³λ‘ ꡬλΆλμ΄ μμ΄ μ¬μ©μκ° μνλ μ΄λͺ¨μ§λ₯Ό μ½κ² μ°Ύμ μ μλ€.
- μ¬μ©μ μ μ₯/ν΄μ₯ μλ¦Ό: μ¬μ©μκ° μ±ν λ°©μ μ μ₯νκ±°λ ν΄μ₯ν λ μμ€ν λ©μμ§λ₯Ό ν΅ν΄ μλ¦Όμ μ 곡νλ€.
μ£Όμ νμΌ λ° κ΅¬μ±
- ChatController.java: μ¬μ©μ λͺ©λ‘ κ΄λ¦¬ λ° λ©μμ§ μ μ‘ λ‘μ§μ μ²λ¦¬νλ€.
- chat.jsp: μ¬μ©μ μΈν°νμ΄μ€λ₯Ό ꡬμ±νλ©°, μ΄λͺ¨μ§ μ νκΈ°μ μ¬μ©μ λͺ©λ‘μ ν¬ν¨νλ€.
UI/UX κ°μ
μ΄λͺ¨μ§ μ νκΈ°μ λμμΈμ κ°μ νμ¬ μ¬μ©μ κ²½νμ ν₯μμμΌ°λ€. μ΄λͺ¨μ§λ₯Ό μΉ΄ν κ³ λ¦¬λ³λ‘ ꡬλΆνκ³ , λ§μ°μ€ μ€λ² μ νλλλ ν¨κ³Όλ₯Ό μΆκ°νμ¬ μκ°μ μΌλ‘ λ λ§€λ ₯μ μΌλ‘ λ§λ€μλ€.
μμ‘΄μ± μ€μ
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
// JSP Support Dependencies
implementation group: 'org.glassfish.web', name: 'jakarta.servlet.jsp.jstl', version: '2.0.0'
implementation 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0'
implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
implementation 'org.apache.taglibs.taglib-standard-impl:1.2.5'
implementation 'org.apache.taglibs.taglib-standard-spec:1.2.5'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java:8.0.33' // MySQL Connector
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
WebConfig.java νμΌλ§λ€κΈ°
/**
* WebConfig ν΄λμ€λ Spring MVCμ CORS(Cross-Origin Resource Sharing) μ€μ μ ꡬμ±ν©λλ€.
* CORSλ λ€λ₯Έ μΆμ²μ μΉ νμ΄μ§κ° νμ¬ μΆμ²μ 리μμ€μ μ κ·Όν μ μλλ‘ νμ©νλ λ©μ»€λμ¦μ
λλ€.
* μ΄ μ€μ μ ν΅ν΄ νΉμ μΆμ²μμ μ€λ μμ²μ νμ©νκ³ , νμ©ν HTTP λ©μλ λ° μ격 μ¦λͺ
μ¬μ© μ¬λΆλ₯Ό μ§μ ν©λλ€.
*/
package com.example.chatproject.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// CORS μ€μ μΆκ°
registry.addMapping("/chat/**") // "/chat/**" κ²½λ‘μ λν CORS μ€μ
.allowedOrigins("http://localhost:8080", "http://localhost:3000") // νμ©ν μΆμ²
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // νμ©ν HTTP λ©μλ
.allowCredentials(true); // μ격 μ¦λͺ
(μΏ ν€, μΈμ¦ ν€λ λ±) νμ©
}
}
WebSocketConfig.java νμΌλ§λ€κΈ°
/**
* WebSocketConfig ν΄λμ€λ Spring WebSocket λ©μμ§ λΈλ‘컀λ₯Ό μ€μ νλ ν΄λμ€μ΄λ€.
* μ΄ ν΄λμ€μμλ STOMP νλ‘ν μ½μ μ¬μ©νμ¬ μΉμμΌ μλν¬μΈνΈλ₯Ό λ±λ‘νκ³ ,
* λ©μμ§ λΈλ‘컀λ₯Ό ꡬμ±νμ¬ ν΄λΌμ΄μΈνΈμ μλ² κ°μ μ€μκ° λ©μμ§ μ μ‘μ κ°λ₯νκ² νλ€.
*/
package com.example.chatproject.config;
import com.example.chatproject.listener.CustomHttpSessionInterceptor;
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;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// STOMP μλν¬μΈνΈ λ±λ‘
registry.addEndpoint("/ws") // μΉμμΌ μλν¬μΈνΈλ₯Ό "/ws"λ‘ μ€μ
.setAllowedOriginPatterns("http://localhost:8080") // νμ©ν μΆμ²λ₯Ό μ€μ
.withSockJS() // SockJSλ₯Ό μ¬μ©νμ¬ λΈλΌμ°μ νΈνμ± μ 곡
.setInterceptors(new CustomHttpSessionInterceptor()); // 컀μ€ν
HTTP μΈμ
μΈν°μ
ν° μ¬μ©
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// λ©μμ§ λΈλ‘컀 μ€μ
config.enableSimpleBroker("/topic"); // λ©μμ§ λΈλ‘μ»€κ° "/topic" κ²½λ‘λ₯Ό ꡬλ
νλλ‘ μ€μ
config.setApplicationDestinationPrefixes("/app"); // μ ν리μΌμ΄μ
λͺ©μ μ§μ μ λμ¬λ₯Ό "/app"μΌλ‘ μ€μ
}
}
μ΄ νμΌλ€μ κ°κ° CORS μ€μ κ³Ό WebSocket λ©μμ§ λΈλ‘컀 μ€μ μ λ΄λΉνλ€.
μ΄ λ μ€μ νμΌμ Spring Boot κΈ°λ°μ μΉ μ ν리μΌμ΄μ μμ μ€μν μν μ νλ€.
WebConfig.javaλ CORS μ€μ μ ν΅ν΄ μΈλΆ μΆμ²μ μμ²μ νμ©νκ³ , WebSocketConfig.javaλ μ€μκ° λ©μμ§ μ μ‘μ μν μΉμμΌ μ€μ μ λ΄λΉνλ€. μ΄λ¬ν μ€μ μ ν΅ν΄ μ¬μ©μμκ² λ λμ κ²½νμ μ 곡ν μ μλ€.