새로운 서비스(앱, 게임 등) 생성 시, GameData, UserData, OtherData 폴더가 함께 생성되도록 하고, UserData 폴더에는 Info.json 파일을 생성하여 신규 유저의 UID 부여에 참고하도록 한다.
{"next_uid": "000000000"}
유저 정보 생성(회원가입)
회원가입을 위해 서비스 이름, 입력ID, 입력Password와 함께 서버에 요청한다.
서비스가 있는지 확인, 겹치는 유저 ID가 있는지 확인
(입력Password + 16자리의 salt) 를 해시 암호화 한 패스워드를 얻는다
UID의 폴더를 생성하고, Base.json을 작성한다.
uid, id, pass, salt 를 보관한다.
데이터 백업 압축파일 다운로드
백업했던 데이터 업로드하여 복원(덮어쓰기)
게임 데이터 업로드(기존 서버의 게임 데이터를 덮기)
게임 데이터 GET
로그인 기능
SERVICE 내 ID PASS 검증.(즉 이 세 요소를 서버에 같이 전송해야함)
토큰발행 후 유저에게 전송, 서버에 보관, (토큰-UID) 쌍이면 괜찮으려나
아까 UserData 폴더 내에 Info.json 파일로 UID 관리했듯이, Token.json 하나 미리 마련해두고 여기에서 동적으로 관리하면 될 것 같다.
로그아웃 기능
클라이언트 앱이 종료되거나, 로그아웃 버튼을 누르면 서버에서 로그아웃 기능 수행. Key값이 해당 계정의 토큰값인 아이템을 삭제하면 되나?
또는 토큰이 추가된 후 일정 시간(24시간?) 지난 게 확인되면 역시 보관된 아이템을 삭제하면 될듯. 만약 삭제된 뒤로 유저가 토큰으로 유저데이터에 접근을 시도할 경우, 클라이언트에 “님 지금 토큰이 보관되어있지 않은 것 같은데 로그인좀 다시 하셈” 이라고 메시지를 보내면 될 것 같다.
import sys
def LocalInput():
with open("input.txt") as file:
datas = file.read().strip().splitlines()
return datas
def BaekjoonInput():
datas = sys.stdin.read().strip().splitlines()
return datas
# datas = LocalInput()[1:]
datas = BaekjoonInput()[1:]
datas.sort()
for data in datas:
print(data)
인풋 단계에서 메모리를 낭비하지 말자는 아이디어는 있었지만, 어떻게 하면 좋을지 모르겠고 그 외 방도도 떠오르지 않아 GPT에 물어보고, 해당 내용을 학습해보려고 한다.
그 내용은 아래와 같다.
메모리를 초과하는 문제는 주로 정렬 시 사용되는 메모리, 데이터 저장 방식, 또는 출력 방식에서 발생할 수 있습니다. 아래에서는 코드의 메모리 사용량을 줄이고 효율적으로 개선할 수 있는 방법을 제시하겠습니다.
문제 분석
datas = sys.stdin.read().strip().splitlines(): 이 코드는 입력을 한꺼번에 메모리로 읽어와 모든 줄을 리스트로 저장합니다.
datas.sort(): 정렬 과정에서 추가적인 메모리 사용이 발생할 수 있습니다.
for data in datas: print(data): 출력할 때도 리스트의 전체 요소를 메모리에 유지한 상태에서 하나씩 출력합니다.
개선 방향
입력 처리 방식 최적화: 한꺼번에 메모리로 읽지 않고, 줄 단위로 읽으며 즉시 처리하는 방식으로 변경합니다. 이렇게 하면 메모리 사용을 줄일 수 있습니다.
정렬을 메모리 효율적으로 수행: 메모리 사용량을 줄이기 위해 외부 정렬(external sorting)처럼 동작하게 만들거나, 파일을 사용하는 방법을 고려할 수 있습니다. 그러나 Python에서는 sorted()를 사용하여 한 줄씩 정렬하는 방식으로도 효과적으로 처리할 수 있습니다.
입력과 정렬을 동시 처리: 입력을 받을 때마다 즉시 처리하여 메모리를 덜 사용하게 합니다.
개선된 코드 예시
import sys
import heapq
def LocalInput():
with open("input.txt") as file:
datas = file.read().strip().splitlines()
return datas
def BaekjoonInput():
return sys.stdin
# 메모리 초과 방지를 위해 제너레이터를 사용하여 입력 처리
def process_input_and_sort(input_source):
min_heap = []
# 첫 번째 줄은 개수 정보이므로 제외하고, 입력을 한 줄씩 처리
next(input_source)
# 각 줄을 힙에 추가 (메모리를 효율적으로 사용)
for line in input_source:
heapq.heappush(min_heap, line.strip())
# 힙에서 하나씩 꺼내면서 출력 (정렬된 순서로 출력)
while min_heap:
print(heapq.heappop(min_heap))
# main 함수 호출부
# process_input_and_sort(LocalInput()) # 로컬 테스트용
process_input_and_sort(BaekjoonInput()) # 백준 제출용
개선 포인트 설명
제너레이터 사용: 입력을 한꺼번에 메모리에 로드하지 않고, sys.stdin 제너레이터를 사용하여 한 줄씩 읽어 메모리를 절약합니다.
힙 정렬 (heapq) 사용: 메모리 사용량을 줄이기 위해 힙 자료구조를 사용해 점진적으로 정렬된 데이터를 출력합니다. heapq는 파이썬 표준 라이브러리에서 제공하는 힙 자료구조로, 효율적인 메모리 사용과 정렬을 동시에 제공합니다.
지연된 출력 처리: 정렬된 데이터를 즉시 출력하여, 리스트에 모든 데이터를 담고 있지 않도록 합니다.
추가 고려사항
파일 기반 정렬: 입력 크기가 매우 클 경우, 파일 기반 외부 정렬(External Sorting) 기법을 사용할 수도 있지만, 이는 보통 경쟁 프로그래밍에서 사용하지 않는 방법입니다.
Python 버전 및 최적화: 최신 Python 버전에서는 메모리 관리가 조금 더 효율적일 수 있으므로, Python 3.8 이상을 사용하는 것도 고려해볼 만합니다.
그래서 예전에 지나가다 들었던 방법이 ECS(엔티티 컴포넌트 시스템).. 얘인지는 모르겠는데, 지금 아무튼 Monobehavior 방식에서 ECS로 스크립팅하여 사용하는 Unity Physics/DOTS 와 Havok물리엔진을 다시 한 번 추천받아(GPT4o), DOTS에 Havok 이 포함되어있다고 하나 어쩌나 무튼 잘 모르겠지만 더 진행한다면 이 녀석들을 이용 해 보아야겠다.