애플 맥 스튜디오 M3 Ultra 512GB 모델과 Ollama를 통해 LocalLLM 을 구성해 사용하다보니 이런저런 모델을 사용해보곤 합니다. 따로 특별히 기록을 하지 않고 그냥 그때그때 막 바꿔 쓰다보니 전에 사용하던 모델이랑 어떤 차이가 나는지 알기가 힘들어서 기록 차원에서 정보를 좀 공유해보겠습니다.
qwen3-coder-next 모델에 대한 정보는 아래 링크에서 확인하시구요.
https://ollama.com/library/qwen3-coder-next
에이전틱 코딩 워크플로과 로컬 개발에 최적화된 모델이라 해서 사용해보고 있습니다.
Ollama의 Models 사이트에서는 q4_K_M, q8_0 2가지 양자화 모델을 제공중이구요, 저는 그 둘을 다 받아 사용중이긴 합니다만 최근에는 q8_0 모델을 더 많이 사용한것 같긴 합니다.
pirogom@pirogom-Mac-Studio Desktop % ollama show qwen3-coder-next:q4_K_M
Model
architecture qwen3next
parameters 79.7B
context length 262144
embedding length 2048
quantization Q4_K_M
requires 0.15.5
Capabilities
completion
tools
Parameters
temperature 1
top_k 40
top_p 0.95
License
Apache License
Version 2.0, January 2004
...pirogom@pirogom-Mac-Studio Desktop % ollama show qwen3-coder-next:q8_0
Model
architecture qwen3next
parameters 79.7B
context length 262144
embedding length 2048
quantization Q8_0
requires 0.15.5
Capabilities
completion
tools
Parameters
top_k 40
top_p 0.95
temperature 1
License
Apache License
Version 2.0, January 2004
...이렇게 2가지 양자화 버전을 제공합니다. 맥을 쓰는데 왜 MLX 모델을 쓰지 않느냐 물으신다면 우선 아직 mlx 관련 솔루션들 안정성이 좀 아쉽고 LM Studio는 업데이트가 더딘 느낌이고 성향에 안 맞아서 ollama를 사용중입니다. 언젠가 ollama에도 mlx 백엔드를 쓸 수 있는 날이 오겠지요 ..

우선 ollama 를 구동하기 전의 메모리 사용량입니다.
우선 q4_K_M 양자화 모델을 먼저 돌려보겠습니다.
구동 후 첫 요청시에 모델을 로드하는데 시간이 꽤 걸림으로.. 처음엔 간단히 hi 정도로 ㅎㅎ
pirogom@pirogom-Mac-Studio Desktop % ollama run qwen3-coder-next:q4_K_M "hi" --verbose
Hello! How can I help you today? 😊
total duration: 7.504174875s
load duration: 6.554922583s
prompt eval count: 9 token(s)
prompt eval duration: 622.734042ms
prompt eval rate: 14.45 tokens/s
eval count: 12 token(s)
eval duration: 316.805375ms
eval rate: 37.88 tokens/s
pirogom@pirogom-Mac-Studio Desktop % ollama run qwen3-coder-next:q4_K_M "hi" --verbose
Hello! 😊 How can I help you today?
total duration: 999.43025ms
load duration: 64.577209ms
prompt eval count: 9 token(s)
prompt eval duration: 614.886875ms
prompt eval rate: 14.64 tokens/s
eval count: 12 token(s)
eval duration: 317.202626ms
eval rate: 37.83 tokens/s첫번째 요청은 load diration이 6.5초 정도, 이후에는 64ms 정도입니다. prompt eval 값들은 입력한 프롬프트에 대한 통계이고 출력 토큰에 대한부분은 eval 값을 보시면 됩니다. 37.83 정도네요..

