랜덤 닉네임 기능 생성기

Kevin·2025년 1월 25일
8

개발.log

목록 보기
7/7
post-thumbnail

서론

이번에 회사에서 서비스 런칭을 하게 되면서, 담당으로 맡아 개발 하게 된 기능들이 있다.

그 기능들 중에 개발 하면서 가장 재미도 있었고, 나름대로 어려움이 있었던 기능인 랜덤 닉네임 생성 기능에 대해서 이야기 해보고자 한다.

대략적인 기능의 요구 사항은 다음과 같다.

  1. 형용사(ex: 아름다운)와 명사(ex: 달)을 조합 하여 닉네임을 생성 할 수 있어야 한다.
  2. 만약 해당 닉네임(ex: 아름다운달)이 기존에 존재 한다면 해당 닉네임 뒤에 숫자를 붙여 주어야 한다.(ex: 아름다운달1)
    • 이 때 만약 뒤에 숫자를 붙여진 해당 닉네임이 존재한다면 해당 닉네임 뒤 숫자를 1 증가 시켜주어야 한다.(ex: 아름다운달2)
  3. 랜덤 닉네임을 동시에 N만건까지 동시 생성 할 수 있어야 하며, 이 때 생성되는 닉네임들간에 동일하면 안된다.

위 요구 사항을 개발 하면서 발생한 문제들과 이 문제들을 어떻게 해결 하였는지에 대해서 이야기 해보고자 한다.

해당 글에 작성 된 코드는 실제 코드으로부터 모두 각색 되었음을 사전에 알립니다.


겪은 문제들 & 해결 방법

첫 번째로 겪었던 문제는 다음과 같다.

형용사와 명사를 조합을 하여 랜덤 닉네임을 생성 해야 한다.

가장 핵심적인 요구사항인데 이 때 고려 해야 할 부분들이 있었다.

아래 리스트를 통해서 고려 해야 했던 부분들을 순차적으로 이야기 해보고자 한다.


1. 형용사와 명사를 DB와 메모리 중 어디에 저장 해야 하는가?

형용사와 명사를 맨 처음에는 메모리에 저장 하고자 하였다.

별도 ENUM 등으로 관리하여 이를 가져오면 DB에서 질의 하여 가져오는 것보다 훨씬 더 리소스를 아낄 수 있을 것이라고 판단 하였다.

그러나 해당 기능의 확장성을 고려 하던 중 “훗날 관리자 페이지에서 관리자가 형용사와 명사를 직접 추가 할 수 있거나 특정 용어에 사회적인 문제가 발생했을 때 제거할 수 있게 하는 기능”이 도입 될 가능성이 높다 판단하여 DB에 저장하는 것으로 정하였다.


2. DB에서 가져올 때의 방식

1번에서 메모리가 아닌 DB에 저장하기로 결정하였다.

이 때 원래는 요구 사항 자체가 단순히 하나의 랜덤 닉네임만 생성하여 반환하는 API였기에 아래와 같은 코드를 가지고 있었다.

NicknameAdjective adjective = nicknameAdjectiveRepository.findById(randomIdx);
NicknameNoun noun = nicknameNounRepository.findById(randomIdx);

그러나 요구 사항 중 3번 요구 사항이 추가 되면서 코드가 변경 될 필요성을 느끼게 되었다.

3. 랜덤 닉네임을 동시에 N만건까지 동시 생성 할 수 있어야 하며, 이 때 생성되는 닉네임들간에 동일하면 안된다.

그래서 N개의 랜덤 닉네임을 생성 해야 할 경우 단 건으로 랜덤 닉네임을 생성 하는 코드를 N번 호출 하는 방식으로 구현 하였다.

  @Transactional
  public RandomNicknameResponseDto getRandomNickname(int size) {
			
			List<String> nicknames = new ArrayList<>();
			
			for (int i=0; i < size; i++) {
	      nicknames.add(makeNickname());
			}
     
      return nicknames;
  }

그러나 이 때 아래의 코드를 N번 호출 하여 형용사와 명사들을 가져오는 것이 속도적인 측면에서 큰 부담이 되었다.

NicknameAdjective adjective = nicknameAdjectiveRepository.findById(randomIdx);
NicknameNoun noun = nicknameNounRepository.findById(randomIdx);

단 1건에 대해서 랜덤 닉네임을 생성 했을 때는 위의 코드로 하였을 때 큰 무리가 안되었지만, N만건 되는 순간 말도 안될 수준으로 속도가 느려졌다.

이에 단건 랜덤 닉네임 생성 API 로직과 다건 랜덤 닉네임 생성 API 로직을 분리 하기로 결정 하였다.

다건 랜덤 닉네임 생성 API 로직간에는 아래 코드를 사용하였다.

List<NicknameAdjective> adjectives = nicknameAdjectiveRepository.findAll();
List<NicknameNoun> nouns = nicknameNounRepository.findAll();

