이전 글 : 채팅 서비스에 Redis 도입 (1) [ https://techforme.tistory.com/16 ] 이전 글 : 채팅 서비스에 Strategy Pattern 적용 [ https://techforme.tistory.com/15 ] 구독 정보 Repository 로서 Redis 도입 이전 글에서 채팅 서비스에 Message Broker 로서 Redis 를 도입했던 글을 썼었는데, 이번에는 구독 정보 Repository 로서 Redis 를 적용한 부분에 대해서 쓰려고 한다. 구독 정보 Repository 는 이전에 인메모리 캐시를 이용한 ConcurrentHashMap 으로 구현하면서 Strategy 패턴을 적용했었는데, 그렇기 때문에 아래와 같이 인터페이스만 구현하고 yml 파일 설정만 변경..
분류 전체보기
초기 아이디어 조합이 가장 먼저 떠올랐다. 알파벳 스물여섯개 중 주어진 숫자만큼 조합으로 이용해서 뽑고, 단어마다 해당 단어가 뽑은 단어에 포함되어 있는지를 셈해보는 것이다. 최악의 경우 21C10 의 경우의 수에 각각 50개의 단어를 판별해야 한다. (acnti 다섯글자는 반드시 있어야 하므로) 대충 보면 시간 초과가 날 것 같진 않은데 ... 비슷한 문제를 재귀를 이용한 조합으로 단순히 풀었다가 시간 초과가 난 기억이 있어서 그냥 비트마스킹 연습도 할겸 비트마스킹으로 풀어보기로 한다. 비트마스킹은 사실 근본적인 알고리즘이라기 스킬의 일종이다. 이진법으로 나타낸 수의 각 자리를 하나의 불리언이라고 생각하고 특정 조합을 하나의 숫자로 나타내는 것이다. 예컨대 13을 이진수로 표현하면 1101 인데 '첫번..
초기 아이디어 부분적으로 최단거리를 구하는 문제이므로 DFS, BFS 가 쓰일 것 같다는 생각은 바로 들었는데, 다소 복잡하다. 처음엔 "가장 먼 두 지점" 이라는 말에서 DFS 를 생각했는데 돌아서 가면 안된다는 조건 때문에 결국 가장 먼 지점이라고 해도 BFS 로 풀어내야 한다는 것을 깨달았다. 모든 육지에 대해서 BFS 를 수행하고 가장 멀리까지 갈 수 있는 지점을 계산 해보기로 했다. 문제풀이 1. 모든 두 지점을 순회하면서 BFS #include using namespace std; int n, m; char a[51][51]; int visited[51][51]; int dx[4] = {0, 1, 0, -1}; int dy[4] = {1, 0, -1, 0}; int bfs(int sX, int..
초기 아이디어 최단 거리를 묻는 문제는 우선 직관적으로 DFS, BFS 를 생각할 수 있다. 더 코드가 짧은 DFS 를 하기로 해보고 연습겸 BFS 로도 구현해보기로 한다. 문제 풀이 1. DFS #include using namespace std; int a[101][101]; int visited[101][101]; int n, m, ret=987654321; int dx[4] = {1, 0, -1, 0}; int dy[4] = {0, 1, 0, -1}; void dfs(int x, int y, int dept){ if(x==n-1 && y==m-1) { ret = ret>dept?dept:ret; return; } for(int i=0;i> n >> m; for(int i=0;i> m; for(in..
파사드 패턴이란? 파사드(Facade)는 '건축물의 외관, 겉면'을 뜻하는 단어로, 프랑스어(façade)에서 건너온 단어이다. 원래 어원은 라틴어에서 얼굴(Face)을 뜻하는 facies(파시에스) 라고 하는데 건출물 외관 = 얼굴 로 이해해볼 수 있다. 디자인 패턴에서 말하는 파사드 패턴은 내부의 코드를 가려놓고 전면에 단순화된 인터페이스를 내세우는 구조가 마치 내부의 인테리어나 구조를 덮어놓은 건축물의 외벽과 유사하다는 데서 차용되었다. 여러 클래스들을 직접 가져와서 쓰게 되면 가독성도 떨어지고 의존관계도 복잡해지니, 하나의 단순화된 클래스를 만들어서 이를 쉽게 이용할 수 있도록 만드는 것이다. 아래 그림과 같이 말이다. 언뜻 듣기에 너무 쉬운 개념이라서 '이걸 따로 배울 필요가 있었나?' 라는 생..
오늘은 너무 유명한 N+1 문제와 이와 관련한 EntityManager 의 getReference 라는 메서드를 이야기 하려고 한다. 사실 N+1 이 발생하는 원인이나 해결책은 간단한데, 조금 애매한 부분이 있어서 혼란을 겪었다. N+1 문제 N+1 문제는 자바 ORM 에서 객체 내부의 연관된 객체에 접근하려고 할때 발생한다. DB에서 객체를 로드해 올때 객체의 필드에 다른 엔티티가 포함되어 있는 경우, ORM 은 해당 엔티티의 정보를 전부 가지고 오지 않는다. (select query 를 생각해보면 당연하다. 연관된 다른 테이블의 자료는 조회해오지 않는다.) 그 대신 객체 행세(?)를 할 수 있는 프록시 객체(위임 객체)를 넣어주는데, 이 프록시 객체는 껍데기만 가지고 있을 뿐이고 변수에 데이터를 가지..
채팅서비스의 메세지 브로커 및 구독 관리에 Redis 를 적용하였다. (+ RefreshToken 저장) 이번 프로젝트를 진행하면서 손에 꼽을 정도 이해하기 힘들었던 주제였던거 같다. 어떤 구조로 동작하는 것인지 도무지 감이 안와서 코드 한참을 들여다 보고, 실제로 실습을 진행해 보고서야 느낌을 알게 됐다. 솔직히 그렇게 복잡하거나 어려운 내용은 아닌데 뭐랄까 속시원하게 설명해주는 레퍼런스가 없던게 문제 같다... 아닌가... 내 배경지식의 탓일 수도 있고. 여튼 시간이 이틀 꼬박 걸렸다. (사실 여전히 내가 올바르게 적용을 한 것인지도 잘 모르겠다.) 메세지 브로커로서 Redis 의 역할 메세지 브로커는 브로커(broker, 중개인) 라는 단어의 의미 그대로, 메세지를 발행한 곳에서 구독한 곳으로 전달..
1. 채팅 서비스의 Subscription 정보 관리 채팅 서비스에서 메세지를 주고 받는 과정은 특정 토픽에 대한 발행과 구독이라는 행위로 이루어 진다. 채팅 서비스를 이용하는 유저가 서버에 메세지 전송을 요청하면, 채팅 서버에서는 메세지를 해당하는 토픽에 발행한다. 발행된 메세지는 해당 토픽을 구독하고 있는 모든 유저에게 전송된다. 이러한 송신 → 수신 과정을 Message Broking 이라고 한다. 전송이 요청된 메세지를 올바르게 전달하기 위해서는 어떤 유저가 웹소켓 서버와 연결되어 있고, 또 해당 페이지를 구독하고 있는지를 알고 있어야 하기 때문에 채팅서버에서는 구독 정보를 저장해 두어야 한다. 스프링 웹소켓은 자체적인 Message Broker 가 내장되어 있어서 이러한 구독 정보 관리를 관리한..
지난 글 마지막에 Enum Type 의 필드에 대해서는 1. Enum Type 은 일반적인 String 또는 Long, Double 같은 클래스와 다르게 별도의 애너테이션을 만들어야 한다. 2. 아예 엉뚱한 값이 들어오면 직접 구현한 Validator 가 작동하기 전에 Parsing 과정에서 Exception 이 터지기도 한다. 라고 이야기 했는데 이 두 문제를 해결하여 적절한 에러메세지를 반환해 보았다. 일단 2번 문제에 대해서 이야기하자면 Serialize 와 Deserialize 의 개념에 대해서 먼저 정리를 해야한다. (직렬화 / 역직렬화) 위 개념은 객체나 데이터를 더 낮은 수준의 데이터 형태로 전환 하거나 그 반대 과정을 말한다. 더 낮은 수준의 데이터라는 건 가만히 생각해보면 조금 모호한 개..
Pull Request 내용 하 글쓰다가 날라가서 쓸 맛이 안난다 Issue / PR 내용만 복붙하고 어떻게 구현 했는지 써야겠다. Issue 내용 요청에 대한 유효성 검사(Validation) 구현 #21 현재 Web 에서 API 로 향하는 요청에 대하여 Front-end 에서의 유효성 검사가 수행되고 있으나 Postman 등 다른 경로를 통해 들어온 요청에 대해서는 해당 유효성 검사를 거치지 않으므로 서버에서 별도의 Validation 을 수행하여 예기치 못한 오류가 발생하지 않도록 해야합니다. (예를 들어 특정 좌표 및 반경을 기준으로 창고를 조회하는 api 에서 반경 값을 아주 큰 수로 지정하게 되면 DB에 저장된 모든 Storage 를 서버로 가져오게 되므로 아주 큰 부하를 야기할 수 있습니다...