inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

173만명의 커뮤니티!! 함께 토론해봐요.

실시간 메시지 읽지 않음 표시 SSE 질문 드립니다.

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

읽지 않은 메시지 표시를 SSE로 한번 구현 해보라고 하셨는데, 웹소켓이나 stomp를 써도 상관 없나요? 토큰 정보는 상황에 따라 저장 위치(쿠키 or 로컬스토리지)를 다르게 개발 하나요? 그렇다면 통상 실무에서는 토큰 정보를 어디에 저장 하는지 그리고 몇 가지 예시 좀 부탁 드립니다.

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
ㅌㅇ 댓글 2 좋아요 0 조회수 241

ChatListResponse에 @Valid을 붙인 이유

해결됨

Spring Boot를 활용하여 채팅 플랫폼 만들어보기

안녕하세요! 강의 잘듣고 있습니다. 다름이 아니라 ChatControllerV1 에 @GetMapping("/chat-list") public ChatListResponse chatList( @RequestParam("name") @Valid String to, @RequestParam("from") @Valid String from ) { return chatServiceV1.chatList(from, to); } @Valid 를 붙이셨는데 제가 알기론 @Valid 가 붙는 쪽은 컨트롤러단에서 DTO 또는 Entity 매개변수 앞에 붙어서 유효성 검사를 하는걸로 알고있습니다! 제 지식이 맞다면 왜 String 에 앞단에 넣은 이유가 궁금합니다..! 아니면 이것도 추후 DTO 또는 request , response 객체들이 들어갈 수 있기 때문에 들어가나요?

  • mysql
  • spring-boot
  • jpa
  • jwt
  • websocket
한상희 댓글 2 좋아요 0 조회수 151

생성자 질문드립니다

해결됨

RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기

NotificationMessage 모델에 생성자를 추가하는 이유가 Jackson 역직렬화때문에 추가하셨다 했는데 setter만 있으면 필드명과 알아서 바인딩되어서 생성자가 없어도 되는거 아닌가요? 실제로 생성자 삭제하고 message key값으로 /app/send 요청 찌르면 객체에 바인딩이 잘된상태인데 궁금합니다

  • java
  • spring-boot
  • jpa
  • msa
  • websocket
  • rabbitmq
댓글 2 좋아요 0 조회수 131

세션이 종료되는데 이유를 찾지 못하겠습니다..

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

채팅방 목록 메뉴에서 참여하기를 눌렀을때 connect sessiond IDnubkqe0a total session1 subscribe 검증 sub 토큰 검증 완료 Destination: /topic/1 roomId: 1 Hibernate: select cr1_ 0.id ,cr1_0.created_time,cr1_ 0.is _group_chat,cr1_ 0.name ,cr1_0.updated_time from chat_room cr1_0 where cr1_ 0.id =? disconnect sessiond IDnubkqe0a total session0 서버에서 세션 종료 감지: nubkqe0a 세션이 자동으로 종료됩니다.. 당연히 채팅 메세지도 화면에 안나오는데 토큰 검증은 StompWebSocketConfig 에서 다 되는 것 같은데... 잘모르겠습니다 의심가는 로직이 있으신가요 ?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
열심인 참새 댓글 4 좋아요 0 조회수 305

Pub/Sub & WebSocket 활용한 실시간 알림

해결됨

RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기

SSE & Redis와 Pub/Sub & WebSocket을 비교하고 있는데요. 실시간성과 정확성을 위해서라면 Pub/Sub & WebSocket을 더 많이 쓰나요? 알림의 특성상 채팅과 같은 양방향은 아니기 때문에 WebSocket이 적합한 선택인지 궁금합니다.

  • java
  • spring-boot
  • jpa
  • msa
  • websocket
  • rabbitmq
피곤한개발자 댓글 2 좋아요 0 조회수 255

checkTokenForRefresh에 대해 궁금한점

해결됨

Spring Boot를 활용하여 채팅 플랫폼 만들어보기

