diff --git a/admin/client.go b/admin/client.go
index fddf21044..1883d032b 100644
--- a/admin/client.go
+++ b/admin/client.go
@@ -377,3 +377,30 @@ func withShardKey[T any](conn *connect.Request[T], keys ...string) *connect.Requ
 
 	return conn
 }
+
+// DeleteAccount deletes the user's account.
+func (c *Client) DeleteAccount(ctx context.Context, username, password string) error {
+	_, err := c.client.DeleteAccount(ctx, connect.NewRequest(&api.DeleteAccountRequest{
+		Username: username,
+		Password: password,
+	}))
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// ChangePassword changes the user's password.
+func (c *Client) ChangePassword(ctx context.Context, username, password, newPassword string) error {
+	_, err := c.client.ChangePassword(ctx, connect.NewRequest(&api.ChangePasswordRequest{
+		Username:        username,
+		CurrentPassword: password,
+		NewPassword:     newPassword,
+	}))
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/cmd/yorkie/commands.go b/cmd/yorkie/commands.go
index 7e5418daa..c20fe6305 100644
--- a/cmd/yorkie/commands.go
+++ b/cmd/yorkie/commands.go
@@ -27,6 +27,7 @@ import (
 	"github.com/yorkie-team/yorkie/cmd/yorkie/context"
 	"github.com/yorkie-team/yorkie/cmd/yorkie/document"
 	"github.com/yorkie-team/yorkie/cmd/yorkie/project"
+	"github.com/yorkie-team/yorkie/cmd/yorkie/user"
 )
 
 var rootCmd = &cobra.Command{
@@ -49,6 +50,7 @@ func init() {
 	rootCmd.AddCommand(project.SubCmd)
 	rootCmd.AddCommand(document.SubCmd)
 	rootCmd.AddCommand(context.SubCmd)
+	rootCmd.AddCommand(user.SubCmd)
 	viper.SetConfigName("config")
 	viper.SetConfigType("json")
 	viper.AddConfigPath(path.Join(os.Getenv("HOME"), ".yorkie"))
diff --git a/cmd/yorkie/user/change_password.go b/cmd/yorkie/user/change_password.go
new file mode 100644
index 000000000..ca4e51f6a
--- /dev/null
+++ b/cmd/yorkie/user/change_password.go
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2024 The Yorkie Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package user
+
+import (
+	"context"
+	"fmt"
+	"os"
+
+	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
+	"golang.org/x/term"
+
+	"github.com/yorkie-team/yorkie/admin"
+	"github.com/yorkie-team/yorkie/cmd/yorkie/config"
+)
+
+var (
+	newPassword string
+)
+
+func changePasswordCmd() *cobra.Command {
+	return &cobra.Command{
+		Use:     "change-password",
+		Short:   "Change user password",
+		PreRunE: config.Preload,
+		RunE: func(cmd *cobra.Command, args []string) error {
+			password, newPassword, err := getPasswords()
+			if err != nil {
+				return err
+			}
+
+			if rpcAddr == "" {
+				rpcAddr = viper.GetString("rpcAddr")
+			}
+
+			cli, err := admin.Dial(rpcAddr, admin.WithInsecure(insecure))
+			if err != nil {
+				return fmt.Errorf("failed to dial admin: %w", err)
+			}
+			defer func() {
+				cli.Close()
+			}()
+
+			ctx := context.Background()
+			if err := cli.ChangePassword(ctx, username, password, newPassword); err != nil {
+				return err
+			}
+
+			if err := deleteAuthSession(rpcAddr); err != nil {
+				return err
+			}
+
+			return nil
+		},
+	}
+}
+
+func getPasswords() (string, string, error) {
+	fmt.Print("Enter Password: ")
+	bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
+	if err != nil {
+		return "", "", fmt.Errorf("failed to read password: %w", err)
+	}
+	password := string(bytePassword)
+	fmt.Println()
+
+	fmt.Print("Enter New Password: ")
+	bytePassword, err = term.ReadPassword(int(os.Stdin.Fd()))
+	if err != nil {
+		return "", "", fmt.Errorf("failed to read password: %w", err)
+	}
+	newPassword := string(bytePassword)
+	fmt.Println()
+
+	return password, newPassword, nil
+}
+
+func deleteAuthSession(rpcAddr string) error {
+	conf, err := config.Load()
+	if err != nil {
+		return err
+	}
+
+	delete(conf.Auths, rpcAddr)
+	if err := config.Save(conf); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func init() {
+	cmd := changePasswordCmd()
+	cmd.Flags().StringVarP(
+		&username,
+		"username",
+		"u",
+		"",
+		"Username (required)",
+	)
+	cmd.Flags().StringVar(
+		&rpcAddr,
+		"rpc-addr",
+		"",
+		"Address of the RPC server",
+	)
+	cmd.Flags().BoolVar(
+		&insecure,
+		"insecure",
+		false,
+		"Skip the TLS connection of the client",
+	)
+	_ = cmd.MarkFlagRequired("username")
+	SubCmd.AddCommand(cmd)
+}
diff --git a/cmd/yorkie/user/delete_account.go b/cmd/yorkie/user/delete_account.go
new file mode 100644
index 000000000..80eeef454
--- /dev/null
+++ b/cmd/yorkie/user/delete_account.go
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2024 The Yorkie Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package user
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"time"
+
+	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
+	"golang.org/x/term"
+
+	"github.com/yorkie-team/yorkie/admin"
+	"github.com/yorkie-team/yorkie/cmd/yorkie/config"
+)
+
+func deleteAccountCmd() *cobra.Command {
+	return &cobra.Command{
+		Use:     "delete-account",
+		Short:   "Delete user account",
+		PreRunE: config.Preload,
+		RunE: func(_ *cobra.Command, args []string) error {
+			password, err := getPassword()
+			if err != nil {
+				return err
+			}
+
+			if confirmation, err := makeConfirmation(); !confirmation || err != nil {
+				if err != nil {
+					return err
+				}
+				return nil
+			}
+
+			conf, err := config.Load()
+			if err != nil {
+				return err
+			}
+
+			if rpcAddr == "" {
+				rpcAddr = viper.GetString("rpcAddr")
+			}
+
+			if err := deleteAccountFromServer(conf, rpcAddr, insecure, username, password); err != nil {
+				fmt.Println("Failed to delete your account." +
+					"The account may not exist or the password might be incorrect. Please try again.")
+			} else {
+				fmt.Println("Your account has been successfully deleted.")
+			}
+
+			return nil
+		},
+	}
+}
+
+func getPassword() (string, error) {
+	fmt.Print("Enter Password: ")
+	bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
+	if err != nil {
+		return "", fmt.Errorf("failed to read password: %w", err)
+	}
+	password = string(bytePassword)
+	fmt.Println()
+
+	return password, nil
+}
+
+func makeConfirmation() (bool, error) {
+	fmt.Println(
+		"WARNING: This action is irreversible. Your account and all associated data will be permanently deleted.",
+	)
+
+	fmt.Print("Are you absolutely sure? Type 'DELETE' to confirm: ")
+	var confirmation string
+	if _, err := fmt.Scanln(&confirmation); err != nil {
+		return false, fmt.Errorf("failed to read confirmation from user: %w", err)
+	}
+
+	if confirmation != "DELETE" {
+		return false, fmt.Errorf("account deletion aborted")
+	}
+
+	return true, nil
+}
+
+func deleteAccountFromServer(conf *config.Config, rpcAddr string, insecureFlag bool, username, password string) error {
+	cli, err := admin.Dial(rpcAddr,
+		admin.WithInsecure(insecureFlag),
+		admin.WithToken(conf.Auths[rpcAddr].Token),
+	)
+	if err != nil {
+		return fmt.Errorf("failed to dial admin: %w", err)
+	}
+	defer cli.Close()
+
+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+	defer cancel()
+
+	if err := cli.DeleteAccount(ctx, username, password); err != nil {
+		return fmt.Errorf("server failed to delete account: %w", err)
+	}
+
+	delete(conf.Auths, rpcAddr)
+	if conf.RPCAddr == rpcAddr {
+		for addr := range conf.Auths {
+			conf.RPCAddr = addr
+			break
+		}
+	}
+
+	if err := config.Save(conf); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func init() {
+	cmd := deleteAccountCmd()
+	cmd.Flags().StringVarP(
+		&username,
+		"username",
+		"u",
+		"",
+		"Username (required)",
+	)
+	cmd.Flags().StringVar(
+		&rpcAddr,
+		"rpc-addr",
+		"",
+		"Address of the RPC server",
+	)
+	cmd.Flags().BoolVar(
+		&insecure,
+		"insecure",
+		false,
+		"Skip the TLS connection of the client",
+	)
+	_ = cmd.MarkFlagRequired("username")
+	SubCmd.AddCommand(cmd)
+}
diff --git a/cmd/yorkie/login.go b/cmd/yorkie/user/login.go
similarity index 82%
rename from cmd/yorkie/login.go
rename to cmd/yorkie/user/login.go
index da636f0c8..ac39a6b1b 100644
--- a/cmd/yorkie/login.go
+++ b/cmd/yorkie/user/login.go
@@ -14,12 +14,16 @@
  * limitations under the License.
  */
 
-package main
+// Package user provides the user command.
+package user
 
 import (
 	"context"
+	"fmt"
+	"os"
 
 	"github.com/spf13/cobra"
+	"golang.org/x/term"
 
 	"github.com/yorkie-team/yorkie/admin"
 	"github.com/yorkie-team/yorkie/cmd/yorkie/config"
@@ -38,6 +42,14 @@ func newLoginCmd() *cobra.Command {
 		Short:   "Log in to Yorkie server",
 		PreRunE: config.Preload,
 		RunE: func(cmd *cobra.Command, args []string) error {
+			fmt.Print("Enter Password: ")
+			bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
+			if err != nil {
+				return fmt.Errorf("failed to read password: %w", err)
+			}
+			password = string(bytePassword)
+			fmt.Println()
+
 			cli, err := admin.Dial(rpcAddr, admin.WithInsecure(insecure))
 			if err != nil {
 				return err
@@ -81,14 +93,7 @@ func init() {
 		"username",
 		"u",
 		"",
-		"Username (required if password is set)",
-	)
-	cmd.Flags().StringVarP(
-		&password,
-		"password",
-		"p",
-		"",
-		"Password (required if username is set)",
+		"Username (required)",
 	)
 	cmd.Flags().StringVar(
 		&rpcAddr,
@@ -102,6 +107,6 @@ func init() {
 		false,
 		"Skip the TLS connection of the client",
 	)
-	cmd.MarkFlagsRequiredTogether("username", "password")
-	rootCmd.AddCommand(cmd)
+	_ = cmd.MarkFlagRequired("username")
+	SubCmd.AddCommand(cmd)
 }
diff --git a/cmd/yorkie/logout.go b/cmd/yorkie/user/logout.go
similarity index 97%
rename from cmd/yorkie/logout.go
rename to cmd/yorkie/user/logout.go
index ab9047880..e3ecf6336 100644
--- a/cmd/yorkie/logout.go
+++ b/cmd/yorkie/user/logout.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package main
+package user
 
 import (
 	"github.com/spf13/cobra"
@@ -68,5 +68,5 @@ func init() {
 		false,
 		"force log out from all servers",
 	)
-	rootCmd.AddCommand(cmd)
+	SubCmd.AddCommand(cmd)
 }
diff --git a/cmd/yorkie/user/user.go b/cmd/yorkie/user/user.go
new file mode 100644
index 000000000..f572458cf
--- /dev/null
+++ b/cmd/yorkie/user/user.go
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 The Yorkie Authors. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Package user provides the user command.
+package user
+
+import "github.com/spf13/cobra"
+
+var (
+	// SubCmd represents the user command
+	SubCmd = &cobra.Command{
+		Use:   "user",
+		Short: "Manage user account",
+	}
+)
diff --git a/go.mod b/go.mod
index 3174eb884..ec2fce562 100644
--- a/go.mod
+++ b/go.mod
@@ -27,6 +27,7 @@ require (
 	google.golang.org/grpc v1.58.3
 	google.golang.org/protobuf v1.31.0
 	gopkg.in/yaml.v2 v2.4.0
+	gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
@@ -72,10 +73,10 @@ require (
 	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
 	golang.org/x/sync v0.7.0 // indirect
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/sys v0.23.0 // indirect
+	golang.org/x/term v0.23.0
 	golang.org/x/text v0.14.0 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
-	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
 replace github.com/hashicorp/go-memdb => github.com/hackerwins/go-memdb v1.3.3-0.20211225080334-513a74641622
diff --git a/go.sum b/go.sum
index daf71193d..10b9cb034 100644
--- a/go.sum
+++ b/go.sum
@@ -524,10 +524,12 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
+golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=