반응형

전체 글 135

트라이픽스 솔리테어 — 부모-자식 관계로 표현한 피라미드

오프라인 인디팩 · 개발일지트라이픽스 솔리테어 — 부모-자식 관계로 표현한 피라미드2026-06-09 · v1.0 · 카드 솔리테어 / 알고리즘요약 — 3개의 봉우리 모양 피라미드에서 카드를 제거해나가는 트라이픽스. 각 카드가 몇 번 위치의 "자식"인지를 미리 정의한 매핑 테이블로 앞면/뒷면을 결정한다.위치 → 자식 2개 매핑으로 face-up 판정28개 위치 중 상위 18개는 각각 아래 2개의 자식 위치를 가진다. 두 자식이 모두 제거되면(=null) 그 카드가 face-up이 된다. 베이스 행(18~27번)은 애초에 자식이 없어 항상 face-up이다.bool isFaceUp(int pos) { if (pyramid[pos] == null) return false; if (pos >= 18..

앱 시작 시 초기화 순서 — 저장된 로그인 정보부터 순서대로 복원하기

실무 프로젝트 · 개발일지 앱 시작 시 초기화 순서 — 저장된 로그인 정보부터 순서대로 복원하기 Flutter · GetX · FCM 요약 — 앱이 켜질 때 로그인 토큰, 주소, 약관 동의 여부를 순서대로 복원하고, 다른 기기에서 먼저 로그인했는지 검사한 뒤에야 알림/화면 비율 등 나머지 초기화를 진행한다. 1. 초기화는 반드시 순서가 있다 — await 체인으로 명시 사용자 정보 → 주소 → 토큰 → 약관 동의 → 토큰 재검증 → 로그인 방식(카카오/네이버/애플) 순서로 하나씩 복원한다. 병렬로 실행하면 서로 참조하는 값이 아직 없는 상태에서 읽힐 수 있어서, 의도적으로 순차 await 체인으로 작성했다. static appInit(BuildContext context)..

Flutter & Dart 2026.10.06

알림톡 발송 서비스 — 템플릿 변수 치환을 문자열 replace로 처리하기

실무 프로젝트 · 개발일지 알림톡 발송 서비스 — 템플릿 변수 치환을 문자열 replace로 처리하기 Spring Boot · 비즈메시지(알림톡) API 요약 — DB에 저장된 알림톡 템플릿 문자열의 플레이스홀더를 실제 값으로 치환한 뒤, 외부 알림톡 발송 API에 JSON으로 쏘는 서비스. 템플릿 내용과 발송 로직을 분리해서 문구는 코드 배포 없이 DB에서만 수정 가능하게 만들었다. 1. DB에 저장된 템플릿을 코드에서 변수 치환 템플릿 문구 자체는 #{이름}, #{신청일} 같은 플레이스홀더가 포함된 채로 DB에 저장돼 있고, 발송 시점에 실제 값으로 하나씩 replace()한다. 템플릿을 코드로 하드코딩하지 않아서 운영팀이 문구를 바꿀 때 배포가 필요 없다. Strin..

SpringBoot (JAVA) 2026.10.05

두더지 잡기 — 등장/유지/퇴장 3단계 진행도

오프라인 인디팩 · 개발일지두더지 잡기 — 등장/유지/퇴장 3단계 진행도2026-06-08 · v1.0 · 아케이드 / 반응속도요약 — 30초 동안 무작위로 튀어나오는 두더지를 때리는 게임. 시간이 지날수록 등장 간격은 짧아지고 유지 시간도 줄어들어 후반부로 갈수록 훨씬 빡빡해진다.진행률에 따라 스폰 간격과 생존시간 선형 보간게임 진행률(0=시작, 1=종료)에 따라 스폰 간격은 0.9초에서 0.25초로, 두더지 생존시간은 1.4초에서 0.6초로 줄어든다. 둘 다 단순 선형 보간이라 코드가 짧지만 체감 난이도 곡선은 뚜렷하다.double get _spawnInterval => 0.9 - 0.65 * _progress;double get _moleLifetime => 1.4 - 0.8 * _progr..

매장 홈 화면을 위젯 단위로 쪼개기 — 31KB 파일이 감당 가능해진 이유

실무 프로젝트 · 개발일지 매장 홈 화면을 위젯 단위로 쪼개기 — 31KB 파일이 감당 가능해진 이유 Flutter · GetX 요약 — 캐러셀 배너, 검색바, 카테고리, 상세 다이얼로그까지 들어가는 매장 홈 화면. 전체를 한 파일에 몰아넣는 대신 컨트롤러와 하위 위젯을 폴더 단위로 분리해서 파일 하나의 책임을 좁혔다. 1. 상태는 전용 컨트롤러로, 화면은 조립만 StoreHomeController가 캐러셀 인덱스, 카테고리 선택 상태 등을 전부 들고 있고, 메인 위젯(StoreHome)은 Get.put으로 컨트롤러를 주입받아 하위 위젯들을 배치하는 역할만 한다. import 목록만 봐도 appSearch, bannerDetailView, middle_category, St..

Flutter & Dart 2026.10.04

MyBatis Mapper로 저장 프로시저 호출하기 — 비즈니스 로직을 DB에 둔 이유

실무 프로젝트 · 개발일지 MyBatis Mapper로 저장 프로시저 호출하기 — 비즈니스 로직을 DB에 둔 이유 Spring Boot · MyBatis 요약 — 복잡한 쿼리 로직 상당수를 저장 프로시저로 두고, Java 계층은 @Mapper 인터페이스로 프로시저를 호출하는 아주 얇은 래퍼 역할만 한다. 1. @Select 애노테이션 하나로 프로시저 실행 MyBatis의 XML 매퍼 파일 없이, 인터페이스 메서드에 @Select("exec SP_xxx #{param}")만 붙이면 파라미터 바인딩까지 자동 처리된다. 반환 타입은 대부분 List>로 통일해서, 프로시저 결과 컬럼이 바뀌어도 Java 쪽 DTO를 매번 수정할 필요가 없다. @Mapper@Repositorypub..

SpringBoot (JAVA) 2026.10.03

공룡 러너 — 무한 장애물 생성과 하드코어 히트박스

오프라인 인디팩 · 개발일지공룡 러너 — 무한 장애물 생성과 하드코어 히트박스2026-06-08 · v1.0 · 아케이드 / 무한 러너요약 — 크롬 오프라인 게임을 오마주한 무한 러너. 거리에 비례해 속도가 계속 빨라지고, 점수가 일정 이상 넘어가면 새 장애물(새)이 등장한다. 히트박스는 그래픽보다 살짝 작게 잡아 억울한 충돌을 줄였다.거리 기반 스폰과 난이도 곡선장애물은 고정 간격이 아니라 "다음 스폰 거리"를 매번 무작위로 갱신하는 방식이다. 최소 간격은 현재 속도에 비례해서 늘어나기 때문에, 빨라질수록 장애물 사이 여유가 자동으로 조정된다.if (distance > _nextSpawnDistance) { _spawnObstacle(); final minGap = 280.0 + 80 * (..

본인인증 SDK 연동 — 서버에서 키를 받아오는 이유

실무 프로젝트 · 개발일지 본인인증 SDK 연동 — 서버에서 키를 받아오는 이유 Flutter · iamport_flutter 요약 — 회원가입 시 휴대폰 본인인증을 아임포트(PortOne) SDK로 처리한다. 인증 완료 콜백에서 결과를 그대로 믿지 않고, 서버에 다시 조회해서 검증한 뒤에야 다음 화면(가입 정보 입력)으로 넘어간다. 1. 가맹점 시크릿은 클라이언트에 두지 않는다 아임포트 인증 토큰을 발급받으려면 imp_key/imp_secret이 필요한데, 이 값을 앱에 하드코딩하지 않고 자체 API에서 매번 조회해온다. 클라이언트 코드에는 공개 식별자인 userCode만 남는다. var getKeyUrl = '${ApiAdress.getApiAdress()}v1/SP_..

Flutter & Dart 2026.10.02

FCM 푸시 — 일반 사용자와 파트너를 별도 Firebase 프로젝트로 분리하기

실무 프로젝트 · 개발일지 FCM 푸시 — 일반 사용자와 파트너를 별도 Firebase 프로젝트로 분리하기 Spring Boot · Firebase Admin SDK 요약 — 앱이 두 개(고객용/파트너용)라 Firebase 프로젝트도 둘로 나눠서 관리하고, 서버에서는 FirebaseApp 인스턴스를 이름으로 구분해 알맞은 프로젝트로 메시지를 보낸다. 1. 이름을 가진 FirebaseApp 인스턴스 2개 FirebaseApp.getInstance("이름")으로 이미 초기화된 인스턴스가 있으면 재사용하고, 없으면(IllegalStateException) 서비스 계정 키 파일로 새로 초기화한다. 일반 사용자용과 파트너용이 각각 별도 이름의 인스턴스로 관리되기 때문에 서로 다른 F..

SpringBoot (JAVA) 2026.10.01

벽돌깨기 — 하강하는 벽돌과 패들 반사각

오프라인 인디팩 · 개발일지벽돌깨기 — 하강하는 벽돌과 패들 반사각2026-06-08 · v1.0 · 아케이드 / 물리요약 — 고전 벽돌깨기에 시간이 지나면 벽돌이 한 줄씩 내려오는 압박 요소를 더했다. 패들의 어디에 맞았는지에 따라 반사각이 달라지고, 벽돌을 깰 때마다 공이 조금씩 빨라진다.패들 위치 기반 반사각패들 정중앙에 맞으면 수직으로, 끝쪽에 맞을수록 최대 ±60도까지 각도가 꺾인다. hitPos를 -1~1로 정규화해서 각도에 매핑하는 방식이라 조작감이 직관적이다.final hitPos = ((ballX - paddleX) / (paddleWidth / 2)).clamp(-1.0, 1.0);final angle = -pi / 2 + hitPos * (pi / 3); // 최대 ±60°ba..

반응형