안녕하세요! 항상 강의 잘 듣고 있습니다! 그런데 강의를 듣다가 checkTokenForRefresh 을 해주는 메서드를 만드셨는데 제가 이해한것이 맞는지 궁금해서 질문드립니다! 이 메서드에서 만료가 되면 TokenExpiredException 이 일어나면 토큰이 만료되서 decode 을 하시는데 위에 메서드들 처럼 createToken 을 안하는 이유가 만료된 토큰의 정보 바탕으로 바로 똑같이 바로 만들어지는 건가요?

  • mysql
  • spring-boot
  • jpa
  • jwt
  • websocket
한상희 댓글 2 좋아요 0 조회수 138

로컬 스토리지에 토큰 저장하는 방식 질문입니다!

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

보통 토큰을 로컬 스토리지에 저장하나요? 그러면 명시적으로 로그아웃을 누르지 않는이상은 클라이언트가 로컬스토리지 비우는 방식을 사용해서 토큰을 초기화 하지는 않을 것 같은데 혹시 강의에서 로컬 스토리지 말고 쿠키 같은 것에 저장하는 내용이 뒤에서 나오나요? 안나온다면 어떤식으로 처리해야하나요? 서버에서 토큰을 내려보내줄때 쿠키에 담아서 내려보내주어야 하는건가요 ?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
열심인 참새 댓글 2 좋아요 0 조회수 166

강사님 질문있습니다~

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

http,websocket의 비교라는 챕터에서는(12:07) 처음에 http 요청으로 연결을 맺는다라고 하셨는데 순수웹소켓-백엔드 강의에서는 (6:20) http 요청이 아니기 때문에 컨트롤러에서 안받고 핸들러에서 받는다고 하셨는데 중요한 개념인 것 같아서 어떻게 이해하면 될까요? 검색해보니까 처음에 연결은 http 요청에 get이 맞고 헤더에 웹소켓 요청이라는 정보가 있으므로 http 요청과는 구분된다라는 정보가 있는데 잘 모르겠어요~

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
열심인 참새 댓글 2 좋아요 1 조회수 166

강사님 프로젝트 디렉토리 구조에 대해서 질문있어요!

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

보통 contoller service repository 이렇게 폴더 두고 그 안에서 여러개의 MemerConroller ChatController 이런식으로 나누는 것만 봐서 chat과 member 디렉토리를 나누고 그 안에서 다시 controller 디렉토리하고 만드는 방법을 처음 써보는데요~ 저는 강사님 방법이 더 좋은데 보통 어떻게 사용하나요? 특별히 강사님 처럼 디렉토리 나눈 이유가 있을까요 ??

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
열심인 참새 댓글 2 좋아요 0 조회수 137

싱글톤 객체 질문있습니다.

해결됨

웹소켓/STOMP 채팅서비스(spring, vue, redis)

@Bean public PasswordEncoder makePassword() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } 이거를 싱글톤 객체로 만들어주셨는데요 그런데 String encodedPassword = passwordEncoder.encode(memberSaveReqDto.getPassword()); 이부분을 static 으로 두고 참조변수를 사용해서 사용하는 것과 어떤 차이가 있나요? 찾아보니 전역변수는 static 이니까 메모리에 미리 올라가고 싱글톤은 사용할떄 올라가는 장점이 있다고 하는데 이 예시는 어차피 클래스 초기화될 때 생성되니까 그런 장점이 없을 것 같은데... 궁금합니다.

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
열심인 참새 댓글 2 좋아요 0 조회수 135

메시지 저장순서에 대한 질문입니다.

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

안녕하세요 수업을 바탕으로 프로젝트 적용중입니다. 프론트에서 채팅입력하면 백엔드의 연결된 소켓에서 이를 redis 로 publish 하고 이때 같이 채팅메시지를 db에 저장하는 방식으로 구현했습니다. 나중에 채팅방에 다시 입장하는 경우 채팅 저장 날짜를 기반으로 일부 가져오려하니 초까지 같은 경우 순서가 엉키는 현상이 발생하는데 auto_increment 로 저장한 pk 를 순서로 가져와도 될까요? redis 는 싱글스레드이지만 websocket 가 병렬처리되면 결국 pk 순서가 실제 순서를 보장할 수 있을까요?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
minjun 댓글 2 좋아요 0 조회수 128