pirogom@pirogom-Mac-Studio Desktop % ollama ps
NAME ID SIZE PROCESSOR CONTEXT UNTIL
qwen3-coder-next:q4_K_M ca06e9e4087c 61 GB 100% GPU 262144 Forever메모리 사용량은 이정도 됩니다. 기본 컨텍스트 크기를 256k로 잡아논 상태입니다.
간단한 숫자야구 게임을 만들어 보겠습니다.
pirogom@pirogom-Mac-Studio Desktop % ollama run qwen3-coder-next:q4_K_M "간단한 숫자야구 게임을 go언어로 작성해줘" --verbose
물론입니다! Go 언어로 간단한 **숫자 야구 게임**을 구현해드릴게요.
### 📌 게임 규칙 (3자리 숫자 야구)
- 컴퓨터는 중복되지 않는 3자리 난수(1~9)를 생성합니다. (예: 123, 456, 789 등)
- 사용자는 3자리 숫자를 입력합니다.
- **스트라이크(S)**: 숫자와 위치가 모두 같음
- **볼(B)**: 숫자는 같지만 위치가 다름
- **아웃(O)**: 숫자도 틀림
- 입력이 정확할 때까지 반복 (3스트라이크면 종료)
---
### ✅ Go 소스 코드 (`main.go`)
```go
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func generateSecretNumber() []int {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
rand.Shuffle(len(numbers), func(i, j int) {
numbers[i], numbers[j] = numbers[j], numbers[i]
})
return numbers[:3]
}
func parseInput(input string) ([]int, error) {
if len(input) != 3 {
return nil, fmt.Errorf("3자리 숫자만 입력 가능합니다.")
}
digits := []int{}
for _, ch := range input {
digit, err := strconv.Atoi(string(ch))
if err != nil {
return nil, fmt.Errorf("숫자만 입력 가능합니다.")
}
if digit < 1 || digit > 9 {
return nil, fmt.Errorf("1~9 범위의 숫자만 사용 가능합니다.")
}
digits = append(digits, digit)
}
// 중복 확인
if len(digits) != len(unique(digits)) {
return nil, fmt.Errorf("중복되지 않는 숫자를 입력하세요.")
}
return digits, nil
}
func unique(intSlice []int) []int {
keys := make(map[int]bool)
list := []int{}
for _, entry := range intSlice {
if _, ok := keys[entry]; !ok {
keys[entry] = true
list = append(list, entry)
}
}
return list
}
func calculateResult(guess, secret []int) (strike, ball int) {
for i := 0; i < 3; i++ {
if guess[i] == secret[i] {
strike++
} else if contains(secret, guess[i]) {
ball++
}
}
return
}
func contains(slice []int, val int) bool {
for _, v := range slice {
if v == val {
return true
}
}
return false
}
func main() {
rand.Seed(time.Now().UnixNano())
secret := generateSecretNumber()
fmt.Println("🔢 숫자 야구 게임을 시작합니다! (1~9, 중복 없는 3자리 숫자)")
fmt.Println("정답은 중복되지 않는 1~9 범위의 3자리 숫자입니다.")
fmt.Println("입력 예: 123, 789, 456 등")
fmt.Println("quit 입력 시 게임 종료")
scanner := bufio.NewScanner(os.Stdin)
attempts := 0
for {
fmt.Print("\n>> ")
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
if input == "quit" || input == "q" {
fmt.Println("게임을 종료합니다. 정답:", secret)
return
}
guess, err := parseInput(input)
if err != nil {
fmt.Println("⚠️", err)
continue
}
strike, ball := calculateResult(guess, secret)
out := 3 - (strike + ball)
attempts++
fmt.Printf("📊 결과: %dS %dB %dO\n", strike, ball, out)
if strike == 3 {
fmt.Printf("🎉 정답입니다! %d회 만에 성공!\n", attempts)
return
}
}
}
```
---
### 🚀 실행 방법
1. `main.go` 파일로 저장
2. 터미널에서:
```bash
go run main.go
```
---
### 💡 예시 실행 화면
```
🔢 숫자 야구 게임을 시작합니다! (1~9, 중복 없는 3자리 숫자)
정답은 중복되지 않는 1~9 범위의 3자리 숫자입니다.
입력 예: 123, 789, 456 등
quit 입력 시 게임 종료
>> 123
📊 결과: 1S 0B 2O
>> 145
📊 결과: 2S 1B 0O
>> 142
⚠️ 중복되지 않는 숫자를 입력하세요.
>> 165
📊 결과: 3S 0B 0O
🎉 정답입니다! 3회 만에 성공!
```
---
필요시 규칙 변경(4자리, 0~9 포함 등)도 도와드릴 수 있어요 😊
궁금한 부분 있으면 알려주세요!
total duration: 35.760818959s
load duration: 68.150167ms
prompt eval count: 25 token(s)
prompt eval duration: 642.200666ms
prompt eval rate: 38.93 tokens/s
eval count: 1212 token(s)
eval duration: 34.830003762s
eval rate: 34.80 tokens/s34.80 tps 정도네요..
이번에는 q8_0 양자화 모델을 사용해 보겠습니다.
pirogom@pirogom-Mac-Studio Desktop % ollama ps
NAME ID SIZE PROCESSOR CONTEXT UNTIL
qwen3-coder-next:q8_0 3f68e12b44ee 94 GB 100% GPU 262144 Forever
대량 30기가 정도 램을 더 차지하는군요 ㄷㄷㄷ;; 제가 512g 모델을 쓰고 있어서 그렇지;;; 양자화 정도차이에 따라 ;; 5090 급 vram 이 왔다갔다 거립니다 ㅎㅎ(용량만 놓고 말하는 겁니다 5090 같은 놈은 용량을 떠나서 대역폭이 어마무시 합니다. 제 맥 스튜디오는 덩치로 승부하는 놈이구요..)
pirogom@pirogom-Mac-Studio Desktop % ollama run qwen3-coder-next:q8_0 "간단한 숫자야구 게임을 go언어로 작성해줘" --verbose
Go 언어로 간단한 숫자야구 게임(3자리 기준, 중복 없음, 0~9 숫자 사용)을 구현한 예제입니다.
---
### ✅ 게임 규칙 요약:
- 컴퓨터는 중복되지 않는 **3자리 숫자**를 랜덤으로 생성합니다.
- 플레이어는 3자리 숫자를 입력하여 추측합니다.
- 입력 후, **Strike**(자리와 숫자가 일치), **Ball**(숫자는 일치하지만 자리 다름), **Out**(아무것도 일치하지 않음)을
알려줍니다.
- 3 Strike가 나면 게임이 종료되고, 재시작 여부를 묻습니다.
---
### 📜 `main.go`
```go
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
const digitCount = 3
func main() {
rand.Seed(time.Now().UnixNano())
for {
playGame()
if !askPlayAgain() {
break
}
}
fmt.Println("게임을 이용해주셔서 감사합니다! 👋")
}
func playGame() {
// 랜덤 3자리 숫자 생성 (중복 X)
secret := generateSecretNumber()
fmt.Println("=== 숫자야구 게임 ===")
fmt.Printf("0~9의 숫자로 구성된 중복 없는 %d자리 숫자를 맞춰보세요!\n", digitCount)
fmt.Println("예: 123, 456, 901 (각 자리 수는 중복 불가)")
scanner := bufio.NewScanner(os.Stdin)
attempts := 0
for {
fmt.Print("\n예상하는 숫자를 입력하세요: ")
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
attempts++
// 유효성 검사
if !isValidInput(input) {
fmt.Println("❌ 유효한 입력이 아닙니다. (", digitCount, "자리의 숫자, 중복 없어야 함)")
continue
}
// 결과 계산
strike, ball := calculateScore(input, secret)
if strike == digitCount {
fmt.Printf("🎉 정답입니다! 숫자는 %s였습니다.\n", secret)
fmt.Printf("총 %d번 시도하셨습니다.\n", attempts)
break
}
out := digitCount - strike - ball
fmt.Printf("✅ 결과: %d Strike, %d Ball, %d Out\n", strike, ball, out)
}
}
func generateSecretNumber() string {
nums := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
rand.Shuffle(len(nums), func(i, j int) {
nums[i], nums[j] = nums[j], nums[i]
})
result := ""
for i := 0; i < digitCount; i++ {
result += strconv.Itoa(nums[i])
}
return result
}
func isValidInput(input string) bool {
if len(input) != digitCount {
return false
}
seen := make(map[rune]bool)
for _, r := range input {
if r < '0' || r > '9' {
return false
}
if seen[r] {
return false // 중복 감지
}
seen[r] = true
}
return true
}
func calculateScore(guess, secret string) (strike, ball int) {
for i := 0; i < digitCount; i++ {
if guess[i] == secret[i] {
strike++
} else {
// 자리가 다를 때, 숫자가 포함되어 있으면 Ball
if strings.Contains(secret, string(guess[i])) {
ball++
}
}
}
return
}
func askPlayAgain() bool {
fmt.Print("\n다시 하시겠습니까? (y/n): ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
resp := strings.TrimSpace(strings.ToLower(scanner.Text()))
return resp == "y" || resp == "yes"
}
```
---
### ▶ 실행 방법
```bash
go run main.go
```
---
### ✅ 예시 실행 화면
```
=== 숫자야구 게임 ===
0~9의 숫자로 구성된 중복 없는 3자리 숫자를 맞춰보세요!
예: 123, 456, 901 (각 자리 수는 중복 불가)
예상하는 숫자를 입력하세요: 123
✅ 결과: 0 Strike, 1 Ball, 2 Out
예상하는 숫자를 입력하세요: 456
✅ 결과: 1 Strike, 0 Ball, 2 Out
예상하는 숫자를 입력하세요: 476
🎉 정답입니다! 숫자는 476였습니다.
총 3번 시도하셨습니다.
다시 하시겠습니까? (y/n): n
게임을 이용해주셔서 감사합니다! 👋
```
---
필요에 따라 난이도 조절(자리수 증가), 힌트 제공, 시도 횟수 제한 등을 추가할 수 있어요! 😊
원하시면 확장 기능도 알려드릴게요.
total duration: 38.475538209s
load duration: 66.668375ms
prompt eval count: 25 token(s)
prompt eval duration: 835.311584ms
prompt eval rate: 29.93 tokens/s
eval count: 1217 token(s)
eval duration: 37.353103146s
eval rate: 32.58 tokens/s코드를 보면 q4_K_M 양자화의 경우 한번 게임이 끝나면 종료되는 반면 Q8_0이 작성한 코드는 한판 끝난 후에 다시 하겠는지를 묻는 처리가 추가되었네요.. 미묘한 차이이긴 하지만 q4_K_M 대비 Q8이 조금 섬세?? 한 결과를 만드는 편이고 메모리 사용량 대비 TPS 감소는 상대적으로 크지 않아서 제 경우 Q8_0 양자화 모델을 주로 사용했던 모델입니다.
하지만 .. 비슷한 규모의 모델들 대비 상대적으로 속도가 좀 아쉽긴 합니다.
물론 모델명에 coder 가 들어간 놈이고 에이전틱 코딩에 맞춰서 최적화 해둔놈이고 최신 모델이라 끌린점도 있긴 하지만 전반적으로 다른 모델 대비 속도가 좀 아쉬운데.. 지금까지는 제가 클로드 코드 같은 에이전틱 툴보다 채팅 기반의 보조수단으로 좀더 활용을 많이하다보니 .. gpt-oss:120b 같은 모델보다 훨씬 느린건 좀 고민이 되네요 ..
pirogom@pirogom-Mac-Studio Desktop % ollama run gpt-oss:120b "간단한 숫자야구 게임을 go언어로 작성해줘" --verbose Thinking...
The user wants a simple number baseball game (숫자야구) implemented in Go language. Provide code with explanation.
Probably need to explain rules: 3-digit number, no duplicate digits, guess feedback strikes and balls. Provide
full Go program, with input handling, random number generation, loop until 3 strikes. Also maybe mention edge
cases, testing. Provide instructions on running.
Write in Korean. Provide code with comments. Possibly also show go.mod optional. Provide final answer.
...done thinking.
## 간단한 숫자야구(숫자 맞추기) 게임 – Go 구현
아래 코드는 **3자리 숫자 야구**(Strike & Ball) 게임을 콘솔에서 즐길 수 있게 만든 Go 프로그램입니다.
### 게임 규칙
1. 컴퓨터가 0~9 사이의 서로 다른 숫자 3개를 무작위로 만든다. (예: 527)
2. 사용자는 3자리 숫자를 입력한다.
- 각 자리의 숫자는 중복되지 않아야 한다.
3. 프로그램은 **Strike**와 **Ball**을 알려준다.
- **Strike** : 같은 자리·같은 숫자
- **Ball** : 다른 자리이지만 같은 숫자
4. `3 Strike`가 나오면 정답! 프로그램이 종료된다.
---
## 1. 전체 코드
```go
// 파일명: main.go
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
// -----------------------------------------------------
// 1) 컴퓨터가 만든 무작위 3자리 숫자 (중복 없음) 반환
// -----------------------------------------------------
func generateNumber() []int {
rand.Seed(time.Now().UnixNano())
num := make([]int, 0, 3)
for len(num) < 3 {
n := rand.Intn(10) // 0~9
// 중복 검사
dup := false
for _, v := range num {
if v == n {
dup = true
break
}
}
if !dup {
num = append(num, n)
}
}
return num
}
// -----------------------------------------------------
// 2) 사용자가 입력한 문자열을 3자리 정수 슬라이스로 변환
// - 길이, 숫자, 중복 체크
// -----------------------------------------------------
func parseInput(input string) ([]int, error) {
input = strings.TrimSpace(input)
if len(input) != 3 {
return nil, fmt.Errorf("3자리 숫자를 입력해주세요")
}
// 문자열이 모두 숫자인지 확인
if _, err := strconv.Atoi(input); err != nil {
return nil, fmt.Errorf("숫자만 입력 가능합니다")
}
res := make([]int, 3)
seen := make(map[int]bool)
for i, ch := range input {
d := int(ch - '0')
if seen[d] {
return nil, fmt.Errorf("숫자는 중복될 수 없습니다")
}
seen[d] = true
res[i] = d
}
return res, nil
}
// -----------------------------------------------------
// 3) Strike & Ball 계산
// -----------------------------------------------------
func countStrikeBall(answer, guess []int) (strike, ball int) {
for i := 0; i < 3; i++ {
if guess[i] == answer[i] {
strike++
continue
}
// 다른 자리에 같은 숫자가 있는지 확인
for j := 0; j < 3; j++ {
if guess[i] == answer[j] {
ball++
break
}
}
}
return
}
// -----------------------------------------------------
// 4) 메인 루프
// -----------------------------------------------------
func main() {
answer := generateNumber()
// fmt.Println("DEBUG:", answer) // 디버그용: 정답을 확인하고 싶다면 주석 해제
fmt.Println("=== 숫자 야구 (3자리) ===")
fmt.Println("0~9 사이의 서로 다른 숫자 3개를 맞춰보세요.")
fmt.Println("입력 형식: 예) 527")
fmt.Println("각 자리마다 같은 숫자는 중복될 수 없습니다.\n")
scanner := bufio.NewScanner(os.Stdin)
attempt := 0
for {
attempt++
fmt.Printf("%d번째 시도 > ", attempt)
if !scanner.Scan() {
// EOF 혹은 오류 발생
fmt.Println("\n입력이 종료되었습니다.")
return
}
line := scanner.Text()
guess, err := parseInput(line)
if err != nil {
fmt.Println("입력 오류:", err)
attempt-- // 유효하지 않은 입력은 시도 횟수에 포함하지 않음
continue
}
strike, ball := countStrikeBall(answer, guess)
if strike == 3 {
fmt.Printf("축하합니다! %d번만에 정답을 맞추셨습니다. 정답: %s\n", attempt, line)
break
}
fmt.Printf("=> %d Strike, %d Ball\n", strike, ball)
}
}
```
### 코드 흐름 요약
| 단계 | 수행 내용 |
|------|-----------|
| 1️⃣ | `generateNumber()` : 중복 없는 3자리 숫자를 랜덤 생성 |
| 2️⃣ | `parseInput()` : 사용자가 입력한 문자열을 검증·변환 |
| 3️⃣ | `countStrikeBall()` : 정답과 추측을 비교해 Strike, Ball 개수 계산 |
| 4️⃣ | `main()` : 게임 루프, 입력·출력·시도 횟수 관리 |
---
## 2. 실행 방법
1. **Go 설치** (버전 1.18 이상 권장)
```bash
go version
```
2. **프로젝트 디렉터리 생성**
```bash
mkdir number-baseball && cd number-baseball
```
3. **위 코드를 `main.go` 파일에 저장**
4. **빌드 및 실행**
```bash
go run main.go
```
혹은 실행 파일을 만들고 싶다면:
```bash
go build -o baseball main.go
./baseball
```
---
## 3. 커스터마이징 아이디어
| 기능 | 구현 방법 |
|------|-----------|
| **자리수 변경** (예: 4자리) | `generateNumber`, `parseInput`, `countStrikeBall` 에서 `3`을 원하는 자리수
(`digitCount`) 변수로 교체 |
| **힌트 제한** (예: 최대 10번) | `attempt` 변수를 체크하고 `attempt > 10`이면 게임 오버 처리 |
| **정답 공개 옵션** | 디버그용 `fmt.Println("DEBUG:", answer)` 주석 해제 |
| **다른 언어와의 비교** | `strconv.Atoi` 대신 `fmt.Sscanf` 등 사용해 보기 |
| **GUI/웹** | `fyne`, `gioui` 같은 GUI 라이브러리 혹은 `net/http` 로 웹 버전 구현 |
---
## 4. 동작 예시
```
=== 숫자 야구 (3자리) ===
0~9 사이의 서로 다른 숫자 3개를 맞춰보세요.
입력 형식: 예) 527
각 자리마다 같은 숫자는 중복될 수 없습니다.
1번째 시도 > 123
=> 0 Strike, 1 Ball
2번째 시도 > 456
=> 1 Strike, 0 Ball
3번째 시도 > 789
=> 0 Strike, 2 Ball
4번째 시도 > 527
=> 3 Strike, 0 Ball
축하합니다! 4번만에 정답을 맞추셨습니다. 정답: 527
```
---
### 🎉 마무리
위 코드만 복사해서 `main.go`에 붙여넣고 `go run` 하면 바로 **숫자 야구**를 즐길 수 있습니다.
게임 로직이 간단하기 때문에 스스로 변형해 보면서 Go의 입출력, 슬라이스, 난수 생성 등을 연습해 보세요!
궁금한 점이나 추가 기능이 필요하면 언제든 물어봐 주세요. Happy coding! 🚀
total duration: 35.042592792s
load duration: 8.077597209s
prompt eval count: 83 token(s)
prompt eval duration: 940.770625ms
prompt eval rate: 88.23 tokens/s
eval count: 1826 token(s)
eval duration: 25.64118875s
eval rate: 71.21 tokens/sMXFP4로 양자화한 gpt-oss 120b 모델의 결과입니다. tps 가 2배;; 차이가 나는 상황이라 ㅎㅎㅎ
pirogom@pirogom-Mac-Studio Desktop % ollama ps
NAME ID SIZE PROCESSOR CONTEXT UNTIL
gpt-oss:120b a951a23b46a1 92 GB 100% GPU 131072 Forever
qwen3-coder-next:q8_0 3f68e12b44ee 94 GB 100% GPU 262144 Forever
qwen3-coder-next q8 + gpt-oss:120b 둘 다 올리면 213기가 정도 램을 씁니다? ㅎㅎㅎㅎ
이렇게 qwen3-coder-next 모델에 대한 간단한 실행정보?에 대한 글을 마무리 해보겠습니다.
LocalLLM을 사용해 가면서 이런류의 정보는 계속 지속적으로 남겨 보도록 하겠습니다.
댓글을 달려면 로그인해야 합니다.