Project

μΉ΄μΉ΄μ˜€ν†‘ λ””μžμΈμ„ μ°Έκ³ ν•œ μ‹€μ‹œκ°„ μ±„νŒ… μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ§Œλ“€μ–΄ 보기 (1)

2μ£Όλ…˜ 2024. 10. 12. 22:06
λ°˜μ‘ν˜•
πŸ’» ν”„λ‘œμ νŠΈ 미리보기

 

 

μ„œμšΈλ‘œ μ΄μ‚¬ν•˜κ³  νšŒμ‚¬μ— μž…μ‚¬ν•œ μ§€ 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λŠ” μ‹€μ‹œκ°„ λ©”μ‹œμ§€ μ „솑을 μœ„ν•œ μ›Ήμ†ŒμΌ“ μ„€μ •을 λ‹΄λ‹Ήν•œλ‹€. μ΄λŸ¬ν•œ μ„€μ •을 ν†΅ν•΄ μ‚¬μš©μžμ—κ²Œ λ” λ‚˜μ€ κ²½ν—˜μ„ μ œκ³΅ν•  μˆ˜ μžˆλ‹€.

 

 

 

λ°˜μ‘ν˜•