비동기 서버 구성하다 알 수 없는 에러에 빠졌는데...

해결됨

실전! FastAPI 활용(비동기)

안녕하세요. 좋은 강의 감사합니다. 강의를 기반으로 제 방식대로 서버를 구성하다가 알 수 없는 에러에 빠졌습니다. 서버는 정상 구동은 되고, postman으로 root url인 localhost:8000/ 에 request를 날리면 정상적으로 결과값을 반환 받는데 localhost:8000/api/recommend?userId=1 만 호출하면 바로 에러메세지 없이 500만 응답으로 받고 있습니다. print(1) 도 서버 로그에 찍히지 않고 서버 로그는 아예 나오질 않네요. localhost:8000/ 에서도 동일하게 서버 로그는 찍히지 않습니다 우선 의도는 BaseRepository 클래스를 만들어서 find_by_id 같은 중복 코드를 하나로 관리해보려고 했습니다. 의존성 주입 부분은 지피티의 도움을 받아서 위치를 조정했습니다. 도저히 어디서 문제가 난건지 알 수 없어서 도움 요청 드립니다 ㅜㅜ # main.py from typing import Dict from dotenv import load_dotenv from fastapi import FastAPI from src.app.app import create_app load_dotenv() app: FastAPI = create_app() @app.get("/") async def health_check_handler() -> Dict[str, str]: return {"statusMsg": "good"} # app.py from contextlib import asynccontextmanager from typing import AsyncGenerator import anyio from fastapi import FastAPI from src.app.endpoints.recommend import router @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator: limiter = anyio.to_thread.current_default_thread_limiter() limiter.total_tokens = 200 yield def create_app() -> FastAPI: app = FastAPI(lifespan=lifespan) app.include_router(router, prefix="/api") # 다른 설정들(예: 미들웨어, 이벤트 핸들러 등)을 추가할 수 있습니다. return app # connection.py import os import urllib from typing import AsyncGenerator from dotenv import load_dotenv from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine load_dotenv() DB_USERNAME: str = os.getenv("DB_USERNAME", "root") DB_PASSWORD: str = os.getenv("DB_PASSWORD", "root") DB_HOST: str = os.getenv("DB_HOST", "127.0.0.1") DB_NAME: str = os.getenv("DB_NAME", "") DB_PORT: str = os.getenv("DB_PORT", "3306") DB_ECHO: bool = os.getenv("DB_ECHO", "true").lower() == "true" if not DB_NAME: raise ValueError("DB_NAME 환경변수가 설정되지 않았습니다.") # 비밀번호 특수문자 허용 encoded_password = urllib.parse.quote_plus(DB_PASSWORD) DATABASE_URL: str = f"mysql+asyncmy://{DB_USERNAME}:{encoded_password}@{DB_HOST}:{DB_PORT}/{DB_NAME}" engine: AsyncEngine = create_async_engine( DATABASE_URL, echo=DB_ECHO, pool_size=10, max_overflow=0, pool_timeout=30, # second pool_recycle=60, # second pool_pre_ping=True, ) SessionFactory = async_sessionmaker(autocommit=False, autoflush=False, bind=engine) async def get_db() -> AsyncGenerator[AsyncSession, None]: session = SessionFactory() try: yield session finally: await session.close() # user_route.py from typing import Dict from fastapi import APIRouter, Depends, status from src.app.dependency.query_param_denpendency import snake_case_query from src.core.common_type import V from src.core.exception.not_found_exceptions import UserNotFoundExceiption from src.db.connection import get_db from src.entity.user import UserEntity from src.repository.user import UserRepository, get_user_repository from src.dto.response.user_response import UserResponse router = APIRouter(prefix="/recommend") @router.get(path="", status_code=status.HTTP_200_OK, response_model=UserResponse) async def get_recommend_schedule( params: Dict[str, V]=Depends(snake_case_query), user_repo: UserRepository=Depends(get_user_repository) ): print(1) user_id: int = int(params.get("user_id", None)) user: UserEntity | None = await user_repo.get_user_by_id(user_id) if not user: raise UserNotFoundExceiption() user = UserResponse.model_validate(user) return user # base_repository.py from typing import Type from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from src.core.common_type import E class BaseRepository: def __init__(self, db: AsyncSession): self.db = db async def get_entity_by_id(self, model: Type[E], entity_id: int) -> E | None: print(2) entity: E | None = await self.db.execute(select(model).where(model.id==entity_id)) return entity.scalars().first() # user_repo.py from fastapi import Depends from sqlalchemy.ext.asyncio import AsyncSession from src.db.connection import get_db from src.entity.user import UserEntity from src.repository.base_repository import BaseRepository def get_user_repository(db: AsyncSession = Depends(get_db)) -> "UserRepository": return UserRepository(db) class UserRepository(BaseRepository): async def get_user_by_id(self, user_id: int) -> UserEntity | None: print(3) return await self.get_entity_by_id(UserEntity, user_id) # user_response.py from datetime import datetime from typing import Optional from pydantic import BaseModel class UserResponse(BaseModel): id: int name: str nickname: str email: str phone: str join_date: datetime updated_at: Optional[datetime] = None deleted_at: Optional[datetime] = None class Config: from_attributes = True 도대체 어디서 문제가 생긴걸까요...

  • python
  • FastAPI
  • websocket
  • asyncio
  • pubsub