이는 로직 시작 시점에 DB에 있는 모든 형용사와 명사 조합을 가지고 와서 이를 조합하는 방식으로 사용하고자 하기 위함이었다.

그리고 불필요하게 DB에 접근하지 않고 메모리상에서 List의 인덱스에 접근 하여 처리 하는 방식으로 변경 하였다.

nickname += adjectives.get(randomIdx);
nickname += nouns.get(randomIdx);

3. 기존 닉네임 여부 확인 쿼리

요구 사항으로 다음과 같은 요구 사항이 존재했다.

만약 해당 닉네임(ex: 아름다운달)이 기존에 존재 한다면 해당 닉네임 뒤에 숫자를 붙여 주어야 한다.(ex: 아름다운달1)

이 때 기존에 해당 닉네임이 존재 했는지에 대한 여부 확인을 위해서 아래와 같이 코드를 작성 하였다.

    private Boolean isExistNickname(String nickname) {

        Optional<User> userOp = userRepository.findByNickname(nickname);

        return userOp.isPresent();
    }

이 때 중요한 것은 랜덤 닉네임을 생성 해서 반환 하였다 하더라도, 해당 닉네임은 유저가 사용 하기 전(회원가입 전) 시점이라는 것이다.

굳이 User 엔티티를 조회 하여 필드 값들을 가져올 필요가 없었다.

중요한 것은 해당 닉네임을 가진 유저의 값들이 아니라 해당 닉네임을 가진 유저가 있는지, 없는지에 대한 여부였다.

이를 위해 나는 exists를 사용하였다.

private Boolean isExistNickname(String nickname) {
        
		return userRepository.existsByNickname(nickname);
}

 exists는 조건을 만족하는 데이터가 존재하는지 여부만 확인하므로, 최소한의 데이터 검색 및 처리만 수행하지만, findBy는 조건을 만족하는 데이터를 완전히 읽고 반환하기 때문에, 데이터 전송 및 메모리 할당 비용이 추가된다.

10,000건을 기준으로 테스트 해보았을 때 각각 아래의 성능 차이를 보였다.

  • findBy 메서드를 사용 하였을 떄 : 2m 30s
  • exists 메서드를 사용 하였을 때 : 18s

아직 부족한 부분

멀리까지 보게 되는 능력이 부족하다는 것을 느끼게 되었다.

현재 로직에서 1만건 정도가 아니라, 10만건 정도의 요청사항이 들어오게 된다면 명사와 형용사의 개수 한개로 인해서 문제가 발생할 가능성이 크다.

그러면 요청 건이 커지면 커질 수록 명사와 형용사의 개수를 단순히 늘려야 할까?

아니다.

명사와 형용사 외에 관형사나 부사 같은 품사가 추가 될 수도 있다.

또는 애플리케이션 로직 안에서 동시에 생성 된 랜덤 닉네임을 비교 해서 다른 숫자를 부여 할 수도 있다.

이러한 생각들이 설계 당시 생각이 나면 좋으려만, 아직까지는 구현 후 다른 사람들의 의견이나 정적 분석 간 들게 되는 것 같아 아쉽다.

그러나 이 또한 내가 작성한 코드가 더 나은 코드가 될 수 없을까? 더 효율적일 수는 없을까? 라는 고민을 계속 가지고 있다 보면 언젠가는 이 능력을 갖게 되지 않을까라는 생각을 가져본다.


얻게 된 점

랜덤 닉네임 생성기는 원래 validation 조건들에만 통과 되도록 구현 하면 되는 기획 구성이었다.

그러나 내가 다른 서비스들을 사용 할 때 랜덤하게 생성되는 닉네임을 통해서 주변 지인 분들과 재밌게 이야기 하고, 은연 중 해당 서비스에 더욱 친밀한 감정을 느꼈던 경험들이 있어 유저들에게 단순한 문자열보다 형용사와 명사의 조합을 통해 해당 기능을 통해서 재미를 느끼고자 노력 하였다.

아래 사진은 랜덤 닉네임 생성 기능을 통해서 나와 같은 경험을 가진 유저들의 반응이다.

해당 기능이 사용자로 하여금 우리 서비스에 더욱 친밀함을 느낄 수 있게 할 수 있는 기능이라는 확신이 있어, 기획자 분과 다른 개발자 분의 동의를 얻어 해당 기능을 개발 하게 되었다.

그 과정에서 서비스란 단순히 기획자만이 기획을 맡는게 아니라, 개발자인 나 또한 서비스를 사랑하는 한 명의 입장으로서 어떻게 더 서비스를 재미있고, 몰입감 있게 만드는지 고민 뿐만 아니라 의견을 낼 수 있다는 것을 알게 되었다.

profile
Hello, World! \n

0개의 댓글

관련 채용 정보