해결된 질문
작성
·
1K
·
수정됨
1
안녕하세요 제로초님! 강의 잘 듣고 있습니다.
제가 현재 프론트엔드를 NextJS 14.xx(app router)로 작성하고 있고, 백엔드는 제로초님 강의 따라서 NestJS로 만들고 있는데 현재 연결은 로컬에서 HTTP로 하고 있습니다.
그런데 소켓을 연결하는 과정에서 계속
'WebSocket connection to 'ws://localhost:8080/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.'
위와 같은 에러가 뜹니다. 이틀간 계속 검색해봤는데 도대체 왜 연결이 안되는지 모르겠습니다... ㅠㅠ
프론트는 현재 아래와 같이 되어있구요.
localhost:3000으로 돌리고 있습니다.
"socket.io-client": "^4.7.4",
import io from 'socket.io-client';
useEffect(() => {
const options = {
auth: `${getCookie('accessToken')}`,
extraHeaders: { id: chatRoomId },
};
const socket = io(`http://localhost:8080/chats`, options);
console.log(socket);
socket.on('connect', () => {
console.log('WebSocket connected.');
});
return () => {
socket.off();
};
}, []);
백엔드는 아래와 같이 되어있습니다.
import { Socket } from 'socket.io';
import {
ConnectedSocket,
MessageBody,
OnGatewayConnection,
OnGatewayDisconnect,
OnGatewayInit,
SubscribeMessage,
WebSocketGateway,
} from '@nestjs/websockets';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Message } from './entity/message.entity';
import { Logger } from '@nestjs/common';
@WebSocketGateway({
namespace: 'chats',
cors: true,
})
export class ChatsGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
private logger = new Logger('CHAT-SERVICE');
constructor(
@InjectRepository(Message)
private readonly messageRepository: Repository<Message>,
) {
this.logger.log('constructor');
}
afterInit() {
this.logger.log('init');
}
async handleConnection(@ConnectedSocket() socket: Socket) {
this.logger.log(`connected: ${socket.id} ${socket.nsp.name}`);
}
async handleDisconnect(@ConnectedSocket() socket: Socket) {
this.logger.log(`disconnected: ${socket.id} ${socket.nsp.name}`);
}
@SubscribeMessage('send-message')
async handleSubmitChat(
@MessageBody() message: string,
@ConnectedSocket() socket: Socket,
) {}
}
chat-service의 main.ts는 아래와 같습니다.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const port = 8080;
await app.listen(port);
console.log(`CHAT-SERVICE listening on ${port}!`);
}
bootstrap();
app.module.ts는 아래와 같습니다.
import { Module } from '@nestjs/common';
import { ChatModule } from './chat/chat.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import jwtConfig from './config/jwt.config';
import mysqlConfig from './config/mysql.config';
import sentryConfig from './config/sentry.config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [jwtConfig, mysqlConfig, sentryConfig],
}),
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
let object: TypeOrmModuleOptions = {
type: 'mysql',
host: configService.get('mysql.host'),
port: configService.get('mysql.port'),
database: configService.get('mysql.database'),
username: configService.get('mysql.username'),
password: configService.get('mysql.password'),
autoLoadEntities: true,
synchronize: true,
};
if (configService.get('STAGE') === 'LOCAL') {
object = Object.assign(object, {
logging: true,
});
}
return object;
},
}),
ChatModule,
],
controllers: [],
providers: [],
})
export class AppModule {}
소켓 객체는 프론트에서 찍어보면 다음과 같이 나옵니다.
@WebSocketGateway({ namespace: 'chats', cors: true, }) 에서 cors를 http://localhost:3000으로 설정하고 main에서도 다 열었을때도 안되는걸로 보아 cors 문제는 아닌듯합니다.
답변 1
1
네 맞습니다. init 조차 뜨질 않습니다. ㅠㅠ exports에 추가해도 여전히
이와 같이 connected가 false 상태로 뜨네요... ㅠㅠ
서버쪽에는 아무것도 안들어오구요...
@WebSocketGateway(8080, { namespace: 'chats', cors: true, transports: ['websocket'] })
한 번 해보세요. 또한 프론트랑 백엔드의 웹소켓 버전이 4로 동일한지도 확인해보세요.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const port = 8000;
await app.listen(port);
console.log(`CHAT-SERVICE listening on ${port}!`);
}
bootstrap();
일단 포트 충돌을 방지하기 위하여 main.ts의 포트를 8000으로 바꾼 뒤,
@WebSocketGateway(8080, {
transports: ['websocket'],
namespace: 'chats',
cors: true,
})
제로초님 말씀처럼 위와 같이 바꿨더니 오류 메시지가 아래처럼 바뀌기는 했습니다.
GET http://localhost:8080/socket.io/?EIO=4&transport=polling&t=OujvTur 400 (Bad Request)
그래도 여전히 문제는 해결되지 않네요... ㅠㅠ
백엔드 소켓 버전도 ^4.7.4 버전으로 프론트 엔드와 동일합니다.
"@nestjs/platform-socket.io": "^10.3.3",
"@nestjs/websockets": "^10.3.3",
"socket.io": "^4.7.4"
해결했습니다!
혹시 다른 분들에게도 도움이 될까하여 공유합니다.
useEffect(() => {
const options = {
transports: ['websocket'],
// auth: `${getCookie('accessToken')}`, <- problem!
extraHeaders: { id: chatRoomId },
};
const socket = io(`http://localhost:8080/chats`, options);
socket.on('connect', () => {
console.log('WebSocket connected.');
});
return () => {
socket.disconnect();
};
}, []);
문제는 위의 프론트엔드 코드에서 주석 처리 되어있는 부분이었습니다.
백엔드 main.ts는 아래와 같습니다.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const port = 8000;
await app.listen(port);
console.log(`CHAT-SERVICE listening on ${port}!`);
}
bootstrap();
chat.gateway.ts는 아래와 같습니다.
@WebSocketGateway(8080, {
transports: ['websocket'],
namespace: 'chats',
cors: {
origin: ['http://localhost:3000'],
},
})
그간 답변해주셔서 감사합니다 제로초님! :)
백엔드에서 chat-service 구동시 다음과 같이 뜹니다.
웹에서 테스트로 만든 'localhost:8080/ping'으로 들어가면
와 같이 떠서, HTTP 서버는 잘 구동되고 있구요.
chat.module.ts는 아래와 같습니다.