윤서준 댓글 5 좋아요 0 조회수 591

채팅 메시지 저장에 관한 질문입니다.

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

채팅 메시지를 보낼 때마다 db에 접근해서 저장하는 방식이면 디스크 io 작업이 굉장히 잦아질 거 같은데 보통 이런 경우에는 redis 를 쓴다면 redis에 저장해두었다가 스케줄링같은 방식으로 한번에 db에 저장하는 방식을 사용하는 걸까요?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
minjun 댓글 2 좋아요 0 조회수 132

stomp관련 질문입니다.

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

현재 메세지만 redis에 저장해서 공통적으로 사용되는 것으로 생각하는데 사용자의 연결정보는 각각의 서버가 가지고 있고 redis에서 메세지가 발행되는 경우 각각의 서버에서 연결된 사용자에게 메세지를 전달한다고 이해하면 될까요?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
hxcva1 댓글 2 좋아요 0 조회수 141

채팅 방식 질문입니다!

해결됨

RabbitMQ를 이용한 비동기 아키텍처 한방에 해결하기

학습중 궁금한 것은 언제든 문의 하세요. 질문을 최대한 자세히 남겨주시면 반드시 답변 드리도록 하겠습니다. 추가로 알고 싶은 내용도 요청해주시면 강의 자료를 업데이트 해서 제공할 예정입니다. 해당 강의에서 http요청은 mq를 사용하게 되는데 채팅의 경우 스프링의 기본 내장브로커를 사용하게 되는 것이 아닌가요?

  • java
  • spring-boot
  • jpa
  • msa
  • websocket
  • rabbitmq
hxcva1 댓글 2 좋아요 0 조회수 158

CORS 설정 어떻게 하셨나요?

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

원래는 백엔드에서 진행 하는걸로 알고 있는데, 간단하게 하기 위해서 프론트쪽에서 설정을 몇 번이고 진행 했는데도 불구하고 계속해서 cors 에러가 납니다. 강의에서는 따로 cors 설정을 하셨던건 안 나온거 같은데, cors 설정 어떻게 하셨는지 질문 드립니다. (vue.config.js) const { defineConfig } = require('@vue/cli-service'); module.exports = defineConfig({ transpileDependencies: true, devServer: { proxy: { member: { target: 'http://localhost:8080', changeOrigin: true, pathRewrite: { '^/member': '', }, }, }, }, });

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
ㅌㅇ 댓글 2 좋아요 0 조회수 244

강의 내 1 번 방법에 대한 질문

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

강의 설명중 1 번 방법에서 누가 서버에 커넥션을 맺고 있고 subscribe 하는지 서버에 메모리를 만들어서 관리하는 로직을 사용한다고 하셨는데 이전에 강의에서 배운내용에 따르면 스프링과 stomp 는 기본적으로 세션관리를 내부적으로 처리한다고 하셔서 즉 저희가 직접 접근을 하지못하는데 이러면 이벤트 리스너로 따로 sessions라는 자료구조를 만든 것을 활용해서 코드를 작성해야 하잖아요 ? 그리고 세션은 랜덤으로 스프링에서 생성하는데 이러면 세션이 몇개인지 카운트 및 각각 세션id가 부여되긴하는데 그게 어떤 사용자인지 구분이 안되기에 StompHandler에서 connect 맺을때 검증 후에 추가적으로 이메일정보를 String email = claims.getSubject(); accessor.getSessionAttributes().put("email", email); 로 설정해서 이벤트 리스너에 넘겨서 세션을 저장하는 식으로 생각했는데 맞을까요 ? 이후 서버에서 처리할때 subscribe하면서 , 동시에 누가 서버에 커넥션을 맺고있는지 아닌지 여부를 파악하는 (다소 복잡한) 로직을 작성해서 처리할 수 있다 이게 맞는 흐름일까요 ?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
kkkkkk 댓글 2 좋아요 0 조회수 176

npm 한번에 추가하기

해결됨

웹소켓/STOMP 채팅서비스(spring, vue, redis)

npm install vue-router && npm install axios && npm install vuetify@3 && npm install jwt-decode && npm install sockjs-client && npm install webstomp-client 질문은 아니고 한번에 추가할수 있는 명령어 공유하면 좋을거 같아서 작성합니다!

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
nhs0912 댓글 1 좋아요 1 조회수 150

jwt토큰 & 시큐리티 질문이요

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

안녕하세요. 토큰 발행, 검증 및 시큐리티 코드가 좀 복잡 하다고 느끼는데요. 이거는 한번만 개발 해놓으면 다른 곳에서도 그대로 혹은 유사하게 가져다 쓸 수 있는건가요? 시큐리티 코드는 반복 되는 패턴 혹은 개념인가요?

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
ㅌㅇ 댓글 2 좋아요 0 조회수 172

return type ?에 대해서

미해결

웹소켓/STOMP 채팅서비스(spring, vue, redis)

@PostMapping("/doLogin") public ResponseEntity<?> doLogin(@RequestBody MemberLoginRequestDto memberLoginRequestDto) { //email, password 검증 Member member = memberService.login(memberLoginRequestDto); //일치할 경우 access token 발행 String jwtToken = jwtTokenProvider.createToken(member.getEmail(), member.getRole().toString()); Map<String, Object> loginInfo = new HashMap<>(); loginInfo.put("id", member.getId()); loginInfo.put("token", jwtToken); return new ResponseEntity<>(loginInfo, HttpStatus.OK); } 어찌보면 자바 질문일수도 있는데요. 수업 내용 듣다가 궁금해서요! 여기 메서드 보시면 return type이 ? 사용하였는데요. ?는 어떤 타입이 와도 통과 되는 거라고 알고 있는데요. 명시적으로 특정타입으로 표현을 해도 될거 같은데 그냥 교육상 ?로 하신건가요? 실제 실무에서도 ?를 자주 사용할까요?? 코딩하다가 궁금해서 여쭤봅니다 ㅋㅋ

  • spring-boot
  • websocket
  • stomp-websocket
  • pubsub
  • vue-3
nhs0912 댓글 2 좋아요 1 조회수 107

인기 태그

인프런 TOP Writers

주간 인기글